diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3e2742de11..46e509cb8f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -125,6 +125,9 @@ var/path_type = /obj/item/baseball_bat var/path_type = "/obj/item/baseball_bat" ``` +### Use var/name format when declaring variables +While DM allows other ways of declaring variables, this one should be used for consistency. + ### Tabs, not spaces You must use tabs to indent your code, NOT SPACES. diff --git a/.travis.yml b/.travis.yml index ba11b40c97..b353761b2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: generic sudo: false -dist: precise - env: global: - BYOND_MAJOR="511" @@ -23,12 +21,15 @@ cache: addons: apt: + sources: + - sourceline: 'ppa:ondrej/php' packages: - libc6-i386 - libgcc1:i386 - libstdc++6:i386 - python - python-pip + - php5.6 install: - tools/travis/install_build_tools.sh diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm index 5ed42e8922..214ff213c8 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm @@ -47,7 +47,7 @@ /area/ruin/powered/animal_hospital) "al" = ( /obj/structure/table/wood, -/obj/item/toy/carpplushie, +/obj/item/toy/plush/carpplushie, /turf/open/floor/plasteel/cmo, /area/ruin/powered/animal_hospital) "am" = ( diff --git a/_maps/RandomRuins/SpaceRuins/caravanambush.dmm b/_maps/RandomRuins/SpaceRuins/caravanambush.dmm index d2a416bba2..2f395e4f1c 100644 --- a/_maps/RandomRuins/SpaceRuins/caravanambush.dmm +++ b/_maps/RandomRuins/SpaceRuins/caravanambush.dmm @@ -590,9 +590,9 @@ "bW" = ( /obj/structure/closet/crate/secure/gear, /obj/item/ammo_box/c10mm, -/obj/item/ammo_casing/shotgun/meteorshot, -/obj/item/ammo_casing/shotgun/meteorshot, -/obj/item/ammo_casing/shotgun/meteorshot, +/obj/item/ammo_casing/shotgun/meteorslug, +/obj/item/ammo_casing/shotgun/meteorslug, +/obj/item/ammo_casing/shotgun/meteorslug, /turf/open/floor/mineral/titanium/yellow/airless, /area/ruin/unpowered) "bX" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 6f385e23ee..a4ec56f95e 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -5118,7 +5118,7 @@ /area/maintenance/starboard/fore) "alA" = ( /obj/structure/table/wood, -/obj/item/toy/carpplushie, +/obj/item/toy/plush/carpplushie, /obj/effect/decal/cleanable/cobweb, /turf/open/floor/plasteel/vault{ dir = 8 diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 17572d65f0..b12cbde21c 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -49068,7 +49068,7 @@ /area/bridge/showroom/corporate) "bQl" = ( /obj/structure/table/wood, -/obj/item/toy/carpplushie{ +/obj/item/toy/plush/carpplushie{ color = "red"; name = "Nanotrasen wildlife department space carp plushie" }, @@ -122233,7 +122233,7 @@ cRu cRi cRi cRi -bpu +cRi aaf aaa aaf @@ -129583,7 +129583,7 @@ arI atd bai ate -dDM +dDL axP dnS axY diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 9509e69220..13bd789d72 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -2243,7 +2243,6 @@ req_access = null; req_access_txt = "57" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/stripes/line{ dir = 2 }, @@ -5297,9 +5296,6 @@ icon_state = "0-2" }, /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -10506,6 +10502,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, +/obj/structure/closet/l3closet/security, /turf/open/floor/plasteel/vault{ dir = 5 }, @@ -27154,6 +27151,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, +/obj/structure/closet/l3closet, /turf/open/floor/plasteel/vault{ dir = 5 }, @@ -34636,6 +34634,7 @@ /turf/open/floor/plasteel/whitepurple/side, /area/science/xenobiology) "bjG" = ( +/obj/structure/closet/l3closet/scientist, /turf/open/floor/plasteel/whitepurple/side{ dir = 6 }, @@ -80685,13 +80684,13 @@ aDc aYc aYW byo -byt +byo bbx bcm bdd beb -byy -byA +byo +bys bfK aQd bgT @@ -80941,14 +80940,14 @@ aWQ abt aYc aYW -byp +byo baI bby bcn bde bec beH -byB +byo bfK aQd bgU @@ -81455,14 +81454,14 @@ aWS abt aYe aYW -byr +byo baK bbA bcp bdg bee beJ -byC +byo bfK avV bgU @@ -81713,13 +81712,13 @@ aIZ aYc aYW bys -byu -byv -byw +byo +byo +byo bdh -byx -byz -byD +byo +byo +byo bfM avV bgV @@ -86304,7 +86303,7 @@ ape aqm abt abN -atu +acw abt aad aad diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index e482dcc0bc..f0476df53d 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -6423,7 +6423,7 @@ "qX" = ( /obj/structure/table, /obj/item/toy/katana, -/obj/item/toy/carpplushie, +/obj/item/toy/plush/carpplushie, /obj/effect/turf_decal/stripes/line{ dir = 1 }, diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index d305bfa69c..dd5a25d8ff 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -132,5 +132,6 @@ #define NOLIVER 29 #define NOSTOMACH 30 //citadel code -#define NOAROUSAL 29//Stops all arousal effects -#define NOGENITALS 30//Cannot create, use, or otherwise have genitals +#define NOAROUSAL 29 //Stops all arousal effects +#define NOGENITALS 30 //Cannot create, use, or otherwise have genitals +#define NO_DNA_COPY 31 diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 641454a799..6f20117d36 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -12,33 +12,55 @@ // When the signal is called: (signal arguments) // /datum signals -#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (datum/component) -#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (datum/component) +#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) +#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) #define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: () // /atom signals -#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (obj/item, mob/living, params) -#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (mob/living/carbon/human) -#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (mob) -#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom) +#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) +#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human) +#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob) +#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (/atom/movable, /atom) #define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) #define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity) #define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume) -#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (obj/item/projectile, def_zone) -#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (obj/structure/blob) +#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone) +#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob) #define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume) #define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): () #define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): () #define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): () -#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (mob, obj/item/construction/rcd, passed_mode) +#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) #define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size) +#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params) +#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob) +#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob) +#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob) +#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob) + // /atom/movable signals -#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (atom, dir) -#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable) -#define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (atom) -#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (atom, throwingdatum) +#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) +#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) +#define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (/atom) +#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom, throwingdatum) + +// /obj/item signals +#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) + +// /obj/item/clothing signals +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () + +// /obj/item signals +#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (mob/living/target, mob/living/user) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (mob) +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (obj, mob) + +// /obj/item/clothing signals +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () // /obj/machinery signals #define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): () -#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () \ No newline at end of file +#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () diff --git a/code/__DEFINES/voreconstants.dm b/code/__DEFINES/voreconstants.dm index ea4c26d79e..edcf4f7fd2 100644 --- a/code/__DEFINES/voreconstants.dm +++ b/code/__DEFINES/voreconstants.dm @@ -3,6 +3,7 @@ #define DM_DIGEST "Digest" #define DM_HEAL "Heal" #define DM_NOISY "Noisy" +#define DM_DRAGON "Dragon" #define VORE_STRUGGLE_EMOTE_CHANCE 40 diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index 41d2f721f5..8374b305ad 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -155,7 +155,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1 return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5 - //to_chat(world, "Transform multiplier of [src] is [size_factor + scaling_modifer]") //converts a uniform distributed random number into a normal distributed one //since this method produces two random numbers, one is saved for subsequent calls diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 0eeca2eaf7..2bc6e144dd 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -32,6 +32,7 @@ */ /atom/Click(location,control,params) if(initialized) + SendSignal(COMSIG_CLICK, location, control, params) usr.ClickOn(src, params) /atom/DblClick(location,control,params) @@ -305,6 +306,7 @@ A.ShiftClick(src) return /atom/proc/ShiftClick(mob/user) + SendSignal(COMSIG_CLICK_SHIFT, user) if(user.client && user.client.eye == user || user.client.eye == user.loc) user.examinate(src) return @@ -319,6 +321,7 @@ return /atom/proc/CtrlClick(mob/user) + SendSignal(COMSIG_CLICK_CTRL, user) var/mob/living/ML = user if(istype(ML)) ML.pulled(src) @@ -348,6 +351,7 @@ ..() /atom/proc/AltClick(mob/user) + SendSignal(COMSIG_CLICK_ALT, user) var/turf/T = get_turf(src) if(T && user.TurfAdjacent(T)) if(user.listed_turf == T) @@ -373,6 +377,7 @@ return /atom/proc/CtrlShiftClick(mob/user) + SendSignal(COMSIG_CLICK_CTRL_SHIFT) return /* diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 85ecd036de..d4d2c2d8a5 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -78,7 +78,7 @@ /obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(datum/hud/owner_hud) - var settings = owner_hud.get_action_buttons_icons() + var/settings = owner_hud.get_action_buttons_icons() icon = settings["bg_icon"] icon_state = settings["bg_state"] hide_icon = settings["toggle_icon"] diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 638b4a31cf..b361ef1a78 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -242,9 +242,12 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." icon_state = "fire" /obj/screen/alert/fire/Click() - if(isliving(usr)) - var/mob/living/L = usr - return L.resist() + var/mob/living/L = usr + if(!L.can_resist()) + return + L.changeNext_move(CLICK_CD_RESIST) + if(L.canmove) + return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt. //ALIENS @@ -644,9 +647,20 @@ so as to remain in compliance with the most up-to-date laws." desc = "You're legcuffed, which slows you down considerably. Click the alert to free yourself." /obj/screen/alert/restrained/Click() - if(isliving(usr)) - var/mob/living/L = usr - return L.resist() + var/mob/living/L = usr + if(!L.can_resist()) + return + L.changeNext_move(CLICK_CD_RESIST) + if((L.canmove) && (L.last_special <= world.time)) + return L.resist_restraints() + +/obj/screen/alert/restrained/buckled/Click() + var/mob/living/L = usr + if(!L.can_resist()) + return + L.changeNext_move(CLICK_CD_RESIST) + if(L.last_special <= world.time) + return L.resist_buckle() // PRIVATE = only edit, use, or override these if you're editing the system as a whole diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 5265a8e8ea..987818924f 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -9,17 +9,18 @@ // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) - return + SendSignal(COMSIG_ITEM_ATTACK_SELF, user) + interact(user) /obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby! return TRUE //return FALSE to avoid calling attackby after this proc does stuff // No comment /atom/proc/attackby(obj/item/W, mob/user, params) - return + return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params) /obj/attackby(obj/item/I, mob/living/user, params) - return I.attack_obj(src, user) + return ..() || I.attack_obj(src, user) /mob/living/attackby(obj/item/I, mob/living/user, params) user.changeNext_move(CLICK_CD_MELEE) @@ -35,6 +36,7 @@ /obj/item/proc/attack(mob/living/M, mob/living/user) + SendSignal(COMSIG_ITEM_ATTACK, M, user) if(flags_1 & NOBLUDGEON_1) return if(!force) @@ -54,6 +56,7 @@ //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) + SendSignal(COMSIG_ITEM_ATTACK_OBJ, O, user) if(flags_1 & NOBLUDGEON_1) return user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/citadel/custom_loadout/custom_items.dm b/code/citadel/custom_loadout/custom_items.dm index 5ee9f3f508..dcc275c03b 100644 --- a/code/citadel/custom_loadout/custom_items.dm +++ b/code/citadel/custom_loadout/custom_items.dm @@ -68,3 +68,13 @@ attack_verb = list("slapped") resistance_flags = FLAMMABLE var/bitesound = 'sound/items/bikehorn.ogg' + + + +/*Zigfie*/ + +/obj/item/clothing/mask/luchador/zigfie + name = "Alboroto Rosa mask" + icon = 'icons/mob/mask.dmi' + icon_state = "lucharzigfie" + item_state = "lucharzigfie" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 6a9cf9b963..0c0baccc56 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -136,7 +136,7 @@ GLOBAL_PROTECT(config_dir) var/list/probabilities = list() // relative probability of each mode var/list/min_pop = list() // overrides for acceptible player counts in a mode var/list/max_pop = list() - + var/list/repeated_mode_adjust = list() // weight adjustments for recent modes var/humans_need_surnames = 0 var/allow_ai = 0 // allow ai job var/forbid_secborg = 0 // disallow secborg module to be chosen. @@ -278,6 +278,7 @@ GLOBAL_PROTECT(config_dir) var/error_msg_delay = 50 // How long to wait between messaging admins about occurrences of a unique error var/arrivals_shuttle_dock_window = 55 //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station + var/arrivals_shuttle_require_undocked = FALSE //Require the arrivals shuttle to be undocked before latejoiners can join var/arrivals_shuttle_require_safe_latejoin = FALSE //Require the arrivals shuttle to be operational in order for latejoiners to join var/mice_roundstart = 10 // how many wire chewing rodents spawn at roundstart. @@ -722,7 +723,14 @@ GLOBAL_PROTECT(config_dir) WRITE_FILE(GLOB.config_error_log, "Unknown game mode probability configuration definition: [prob_name].") else WRITE_FILE(GLOB.config_error_log, "Incorrect probability configuration definition: [prob_name] [prob_value].") - + if("repeated_mode_adjust") + if(value) + repeated_mode_adjust.Cut() + var/values = splittext(value," ") + for(var/v in values) + repeated_mode_adjust += text2num(v) + else + WRITE_FILE(GLOB.config_error_log, "Incorrect round weight adjustment configuration definition for [value].") if("protect_roles_from_antagonist") protect_roles_from_antagonist = 1 if("protect_assistant_from_antagonist") @@ -818,6 +826,8 @@ GLOBAL_PROTECT(config_dir) GLOB.MAX_EX_FLAME_RANGE = BombCap if("arrivals_shuttle_dock_window") arrivals_shuttle_dock_window = max(PARALLAX_LOOP_TIME, text2num(value)) + if("arrivals_shuttle_require_undocked") + arrivals_shuttle_require_undocked = TRUE if("arrivals_shuttle_require_safe_latejoin") arrivals_shuttle_require_safe_latejoin = TRUE if("mice_roundstart") @@ -962,7 +972,6 @@ GLOBAL_PROTECT(config_dir) var/list/datum/game_mode/runnable_modes = new for(var/T in gamemode_cache) var/datum/game_mode/M = new T() - //to_chat(world, "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]") if(!(M.config_tag in modes)) qdel(M) continue @@ -974,8 +983,15 @@ GLOBAL_PROTECT(config_dir) if(max_pop[M.config_tag]) M.maximum_players = max_pop[M.config_tag] if(M.can_start()) - runnable_modes[M] = probabilities[M.config_tag] - //to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]") + var/final_weight = probabilities[M.config_tag] + if(SSpersistence.saved_modes.len == 3 && repeated_mode_adjust.len == 3) + var/recent_round = min(SSpersistence.saved_modes.Find(M.config_tag),3) + var/adjustment = 0 + while(recent_round) + adjustment += repeated_mode_adjust[recent_round] + recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0) + final_weight *= ((100-adjustment)/100) + runnable_modes[M] = final_weight return runnable_modes /datum/configuration/proc/get_runnable_midround_modes(crew) diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 8143385486..2870305c3e 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -274,7 +274,7 @@ SUBSYSTEM_DEF(blackbox) details += "\"[deets]\"" /datum/feedback_variable/proc/get_details() - return details.Join(" | ") + return details ? details.Join(" | ") : null /datum/feedback_variable/proc/get_parsed() return list(variable,value,details.Join(" | ")) diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index 13762b83f9..df7121455c 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -8,7 +8,7 @@ SUBSYSTEM_DEF(persistence) var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() - + var/list/saved_modes = list(1,2,3) var/list/saved_trophies = list() /datum/controller/subsystem/persistence/Initialize() @@ -16,6 +16,7 @@ SUBSYSTEM_DEF(persistence) LoadPoly() LoadChiselMessages() LoadTrophies() + LoadRecentModes() ..() /datum/controller/subsystem/persistence/proc/LoadSatchels() @@ -41,8 +42,7 @@ SUBSYSTEM_DEF(persistence) var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") if(!fexists(json_file)) return - var/list/json = list() - json = json_decode(file2text(json_file)) + var/list/json = json_decode(file2text(json_file)) old_secret_satchels = json["data"] if(old_secret_satchels.len) if(old_secret_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear. @@ -84,8 +84,7 @@ SUBSYSTEM_DEF(persistence) var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json") if(!fexists(json_file)) return - var/list/json - json = json_decode(file2text(json_file)) + var/list/json = json_decode(file2text(json_file)) if(!json) return @@ -129,13 +128,22 @@ SUBSYSTEM_DEF(persistence) var/json_file = file("data/npc_saves/TrophyItems.json") if(!fexists(json_file)) return - var/list/json = list() - json = json_decode(file2text(json_file)) + var/list/json = json_decode(file2text(json_file)) if(!json) return saved_trophies = json["data"] SetUpTrophies(saved_trophies.Copy()) +/datum/controller/subsystem/persistence/proc/LoadRecentModes() + var/json_file = file("data/RecentModes.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_modes = json["data"] + + /datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) for(var/A in GLOB.trophy_cases) var/obj/structure/displaycase/trophy/T = A @@ -165,6 +173,7 @@ SUBSYSTEM_DEF(persistence) CollectChiselMessages() CollectSecretSatchels() CollectTrophies() + CollectRoundtype() /datum/controller/subsystem/persistence/proc/CollectSecretSatchels() var/list/satchels = list() @@ -224,3 +233,13 @@ SUBSYSTEM_DEF(persistence) data["message"] = T.trophy_message data["placer_key"] = T.placer_key saved_trophies += list(data) + +/datum/controller/subsystem/persistence/proc/CollectRoundtype() + saved_modes[3] = saved_modes[2] + saved_modes[2] = saved_modes[1] + saved_modes[1] = SSticker.mode.config_tag + var/json_file = file("data/RecentModes.json") + var/list/file_data = list() + file_data["data"] = saved_modes + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) \ No newline at end of file diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index de6445831d..4770689778 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -430,17 +430,14 @@ SUBSYSTEM_DEF(shuttle) continue base if(!(T.flags_1 & UNUSED_TRANSIT_TURF_1)) continue base - //to_chat(world, "[COORD(topleft)] and [COORD(bottomright)]") break base if((!proposed_zone) || (!proposed_zone.len)) return FALSE var/turf/topleft = proposed_zone[1] - //to_chat(world, "[COORD(topleft)] is TOPLEFT") // Then create a transit docking port in the middle var/coords = M.return_coords(0, 0, dock_dir) - //to_chat(world, json_encode(coords)) /* 0------2 | | | | @@ -478,11 +475,9 @@ SUBSYSTEM_DEF(shuttle) if(WEST) transit_path = /turf/open/space/transit/west - //to_chat(world, "Docking port at [transit_x], [transit_y], [topleft.z]") var/turf/midpoint = locate(transit_x, transit_y, topleft.z) if(!midpoint) return FALSE - //to_chat(world, "Making transit dock at [COORD(midpoint)]") var/area/shuttle/transit/A = new() A.parallax_movedir = travel_dir A.contents = proposed_zone diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/squeak.dm index d94efd0a4a..16b722c71b 100644 --- a/code/controllers/subsystem/squeak.dm +++ b/code/controllers/subsystem/squeak.dm @@ -1,6 +1,6 @@ // The Squeak // because this is about placement of mice mobs, and nothing to do with -// mice - the computer peripheral +// mice - the computer peripheral SUBSYSTEM_DEF(squeak) name = "Squeak" @@ -32,8 +32,9 @@ SUBSYSTEM_DEF(squeak) /datum/controller/subsystem/squeak/proc/find_exposed_wires() exposed_wires.Cut() - - var/list/all_turfs = block(locate(1,1,1), locate(world.maxx,world.maxy,1)) + var/list/all_turfs + for (var/z in GLOB.station_z_levels) + all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z)) for(var/turf/open/floor/plating/T in all_turfs) if(is_blocked_turf(T)) continue diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 24daad00f9..2222a959bc 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -310,7 +310,7 @@ replaceable_groups[LAW_INHERENT] = inherent.len if(supplied.len && (LAW_SUPPLIED in groups)) replaceable_groups[LAW_SUPPLIED] = supplied.len - var picked_group = pickweight(replaceable_groups) + var/picked_group = pickweight(replaceable_groups) switch(picked_group) if(LAW_ZEROTH) . = zeroth diff --git a/code/datums/browser.dm b/code/datums/browser.dm index c854d20f18..cae6e04e9b 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -256,7 +256,6 @@ winset(user, windowid, "on-close=\".windowclose [param]\"") - //to_chat(world, "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]") // the on-close client verb @@ -268,12 +267,10 @@ set hidden = 1 // hide this verb from the user's panel set name = ".windowclose" // no autocomplete on cmd line - //to_chat(world, "windowclose: [atomref]") if(atomref!="null") // if passed a real atomref var/hsrc = locate(atomref) // find the reffed atom var/href = "close=1" if(hsrc) - //to_chat(world, "[src] Topic [href] [hsrc]") usr = src.mob src.Topic(href, params2list(href), hsrc) // this will direct to the atom's return // Topic() proc via client.Topic() @@ -281,6 +278,5 @@ // no atomref specified (or not found) // so just reset the user mob's machine var if(src && src.mob) - //to_chat(world, "[src] was [src.mob.machine], setting to null") src.mob.unset_machine() return diff --git a/code/datums/material_container.dm b/code/datums/components/material_container.dm similarity index 61% rename from code/datums/material_container.dm rename to code/datums/components/material_container.dm index a8863c70bc..55504d47d5 100644 --- a/code/datums/material_container.dm +++ b/code/datums/components/material_container.dm @@ -5,22 +5,34 @@ amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000. max_amount - max raw amount of mineral this container can hold. sheet_type - type of the mineral sheet the container handles, used for output. - owner - object that this container is being used by, used for output. + parent - object that this container is being used by, used for output. MAX_STACK_SIZE - size of a stack of mineral sheets. Constant. */ -/datum/material_container +/datum/component/material_container var/total_amount = 0 var/max_amount var/sheet_type - var/obj/owner - var/list/materials = list() + var/list/materials + var/show_on_examine + var/list/allowed_typecache + var/last_inserted_type + var/last_amount_inserted + var/last_insert_success + var/datum/callback/precondition //MAX_STACK_SIZE = 50 //MINERAL_MATERIAL_AMOUNT = 2000 -/datum/material_container/New(obj/O, list/mat_list, max_amt = 0) - owner = O +/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition) + materials = list() max_amount = max(0, max_amt) + show_on_examine = _show_on_examine + if(allowed_types) + allowed_typecache = typecacheof(allowed_types) + precondition = _precondition + + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) + RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/OnExamine) var/list/possible_mats = list() for(var/mat_type in subtypesof(/datum/material)) @@ -31,12 +43,47 @@ var/mat_path = possible_mats[id] materials[id] = new mat_path() -/datum/material_container/Destroy() - owner = null - return ..() +/datum/component/material_container/proc/OnExamine(mob/user) + for(var/I in materials) + var/datum/material/M = materials[I] + var/amt = amount(M.id) + if(amt) + to_chat(user, "It has [amt] units of [lowertext(M.name)] stored.") + +/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user) + var/list/tc = allowed_typecache + if(user.a_intent == INTENT_HARM || (I.flags_2 & HOLOGRAM_2) || (tc && !is_type_in_typecache(I, tc))) + return FALSE + . = TRUE + last_insert_success = FALSE + var/datum/callback/pc = precondition + if(pc && !pc.Invoke()) + return + var/material_amount = get_item_material_amount(I) + if(!material_amount) + to_chat(user, "[I] does not contain sufficient amounts of metal or glass to be accepted by [parent].") + return + if(!has_space(material_amount)) + to_chat(user, "[parent] is full. Please remove metal or glass from [parent] in order to insert more.") + return + if(!user.temporarilyRemoveItemFromInventory(I)) + to_chat(user, "[I] is stuck to you and cannot be placed into [parent].") + return + var/inserted = insert_item(I) + if(inserted) + last_insert_success = TRUE + if(istype(I, /obj/item/stack)) + to_chat(user, "You insert [inserted] sheet[inserted>1 ? "s" : ""] into [parent].") + if(!QDELETED(I)) + user.put_in_active_hand(I) + else + to_chat(user, "You insert a material total of [inserted] into [parent].") + qdel(I) + else + user.put_in_active_hand(I) //For inserting an amount of material -/datum/material_container/proc/insert_amount(amt, id = null) +/datum/component/material_container/proc/insert_amount(amt, id = null) if(amt > 0 && has_space(amt)) var/total_amount_saved = total_amount if(id) @@ -52,7 +99,7 @@ return (total_amount - total_amount_saved) return 0 -/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0) +/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt = 0) if(amt <= 0) return 0 if(amt > S.amount) @@ -67,10 +114,12 @@ return 0 insert_materials(S,amt) + last_inserted_type = S.type S.use(amt) + last_amount_inserted = amt return amt -/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1) +/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1) if(!I) return 0 if(istype(I, /obj/item/stack)) @@ -82,9 +131,11 @@ return 0 insert_materials(I, multiplier) + last_inserted_type = I.type + last_amount_inserted = material_amount return material_amount -/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only +/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only var/datum/material/M for(var/MAT in materials) M = materials[MAT] @@ -93,7 +144,7 @@ //For consuming material //mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200) -/datum/material_container/proc/use_amount(list/mats, multiplier=1) +/datum/component/material_container/proc/use_amount(list/mats, multiplier=1) if(!mats || !mats.len) return 0 @@ -112,7 +163,7 @@ return total_amount_save - total_amount -/datum/material_container/proc/use_amount_type(amt, id) +/datum/component/material_container/proc/use_amount_type(amt, id) var/datum/material/M = materials[id] if(M) if(M.amount >= amt) @@ -121,7 +172,7 @@ return amt return 0 -/datum/material_container/proc/can_use_amount(amt, id, list/mats) +/datum/component/material_container/proc/can_use_amount(amt, id, list/mats) if(amt && id) var/datum/material/M = materials[id] if(M && M.amount >= amt) @@ -136,7 +187,7 @@ return FALSE //For spawning mineral sheets; internal use only -/datum/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) +/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) if(!M.sheet_type) return 0 if(sheet_amt > 0) @@ -144,12 +195,12 @@ sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) var/count = 0 while(sheet_amt > MAX_STACK_SIZE) - new M.sheet_type(get_turf(owner), MAX_STACK_SIZE) + new M.sheet_type(get_turf(parent), MAX_STACK_SIZE) count += MAX_STACK_SIZE use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) sheet_amt -= MAX_STACK_SIZE if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT)) - var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(owner), sheet_amt) + var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt) if(target) s.forceMove(target) count += sheet_amt @@ -157,15 +208,15 @@ return count return 0 -/datum/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) +/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) if(materials[id]) return retrieve(sheet_amt, materials[id], target) return 0 -/datum/material_container/proc/retrieve_amount(amt, id, target) +/datum/component/material_container/proc/retrieve_amount(amt, id, target) return retrieve_sheets(amount2sheet(amt), id, target) -/datum/material_container/proc/retrieve_all(target = null) +/datum/component/material_container/proc/retrieve_all(target = null) var/result = 0 var/datum/material/M for(var/MAT in materials) @@ -173,10 +224,10 @@ result += retrieve_sheets(amount2sheet(M.amount), MAT, target) return result -/datum/material_container/proc/has_space(amt = 0) +/datum/component/material_container/proc/has_space(amt = 0) return (total_amount + amt) <= max_amount -/datum/material_container/proc/has_materials(list/mats, multiplier=1) +/datum/component/material_container/proc/has_materials(list/mats, multiplier=1) if(!mats || !mats.len) return 0 @@ -187,23 +238,23 @@ return 0 return 1 -/datum/material_container/proc/amount2sheet(amt) +/datum/component/material_container/proc/amount2sheet(amt) if(amt >= MINERAL_MATERIAL_AMOUNT) return round(amt / MINERAL_MATERIAL_AMOUNT) return 0 -/datum/material_container/proc/sheet2amount(sheet_amt) +/datum/component/material_container/proc/sheet2amount(sheet_amt) if(sheet_amt > 0) return sheet_amt * MINERAL_MATERIAL_AMOUNT return 0 -/datum/material_container/proc/amount(id) +/datum/component/material_container/proc/amount(id) var/datum/material/M = materials[id] return M ? M.amount : 0 //returns the amount of material relevant to this container; //if this container does not support glass, any glass in 'I' will not be taken into account -/datum/material_container/proc/get_item_material_amount(obj/item/I) +/datum/component/material_container/proc/get_item_material_amount(obj/item/I) if(!istype(I)) return 0 var/material_amount = 0 diff --git a/code/datums/components/squeek.dm b/code/datums/components/squeek.dm new file mode 100644 index 0000000000..40fd0af598 --- /dev/null +++ b/code/datums/components/squeek.dm @@ -0,0 +1,61 @@ +/datum/component/squeak + var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1) + var/list/override_squeak_sounds + var/squeak_chance = 100 + var/volume = 30 + + // This is so shoes don't squeak every step + var/steps = 0 + var/step_delay = 1 + + // This is to stop squeak spam from inhand usage + var/last_use = 0 + var/use_delay = 20 + +/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) + if(custom_sounds) + override_squeak_sounds = custom_sounds + if(chance_override) + squeak_chance = chance_override + if(volume_override) + volume = volume_override + if(step_delay_override) + step_delay = step_delay_override + if(use_delay_override) + use_delay = use_delay_override + + if(istype(parent, /atom)) + RegisterSignal(COMSIG_ATOM_BLOB_ACT, .proc/play_squeak) + RegisterSignal(COMSIG_ATOM_HULK_ATTACK, .proc/play_squeak) + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/play_squeak) + if(istype(parent, /atom/movable)) + RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/play_squeak) + RegisterSignal(COMSIG_MOVABLE_COLLIDE, .proc/play_squeak) + RegisterSignal(COMSIG_MOVABLE_IMPACT, .proc/play_squeak) + if(istype(parent, /obj/item)) + RegisterSignal(COMSIG_ITEM_ATTACK, .proc/play_squeak) + RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak) + RegisterSignal(COMSIG_ITEM_ATTACK_OBJ, .proc/play_squeak) + if(istype(parent, /obj/item/clothing/shoes)) + RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak) + else + RegisterSignal(COMSIG_ATOM_ENTERED, .proc/play_squeak) + +/datum/component/squeak/proc/play_squeak() + if(prob(squeak_chance)) + if(!override_squeak_sounds) + playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) + else + playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) + +/datum/component/squeak/proc/step_squeak() + if(steps > step_delay) + play_squeak() + steps = 0 + else + steps++ + +/datum/component/squeak/proc/use_squeak() + if(last_use + use_delay < world.time) + last_use = world.time + play_squeak() \ No newline at end of file diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index d55a32609a..b653e5c6ae 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -83,10 +83,10 @@ if(isliving(A)) atomsnowflake += "[D]" if(A.dir) - atomsnowflake += "
<< [dir2text(A.dir)] >>" + atomsnowflake += "
<< [dir2text(A.dir)] >>" var/mob/living/M = A atomsnowflake += {" -
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] +
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"]
BRUTE:[M.getBruteLoss()] FIRE:[M.getFireLoss()] diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 9be242a391..26f42fa059 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -245,7 +245,6 @@ /datum/disease/advance/proc/GenerateCure() if(properties && properties.len) var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) - //to_chat(world, "Res = [res]") cures = list(advance_cures[res]) // Get the cure name from the cure_id @@ -333,9 +332,6 @@ // Mix a list of advance diseases and return the mixed result. /proc/Advance_Mix(var/list/D_list) - - //to_chat(world, "Mixing!!!!") - var/list/diseases = list() for(var/datum/disease/advance/A in D_list) @@ -359,7 +355,6 @@ D2.Mix(D1) // Should be only 1 entry left, but if not let's only return a single entry - //to_chat(world, "END MIXING!!!!!") var/datum/disease/advance/to_return = pick(diseases) to_return.Refresh(1) return to_return diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 2b77885359..c96a22d472 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -1,74 +1,74 @@ -/datum/disease/dnaspread - name = "Space Retrovirus" - max_stages = 4 - spread_text = "On contact" - spread_flags = CONTACT_GENERAL - cure_text = "Mutadone" - cures = list("mutadone") - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE - agent = "S4E1 retrovirus" - viable_mobtypes = list(/mob/living/carbon/human) - var/datum/dna/original_dna = null - var/transformed = 0 - desc = "This disease transplants the genetic code of the initial vector into new hosts." - severity = MEDIUM - - -/datum/disease/dnaspread/stage_act() - ..() - if(!affected_mob.dna) - cure() - if(NOTRANSSTING in affected_mob.dna.species.species_traits) //Only species that can be spread by transformation sting can be spread by the retrovirus - cure() - - if(!strain_data["dna"]) - //Absorbs the target DNA. - strain_data["dna"] = new affected_mob.dna.type - affected_mob.dna.copy_dna(strain_data["dna"]) +/datum/disease/dnaspread + name = "Space Retrovirus" + max_stages = 4 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Mutadone" + cures = list("mutadone") + disease_flags = CAN_CARRY|CAN_RESIST|CURABLE + agent = "S4E1 retrovirus" + viable_mobtypes = list(/mob/living/carbon/human) + var/datum/dna/original_dna = null + var/transformed = 0 + desc = "This disease transplants the genetic code of the initial vector into new hosts." + severity = MEDIUM + + +/datum/disease/dnaspread/stage_act() + ..() + if(!affected_mob.dna) + cure() + if((NOTRANSSTING in affected_mob.dna.species.species_traits) || (NO_DNA_COPY in affected_mob.dna.species.species_traits)) //Only species that can be spread by transformation sting can be spread by the retrovirus + cure() + + if(!strain_data["dna"]) + //Absorbs the target DNA. + strain_data["dna"] = new affected_mob.dna.type + affected_mob.dna.copy_dna(strain_data["dna"]) carrier = TRUE stage = 4 - return - - switch(stage) - if(2 || 3) //Pretend to be a cold and give time to spread. - if(prob(8)) - affected_mob.emote("sneeze") - if(prob(8)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(2) - affected_mob.updatehealth() - if(4) - if(!transformed && !carrier) - //Save original dna for when the disease is cured. - original_dna = new affected_mob.dna.type - affected_mob.dna.copy_dna(original_dna) - - to_chat(affected_mob, "You don't feel like yourself..") - var/datum/dna/transform_dna = strain_data["dna"] - - transform_dna.transfer_identity(affected_mob, transfer_SE = 1) - affected_mob.real_name = affected_mob.dna.real_name - affected_mob.updateappearance(mutcolor_update=1) - affected_mob.domutcheck() - - transformed = 1 - carrier = 1 //Just chill out at stage 4 - - return - -/datum/disease/dnaspread/Destroy() - if (original_dna && transformed && affected_mob) - original_dna.transfer_identity(affected_mob, transfer_SE = 1) - affected_mob.real_name = affected_mob.dna.real_name - affected_mob.updateappearance(mutcolor_update=1) - affected_mob.domutcheck() - - to_chat(affected_mob, "You feel more like yourself.") - return ..() \ No newline at end of file + return + + switch(stage) + if(2 || 3) //Pretend to be a cold and give time to spread. + if(prob(8)) + affected_mob.emote("sneeze") + if(prob(8)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(2) + affected_mob.updatehealth() + if(4) + if(!transformed && !carrier) + //Save original dna for when the disease is cured. + original_dna = new affected_mob.dna.type + affected_mob.dna.copy_dna(original_dna) + + to_chat(affected_mob, "You don't feel like yourself..") + var/datum/dna/transform_dna = strain_data["dna"] + + transform_dna.transfer_identity(affected_mob, transfer_SE = 1) + affected_mob.real_name = affected_mob.dna.real_name + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() + + transformed = 1 + carrier = 1 //Just chill out at stage 4 + + return + +/datum/disease/dnaspread/Destroy() + if (original_dna && transformed && affected_mob) + original_dna.transfer_identity(affected_mob, transfer_SE = 1) + affected_mob.real_name = affected_mob.dna.real_name + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() + + to_chat(affected_mob, "You feel more like yourself.") + return ..() diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 4bacf2d9e8..27a9338191 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -235,7 +235,9 @@ flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text if(mrace) - set_species(mrace, icon_update=0) + var/datum/species/newrace = new mrace.type + newrace.copy_properties_from(mrace) + set_species(newrace, icon_update=0) if(newreal_name) real_name = newreal_name @@ -396,4 +398,4 @@ value = values return value -/////////////////////////// DNA HELPER-PROCS +/////////////////////////// DNA HELPER-PROCS \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index e824cc9914..ad73b164b7 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -121,8 +121,9 @@ new_character.key = key //now transfer the key to link the client to our new body if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. var/mob/living/L = new_character - L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... - L.update_arousal_hud() //Removes the old icon + if(L.client && L.client.prefs) + L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... + L.update_arousal_hud() //Removes the old icon /datum/mind/proc/store_memory(new_text) memory += "[new_text]
" @@ -1278,7 +1279,6 @@ src = null M = H.monkeyize() src = M.mind - //to_chat(world, "DEBUG: \"healthy\": M=[M], M.mind=[M.mind], src=[src]!") else if (istype(M) && length(M.viruses)) for(var/thing in M.viruses) var/datum/disease/D = thing diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm index e3e8d0e366..f9883cfe50 100644 --- a/code/datums/progressbar.dm +++ b/code/datums/progressbar.dm @@ -29,7 +29,6 @@ bar.pixel_y = 32 + (PROGRESSBAR_HEIGHT * (listindex - 1)) /datum/progressbar/proc/update(progress) - //to_chat(world, "Update [progress] - [goal] - [(progress / goal)] - [((progress / goal) * 100)] - [round(((progress / goal) * 100), 5)]") if (!user || !user.client) shown = 0 return diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 9ca564cd2d..b8e51ac860 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -29,11 +29,20 @@ /datum/status_effect/incapacitating/knockdown id = "knockdown" +/datum/status_effect/incapacitating/knockdown/tick() + if(owner.staminaloss) + owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds + + //UNCONSCIOUS /datum/status_effect/incapacitating/unconscious id = "unconscious" needs_update_stat = TRUE +/datum/status_effect/incapacitating/unconscious/tick() + if(owner.staminaloss) + owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds + //SLEEPING /datum/status_effect/incapacitating/sleeping id = "sleeping" @@ -57,7 +66,7 @@ /datum/status_effect/incapacitating/sleeping/tick() if(owner.staminaloss) - owner.adjustStaminaLoss(-0.35) //reduce stamina loss by 0.35 per tick, 7 per 2 seconds + owner.adjustStaminaLoss(-0.5) //reduce stamina loss by 0.5 per tick, 10 per 2 seconds if(human_owner && human_owner.drunkenness) human_owner.drunkenness *= 0.997 //reduce drunkenness by 0.3% per tick, 6% per 2 seconds if(prob(20)) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index a28f4d0dc7..508459188b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -454,7 +454,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons) cur_y = y_arr.Find(src.z) if(cur_y) break -// to_chat(world, "X = [cur_x]; Y = [cur_y]") if(cur_x && cur_y) return list("x"=cur_x,"y"=cur_y) else @@ -637,4 +636,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons) return L.AllowDrop() ? L : get_turf(L) /atom/Entered(atom/movable/AM, atom/oldLoc) - SendSignal(COMSIG_ATOM_ENTERED, AM, oldLoc) \ No newline at end of file + SendSignal(COMSIG_ATOM_ENTERED, AM, oldLoc) + +/atom/proc/return_temperature() + return diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 9b585ea653..64b405bbd5 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -261,7 +261,7 @@ /obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "") - var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T) + var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T) var/mob/living/simple_animal/slaughter/S = new demon_type(holder) S.holder = holder S.key = C.key diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index ccb6b774b3..4e8a0dc6b6 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -80,7 +80,7 @@ antag_candidates -= bro team.members += bro bro.restricted_roles = restricted_jobs - log_game("[key_name(bro)] has been selected as a Brother") + log_game("[bro.key] (ckey) has been selected as a Brother") pre_brother_teams += team return ..() @@ -95,6 +95,9 @@ brother_teams += pre_brother_teams return ..() +/datum/game_mode/traitor/bros/generate_report() + return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." + /datum/game_mode/proc/auto_declare_completion_brother() if(!LAZYLEN(brother_teams)) return diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 14126c69f3..e67ac26d3a 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -340,6 +340,10 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w return if(!target) return + if(NO_DNA_COPY in target.dna.species.species_traits) + if(verbose) + to_chat(user, "[target] is not compatible with our biology.") + return if((target.disabilities & NOCLONE) || (target.disabilities & HUSK)) if(verbose) to_chat(user, "DNA of [target] is ruined beyond usability!") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 82350726d9..4ec01f09e2 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -121,7 +121,7 @@ var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len) var/list/datum/game_mode/usable_modes = list() for(var/datum/game_mode/G in runnable_modes) - if(G.reroll_friendly && living_crew >= G.required_players) + if(G.reroll_friendly && living_crew.len >= G.required_players) usable_modes += G else qdel(G) diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm index b7b20a7311..510883ada5 100644 --- a/code/game/gamemodes/gang/gang_datum.dm +++ b/code/game/gamemodes/gang/gang_datum.dm @@ -331,16 +331,3 @@ adjust_influence(bawss, amount/bosses.len) announce_to_mind(bawss, "[name] Gang: [amount/bosses.len] influence given from internal automatic restructuring.") -//Multiverse - -/datum/gang/multiverse - dom_attempts = 0 - fighting_style = "multiverse" - is_deconvertible = FALSE - -/datum/gang/multiverse/New(loc, multiverse_override) - name = multiverse_override - ganghud = new() - -/datum/gang/multiverse/income() - return diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 3bb3c8b43e..d33dd2127d 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -309,6 +309,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event /obj/effect/meteor/meaty/xeno/New() meteordrop += subtypesof(/obj/item/organ/alien) + meteordrop -= /obj/item/organ/alien/eggsac ..() /obj/effect/meteor/meaty/xeno/ram_turf(turf/T) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm index bcb2218fe6..888a10669e 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm @@ -33,7 +33,7 @@ message_admins("No valid spawn locations found, aborting...") return MAP_ERROR - var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter((pick(spawn_locs))) + var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter((pick(spawn_locs))) var/mob/living/simple_animal/slaughter/S = new /mob/living/simple_animal/slaughter/(holder) S.holder = holder player_mind.transfer_to(S) diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 69ccb4240a..b5175b215f 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -20,28 +20,28 @@ close(1) if("unlock") - locked = FALSE + locked = FALSE update_icon() if("lock") - locked = TRUE + locked = TRUE update_icon() if("secure_open") - locked = FALSE + locked = FALSE update_icon() sleep(2) open(1) - locked = TRUE + locked = TRUE update_icon() if("secure_close") - locked = FALSE + locked = FALSE close(1) - locked = TRUE + locked = TRUE sleep(2) update_icon() @@ -88,7 +88,7 @@ name = "airlock sensor" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - anchored = TRUE + anchored = TRUE power_channel = ENVIRON var/id_tag @@ -97,8 +97,8 @@ var/datum/radio_frequency/radio_connection - var/on = TRUE - var/alert = FALSE + var/on = TRUE + var/alert = FALSE /obj/machinery/airlock_sensor/update_icon() @@ -143,9 +143,9 @@ radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_AIRLOCK) /obj/machinery/airlock_sensor/Initialize() - ..() + . = ..() set_frequency(frequency) /obj/machinery/airlock_sensor/Destroy() - SSradio.remove_object(src,frequency) + SSradio.remove_object(src,frequency) return ..() \ No newline at end of file diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index c185a8f734..9fa53765ed 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -32,8 +32,6 @@ var/selected_category var/screen = 1 - var/datum/material_container/materials - var/list/categories = list( "Tools", "Electronics", @@ -48,15 +46,15 @@ ) /obj/machinery/autolathe/Initialize() - materials = new /datum/material_container(src, list(MAT_METAL, MAT_GLASS)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS)) + . = ..() + wires = new /datum/wires/autolathe(src) files = new /datum/research/autolathe(src) matching_designs = list() - return ..() /obj/machinery/autolathe/Destroy() QDEL_NULL(wires) - QDEL_NULL(materials) return ..() /obj/machinery/autolathe/interact(mob/user) @@ -81,6 +79,7 @@ popup.open() /obj/machinery/autolathe/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() /obj/machinery/autolathe/attackby(obj/item/O, mob/user, params) @@ -123,42 +122,26 @@ busy = FALSE return 1 - if(O.flags_2 & HOLOGRAM_2) - return 1 + return ..() - var/material_amount = materials.get_item_material_amount(O) - if(!material_amount) - to_chat(user, "This object does not contain sufficient amounts of metal or glass to be accepted by the autolathe.") - return 1 - if(!materials.has_space(material_amount)) - to_chat(user, "The autolathe is full. Please remove metal or glass from the autolathe in order to insert more.") - return 1 - if(!user.temporarilyRemoveItemFromInventory(O)) - to_chat(user, "\The [O] is stuck to you and cannot be placed into the autolathe.") - return 1 - - busy = TRUE - var/inserted = materials.insert_item(O) - if(inserted) - if(istype(O, /obj/item/stack)) - if (O.materials[MAT_METAL]) - flick("autolathe_o",src)//plays metal insertion animation - if (O.materials[MAT_GLASS]) - flick("autolathe_r",src)//plays glass insertion animation - to_chat(user, "You insert [inserted] sheet[inserted>1 ? "s" : ""] to the autolathe.") - use_power(inserted*100) - if(!QDELETED(O)) - user.put_in_active_hand(O) +/obj/machinery/mecha_part_fabricator/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) + return + var/lit = M.last_inserted_type + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + use_power(max(500,M.last_amount_inserted/10)) else - to_chat(user, "You insert a material total of [inserted] to the autolathe.") - use_power(max(500,inserted/10)) - qdel(O) - else - user.put_in_active_hand(O) - - busy = FALSE - updateUsrDialog() - return 1 + var/obj/item/stack/S = lit + var/list/initmats = initial(S.materials) + if (initmats[MAT_METAL]) + flick("autolathe_o",src)//plays metal insertion animation + if (initmats[MAT_GLASS]) + flick("autolathe_r",src)//plays glass insertion animation + use_power(M.last_amount_inserted*100) + updateUsrDialog() /obj/machinery/autolathe/Topic(href, href_list) if(..()) @@ -193,6 +176,7 @@ var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) + GET_COMPONENT(materials, /datum/component/material_container) if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff)) busy = TRUE use_power(power) @@ -246,6 +230,7 @@ var/T = 0 for(var/obj/item/stock_parts/matter_bin/MB in component_parts) T += MB.rating*75000 + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = T T=1.2 for(var/obj/item/stock_parts/manipulator/M in component_parts) @@ -294,6 +279,7 @@ dat += "[D.name]" if(ispath(D.build_path, /obj/item/stack)) + GET_COMPONENT(materials, /datum/component/material_container) var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) if (max_multiplier>10 && !disabled) dat += " x10" @@ -325,6 +311,7 @@ dat += "[D.name]" if(ispath(D.build_path, /obj/item/stack)) + GET_COMPONENT(materials, /datum/component/material_container) var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) if (max_multiplier>10 && !disabled) dat += " x10" @@ -339,6 +326,7 @@ return dat /obj/machinery/autolathe/proc/materials_printout() + GET_COMPONENT(materials, /datum/component/material_container) var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
" for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] @@ -351,6 +339,7 @@ var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + GET_COMPONENT(materials, /datum/component/material_container) if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount))) return 0 if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount))) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 2033fd7146..a8e9c7bcca 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -4,17 +4,17 @@ icon_screen = "crew" icon_keyboard = "med_key" circuit = /obj/item/circuitboard/computer/operating - var/mob/living/carbon/human/patient - var/obj/structure/table/optable/table + var/mob/living/carbon/human/patient + var/obj/structure/table/optable/table light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/operating/Initialize() - ..() + . = ..() find_table() /obj/machinery/computer/operating/proc/find_table() - for(var/dir in GLOB.cardinals) + for(var/dir in GLOB.cardinals) table = locate(/obj/structure/table/optable, get_step(src, dir)) if(table) table.computer = src @@ -63,4 +63,4 @@ var/datum/surgery_step/surgery_step = procedure.get_surgery_step() dat += "Next step: [capitalize(surgery_step.name)]
" dat += "" - return dat + return dat \ No newline at end of file diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 8131dbd4a6..2d1d771203 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -84,7 +84,7 @@ light_color = LIGHT_COLOR_CYAN /obj/machinery/computer/atmos_control/Initialize() - ..() + . = ..() set_frequency(frequency) /obj/machinery/computer/atmos_control/Destroy() @@ -227,4 +227,4 @@ else if(output_tag == id_tag) output_info = signal.data else - ..(signal) + ..(signal) \ No newline at end of file diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 44822d3771..f3fabcc21c 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -40,25 +40,25 @@ return ..() /obj/machinery/computer/message_monitor/emag_act(mob/user) - if(emagged) - return - if(!isnull(src.linkedServer)) - emagged = TRUE - screen = 2 - spark_system.set_up(5, 0, src) - src.spark_system.start() - var/obj/item/paper/monitorkey/MK = new/obj/item/paper/monitorkey - MK.loc = src.loc - // Will help make emagging the console not so easy to get away with. - MK.info += "

�%@%(*$%&(�&?*(%&�/{}" - var/time = 100 * length(src.linkedServer.decryptkey) - addtimer(CALLBACK(src, .proc/UnmagConsole), time) - message = rebootmsg - else - to_chat(user, "A no server error appears on the screen.") + if(emagged) + return + if(!isnull(src.linkedServer)) + emagged = TRUE + screen = 2 + spark_system.set_up(5, 0, src) + src.spark_system.start() + var/obj/item/paper/monitorkey/MK = new/obj/item/paper/monitorkey + MK.loc = src.loc + // Will help make emagging the console not so easy to get away with. + MK.info += "

�%@%(*$%&(�&?*(%&�/{}" + var/time = 100 * length(src.linkedServer.decryptkey) + addtimer(CALLBACK(src, .proc/UnmagConsole), time) + message = rebootmsg + else + to_chat(user, "A no server error appears on the screen.") /obj/machinery/computer/message_monitor/Initialize() - ..() + . = ..() //Is the server isn't linked to a server, and there's a server available, default it to the first one in the list. if(!linkedServer) if(GLOB.message_servers && GLOB.message_servers.len > 0) @@ -236,7 +236,7 @@ src.screen = 0 // Return the screen back to normal /obj/machinery/computer/message_monitor/proc/UnmagConsole() - emagged = FALSE + emagged = FALSE /obj/machinery/computer/message_monitor/proc/ResetMessage() customsender = "System Administrator" @@ -309,7 +309,7 @@ message = noserver else if(auth) - var/dkey = trim(stripped_input(usr, "Please enter the decryption key.")) + var/dkey = trim(stripped_input(usr, "Please enter the decryption key.")) if(dkey && dkey != "") if(src.linkedServer.decryptkey == dkey) var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):")) @@ -414,11 +414,11 @@ customrecepient.tnote += "← From [customsender] ([customjob]):
[custommessage]
" if (!customrecepient.silent) playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1) - customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3) + customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3) if( customrecepient.loc && ishuman(customrecepient.loc) ) var/mob/living/carbon/human/H = customrecepient.loc - to_chat(H, "[icon2html(customrecepient, viewers(H))] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)") - log_talk(usr,"[key_name(usr)] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA) + to_chat(H, "[icon2html(customrecepient, viewers(H))] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)") + log_talk(usr,"[key_name(usr)] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA) customrecepient.cut_overlays() customrecepient.add_overlay(mutable_appearance('icons/obj/pda.dmi', "pda-r")) //Sender is faking as someone who exists @@ -427,11 +427,11 @@ customrecepient.tnote += "← From [PDARec.owner] ([customjob]):
[custommessage]
" if (!customrecepient.silent) playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1) - customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3) + customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3) if( customrecepient.loc && ishuman(customrecepient.loc) ) var/mob/living/carbon/human/H = customrecepient.loc - to_chat(H, "[icon2html(customrecepient, H)] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)") - log_talk(usr,"[key_name(usr)] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA) + to_chat(H, "[icon2html(customrecepient, H)] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)") + log_talk(usr,"[key_name(usr)] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA) customrecepient.cut_overlays() customrecepient.add_overlay(mutable_appearance('icons/obj/pda.dmi', "pda-r")) //Finally.. @@ -468,4 +468,4 @@ info = "

Daily Key Reset


The new message monitor key is '[server.decryptkey]'.
Please keep this a secret and away from the clown.
If necessary, change the password to a more secure one." info_links = info add_overlay("paper_words") - break + break \ No newline at end of file diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 3f18cc29e9..943419c548 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -10,7 +10,7 @@ /obj/machinery/computer/pod/Initialize() - ..() + . = ..() for(var/obj/machinery/mass_driver/M in range(range, src)) if(M.id == id) connected = M @@ -21,7 +21,7 @@ return if(!connected) - say("Cannot locate mass driver connector. Cancelling firing sequence!") + say("Cannot locate mass driver connector. Cancelling firing sequence!") return for(var/obj/machinery/door/poddoor/M in range(range, src)) @@ -130,7 +130,7 @@ name = "\improper ProComp Executive IIc" desc = "The Syndicate operate on a tight budget. Operates external airlocks." title = "External Airlock Controls" - req_access = list(ACCESS_SYNDICATE) + req_access = list(ACCESS_SYNDICATE) /obj/machinery/computer/pod/old/syndicate/attack_hand(mob/user) if(!allowed(user)) @@ -142,4 +142,4 @@ /obj/machinery/computer/pod/old/swf name = "\improper Magix System IV" - desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition" + desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition" \ No newline at end of file diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index 678d856dce..52de3830df 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -22,7 +22,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E var/obj/machinery/computer/telecrystals/boss/linkedboss = null /obj/machinery/computer/telecrystals/uplinker/Initialize() - ..() + . = ..() var/ID = pick_n_take(GLOB.possible_uplinker_IDs) if(!ID) @@ -220,4 +220,4 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E src.updateUsrDialog() return -#undef NUKESCALINGMODIFIER +#undef NUKESCALINGMODIFIER \ No newline at end of file diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 02f3f03b91..95adf12875 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -434,6 +434,15 @@ constructionStep = CONSTRUCTION_GUTTED update_icon() return + if(istype(C, /obj/item/device/electroadaptive_pseudocircuit)) + var/obj/item/device/electroadaptive_pseudocircuit/P = C + if(!P.adapt_circuit(user, 30)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a firelock circuit and slot it into the assembly.") + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return return ..() /obj/structure/firelock_frame/heavy diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm index 2d848d95ed..5d7be7fbd8 100644 --- a/code/game/machinery/droneDispenser.dm +++ b/code/game/machinery/droneDispenser.dm @@ -22,7 +22,6 @@ var/icon_recharging = "recharge" var/icon_creating = "make" - var/datum/material_container/materials var/list/using_materials var/starting_amount = 0 var/metal_cost = 1000 @@ -55,14 +54,10 @@ /obj/machinery/droneDispenser/Initialize() . = ..() - materials = new(src, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT*MAX_STACK_SIZE*2) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE) materials.insert_amount(starting_amount) using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost) -/obj/machinery/droneDispenser/Destroy() - QDEL_NULL(materials) - return ..() - /obj/machinery/droneDispenser/preloaded starting_amount = 5000 @@ -148,10 +143,6 @@ ..() if((mode == DRONE_RECHARGING) && !stat && recharging_text) to_chat(user, "[recharging_text]") - if(metal_cost) - to_chat(user, "It has [materials.amount(MAT_METAL)] units of metal stored.") - if(glass_cost) - to_chat(user, "It has [materials.amount(MAT_GLASS)] units of glass stored.") /obj/machinery/droneDispenser/power_change() ..() @@ -166,6 +157,7 @@ if((stat & (NOPOWER|BROKEN)) || !anchored) return + GET_COMPONENT(materials, /datum/component/material_container) if(!materials.has_materials(using_materials)) return // We require more minerals @@ -232,25 +224,8 @@ icon_state = icon_on /obj/machinery/droneDispenser/attackby(obj/item/O, mob/living/user) - if(istype(O, /obj/item/stack)) - if(!O.materials[MAT_METAL] && !O.materials[MAT_GLASS]) - return ..() - if(!metal_cost && !glass_cost) - to_chat(user, "There isn't a place to insert [O]!") - return - var/obj/item/stack/sheets = O - if(!user.canUnEquip(sheets)) - to_chat(user, "[O] is stuck to your hand, you can't get it off!") - return - - var/used = materials.insert_stack(sheets, sheets.amount) - - if(used) - to_chat(user, "You insert [used] sheet[used > 1 ? "s" : ""] into [src].") - else - to_chat(user, "The [src] isn't accepting the [sheets].") - - else if(istype(O, /obj/item/crowbar)) + if(istype(O, /obj/item/crowbar)) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() playsound(loc, O.usesound, 50, 1) to_chat(user, "You retrieve the materials from [src].") diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 518cd8ab09..ebbeb1bee2 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -220,6 +220,16 @@ update_icon() return + else if(istype(W, /obj/item/device/electroadaptive_pseudocircuit)) + var/obj/item/device/electroadaptive_pseudocircuit/P = W + if(!P.adapt_circuit(user, 15)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a fire alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return + else if(istype(W, /obj/item/wrench)) user.visible_message("[user] removes the fire alarm assembly from the wall.", \ "You remove the fire alarm assembly from the wall.") diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index d0d40e7233..36366ffbd9 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -215,7 +215,7 @@ /obj/machinery/magnetic_controller/Initialize() - ..() + . = ..() if(autolink) for(var/obj/machinery/magnetic_module/M in GLOB.machines) if(M.freq == frequency && M.code == code) @@ -391,4 +391,4 @@ if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore rpath += copytext(path, i, i+1) // else, add to list - // there doesn't HAVE to be separators but it makes paths syntatically visible + // there doesn't HAVE to be separators but it makes paths syntatically visible \ No newline at end of file diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index 545414577e..f800309131 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -31,8 +31,6 @@ imap += icon('icons/misc/imap.dmi', "blank") imap += icon('icons/misc/imap.dmi', "blank") - //to_chat(world, "[icount] images in list") - for(var/wx = 1 ; wx <= world.maxx; wx++) @@ -142,13 +140,10 @@ var/rx = ((wx*2+xoff)%32) + 1 var/ry = ((wy*2+yoff)%32) + 1 - //to_chat(world, "trying [ix],[iy] : [ix+icx*iy]") var/icon/I = imap[1+(ix + icx*iy)*2] var/icon/I2 = imap[2+(ix + icx*iy)*2] - //to_chat(world, "icon: [icon2html(I, world)]") - I.DrawBox(colour, rx, ry, rx+1, ry+1) I2.DrawBox(colour2, rx, ry, rx+1, ry+1) @@ -164,8 +159,6 @@ H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]" - //to_chat(world, "[icon2html(I, world)] at [H.screen_loc]") - H.name = (i==0)?"maprefresh":"map" var/icon/HI = new/icon @@ -272,12 +265,8 @@ var/rx = ((wx*2+xoff)%32) + 1 var/ry = ((wy*2+yoff)%32) + 1 - //to_chat(world, "trying [ix],[iy] : [ix+icx*iy]") var/icon/I = imap[1+(ix + icx*iy)] - - //to_chat(world, "icon: [icon2html(I, world)]") - I.DrawBox(colour, rx, ry, rx, ry) @@ -291,8 +280,6 @@ H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]" - //to_chat(world, "[icon2html(I, world)] at [H.screen_loc]") - H.name = (i==0)?"maprefresh":"map" var/icon/I = imap[i+1] diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index ee8363e1b3..b84de7cf18 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -570,8 +570,8 @@ /obj/machinery/porta_turret/syndicate/pod integrity_failure = 20 max_integrity = 40 - stun_projectile = /obj/item/projectile/bullet/weakbullet3 - lethal_projectile = /obj/item/projectile/bullet/weakbullet3 + stun_projectile = /obj/item/projectile/bullet/syndicate_turret + lethal_projectile = /obj/item/projectile/bullet/syndicate_turret /obj/machinery/porta_turret/ai faction = "silicon" diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index b4bee2bdae..fbe02dca37 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -14,15 +14,14 @@ var/blood = 0 var/eat_dir = WEST var/amount_produced = 50 - var/datum/material_container/materials var/crush_damage = 1000 var/eat_victim_items = TRUE var/item_recycle_sound = 'sound/items/welder.ogg' /obj/machinery/recycler/Initialize() - materials = new /datum/material_container(src, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM)) + . = ..() update_icon() - return ..() /obj/machinery/recycler/RefreshParts() var/amt_made = 0 @@ -32,6 +31,7 @@ mat_mod *= 50000 for(var/obj/item/stock_parts/manipulator/M in component_parts) amt_made = 12.5 * M.rating //% of materials salvaged + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = mat_mod amount_produced = min(50, amt_made) + 50 @@ -126,6 +126,7 @@ /obj/machinery/recycler/proc/recycle_item(obj/item/I) I.loc = src.loc + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(I) if(!material_amount) qdel(I) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index d90e91a428..b3a7f99758 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -706,7 +706,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C ..() var/T = pick(subtypesof(/obj/machinery/vending/snack) - /obj/machinery/vending/snack/random) new T(get_turf(src)) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/machinery/vending/snack/blue icon_state = "snackblue" @@ -758,7 +758,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C . = ..() var/T = pick(subtypesof(/obj/machinery/vending/cola) - /obj/machinery/vending/cola/random) new T(get_turf(src)) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/machinery/vending/cola/blue icon_state = "Cola_Machine" @@ -1195,4 +1195,4 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C #undef STANDARD_CHARGE #undef CONTRABAND_CHARGE -#undef COIN_CHARGE +#undef COIN_CHARGE \ No newline at end of file diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index b6b4241402..1e9616ae12 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -251,7 +251,7 @@ icon_state = "mecha_carbine" origin_tech = "materials=4;combat=4" equip_cooldown = 10 - projectile = /obj/item/projectile/bullet/incendiary/shell + projectile = /obj/item/projectile/bullet/incendiary/fnx99 projectiles = 24 projectile_energy_cost = 15 @@ -271,7 +271,7 @@ icon_state = "mecha_scatter" origin_tech = "combat=4" equip_cooldown = 20 - projectile = /obj/item/projectile/bullet/midbullet + projectile = /obj/item/projectile/bullet/scattershot projectiles = 40 projectile_energy_cost = 25 projectiles_per_shot = 4 @@ -283,7 +283,7 @@ icon_state = "mecha_uac2" origin_tech = "combat=4" equip_cooldown = 10 - projectile = /obj/item/projectile/bullet/weakbullet3 + projectile = /obj/item/projectile/bullet/lmg projectiles = 300 projectile_energy_cost = 20 projectiles_per_shot = 3 diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 79c4971665..8efc14d966 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -12,7 +12,6 @@ circuit = /obj/item/circuitboard/machine/mechfab var/time_coeff = 1 var/component_coeff = 1 - var/datum/material_container/materials var/datum/research/files var/sync = 0 var/part_set @@ -36,9 +35,11 @@ ) /obj/machinery/mecha_part_fabricator/Initialize() + AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) + . = ..() files = new /datum/research(src) //Setup the research data holder. - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE)) - return ..() /obj/machinery/mecha_part_fabricator/RefreshParts() var/T = 0 @@ -46,6 +47,7 @@ //maximum stocking amount (default 300000, 600000 at T4) for(var/obj/item/stock_parts/matter_bin/M in component_parts) T += M.rating + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = (200000 + (T*50000)) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) @@ -113,6 +115,7 @@ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() var/output + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] output += "[M.name]: [M.amount] cm³" @@ -133,6 +136,7 @@ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) if(D.reagents_list.len) // No reagents storage - no reagent designs. return 0 + GET_COMPONENT(materials, /datum/component/material_container) if(materials.has_materials(get_resources_w_coeff(D))) return 1 return 0 @@ -142,6 +146,7 @@ desc = "It's building \a [initial(D.name)]." var/list/res_coef = get_resources_w_coeff(D) + GET_COMPONENT(materials, /datum/component/material_container) materials.use_amount(res_coef) add_overlay("fab-active") use_power = ACTIVE_POWER_USE @@ -398,15 +403,34 @@ break if(href_list["remove_mat"] && href_list["material"]) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"]) updateUsrDialog() return /obj/machinery/mecha_part_fabricator/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() +/obj/machinery/mecha_part_fabricator/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) + return + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + else + var/obj/item/stack/S = lit + stack_name = material2name(initial(S.materials)[1]) + add_overlay("fab-load-[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[stack_name]"), 10) + updateUsrDialog() + /obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params) if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) return 1 @@ -417,55 +441,7 @@ if(default_deconstruction_crowbar(W)) return 1 - if(istype(W, /obj/item/stack/sheet)) - - if(!is_insertion_ready(user)) - return 1 - - var/material_amount = materials.get_item_material_amount(W) - - if(!try_insert(user, W, material_amount)) - return 1 - - var/inserted = materials.insert_item(W) - if(inserted) - to_chat(user, "You insert [inserted] sheet\s into [src].") - if(W && W.materials.len) - if(!QDELETED(W)) - user.put_in_active_hand(W) - var/mat_overlay = "fab-load-[material2name(W.materials[1])]" - add_overlay(mat_overlay) - sleep(10) - if(!QDELETED(src)) - cut_overlay(mat_overlay) //No matter what the overlay shall still be deleted - - updateUsrDialog() - - else if(istype(W, /obj/item/ore/bluespace_crystal)) - - if(!is_insertion_ready(user)) - return 1 - - var/material_amount = materials.get_item_material_amount(W) - - if(!try_insert(user, W, material_amount)) - return 1 - - var/inserted = materials.insert_item(W) - if(inserted) - to_chat(user, "You add [W] to the [src].") - if(W && W.materials.len) - qdel(W) - var/mat_overlay = "fab-load-bluespace" - add_overlay(mat_overlay) - sleep(10) - if(!QDELETED(src)) - cut_overlay(mat_overlay) - - updateUsrDialog() - - else - return ..() + return ..() /obj/machinery/mecha_part_fabricator/proc/material2name(ID) return copytext(ID,2) @@ -479,17 +455,3 @@ return FALSE return TRUE - - -/obj/machinery/mecha_part_fabricator/proc/try_insert(mob/user, obj/item/I, material_amount) - if(!material_amount) - to_chat(user, "This object does not contain sufficient amounts of materials to be accepted by [src].") - return FALSE - if(!materials.has_space(material_amount)) - to_chat(user, "\The [src] is full. Please remove some materials from [src] in order to insert more.") - return FALSE - if(!user.temporarilyRemoveItemFromInventory(I)) - to_chat(user, "\The [I] is stuck to you and cannot be placed into [src].") - return FALSE - - return TRUE \ No newline at end of file diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 200f771058..ed2a1ff82a 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -766,7 +766,7 @@ . = t_air.return_pressure() return -/obj/mecha/proc/return_temperature() +/obj/mecha/return_temperature() var/datum/gas_mixture/t_air = return_air() if(t_air) . = t_air.return_temperature() diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index e0cec3af02..7401797a47 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -160,7 +160,7 @@ /obj/effect/landmark/start/wizard/Initialize(mapload) ..() GLOB.wizardstart += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/start/new_player name = "New Player" @@ -173,7 +173,7 @@ /obj/effect/landmark/start/new_player/Initialize(mapload) ..() - qdel(src) + return INITIALIZE_HINT_QDEL @@ -183,7 +183,7 @@ /obj/effect/landmark/latejoin/Initialize(mapload) ..() SSjob.latejoin_trackers += loc - qdel(src) + return INITIALIZE_HINT_QDEL // carp. /obj/effect/landmark/carpspawn @@ -229,7 +229,7 @@ /obj/effect/landmark/xeno_spawn/Initialize(mapload) ..() GLOB.xeno_spawn += loc - qdel(src) + return INITIALIZE_HINT_QDEL // blobs. /obj/effect/landmark/blobstart @@ -238,7 +238,7 @@ /obj/effect/landmark/blobstart/Initialize(mapload) ..() GLOB.blobstart += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/secequipment name = "secequipment" @@ -246,7 +246,7 @@ /obj/effect/landmark/secequipment/Initialize(mapload) ..() GLOB.secequipment += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/prisonwarp name = "prisonwarp" @@ -254,15 +254,15 @@ /obj/effect/landmark/prisonwarp/Initialize(mapload) ..() GLOB.prisonwarp += loc - qdel(src) - + return INITIALIZE_HINT_QDEL + /obj/effect/landmark/ert_spawn name = "Emergencyresponseteam" /obj/effect/landmark/ert_spawn/Initialize(mapload) ..() GLOB.emergencyresponseteamspawn += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/holding_facility name = "Holding Facility" @@ -270,7 +270,7 @@ /obj/effect/landmark/holding_facility/Initialize(mapload) ..() GLOB.holdingfacility += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/thunderdome/observe name = "tdomeobserve" @@ -278,7 +278,7 @@ /obj/effect/landmark/thunderdome/observe/Initialize(mapload) ..() GLOB.tdomeobserve += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/thunderdome/one name = "tdome1" @@ -286,7 +286,7 @@ /obj/effect/landmark/thunderdome/one/Initialize(mapload) ..() GLOB.tdome1 += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/thunderdome/two name = "tdome2" @@ -294,7 +294,7 @@ /obj/effect/landmark/thunderdome/two/Initialize(mapload) ..() GLOB.tdome2 += loc - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/thunderdome/admin name = "tdomeadmin" @@ -302,7 +302,7 @@ /obj/effect/landmark/thunderdome/admin/Initialize(mapload) ..() GLOB.tdomeadmin += loc - qdel(src) + return INITIALIZE_HINT_QDEL //generic event spawns /obj/effect/landmark/event_spawn @@ -330,4 +330,4 @@ /obj/effect/landmark/ruin/Destroy() GLOB.ruin_landmarks -= src ruin_template = null - . = ..() + . = ..() \ No newline at end of file diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 94cabaf6e1..2bfce20ccd 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -18,7 +18,7 @@ if(lootspawn) new lootspawn(T) lootcount-- - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/spawner/lootdrop/armory_contraband name = "armory contraband gun spawner" @@ -89,7 +89,7 @@ /obj/effect/spawner/lootdrop/maintenance/Initialize(mapload) loot = GLOB.maintenance_loot - ..() + . = ..() /obj/effect/spawner/lootdrop/crate_spawner name = "lootcrate spawner" //USE PROMO CODE "SELLOUT" FOR 20% OFF! @@ -130,7 +130,7 @@ loot = list() for(var/path in subtypesof(/obj/effect/spawner/bundle/costume)) loot[path] = TRUE - ..() + . = ..() // Minor lootdrops follow @@ -162,4 +162,4 @@ name = "25% cyborg mask spawner" loot = list( /obj/item/clothing/mask/gas/cyborg = 25, - "" = 75) + "" = 75) \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d8ed75737d..072896ac01 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -61,6 +61,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/equip_delay_other = 20 //In deciseconds, how long an item takes to put on another person var/strip_delay = 40 //In deciseconds, how long an item takes to remove from another person var/breakouttime = 0 + var/being_removed = FALSE var/list/materials var/origin_tech = null //Used by R&D to determine what research bonuses it grants. var/needs_permit = 0 //Used by security bots to determine if this item is safe for public use. @@ -218,9 +219,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) /obj/item/proc/speechModification(message) //For speech modification by mask slot items. return message -/obj/item/attack_self(mob/user) - interact(user) - /obj/item/interact(mob/user) add_fingerprint(user) if(hidden_uplink && hidden_uplink.active) diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 4c4c537859..6e094a5bbb 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -31,7 +31,7 @@ obj/item/construction var/no_ammo_message = "The \'Low Ammo\' light on the device blinks yellow." /obj/item/construction/Initialize() - ..() + . = ..() desc = "A [src]. It currently holds [matter]/[max_matter] matter-units." spark_system = new /datum/effect_system/spark_spread spark_system.set_up(5, 0, src) @@ -144,7 +144,7 @@ obj/item/construction set category = "Object" set src in usr // What does this do? - var window_type_name + var/window_type_name if (window_type == /obj/structure/window/fulltile) window_type = /obj/structure/window/reinforced/fulltile @@ -240,11 +240,11 @@ obj/item/construction set category = "Object" set src in usr - var airlockcat = input(usr, "Select whether the airlock is solid or glass.") in list("Solid", "Glass") + var/airlockcat = input(usr, "Select whether the airlock is solid or glass.") in list("Solid", "Glass") switch(airlockcat) if("Solid") if(advanced_airlock_setting == 1) - var airlockpaint = input(usr, "Select the paintjob of the airlock.") in list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security") + var/airlockpaint = input(usr, "Select the paintjob of the airlock.") in list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security") switch(airlockpaint) if("Default") airlock_type = /obj/machinery/door/airlock @@ -275,7 +275,7 @@ obj/item/construction if("Glass") if(advanced_airlock_setting == 1) - var airlockpaint = input(usr, "Select the paintjob of the airlock.") in list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining") + var/airlockpaint = input(usr, "Select the paintjob of the airlock.") in list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining") switch(airlockpaint) if("Default") airlock_type = /obj/machinery/door/airlock/glass diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index f3e78dfac9..bfc8bc9da3 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -160,7 +160,7 @@ update_label("John Doe", "Clowny") var/anyone = FALSE //Can anyone forge the ID or just syndicate? /obj/item/card/id/syndicate/Initialize() - ..() + . = ..() var/datum/action/item_action/chameleon/change/chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/card/id chameleon_action.chameleon_name = "ID Card" @@ -180,14 +180,14 @@ update_label("John Doe", "Clowny") if(isliving(user) && user.mind) if(user.mind.special_role || anyone) if(alert(user, "Action", "Agent ID", "Show", "Forge") == "Forge") - var t = copytext(sanitize(input(user, "What name would you like to put on this card?", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name))as text | null),1,26) + var/t = copytext(sanitize(input(user, "What name would you like to put on this card?", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name))as text | null),1,26) if(!t || t == "Unknown" || t == "floor" || t == "wall" || t == "r-wall") //Same as mob/dead/new_player/prefrences.dm if (t) alert("Invalid name.") return registered_name = t - var u = copytext(sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Assistant")as text | null),1,MAX_MESSAGE_LEN) + var/u = copytext(sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Assistant")as text | null),1,MAX_MESSAGE_LEN) if(!u) registered_name = "" return @@ -220,7 +220,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/captains_spare/Initialize() var/datum/job/captain/J = new/datum/job/captain access = J.get_access() - ..() + . = ..() /obj/item/card/id/centcom name = "\improper CentCom ID" @@ -231,7 +231,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/centcom/Initialize() access = get_all_centcom_access() - ..() + . = ..() /obj/item/card/id/ert name = "\improper CentCom ID" @@ -242,7 +242,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/ert/Initialize() access = get_all_accesses()+get_ert_access("commander")-ACCESS_CHANGE_IDS - ..() + . = ..() /obj/item/card/id/ert/Security registered_name = "Security Response Officer" @@ -250,7 +250,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/ert/Security/Initialize() access = get_all_accesses()+get_ert_access("sec")-ACCESS_CHANGE_IDS - ..() + . = ..() /obj/item/card/id/ert/Engineer registered_name = "Engineer Response Officer" @@ -258,7 +258,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/ert/Engineer/Initialize() access = get_all_accesses()+get_ert_access("eng")-ACCESS_CHANGE_IDS - ..() + . = ..() /obj/item/card/id/ert/Medical registered_name = "Medical Response Officer" @@ -266,7 +266,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/ert/Medical/Initialize() access = get_all_accesses()+get_ert_access("med")-ACCESS_CHANGE_IDS - ..() + . = ..() /obj/item/card/id/prisoner name = "prisoner ID card" diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 1c3c712db6..aae4aad91d 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -107,39 +107,26 @@ throw_speed = 3 throw_range = 7 attack_verb = list("HONKED") - var/next_usable = 0 - var/honksound = 'sound/items/bikehorn.ogg' - var/cooldowntime = 20 + +/obj/item/bikehorn/Initialize() + . = ..() + AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50) /obj/item/bikehorn/suicide_act(mob/user) user.visible_message("[user] solemnly points the horn at [user.p_their()] temple! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(src.loc, honksound, 50, 1) + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) return (BRUTELOSS) -/obj/item/bikehorn/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!(next_usable > world.time)) - playsound(loc, honksound, 50, 1, -1) //plays instead of tap.ogg! - return ..() - -/obj/item/bikehorn/attack_self(mob/user) - if(!(next_usable > world.time)) - next_usable = world.time + cooldowntime - playsound(src.loc, honksound, 50, 1) - src.add_fingerprint(user) - -/obj/item/bikehorn/Crossed(mob/living/L) - if(isliving(L)) - playsound(loc, honksound, 50, 1, -1) - ..() - /obj/item/bikehorn/airhorn name = "air horn" desc = "Damn son, where'd you find this?" icon_state = "air_horn" - honksound = 'sound/items/airhorn2.ogg' - cooldowntime = 50 origin_tech = "materials=4;engineering=4" +/obj/item/bikehorn/airhorn/Initialize() + . = ..() + AddComponent(/datum/component/squeak, list('sound/items/airhorn2.ogg'=1), 50) + /obj/item/bikehorn/golden name = "golden bike horn" desc = "Golden? Clearly, it's made with bananium! Honk!" @@ -155,14 +142,13 @@ ..() /obj/item/bikehorn/golden/proc/flip_mobs(mob/living/carbon/M, mob/user) - if(!(next_usable > world.time)) - var/turf/T = get_turf(src) - for(M in ohearers(7, T)) - if(ishuman(M) && M.can_hear()) - var/mob/living/carbon/human/H = M - if(istype(H.ears, /obj/item/clothing/ears/earmuffs)) - continue - M.emote("flip") + var/turf/T = get_turf(src) + for(M in ohearers(7, T)) + if(ishuman(M) && M.can_hear()) + var/mob/living/carbon/human/H = M + if(istype(H.ears, /obj/item/clothing/ears/earmuffs)) + continue + M.emote("flip") /obj/item/reagent_containers/food/drinks/soda_cans/canned_laughter name = "Canned Laughter" diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 4f2c1a620a..8ec32f088e 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -1,186 +1,189 @@ -/obj/item/lipstick - gender = PLURAL - name = "red lipstick" - desc = "A generic brand of lipstick." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "lipstick" - w_class = WEIGHT_CLASS_TINY - var/colour = "red" - var/open = FALSE - - -/obj/item/lipstick/purple - name = "purple lipstick" - colour = "purple" - -/obj/item/lipstick/jade - //It's still called Jade, but theres no HTML color for jade, so we use lime. - name = "jade lipstick" - colour = "lime" - -/obj/item/lipstick/black - name = "black lipstick" - colour = "black" - - -/obj/item/lipstick/random - name = "lipstick" - -/obj/item/lipstick/random/New() - ..() - colour = pick("red","purple","lime","black","green","blue","white") - name = "[colour] lipstick" - - - -/obj/item/lipstick/attack_self(mob/user) - cut_overlays() - to_chat(user, "You twist \the [src] [open ? "closed" : "open"].") - open = !open - if(open) - var/mutable_appearance/colored_overlay = mutable_appearance(icon, "lipstick_uncap_color") - colored_overlay.color = colour - icon_state = "lipstick_uncap" - add_overlay(colored_overlay) - else - icon_state = "lipstick" - -/obj/item/lipstick/attack(mob/M, mob/user) - if(!open) - return - - if(!ismob(M)) - return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.is_mouth_covered()) - to_chat(user, "Remove [ H == user ? "your" : "their" ] mask!") - return - if(H.lip_style) //if they already have lipstick on - to_chat(user, "You need to wipe off the old lipstick first!") - return - if(H == user) - user.visible_message("[user] does their lips with \the [src].", \ - "You take a moment to apply \the [src]. Perfect!") - H.lip_style = "lipstick" - H.lip_color = colour - H.update_body() - else - user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ - "You begin to apply \the [src] on [H]'s lips...") - if(do_after(user, 20, target = H)) - user.visible_message("[user] does [H]'s lips with \the [src].", \ - "You apply \the [src] on [H]'s lips.") - H.lip_style = "lipstick" - H.lip_color = colour - H.update_body() - else - to_chat(user, "Where are the lips on that?") - -//you can wipe off lipstick with paper! -/obj/item/paper/attack(mob/M, mob/user) - if(user.zone_selected == "mouth") - if(!ismob(M)) - return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H == user) - to_chat(user, "You wipe off the lipstick with [src].") - H.lip_style = null - H.update_body() - else - user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ - "You begin to wipe off [H]'s lipstick...") - if(do_after(user, 10, target = H)) - user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ - "You wipe off [H]'s lipstick.") - H.lip_style = null - H.update_body() - else - ..() - - -/obj/item/razor - name = "electric razor" - desc = "The latest and greatest power razor born from the science of shaving." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "razor" - flags_1 = CONDUCT_1 - w_class = WEIGHT_CLASS_TINY - - -/obj/item/razor/proc/shave(mob/living/carbon/human/H, location = "mouth") - if(location == "mouth") - H.facial_hair_style = "Shaved" - else - H.hair_style = "Skinhead" - - H.update_hair() - playsound(loc, 'sound/items/welder2.ogg', 20, 1) - - -/obj/item/razor/attack(mob/M, mob/user) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/location = user.zone_selected - if(location == "mouth") - if(!(FACEHAIR in H.dna.species.species_traits)) - to_chat(user, "There is no facial hair to shave!") - return - if(!get_location_accessible(H, location)) - to_chat(user, "The mask is in the way!") - return - if(H.facial_hair_style == "Shaved") - to_chat(user, "Already clean-shaven!") - return - - if(H == user) //shaving yourself - user.visible_message("[user] starts to shave their facial hair with [src].", \ - "You take a moment to shave your facial hair with [src]...") - if(do_after(user, 50, target = H)) - user.visible_message("[user] shaves his facial hair clean with [src].", \ - "You finish shaving with [src]. Fast and clean!") - shave(H, location) - else - var/turf/H_loc = H.loc - user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ - "You start shaving [H]'s facial hair...") - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ - "You shave [H]'s facial hair clean off.") - shave(H, location) - - else if(location == "head") - if(!(HAIR in H.dna.species.species_traits)) - to_chat(user, "There is no hair to shave!") - return - if(!get_location_accessible(H, location)) - to_chat(user, "The headgear is in the way!") - return - if(H.hair_style == "Bald" || H.hair_style == "Balding Hair" || H.hair_style == "Skinhead") - to_chat(user, "There is not enough hair left to shave!") - return - - if(H == user) //shaving yourself - user.visible_message("[user] starts to shave their head with [src].", \ - "You start to shave your head with [src]...") - if(do_after(user, 5, target = H)) - user.visible_message("[user] shaves his head with [src].", \ - "You finish shaving with [src].") - shave(H, location) - else - var/turf/H_loc = H.loc - user.visible_message("[user] tries to shave [H]'s head with [src]!", \ - "You start shaving [H]'s head...") - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message("[user] shaves [H]'s head bald with [src]!", \ - "You shave [H]'s head bald.") - shave(H, location) - else - ..() - else - ..() \ No newline at end of file +/obj/item/lipstick + gender = PLURAL + name = "red lipstick" + desc = "A generic brand of lipstick." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "lipstick" + w_class = WEIGHT_CLASS_TINY + var/colour = "red" + var/open = FALSE + + +/obj/item/lipstick/purple + name = "purple lipstick" + colour = "purple" + +/obj/item/lipstick/jade + //It's still called Jade, but theres no HTML color for jade, so we use lime. + name = "jade lipstick" + colour = "lime" + +/obj/item/lipstick/black + name = "black lipstick" + colour = "black" + + +/obj/item/lipstick/random + name = "lipstick" + +/obj/item/lipstick/random/New() + ..() + colour = pick("red","purple","lime","black","green","blue","white") + name = "[colour] lipstick" + + + +/obj/item/lipstick/attack_self(mob/user) + cut_overlays() + to_chat(user, "You twist \the [src] [open ? "closed" : "open"].") + open = !open + if(open) + var/mutable_appearance/colored_overlay = mutable_appearance(icon, "lipstick_uncap_color") + colored_overlay.color = colour + icon_state = "lipstick_uncap" + add_overlay(colored_overlay) + else + icon_state = "lipstick" + +/obj/item/lipstick/attack(mob/M, mob/user) + if(!open) + return + + if(!ismob(M)) + return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.is_mouth_covered()) + to_chat(user, "Remove [ H == user ? "your" : "their" ] mask!") + return + if(H.lip_style) //if they already have lipstick on + to_chat(user, "You need to wipe off the old lipstick first!") + return + if(H == user) + user.visible_message("[user] does their lips with \the [src].", \ + "You take a moment to apply \the [src]. Perfect!") + H.lip_style = "lipstick" + H.lip_color = colour + H.update_body() + else + user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ + "You begin to apply \the [src] on [H]'s lips...") + if(do_after(user, 20, target = H)) + user.visible_message("[user] does [H]'s lips with \the [src].", \ + "You apply \the [src] on [H]'s lips.") + H.lip_style = "lipstick" + H.lip_color = colour + H.update_body() + else + to_chat(user, "Where are the lips on that?") + +//you can wipe off lipstick with paper! +/obj/item/paper/attack(mob/M, mob/user) + if(user.zone_selected == "mouth") + if(!ismob(M)) + return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H == user) + to_chat(user, "You wipe off the lipstick with [src].") + H.lip_style = null + H.update_body() + else + user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ + "You begin to wipe off [H]'s lipstick...") + if(do_after(user, 10, target = H)) + user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ + "You wipe off [H]'s lipstick.") + H.lip_style = null + H.update_body() + else + ..() + + +/obj/item/razor + name = "electric razor" + desc = "The latest and greatest power razor born from the science of shaving." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "razor" + flags_1 = CONDUCT_1 + w_class = WEIGHT_CLASS_TINY + + +/obj/item/razor/proc/shave(mob/living/carbon/human/H, location = "mouth") + if(location == "mouth") + H.facial_hair_style = "Shaved" + else + H.hair_style = "Skinhead" + + H.update_hair() + playsound(loc, 'sound/items/welder2.ogg', 20, 1) + + +/obj/item/razor/attack(mob/M, mob/user) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/location = user.zone_selected + if((location in list("eyes", "mouth", "head")) && !H.get_bodypart("head")) + to_chat(user, "[H] doesn't have a head!") + return + if(location == "mouth") + if(!(FACEHAIR in H.dna.species.species_traits)) + to_chat(user, "There is no facial hair to shave!") + return + if(!get_location_accessible(H, location)) + to_chat(user, "The mask is in the way!") + return + if(H.facial_hair_style == "Shaved") + to_chat(user, "Already clean-shaven!") + return + + if(H == user) //shaving yourself + user.visible_message("[user] starts to shave their facial hair with [src].", \ + "You take a moment to shave your facial hair with [src]...") + if(do_after(user, 50, target = H)) + user.visible_message("[user] shaves his facial hair clean with [src].", \ + "You finish shaving with [src]. Fast and clean!") + shave(H, location) + else + var/turf/H_loc = H.loc + user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ + "You start shaving [H]'s facial hair...") + if(do_after(user, 50, target = H)) + if(H_loc == H.loc) + user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ + "You shave [H]'s facial hair clean off.") + shave(H, location) + + else if(location == "head") + if(!(HAIR in H.dna.species.species_traits)) + to_chat(user, "There is no hair to shave!") + return + if(!get_location_accessible(H, location)) + to_chat(user, "The headgear is in the way!") + return + if(H.hair_style == "Bald" || H.hair_style == "Balding Hair" || H.hair_style == "Skinhead") + to_chat(user, "There is not enough hair left to shave!") + return + + if(H == user) //shaving yourself + user.visible_message("[user] starts to shave their head with [src].", \ + "You start to shave your head with [src]...") + if(do_after(user, 5, target = H)) + user.visible_message("[user] shaves his head with [src].", \ + "You finish shaving with [src].") + shave(H, location) + else + var/turf/H_loc = H.loc + user.visible_message("[user] tries to shave [H]'s head with [src]!", \ + "You start shaving [H]'s head...") + if(do_after(user, 50, target = H)) + if(H_loc == H.loc) + user.visible_message("[user] shaves [H]'s head bald with [src]!", \ + "You shave [H]'s head bald.") + shave(H, location) + else + ..() + else + ..() diff --git a/code/game/objects/items/dehy_carp.dm b/code/game/objects/items/dehy_carp.dm index 9432a434f0..649efc0802 100644 --- a/code/game/objects/items/dehy_carp.dm +++ b/code/game/objects/items/dehy_carp.dm @@ -4,13 +4,13 @@ */ //Child of carpplushie because this should do everything the toy does and more -/obj/item/toy/carpplushie/dehy_carp +/obj/item/toy/plush/carpplushie/dehy_carp var/mob/owner = null //Carp doesn't attack owner, set when using in hand var/owned = 0 //Boolean, no owner to begin with var/mobtype = /mob/living/simple_animal/hostile/carp //So admins can change what mob spawns via var fuckery //Attack self -/obj/item/toy/carpplushie/dehy_carp/attack_self(mob/user) +/obj/item/toy/plush/carpplushie/dehy_carp/attack_self(mob/user) src.add_fingerprint(user) //Anyone can add their fingerprints to it with this if(!owned) to_chat(user, "You pet [src]. You swear it looks up at you.") @@ -18,7 +18,7 @@ owned = 1 else return ..() -/obj/item/toy/carpplushie/dehy_carp/proc/Swell() +/obj/item/toy/plush/carpplushie/dehy_carp/proc/Swell() desc = "It's growing!" visible_message("[src] swells up!") diff --git a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm new file mode 100644 index 0000000000..204a1f81d9 --- /dev/null +++ b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm @@ -0,0 +1,65 @@ +//Used by engineering cyborgs in place of generic circuits. +/obj/item/device/electroadaptive_pseudocircuit + name = "electroadaptive pseudocircuit" + desc = "An all-in-one circuit imprinter, designer, synthesizer, outfitter, creator, and chef. It can be used in place of any generic circuit board during construction." + icon = 'icons/obj/module.dmi' + icon_state = "boris" + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL = 50, MAT_GLASS = 300) + origin_tech = "engineering=4" + var/recharging = FALSE + var/circuits = 5 //How many circuits the pseudocircuit has left + var/static/recycleable_circuits = typecacheof(list(/obj/item/electronics/firelock, /obj/item/electronics/airalarm, /obj/item/electronics/firealarm, \ + /obj/item/electronics/apc))//A typecache of circuits consumable for material + +/obj/item/device/electroadaptive_pseudocircuit/Initialize() + . = ..() + maptext = "[circuits]" + +/obj/item/device/electroadaptive_pseudocircuit/examine(mob/user) + ..() + if(iscyborg(user)) + to_chat(user, "It has material for [circuits] circuit[circuits == 1 ? "" : "s"]. Use the pseudocircuit on existing circuits to gain material.") + to_chat(user, "Serves as a substitute for fire/air alarm, firelock, and APC electronics.") + to_chat(user, "It can also be used on an APC with no power cell to fabricate a low-capacity cell at a high power cost.") + +/obj/item/device/electroadaptive_pseudocircuit/proc/adapt_circuit(mob/living/silicon/robot/R, circuit_cost = 0) + if(QDELETED(R) || !istype(R)) + return + if(!R.cell) + to_chat(R, "You need a power cell installed for that.") + return + if(!R.cell.use(circuit_cost)) + to_chat(R, "You don't have the power for that (you need [DisplayPower(circuit_cost)].)") + return + if(recharging) + to_chat(R, "[src] needs some time to recharge first.") + return + if(!circuits) + to_chat(R, "You need more material. Use [src] on existing simple circuits to break them down.") + return + playsound(R, 'sound/items/rped.ogg', 50, TRUE) + recharging = TRUE + circuits-- + maptext = "[circuits]" + icon_state = "[initial(icon_state)]_recharging" + var/recharge_time = min(600, circuit_cost * 5) //40W of cost for one fabrication = 20 seconds of recharge time; this is to prevent spamming + addtimer(CALLBACK(src, .proc/recharge), recharge_time) + return TRUE //The actual circuit magic itself is done on a per-object basis + +/obj/item/device/electroadaptive_pseudocircuit/afterattack(atom/target, mob/living/user, proximity) + if(!proximity) + return + if(!is_type_in_typecache(target, recycleable_circuits)) + return + circuits++ + maptext = "[circuits]" + user.visible_message("User breaks down [target] with [src].", \ + "You recycle [target] into [src]. It now has material for [circuits] circuits.") + playsound(user, 'sound/items/deconstruct.ogg', 50, TRUE) + qdel(target) + +/obj/item/device/electroadaptive_pseudocircuit/proc/recharge() + playsound(src, 'sound/machines/chime.ogg', 25, TRUE) + recharging = FALSE + icon_state = initial(icon_state) diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index bd54fda56f..8b27659ada 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -4,13 +4,13 @@ icon = 'icons/obj/radio.dmi' icon_state = "electropack0" item_state = "electropack" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - flags_1 = CONDUCT_1 + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + flags_1 = CONDUCT_1 slot_flags = SLOT_BACK w_class = WEIGHT_CLASS_HUGE materials = list(MAT_METAL=10000, MAT_GLASS=2500) - var/on = TRUE + var/on = TRUE var/code = 2 var/frequency = 1449 var/shock_cooldown = 0 @@ -20,11 +20,11 @@ return (FIRELOSS) /obj/item/device/electropack/Initialize() - ..() + . = ..() SSradio.add_object(src, frequency, GLOB.RADIO_CHAT) /obj/item/device/electropack/Destroy() - SSradio.remove_object(src, frequency) + SSradio.remove_object(src, frequency) return ..() /obj/item/device/electropack/attack_hand(mob/user) @@ -52,8 +52,8 @@ user.put_in_hands(A) A.add_fingerprint(user) - if(src.flags_1 & NODROP_1) - A.flags_1 |= NODROP_1 + if(src.flags_1 & NODROP_1) + A.flags_1 |= NODROP_1 else return ..() @@ -108,7 +108,7 @@ spawn(100) shock_cooldown = 0 var/mob/living/L = loc - step(L, pick(GLOB.cardinals)) + step(L, pick(GLOB.cardinals)) to_chat(L, "You feel a sharp shock!") var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread @@ -143,4 +143,4 @@ Code: "} user << browse(dat, "window=radio") onclose(user, "radio") - return + return \ No newline at end of file diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index 82d4c3d99f..d8be420a08 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -37,10 +37,10 @@ "Very doubtful") /obj/item/toy/eightball/Initialize(mapload) - ..() + . = ..() if(prob(1)) new /obj/item/toy/eightball/haunted(get_turf(src)) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/item/toy/eightball/attack_self(mob/user) if(shaking) @@ -81,7 +81,7 @@ var/fixed_answer /obj/item/toy/eightball/broken/Initialize(mapload) - ..() + . = ..() fixed_answer = pick(possible_answers) /obj/item/toy/eightball/broken/get_answer() @@ -97,7 +97,7 @@ var/list/votes /obj/item/toy/eightball/haunted/Initialize(mapload) - ..() + . = ..() votes = list() GLOB.poi_list |= src diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index bf5cf0417c..50b0f4e7e6 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -253,7 +253,7 @@ var/trap_damage = 20 /obj/item/restraints/legcuffs/beartrap/Initialize() - ..() + . = ..() icon_state = "[initial(icon_state)][armed]" /obj/item/restraints/legcuffs/beartrap/suicide_act(mob/user) @@ -369,4 +369,4 @@ var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom)) B.Crossed(hit_atom) qdel(src) - ..() + ..() \ No newline at end of file diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index 08681ac9e4..0bafff176b 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -61,7 +61,7 @@ return ..() /obj/item/implantcase/Initialize(mapload) - ..() + . = ..() if(imp_type) imp = new imp_type(src) update_icon() @@ -80,4 +80,4 @@ /obj/item/implantcase/adrenaline name = "implant case - 'Adrenaline'" desc = "A glass case containing an adrenaline implant." - imp_type = /obj/item/implant/adrenalin + imp_type = /obj/item/implant/adrenalin \ No newline at end of file diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 24b1928dbc..372671acf5 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -59,7 +59,7 @@ return ..() /obj/item/implanter/Initialize(mapload) - ..() + . = ..() if(imp_type) imp = new imp_type(src) update_icon() @@ -70,4 +70,4 @@ /obj/item/implanter/emp name = "implanter (EMP)" - imp_type = /obj/item/implant/emp + imp_type = /obj/item/implant/emp \ No newline at end of file diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm new file mode 100644 index 0000000000..b22383ad58 --- /dev/null +++ b/code/game/objects/items/plushes.dm @@ -0,0 +1,74 @@ +/obj/item/toy/plush + name = "plush" + desc = "this is the special coder plush, do not steal" + icon = 'icons/obj/plushes.dmi' + icon_state = "debug" + attack_verb = list("thumped", "whomped", "bumped") + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FLAMMABLE + var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this + +/obj/item/toy/plush/Initialize() + . = ..() + AddComponent(/datum/component/squeak, squeak_override) + +/obj/item/toy/plush/attack_self(mob/user) + . = ..() + to_chat(user, "You pet [src]. D'awww.") + +/obj/item/toy/plush/carpplushie + name = "space carp plushie" + desc = "An adorable stuffed toy that resembles a space carp." + icon_state = "carpplush" + item_state = "carp_plushie" + attack_verb = list("bitten", "eaten", "fin slapped") + squeak_override = list('sound/weapons/bite.ogg'=1) + +/obj/item/toy/plush/bubbleplush + name = "bubblegum plushie" + desc = "The friendly red demon that gives good miners gifts." + icon_state = "bubbleplush" + attack_verb = list("rends") + squeak_override = list('sound/magic/demon_attack1.ogg'=1) + +/obj/item/toy/plush/plushvar + name = "ratvar plushie" + desc = "An adorable plushie of the clockwork justiciar himself with new and improved spring arm action." + icon_state = "plushvar" + +/obj/item/toy/plush/narplush + name = "nar'sie plushie" + desc = "A small stuffed doll of the elder god nar'sie. Who thought this was a good children's toy?" + icon_state = "narplush" + +/obj/item/toy/plush/lizardplushie + name = "lizard plushie" + desc = "An adorable stuffed toy that resembles a lizardperson." + icon_state = "plushie_lizard" + item_state = "plushie_lizard" + attack_verb = list("clawed", "hissed", "tail slapped") + squeak_override = list('sound/weapons/slash.ogg' = 1) + +/obj/item/toy/plush/snakeplushie + name = "snake plushie" + desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing." + icon_state = "plushie_snake" + item_state = "plushie_snake" + attack_verb = list("bitten", "hissed", "tail slapped") + squeak_override = list('sound/weapons/bite.ogg' = 1) + +/obj/item/toy/plush/nukeplushie + name = "operative plushie" + desc = "An stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious." + icon_state = "plushie_nuke" + item_state = "plushie_nuke" + attack_verb = list("shot", "nuked", "detonated") + squeak_override = list('sound/effects/hit_punch.ogg' = 1) + +/obj/item/toy/plush/slimeplushie + name = "slime plushie" + desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack." + icon_state = "plushie_slime" + item_state = "plushie_slime" + attack_verb = list("blorbled", "slimed", "absorbed") + squeak_override = list('sound/effects/blobattack.ogg' = 1) \ No newline at end of file diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index fe89f42338..2290ea91d3 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -289,7 +289,7 @@ icon_state = initial(icon_state) /obj/item/storage/backpack/satchel/flat/Initialize(mapload) - ..() + . = ..() SSpersistence.new_secret_satchels += src /obj/item/storage/backpack/satchel/flat/PopulateContents() @@ -306,7 +306,7 @@ var/revealed = 0 /obj/item/storage/backpack/satchel/flat/secret/Initialize() - ..() + . = ..() if(isfloorturf(loc) && !istype(loc, /turf/open/floor/plating/)) hide(1) diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index c1a47742e9..489f1c6bf0 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -735,7 +735,7 @@ var/theme_name /obj/item/storage/box/ingredients/Initialize() - ..() + . = ..() if(theme_name) name = "[name] ([theme_name])" desc = "A box containing supplementary ingredients for the aspiring chef. The box's theme is '[theme_name]'." diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm index 8107c5a1f8..df40b2898c 100644 --- a/code/game/objects/items/storage/briefcase.dm +++ b/code/game/objects/items/storage/briefcase.dm @@ -1,57 +1,56 @@ -/obj/item/storage/briefcase - name = "briefcase" - desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional." - icon_state = "briefcase" - lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi' - flags_1 = CONDUCT_1 - force = 8 - hitsound = "swing_hit" - throw_speed = 2 - throw_range = 4 - w_class = WEIGHT_CLASS_BULKY - max_w_class = WEIGHT_CLASS_NORMAL - max_combined_w_class = 21 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") - resistance_flags = FLAMMABLE - max_integrity = 150 - var/folder_path = /obj/item/folder //this is the path of the folder that gets spawned in New() - -/obj/item/storage/briefcase/PopulateContents() - new /obj/item/pen(src) - var/obj/item/folder/folder = new folder_path(src) - for(var/i in 1 to 6) - new /obj/item/paper(folder) - -/obj/item/storage/briefcase/lawyer - folder_path = /obj/item/folder/blue - -/obj/item/storage/briefcase/lawyer/PopulateContents() - new /obj/item/stamp/law(src) - ..() - -/obj/item/storage/briefcase/sniperbundle - name = "briefcase" - desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding. Smells like L'Air du Temps." - icon_state = "briefcase" - flags_1 = CONDUCT_1 - force = 10 - hitsound = "swing_hit" - throw_speed = 2 - throw_range = 4 - w_class = WEIGHT_CLASS_BULKY - max_w_class = WEIGHT_CLASS_NORMAL - max_combined_w_class = 21 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") - resistance_flags = FLAMMABLE - max_integrity = 150 - -/obj/item/storage/briefcase/sniperbundle/PopulateContents() - ..() // in case you need any paperwork done after your rampage - new /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate(src) - new /obj/item/clothing/neck/tie/red(src) - new /obj/item/clothing/under/syndicate/sniper(src) - new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) - new /obj/item/ammo_box/magazine/sniper_rounds/haemorrhage(src) - new /obj/item/suppressor/specialoffer(src) - +/obj/item/storage/briefcase + name = "briefcase" + desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional." + icon_state = "briefcase" + lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi' + flags_1 = CONDUCT_1 + force = 8 + hitsound = "swing_hit" + throw_speed = 2 + throw_range = 4 + w_class = WEIGHT_CLASS_BULKY + max_w_class = WEIGHT_CLASS_NORMAL + max_combined_w_class = 21 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") + resistance_flags = FLAMMABLE + max_integrity = 150 + var/folder_path = /obj/item/folder //this is the path of the folder that gets spawned in New() + +/obj/item/storage/briefcase/PopulateContents() + new /obj/item/pen(src) + var/obj/item/folder/folder = new folder_path(src) + for(var/i in 1 to 6) + new /obj/item/paper(folder) + +/obj/item/storage/briefcase/lawyer + folder_path = /obj/item/folder/blue + +/obj/item/storage/briefcase/lawyer/PopulateContents() + new /obj/item/stamp/law(src) + ..() + +/obj/item/storage/briefcase/sniperbundle + name = "briefcase" + desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding. Smells like L'Air du Temps." + icon_state = "briefcase" + flags_1 = CONDUCT_1 + force = 10 + hitsound = "swing_hit" + throw_speed = 2 + throw_range = 4 + w_class = WEIGHT_CLASS_BULKY + max_w_class = WEIGHT_CLASS_NORMAL + max_combined_w_class = 21 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") + resistance_flags = FLAMMABLE + max_integrity = 150 + +/obj/item/storage/briefcase/sniperbundle/PopulateContents() + ..() // in case you need any paperwork done after your rampage + new /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate(src) + new /obj/item/clothing/neck/tie/red(src) + new /obj/item/clothing/under/syndicate/sniper(src) + new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) + new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) + new /obj/item/suppressor/specialoffer(src) diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 4b93fde13f..4dc90de6be 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -56,7 +56,7 @@ item_state = "firstaid-ointment" /obj/item/storage/firstaid/fire/Initialize(mapload) - ..() + . = ..() icon_state = pick("ointment","firefirstaid") /obj/item/storage/firstaid/fire/PopulateContents() diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index e6fe6da34d..dfcac18d29 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -19,7 +19,7 @@ var/has_latches = TRUE /obj/item/storage/toolbox/Initialize() - ..() + . = ..() if(has_latches) if(prob(10)) latches = "double_latch" @@ -183,4 +183,4 @@ new/obj/item/stack/cable_coil/pink(src) new/obj/item/stack/cable_coil/orange(src) new/obj/item/stack/cable_coil/cyan(src) - new/obj/item/stack/cable_coil/white(src) + new/obj/item/stack/cable_coil/white(src) \ No newline at end of file diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index c2a1666aef..dd2ea47dc4 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -236,7 +236,6 @@ if(!istype(src.loc, /obj/item/device/transfer_valve)) message_admins("Explosive tank rupture! Last key to touch the tank was [src.fingerprintslast].") log_game("Explosive tank rupture! Last key to touch the tank was [src.fingerprintslast].") - //to_chat(world, "\blue[x],[y] tank is exploding: [pressure] kPa") //Give the gas a chance to build up more pressure through reacting air_contents.react() air_contents.react() @@ -245,7 +244,6 @@ var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE var/turf/epicenter = get_turf(loc) - //to_chat(world, "\blue Exploding Pressure: [pressure] kPa, intensity: [range]") explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5)) if(istype(src.loc, /obj/item/device/transfer_valve)) @@ -254,7 +252,6 @@ qdel(src) else if(pressure > TANK_RUPTURE_PRESSURE) - //to_chat(world, "\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]") if(integrity <= 0) var/turf/T = get_turf(src) if(!T) @@ -266,7 +263,6 @@ integrity-- else if(pressure > TANK_LEAK_PRESSURE) - //to_chat(world, "\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]") if(integrity <= 0) var/turf/T = get_turf(src) if(!T) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 87ff199dfe..a683902a6c 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -14,7 +14,6 @@ * Cards * Toy nuke * Fake meteor - * Carp plushie * Foam armblade * Toy big red button * Beach ball @@ -40,7 +39,7 @@ icon = 'icons/obj/toy.dmi' icon_state = "waterballoon-e" item_state = "balloon-empty" - + /obj/item/toy/balloon/New() create_reagents(10) @@ -987,32 +986,6 @@ shake_camera(M, 3, 1) qdel(src) -/* - * Carp plushie - */ - -/obj/item/toy/carpplushie - name = "space carp plushie" - desc = "An adorable stuffed toy that resembles a space carp." - icon = 'icons/obj/toy.dmi' - icon_state = "carpplushie" - item_state = "carp_plushie" - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("bitten", "eaten", "fin slapped") - resistance_flags = FLAMMABLE - var/bitesound = 'sound/weapons/bite.ogg' - -//Attack mob -/obj/item/toy/carpplushie/attack(mob/M, mob/user) - playsound(loc, bitesound, 20, 1) //Play bite sound in local area - return ..() - -//Attack self -/obj/item/toy/carpplushie/attack_self(mob/user) - playsound(src.loc, bitesound, 20, 1) - to_chat(user, "You pet [src]. D'awww.") - return ..() - /* * Toy big red button */ diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 4f1348f3da..e15f0446a5 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -450,3 +450,7 @@ /obj/structure/closet/AllowDrop() return TRUE + + +/obj/structure/closet/return_temperature() + return \ No newline at end of file diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 081cf186a3..225d634a7f 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -55,7 +55,7 @@ icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi' /obj/structure/lattice/clockwork/Initialize(mapload) - ..() + . = ..() ratvar_act() /obj/structure/lattice/clockwork/ratvar_act() @@ -63,7 +63,7 @@ new /obj/structure/lattice/clockwork/large(loc) // deletes old one /obj/structure/lattice/clockwork/large/Initialize(mapload) - ..() + . = ..() icon = 'icons/obj/smooth_structures/lattice_clockwork_large.dmi' pixel_x = -9 pixel_y = -9 @@ -101,7 +101,7 @@ icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi' /obj/structure/lattice/catwalk/clockwork/Initialize(mapload) - ..() + . = ..() new /obj/effect/temp_visual/ratvar/floor/catwalk(loc) new /obj/effect/temp_visual/ratvar/beam/catwalk(loc) diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index e15a655a63..52d9e38f6b 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -1,214 +1,214 @@ -/////// MANNED TURRET //////// - -/obj/machinery/manned_turret - name = "machine gun turret" - desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets." - icon = 'icons/obj/turrets.dmi' - icon_state = "machinegun" - can_buckle = TRUE - density = TRUE - max_integrity = 100 - buckle_lying = FALSE - layer = ABOVE_MOB_LAYER - var/view_range = 10 - var/cooldown = 0 - var/projectile_type = /obj/item/projectile/bullet/weakbullet3 - var/rate_of_fire = 1 - var/number_of_shots = 40 - var/cooldown_duration = 90 - var/atom/target - var/turf/target_turf - var/warned = FALSE - var/list/calculated_projectile_vars - -/obj/machinery/manned_turret/Destroy() - target = null - target_turf = null - ..() - -//BUCKLE HOOKS - -/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE) - playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) - for(var/obj/item/I in buckled_mob.held_items) - if(istype(I, /obj/item/gun_control)) - qdel(I) - if(istype(buckled_mob)) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 0 - if(buckled_mob.client) - buckled_mob.client.change_view(world.view) - anchored = FALSE - . = ..() - STOP_PROCESSING(SSfastprocess, src) - -/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) - if(user.incapacitated() || !istype(user)) - return - M.forceMove(get_turf(src)) - . = ..() - if(!.) - return - for(var/V in M.held_items) - var/obj/item/I = V - if(istype(I)) - if(M.dropItemToGround(I)) - var/obj/item/gun_control/TC = new(src) - M.put_in_hands(TC) - else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand - var/obj/item/gun_control/TC = new(src) - M.put_in_hands(TC) - M.pixel_y = 14 - layer = ABOVE_MOB_LAYER - setDir(SOUTH) - playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) - anchored = TRUE - if(M.client) - M.client.change_view(view_range) - START_PROCESSING(SSfastprocess, src) - -/obj/machinery/manned_turret/process() - if(!LAZYLEN(buckled_mobs)) - return PROCESS_KILL - update_positioning() - -/obj/machinery/manned_turret/proc/update_positioning() - var/mob/living/controller = buckled_mobs[1] - if(!istype(controller)) - return - var/client/C = controller.client - if(C) - var/atom/A = C.mouseObject - var/turf/T = get_turf(A) - if(istype(T)) //They're hovering over something in the map. - direction_track(controller, T) - calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, C.mouseParams) - -/obj/machinery/manned_turret/proc/direction_track(mob/user, atom/targeted) - if(user.incapacitated()) - return - setDir(get_dir(src,targeted)) - user.setDir(dir) - switch(dir) - if(NORTH) - layer = BELOW_MOB_LAYER - user.pixel_x = 0 - user.pixel_y = -14 - if(NORTHEAST) - layer = BELOW_MOB_LAYER - user.pixel_x = -8 - user.pixel_y = -4 - if(EAST) - layer = ABOVE_MOB_LAYER - user.pixel_x = -14 - user.pixel_y = 0 - if(SOUTHEAST) - layer = BELOW_MOB_LAYER - user.pixel_x = -8 - user.pixel_y = 4 - if(SOUTH) - layer = ABOVE_MOB_LAYER - user.pixel_x = 0 - user.pixel_y = 14 - if(SOUTHWEST) - layer = BELOW_MOB_LAYER - user.pixel_x = 8 - user.pixel_y = 4 - if(WEST) - layer = ABOVE_MOB_LAYER - user.pixel_x = 14 - user.pixel_y = 0 - if(NORTHWEST) - layer = BELOW_MOB_LAYER - user.pixel_x = 8 - user.pixel_y = -4 - -/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user) - target = targeted_atom - if(target == user || user.incapacitated() || target == get_turf(src)) - return - if(world.time < cooldown) - if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing - warned = TRUE - playsound(src, 'sound/weapons/sear.ogg', 100, 1) - return - else - cooldown = world.time + cooldown_duration - warned = FALSE - volley(user) - -/obj/machinery/manned_turret/proc/volley(mob/user) - target_turf = get_turf(target) - for(var/i in 1 to number_of_shots) - addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire) - -/obj/machinery/manned_turret/proc/fire_helper(mob/user) - if(user.incapacitated()) - return - update_positioning() //REFRESH MOUSE TRACKING!! - var/turf/targets_from = get_turf(src) - if(QDELETED(target)) - target = target_turf - var/obj/item/projectile/P = new projectile_type(targets_from) - P.current = targets_from - P.starting = targets_from - P.firer = user - P.original = target - playsound(src, 'sound/weapons/gunshot_smg.ogg', 75, 1) - P.xo = target.x - targets_from.x - P.yo = target.y - targets_from.y - P.Angle = calculated_projectile_vars[1] + rand(-9, 9) - P.p_x = calculated_projectile_vars[2] - P.p_y = calculated_projectile_vars[3] - P.fire() - -/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics - name = "Infinity Gun" - view_range = 12 - projectile_type = /obj/item/projectile/bullet/weakbullet3 - -/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user) - target = targeted_atom - if(target == user || target == get_turf(src)) - return - target_turf = get_turf(target) - fire_helper(user) - -/obj/item/gun_control - name = "turret controls" - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "offhand" - w_class = WEIGHT_CLASS_HUGE - flags_1 = ABSTRACT_1 | NODROP_1 | NOBLUDGEON_1 | DROPDEL_1 - resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF - var/obj/machinery/manned_turret/turret - -/obj/item/gun_control/Initialize() - . = ..() - turret = loc - if(!istype(turret)) - return INITIALIZE_HINT_QDEL - -/obj/item/gun_control/Destroy() - turret = null - ..() - -/obj/item/gun_control/CanItemAutoclick() - return TRUE - -/obj/item/gun_control/attack_obj(obj/O, mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) - O.attacked_by(src, user) - -/obj/item/gun_control/attack(mob/living/M, mob/living/user) - user.lastattacked = M - M.lastattacker = user - M.attacked_by(src, user) - add_fingerprint(user) - -/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params) - ..() - var/obj/machinery/manned_turret/E = user.buckled - E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, params) - E.direction_track(user, targeted_atom) - E.checkfire(targeted_atom, user) +/////// MANNED TURRET //////// + +/obj/machinery/manned_turret + name = "machine gun turret" + desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets." + icon = 'icons/obj/turrets.dmi' + icon_state = "machinegun" + can_buckle = TRUE + density = TRUE + max_integrity = 100 + buckle_lying = FALSE + layer = ABOVE_MOB_LAYER + var/view_range = 10 + var/cooldown = 0 + var/projectile_type = /obj/item/projectile/bullet/manned_turret + var/rate_of_fire = 1 + var/number_of_shots = 40 + var/cooldown_duration = 90 + var/atom/target + var/turf/target_turf + var/warned = FALSE + var/list/calculated_projectile_vars + +/obj/machinery/manned_turret/Destroy() + target = null + target_turf = null + ..() + +//BUCKLE HOOKS + +/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + for(var/obj/item/I in buckled_mob.held_items) + if(istype(I, /obj/item/gun_control)) + qdel(I) + if(istype(buckled_mob)) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + if(buckled_mob.client) + buckled_mob.client.change_view(world.view) + anchored = FALSE + . = ..() + STOP_PROCESSING(SSfastprocess, src) + +/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) + if(user.incapacitated() || !istype(user)) + return + M.forceMove(get_turf(src)) + . = ..() + if(!.) + return + for(var/V in M.held_items) + var/obj/item/I = V + if(istype(I)) + if(M.dropItemToGround(I)) + var/obj/item/gun_control/TC = new(src) + M.put_in_hands(TC) + else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand + var/obj/item/gun_control/TC = new(src) + M.put_in_hands(TC) + M.pixel_y = 14 + layer = ABOVE_MOB_LAYER + setDir(SOUTH) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + anchored = TRUE + if(M.client) + M.client.change_view(view_range) + START_PROCESSING(SSfastprocess, src) + +/obj/machinery/manned_turret/process() + if(!LAZYLEN(buckled_mobs)) + return PROCESS_KILL + update_positioning() + +/obj/machinery/manned_turret/proc/update_positioning() + var/mob/living/controller = buckled_mobs[1] + if(!istype(controller)) + return + var/client/C = controller.client + if(C) + var/atom/A = C.mouseObject + var/turf/T = get_turf(A) + if(istype(T)) //They're hovering over something in the map. + direction_track(controller, T) + calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, C.mouseParams) + +/obj/machinery/manned_turret/proc/direction_track(mob/user, atom/targeted) + if(user.incapacitated()) + return + setDir(get_dir(src,targeted)) + user.setDir(dir) + switch(dir) + if(NORTH) + layer = BELOW_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = -14 + if(NORTHEAST) + layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = -4 + if(EAST) + layer = ABOVE_MOB_LAYER + user.pixel_x = -14 + user.pixel_y = 0 + if(SOUTHEAST) + layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = 4 + if(SOUTH) + layer = ABOVE_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = 14 + if(SOUTHWEST) + layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = 4 + if(WEST) + layer = ABOVE_MOB_LAYER + user.pixel_x = 14 + user.pixel_y = 0 + if(NORTHWEST) + layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = -4 + +/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || user.incapacitated() || target == get_turf(src)) + return + if(world.time < cooldown) + if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing + warned = TRUE + playsound(src, 'sound/weapons/sear.ogg', 100, 1) + return + else + cooldown = world.time + cooldown_duration + warned = FALSE + volley(user) + +/obj/machinery/manned_turret/proc/volley(mob/user) + target_turf = get_turf(target) + for(var/i in 1 to number_of_shots) + addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire) + +/obj/machinery/manned_turret/proc/fire_helper(mob/user) + if(user.incapacitated()) + return + update_positioning() //REFRESH MOUSE TRACKING!! + var/turf/targets_from = get_turf(src) + if(QDELETED(target)) + target = target_turf + var/obj/item/projectile/P = new projectile_type(targets_from) + P.current = targets_from + P.starting = targets_from + P.firer = user + P.original = target + playsound(src, 'sound/weapons/gunshot_smg.ogg', 75, 1) + P.xo = target.x - targets_from.x + P.yo = target.y - targets_from.y + P.Angle = calculated_projectile_vars[1] + rand(-9, 9) + P.p_x = calculated_projectile_vars[2] + P.p_y = calculated_projectile_vars[3] + P.fire() + +/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics + name = "Infinity Gun" + view_range = 12 + projectile_type = /obj/item/projectile/bullet/manned_turret + +/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || target == get_turf(src)) + return + target_turf = get_turf(target) + fire_helper(user) + +/obj/item/gun_control + name = "turret controls" + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + flags_1 = ABSTRACT_1 | NODROP_1 | NOBLUDGEON_1 | DROPDEL_1 + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/obj/machinery/manned_turret/turret + +/obj/item/gun_control/Initialize() + . = ..() + turret = loc + if(!istype(turret)) + return INITIALIZE_HINT_QDEL + +/obj/item/gun_control/Destroy() + turret = null + ..() + +/obj/item/gun_control/CanItemAutoclick() + return TRUE + +/obj/item/gun_control/attack_obj(obj/O, mob/living/user) + user.changeNext_move(CLICK_CD_MELEE) + O.attacked_by(src, user) + +/obj/item/gun_control/attack(mob/living/M, mob/living/user) + user.lastattacked = M + M.lastattacker = user + M.attacked_by(src, user) + add_fingerprint(user) + +/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params) + ..() + var/obj/machinery/manned_turret/E = user.buckled + E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, params) + E.direction_track(user, targeted_atom) + E.checkfire(targeted_atom, user) \ No newline at end of file diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index ed0deef7d9..d253cbcf44 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -97,19 +97,15 @@ cur_acc[i] = "n" for(var/line in lines) - //to_chat(world, line) for(var/beat in splittext(lowertext(line), ",")) - //to_chat(world, "beat: [beat]") var/list/notes = splittext(beat, "/") for(var/note in splittext(notes[1], "-")) - //to_chat(world, "note: [note]") if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case playing = FALSE hearing_mobs = null return if(!lentext(note)) continue - //to_chat(world, "Parse: [copytext(note,1,2)]") var/cur_note = text2ascii(note) - 96 if(cur_note < 1 || cur_note > 7) continue diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 17f7f3f493..116ced183f 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -34,8 +34,8 @@ smooth = SMOOTH_TRUE canSmoothWith = list(/obj/structure/table, /obj/structure/table/reinforced) -/obj/structure/table/New() - ..() +/obj/structure/table/Initialize() + . = ..() for(var/obj/structure/table/T in src.loc) if(T != src) qdel(T) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 1cf8e330fe..16d1072779 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -180,3 +180,6 @@ if(TT.has_exit(direction)) setDir(direction) return + +/obj/structure/transit_tube_pod/return_temperature() + return air_contents.temperature \ No newline at end of file diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index d82428ad98..8e6ba993cb 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -16,7 +16,7 @@ var/datum/effect_system/spark_spread/spark_system /obj/structure/trap/Initialize(mapload) - ..() + . = ..() spark_system = new spark_system.set_up(4,1,src) spark_system.attach(src) diff --git a/code/game/sound.dm b/code/game/sound.dm index cf6d4707a7..13a3343e06 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -178,4 +178,6 @@ 'sound/vore/prey/death_10.ogg') if("bullet_miss") soundin = pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg') + if("law") + soundin = pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg') return soundin diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 2ea3ffe7fc..68e5e31e84 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -69,7 +69,7 @@ icon = 'icons/obj/smooth_structures/reinforced_window.dmi' /turf/closed/indestructible/fakeglass/Initialize() - ..() + . = ..() icon_state = null //set the icon state to null, so our base state isn't visible underlays += mutable_appearance('icons/obj/structures.dmi', "grille") //add a grille underlay underlays += mutable_appearance('icons/turf/floors.dmi', "plating") //add the plating underlay, below the grille diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index df3d2aba86..02206646d2 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -21,7 +21,7 @@ broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5") if (!burnt_states) burnt_states = list() - ..() + . = ..() //This is so damaged or burnt tiles or platings don't get remembered as the default tile var/static/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4", "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2", "foam_plating", diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index 59e7bed8ca..a24642c735 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -71,7 +71,7 @@ var/turfverb = "uproot" /turf/open/floor/grass/Initialize() - ..() + . = ..() update_icon() /turf/open/floor/grass/attackby(obj/item/C, mob/user, params) @@ -109,7 +109,7 @@ slowdown = 0 /turf/open/floor/grass/snow/basalt/Initialize() - ..() + . = ..() if(prob(15)) icon_state = "basalt[rand(0, 12)]" set_basalt_light(src) @@ -126,7 +126,7 @@ slowdown = 0 /turf/open/floor/grass/fakebasalt/Initialize() - ..() + . = ..() if(prob(15)) icon_state = "basalt[rand(0, 12)]" set_basalt_light(src) @@ -144,7 +144,7 @@ flags_1 = NONE /turf/open/floor/carpet/Initialize() - ..() + . = ..() update_icon() /turf/open/floor/carpet/update_icon() @@ -205,7 +205,7 @@ plane = PLANE_SPACE /turf/open/floor/fakespace/Initialize() - ..() + . = ..() icon_state = SPACE_ICON_STATE /turf/open/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index 542a0ed81d..247382d03c 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -13,7 +13,7 @@ /turf/open/floor/light/Initialize() - ..() + . = ..() update_icon() /turf/open/floor/light/break_tile() diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm index c28232410d..6f863d4bd0 100644 --- a/code/game/turfs/simulated/floor/mineral_floor.dm +++ b/code/game/turfs/simulated/floor/mineral_floor.dm @@ -18,7 +18,7 @@ /turf/open/floor/mineral/Initialize() broken_states = list("[initial(icon_state)]_dam") - ..() + . = ..() if (!icons) icons = list() @@ -221,7 +221,7 @@ icons = list("alienpod1", "alienpod2", "alienpod3", "alienpod4", "alienpod5", "alienpod6", "alienpod7", "alienpod8", "alienpod9") /turf/open/floor/mineral/abductor/Initialize() - ..() + . = ..() icon_state = "alienpod[rand(1,9)]" /turf/open/floor/mineral/abductor/break_tile() diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 1461abfcaf..3656e146a6 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -20,7 +20,7 @@ /turf/open/floor/circuit/Initialize() SSmapping.nuke_tiles += src update_icon() - ..() + . = ..() /turf/open/floor/circuit/Destroy() SSmapping.nuke_tiles -= src @@ -145,7 +145,7 @@ var/obj/effect/clockwork/overlay/floor/realappearence /turf/open/floor/clockwork/Initialize() - ..() + . = ..() new /obj/effect/temp_visual/ratvar/floor(src) new /obj/effect/temp_visual/ratvar/beam(src) realappearence = new /obj/effect/clockwork/overlay/floor(src) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 3617759e99..8ad6657784 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -17,7 +17,7 @@ broken_states = list("platingdmg1", "platingdmg2", "platingdmg3") if (!burnt_states) burnt_states = list("panelscorched") - ..() + . = ..() icon_plating = icon_state /turf/open/floor/plating/update_icon() diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index eaf0e512f7..04c97aa7d5 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -108,7 +108,7 @@ var/obj/effect/clockwork/overlay/floor/bloodcult/realappearence /turf/open/floor/engine/cult/Initialize() - ..() + . = ..() new /obj/effect/temp_visual/cult/turf/floor(src) realappearence = new /obj/effect/clockwork/overlay/floor/bloodcult(src) realappearence.linked = src diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 9e0d57d782..630ded7daa 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -30,7 +30,7 @@ pixel_y = -4 pixel_x = -4 icon = smooth_icon - ..() + . = ..() if (mineralType && mineralAmt && spread && spreadChance) for(var/dir in GLOB.cardinals) if(prob(spreadChance)) @@ -153,7 +153,7 @@ /turf/closed/mineral/gibtonite = 4, /turf/open/floor/plating/asteroid/airless/cave = 2, /turf/closed/mineral/bscrystal = 1) if (display_icon_state) icon_state = display_icon_state - ..() + . = ..() if (prob(mineralChance)) var/path = pickweight(mineralSpawnChanceList) var/turf/T = ChangeTurf(path,FALSE,FALSE,TRUE) @@ -393,7 +393,7 @@ /turf/closed/mineral/gibtonite/Initialize() det_time = rand(8,10) //So you don't know exactly when the hot potato will explode - ..() + . = ..() /turf/closed/mineral/gibtonite/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/device/mining_scanner) || istype(I, /obj/item/device/t_scanner/adv_mining_scanner) && stage == 1) diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index f11735d676..cf611560c3 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -73,7 +73,7 @@ /turf/open/space/transit/Initialize() - ..() + . = ..() update_icon() for(var/atom/movable/AM in src) throw_atom(AM) diff --git a/code/modules/admin/DB_ban/functions.dm b/code/modules/admin/DB_ban/functions.dm index c6f44fd1da..086df300d3 100644 --- a/code/modules/admin/DB_ban/functions.dm +++ b/code/modules/admin/DB_ban/functions.dm @@ -354,6 +354,7 @@ output += "
Add custom ban: (ONLY use this if you can't ban through any other method)" output += "" + output += HrefTokenFormField() output += "" output += "
Ban type:" + output += HrefTokenFormField() output += "Ckey: " output += "Admin ckey: " output += "" diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index c2b5c1cd8d..b56caa4e9a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -380,8 +380,6 @@ else dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - //to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]") - //to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]") usr << browse(dat, "window=admincaster_main;size=400x600") onclose(usr, "admincaster_main") @@ -433,7 +431,7 @@ else rebootconfirm = TRUE if(rebootconfirm) - var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options + var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options if(result) SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! switch(result) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 343e954a8d..526d05b76b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -27,7 +27,8 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) return list( /client/proc/invisimin, /*allows our mob to go invisible/visible*/ // /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage - /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags_1*/ + /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ + /datum/verbs/menu/Admin/verb/playerpanel, /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index e76385db59..93c354239b 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -6,7 +6,7 @@ create_mob_html = file2text('html/create_object.html') create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"") - user << browse(replacetext(create_mob_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_mob;size=425x475") + user << browse(create_panel_helper(create_mob_html), "window=create_mob;size=425x475") /proc/randomize_human(mob/living/carbon/human/H) H.gender = pick(MALE, FEMALE) diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index cb947355b1..73bb998231 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -1,3 +1,8 @@ +/datum/admins/proc/create_panel_helper(template) + var/final_html = replacetext(template, "/* ref src */", "\ref[src];[HrefToken()]") + final_html = replacetext(final_html,"/* hreftokenfield */","[HrefTokenFormField()]") + return final_html + /datum/admins/proc/create_object(mob/user) var/static/create_object_html = null if (!create_object_html) @@ -6,7 +11,7 @@ create_object_html = file2text('html/create_object.html') create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"") - user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_object;size=425x475") + user << browse(create_panel_helper(create_object_html), "window=create_object;size=425x475") /datum/admins/proc/quick_create_object(mob/user) var/static/list/create_object_forms = list( @@ -23,4 +28,4 @@ html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"") create_object_forms[path] = html_form - user << browse(replacetext(html_form, "/* ref src */", "\ref[src];[HrefToken()]"), "window=qco[path];size=425x475") + user << browse(create_panel_helper(html_form), "window=qco[path];size=425x475") diff --git a/code/modules/admin/create_turf.dm b/code/modules/admin/create_turf.dm index f38b86a7b9..a25c02554e 100644 --- a/code/modules/admin/create_turf.dm +++ b/code/modules/admin/create_turf.dm @@ -6,4 +6,4 @@ create_turf_html = file2text('html/create_object.html') create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"") - user << browse(replacetext(create_turf_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_turf;size=425x475") + user << browse(create_panel_helper(create_turf_html), "window=create_turf;size=425x475") diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 153fb2d8c2..238512c8b7 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -40,7 +40,7 @@ GLOBAL_PROTECT(href_token) for(var/I in 1 to 32) . += "[rand(10)]" -/proc/HrefToken(forceGlobal = FALSE) +/proc/RawHrefToken(forceGlobal = FALSE) var/tok = GLOB.href_token if(!forceGlobal && usr) var/client/C = usr.client @@ -49,7 +49,13 @@ GLOBAL_PROTECT(href_token) var/datum/admins/holder = C.holder if(holder) tok = holder.href_token - return "admin_token=[tok]" + return tok + +/proc/HrefToken(forceGlobal = FALSE) + return "admin_token=[RawHrefToken(forceGlobal)]" + +/proc/HrefTokenFormField(forceGlobal = FALSE) + return "" /datum/admins/proc/associate(client/C) if(IsAdminAdvancedProcCall()) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index eaa98934d5..4cbac86270 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -37,7 +37,6 @@ if(!query_text || length(query_text) < 1) return - //to_chat(world, query_text) var/list/query_list = SDQL2_tokenize(query_text) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 4349bb307a..16f654bb80 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -211,7 +211,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) return ..() /datum/admin_help/proc/AddInteraction(formatted_message) - if(heard_by_no_admins && usr && usr.client != initiator) + if(heard_by_no_admins && usr && usr.ckey != initiator_ckey) heard_by_no_admins = FALSE send2irc(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]") _interactions += "[gameTimestamp()]: [formatted_message]" diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 1060c2daf2..a37e4d61c4 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -108,8 +108,6 @@ var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow var/temperature = air.temperature var/list/cached_results = air.reaction_results - - //to_chat(world, "pre [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]") cached_results[id] = 0 //General volatile gas burn @@ -165,8 +163,6 @@ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity - //to_chat(world, "post [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]") - //let the floor know a fire is happening if(istype(location)) temperature = air.temperature @@ -201,7 +197,6 @@ //Fusion wont occur if the level of impurities is too high. return NO_REACTION - //to_chat(world, "pre [temperature, [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]]) var/old_heat_capacity = air.heat_capacity() var/carbon_efficency = min(cached_gases["plasma"][MOLES]/cached_gases["co2"][MOLES],MAX_CARBON_EFFICENCY) var/reaction_energy = air.thermal_energy() @@ -226,7 +221,6 @@ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB) //Prevents whatever mechanism is causing it to hit negative temperatures. - //to_chat(world, "post [temperature], [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]]) return REACTING #undef REACTING diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index 1a03c69d49..6de564da6d 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -415,7 +415,6 @@ signal.data["sigtype"] = "command" radio_connection.post_signal(src, signal, GLOB.RADIO_FROM_AIRALARM) -// to_chat(world, text("Signal [] Broadcasted to []", command, target)) return 1 @@ -709,6 +708,16 @@ qdel(W) return + if(istype(W, /obj/item/device/electroadaptive_pseudocircuit)) + var/obj/item/device/electroadaptive_pseudocircuit/P = W + if(!P.adapt_circuit(user, 25)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt an air alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return + if(istype(W, /obj/item/wrench)) to_chat(user, "You detach \the [src] from the wall.") playsound(src.loc, W.usesound, 50, 1) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index f76eb3bb65..786aff1038 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -1,70 +1,63 @@ -//node2, air2, network2 correspond to input -//node1, air1, network1 correspond to output - - -/obj/machinery/atmospherics/components/binary/circulator - name = "circulator/heat exchanger" - desc = "A gas circulator pump and heat exchanger." - icon_state = "circ1-off" - - var/side = CIRC_LEFT - var/status = 0 - - var/last_pressure_delta = 0 - +//node2, air2, network2 correspond to input +//node1, air1, network1 correspond to output + + +/obj/machinery/atmospherics/components/binary/circulator + name = "circulator/heat exchanger" + desc = "A gas circulator pump and heat exchanger." + icon_state = "circ1-off" + + var/side = CIRC_LEFT + var/status = 0 + + var/last_pressure_delta = 0 + anchored = TRUE density = TRUE - - var/global/const/CIRC_LEFT = 1 - var/global/const/CIRC_RIGHT = 2 - - -/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air() - - var/datum/gas_mixture/air1 = AIR1 - var/datum/gas_mixture/air2 = AIR2 - - var/output_starting_pressure = air1.return_pressure() - var/input_starting_pressure = air2.return_pressure() - - if(output_starting_pressure >= input_starting_pressure-10) - //Need at least 10 KPa difference to overcome friction in the mechanism - last_pressure_delta = 0 - return null - - //Calculate necessary moles to transfer using PV = nRT - if(air2.temperature>0) - var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2 - - var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) - - last_pressure_delta = pressure_delta - - //to_chat(world, "pressure_delta = [pressure_delta]; transfer_moles = [transfer_moles];") - - //Actually transfer the gas - var/datum/gas_mixture/removed = air2.remove(transfer_moles) - - update_parents() - - return removed - - else - last_pressure_delta = 0 - -/obj/machinery/atmospherics/components/binary/circulator/process_atmos() - ..() - update_icon() - -/obj/machinery/atmospherics/components/binary/circulator/update_icon() - if(stat & (BROKEN|NOPOWER)) - icon_state = "circ[side]-p" - else if(last_pressure_delta > 0) - if(last_pressure_delta > ONE_ATMOSPHERE) - icon_state = "circ[side]-run" - else - icon_state = "circ[side]-slow" - else - icon_state = "circ[side]-off" - - return 1 + var/global/const/CIRC_LEFT = 1 + var/global/const/CIRC_RIGHT = 2 + + +/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air() + + var/datum/gas_mixture/air1 = AIR1 + var/datum/gas_mixture/air2 = AIR2 + + var/output_starting_pressure = air1.return_pressure() + var/input_starting_pressure = air2.return_pressure() + + if(output_starting_pressure >= input_starting_pressure-10) + //Need at least 10 KPa difference to overcome friction in the mechanism + last_pressure_delta = 0 + return null + + //Calculate necessary moles to transfer using PV = nRT + if(air2.temperature>0) + var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2 + + var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) + + last_pressure_delta = pressure_delta + var/datum/gas_mixture/removed = air2.remove(transfer_moles) + + update_parents() + + return removed + + else + last_pressure_delta = 0 + +/obj/machinery/atmospherics/components/binary/circulator/process_atmos() + ..() + update_icon() + +/obj/machinery/atmospherics/components/binary/circulator/update_icon() + if(!is_operational()) + icon_state = "circ[side]-p" + else if(last_pressure_delta > 0) + if(last_pressure_delta > ONE_ATMOSPHERE) + icon_state = "circ[side]-run" + else + icon_state = "circ[side]-slow" + else + icon_state = "circ[side]-off" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm index 1ef52cc787..15f0ccddd2 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm @@ -1,211 +1,207 @@ -/* -Acts like a normal vent, but has an input AND output. -*/ -#define EXT_BOUND 1 -#define INPUT_MIN 2 -#define OUTPUT_MAX 4 - -/obj/machinery/atmospherics/components/binary/dp_vent_pump - icon = 'icons/obj/atmospherics/components/unary_devices.dmi' //We reuse the normal vent icons! - icon_state = "dpvent_map" - - //node2 is output port - //node1 is input port - - name = "dual-port air vent" - desc = "Has a valve and pump attached to it. There are two ports." - - level = 1 - var/frequency = 0 - var/id = null - var/datum/radio_frequency/radio_connection - +/* +Acts like a normal vent, but has an input AND output. +*/ +#define EXT_BOUND 1 +#define INPUT_MIN 2 +#define OUTPUT_MAX 4 + +/obj/machinery/atmospherics/components/binary/dp_vent_pump + icon = 'icons/obj/atmospherics/components/unary_devices.dmi' //We reuse the normal vent icons! + icon_state = "dpvent_map" + + //node2 is output port + //node1 is input port + + name = "dual-port air vent" + desc = "Has a valve and pump attached to it. There are two ports." + + level = 1 + var/frequency = 0 + var/id = null + var/datum/radio_frequency/radio_connection + var/on = FALSE - var/pump_direction = 1 //0 = siphoning, 1 = releasing - - var/external_pressure_bound = ONE_ATMOSPHERE - var/input_pressure_min = 0 - var/output_pressure_max = 0 - - var/pressure_checks = EXT_BOUND - //EXT_BOUND: Do not pass external_pressure_bound - //INPUT_MIN: Do not pass input_pressure_min - //OUTPUT_MAX: Do not pass output_pressure_max - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/on - on = TRUE - icon_state = "dpvent_map_on" - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/Destroy() + var/pump_direction = 1 //0 = siphoning, 1 = releasing + + var/external_pressure_bound = ONE_ATMOSPHERE + var/input_pressure_min = 0 + var/output_pressure_max = 0 + + var/pressure_checks = EXT_BOUND + //EXT_BOUND: Do not pass external_pressure_bound + //INPUT_MIN: Do not pass input_pressure_min + //OUTPUT_MAX: Do not pass output_pressure_max + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/on + on = TRUE + icon_state = "dpvent_map_on" + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/Destroy() SSradio.remove_object(src, frequency) - return ..() - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume - name = "large dual-port air vent" - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/on - on = TRUE - icon_state = "dpvent_map_on" - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/New() - ..() - var/datum/gas_mixture/air1 = AIR1 - var/datum/gas_mixture/air2 = AIR2 - air1.volume = 1000 - air2.volume = 1000 - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/update_icon_nopipes() - cut_overlays() - if(showpipe) - add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "dpvent_cap")) - - if(!on || stat & (NOPOWER|BROKEN)) - icon_state = "vent_off" - return - - if(pump_direction) - icon_state = "vent_out" - else - icon_state = "vent_in" - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/process_atmos() - ..() - - if(!on) - return FALSE - var/datum/gas_mixture/air1 = AIR1 - var/datum/gas_mixture/air2 = AIR2 - - var/datum/gas_mixture/environment = loc.return_air() - var/environment_pressure = environment.return_pressure() - - if(pump_direction) //input -> external - var/pressure_delta = 10000 - - if(pressure_checks&EXT_BOUND) - pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) - if(pressure_checks&INPUT_MIN) - pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min)) - - if(pressure_delta > 0) - if(air1.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - //Removed can be null if there is no atmosphere in air1 - if(!removed) - return FALSE - - loc.assume_air(removed) - air_update_turf() - - var/datum/pipeline/parent1 = PARENT1 - parent1.update = 1 - - else //external -> output - var/pressure_delta = 10000 - - if(pressure_checks&EXT_BOUND) - pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) - if(pressure_checks&INPUT_MIN) - pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure())) - - if(pressure_delta > 0) - if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - //removed can be null if there is no air in the location - if(!removed) - return FALSE - - air2.merge(removed) - air_update_turf() - - var/datum/pipeline/parent2 = PARENT2 - parent2.update = 1 - - return TRUE - - //Radio remote control - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA) - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = new - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id, - "device" = "ADVP", - "power" = on, - "direction" = pump_direction?("release"):("siphon"), - "checks" = pressure_checks, - "input" = input_pressure_min, - "output" = output_pressure_max, - "external" = external_pressure_bound, - "sigtype" = "status" - ) - radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) - - return 1 - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit() - ..() - if(frequency) - set_frequency(frequency) - broadcast_status() - -/obj/machinery/atmospherics/components/binary/dp_vent_pump/receive_signal(datum/signal/signal) - - if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) - return 0 - if("power" in signal.data) - on = text2num(signal.data["power"]) - - if("power_toggle" in signal.data) - on = !on - - if("set_direction" in signal.data) - pump_direction = text2num(signal.data["set_direction"]) - - if("checks" in signal.data) - pressure_checks = text2num(signal.data["checks"]) - - if("purge" in signal.data) - pressure_checks &= ~1 - pump_direction = 0 - - if("stabalize" in signal.data) - pressure_checks |= 1 - pump_direction = 1 - - if("set_input_pressure" in signal.data) - input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50) - - if("set_output_pressure" in signal.data) - output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50) - - if("set_external_pressure" in signal.data) - external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50) - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - //if(signal.data["tag"]) - spawn(2) - broadcast_status() - update_icon() - -#undef EXT_BOUND -#undef INPUT_MIN -#undef OUTPUT_MAX + return ..() + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume + name = "large dual-port air vent" + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/on + on = TRUE + icon_state = "dpvent_map_on" + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/New() + ..() + var/datum/gas_mixture/air1 = AIR1 + var/datum/gas_mixture/air2 = AIR2 + air1.volume = 1000 + air2.volume = 1000 + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/update_icon_nopipes() + cut_overlays() + if(showpipe) + add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "dpvent_cap")) + + if(!on || !is_operational()) + icon_state = "vent_off" + return + + if(pump_direction) + icon_state = "vent_out" + else + icon_state = "vent_in" + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/process_atmos() + ..() + + if(!on) + return + var/datum/gas_mixture/air1 = AIR1 + var/datum/gas_mixture/air2 = AIR2 + + var/datum/gas_mixture/environment = loc.return_air() + var/environment_pressure = environment.return_pressure() + + if(pump_direction) //input -> external + var/pressure_delta = 10000 + + if(pressure_checks&EXT_BOUND) + pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) + if(pressure_checks&INPUT_MIN) + pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min)) + + if(pressure_delta > 0) + if(air1.temperature > 0) + var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = air1.remove(transfer_moles) + //Removed can be null if there is no atmosphere in air1 + if(!removed) + return + + loc.assume_air(removed) + air_update_turf() + + var/datum/pipeline/parent1 = PARENT1 + parent1.update = 1 + + else //external -> output + var/pressure_delta = 10000 + + if(pressure_checks&EXT_BOUND) + pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) + if(pressure_checks&INPUT_MIN) + pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure())) + + if(pressure_delta > 0) + if(environment.temperature > 0) + var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) + //removed can be null if there is no air in the location + if(!removed) + return + + air2.merge(removed) + air_update_turf() + + var/datum/pipeline/parent2 = PARENT2 + parent2.update = 1 + + //Radio remote control + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA) + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/broadcast_status() + if(!radio_connection) + return + + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id, + "device" = "ADVP", + "power" = on, + "direction" = pump_direction?("release"):("siphon"), + "checks" = pressure_checks, + "input" = input_pressure_min, + "output" = output_pressure_max, + "external" = external_pressure_bound, + "sigtype" = "status" + ) + radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit() + ..() + if(frequency) + set_frequency(frequency) + broadcast_status() + +/obj/machinery/atmospherics/components/binary/dp_vent_pump/receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) + return + + if("power" in signal.data) + on = text2num(signal.data["power"]) + + if("power_toggle" in signal.data) + on = !on + + if("set_direction" in signal.data) + pump_direction = text2num(signal.data["set_direction"]) + + if("checks" in signal.data) + pressure_checks = text2num(signal.data["checks"]) + + if("purge" in signal.data) + pressure_checks &= ~1 + pump_direction = 0 + + if("stabalize" in signal.data) + pressure_checks |= 1 + pump_direction = 1 + + if("set_input_pressure" in signal.data) + input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50) + + if("set_output_pressure" in signal.data) + output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50) + + if("set_external_pressure" in signal.data) + external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50) + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + //if(signal.data["tag"]) + spawn(2) + broadcast_status() + update_icon() + +#undef EXT_BOUND +#undef INPUT_MIN +#undef OUTPUT_MAX diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm index d2e6a3ae72..158c272543 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm @@ -12,7 +12,7 @@ Passive gate is similar to the regular pump except: name = "passive gate" desc = "A one-way air valve that does not require power." - can_unwrench = 1 + can_unwrench = TRUE var/on = FALSE var/target_pressure = ONE_ATMOSPHERE @@ -36,7 +36,7 @@ Passive gate is similar to the regular pump except: /obj/machinery/atmospherics/components/binary/passive_gate/process_atmos() ..() if(!on) - return 0 + return var/datum/gas_mixture/air1 = AIR1 var/datum/gas_mixture/air2 = AIR2 @@ -47,7 +47,7 @@ Passive gate is similar to the regular pump except: if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10)) //No need to pump gas if target is already reached or input pressure is too low //Need at least 10 KPa difference to overcome friction in the mechanism - return 1 + return //Calculate necessary moles to transfer using PV = nRT if((air1.total_moles() > 0) && (air1.temperature>0)) @@ -73,7 +73,7 @@ Passive gate is similar to the regular pump except: /obj/machinery/atmospherics/components/binary/passive_gate/proc/broadcast_status() if(!radio_connection) - return 0 + return var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -89,8 +89,6 @@ Passive gate is similar to the regular pump except: radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) - return 1 - /obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -137,7 +135,7 @@ Passive gate is similar to the regular pump except: /obj/machinery/atmospherics/components/binary/passive_gate/receive_signal(datum/signal/signal) if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) - return 0 + return var/old_on = on //for logging @@ -159,16 +157,14 @@ Passive gate is similar to the regular pump except: broadcast_status() update_icon() - return /obj/machinery/atmospherics/components/binary/passive_gate/power_change() ..() update_icon() /obj/machinery/atmospherics/components/binary/passive_gate/can_unwrench(mob/user) - if(..()) - if(on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - return 1 + . = ..() + if(. && on) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm index 0ec1b57a2e..c5242fb5cc 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm @@ -17,7 +17,7 @@ Thus, the two variables affect pump operation are set in New(): name = "gas pump" desc = "A pump that moves gas by pressure." - can_unwrench = 1 + can_unwrench = TRUE var/on = FALSE var/target_pressure = ONE_ATMOSPHERE @@ -36,7 +36,7 @@ Thus, the two variables affect pump operation are set in New(): return ..() /obj/machinery/atmospherics/components/binary/pump/update_icon_nopipes() - if(stat & NOPOWER) + if(!is_operational()) icon_state = "pump_off" return @@ -44,10 +44,8 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/pump/process_atmos() // ..() - if(stat & (NOPOWER|BROKEN)) - return 0 - if(!on) - return 0 + if(!on || !is_operational()) + return var/datum/gas_mixture/air1 = AIR1 var/datum/gas_mixture/air2 = AIR2 @@ -56,7 +54,7 @@ Thus, the two variables affect pump operation are set in New(): if((target_pressure - output_starting_pressure) < 0.01) //No need to pump gas if target is already reached! - return 1 + return //Calculate necessary moles to transfer using PV=nRT if((air1.total_moles() > 0) && (air1.temperature>0)) @@ -69,8 +67,6 @@ Thus, the two variables affect pump operation are set in New(): update_parents() - return 1 - //Radio remote control /obj/machinery/atmospherics/components/binary/pump/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) @@ -80,7 +76,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/pump/proc/broadcast_status() if(!radio_connection) - return 0 + return var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -96,8 +92,6 @@ Thus, the two variables affect pump operation are set in New(): radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) - return 1 - /obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -121,8 +115,7 @@ Thus, the two variables affect pump operation are set in New(): if("power") on = !on investigate_log("Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) - message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] manipulated a pump at [x], [y], [z]") + message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]") . = TRUE if("pressure") var/pressure = params["pressure"] @@ -139,8 +132,7 @@ Thus, the two variables affect pump operation are set in New(): if(.) target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE) investigate_log("Pump, [src.name], was set to [target_pressure] kPa by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) - message_admins("Pump, [src.name], was set to [target_pressure] kPa by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] manipulated a pump at [x], [y], [z]") + message_admins("Pump, [src.name], was set to [target_pressure] kPa by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]") update_icon() /obj/machinery/atmospherics/components/binary/pump/atmosinit() @@ -150,7 +142,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/pump/receive_signal(datum/signal/signal) if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) - return 0 + return var/old_on = on //for logging @@ -172,21 +164,18 @@ Thus, the two variables affect pump operation are set in New(): broadcast_status() update_icon() - return /obj/machinery/atmospherics/components/binary/pump/power_change() ..() update_icon() /obj/machinery/atmospherics/components/binary/pump/can_unwrench(mob/user) - if(..()) - var/turf/T = get_turf(src) - var/area/A = get_area(src) - if(!(stat & NOPOWER) && on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - investigate_log("Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) - message_admins("Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] unwrenched a pump at [x], [y], [z]") - return 1 - + . = ..() + var/area/A = get_area(src) + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE + else + investigate_log("Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) + message_admins("Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(user)] at [A]") + return TRUE diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm index bbee3bcb59..7ef6cf2142 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm @@ -7,7 +7,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off. name = "manual valve" desc = "A pipe valve" - can_unwrench = 1 + can_unwrench = TRUE var/frequency = 0 var/id = null @@ -57,8 +57,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off. var/turf/T = get_turf(src) var/area/A = get_area(src) investigate_log("Valve, [src.name], was manipiulated by [key_name(usr)] at [x], [y], [z], [A]", "atmos") - message_admins("Valve, [src.name], was manipulated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] manipulated a manual valve at [x], [y], [z]") + message_admins("Valve, [src.name], was manipulated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)], [A]") /obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI @@ -71,7 +70,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off. return src.attack_hand(user) /obj/machinery/atmospherics/components/binary/valve/digital/update_icon_nopipes(animation) - if(stat & NOPOWER) + if(!is_operational()) normalize_dir() icon_state = "dvalve_nopower" return diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm index 4d3cf733fb..227c34d9ca 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm @@ -17,7 +17,7 @@ Thus, the two variables affect pump operation are set in New(): name = "volumetric gas pump" desc = "A pump that moves gas by volume." - can_unwrench = 1 + can_unwrench = TRUE var/on = FALSE var/transfer_rate = MAX_TRANSFER_RATE @@ -34,7 +34,7 @@ Thus, the two variables affect pump operation are set in New(): on = TRUE /obj/machinery/atmospherics/components/binary/volume_pump/update_icon_nopipes() - if(stat & NOPOWER) + if(!is_operational()) icon_state = "volpump_off" return @@ -42,10 +42,8 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/volume_pump/process_atmos() // ..() - if(stat & (NOPOWER|BROKEN)) + if(!on || !is_operational()) return - if(!on) - return 0 var/datum/gas_mixture/air1 = AIR1 var/datum/gas_mixture/air2 = AIR2 @@ -56,7 +54,7 @@ Thus, the two variables affect pump operation are set in New(): var/output_starting_pressure = air2.return_pressure() if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000)) - return 1 + return var/transfer_ratio = min(1, transfer_rate/air1.volume) @@ -66,8 +64,6 @@ Thus, the two variables affect pump operation are set in New(): update_parents() - return 1 - /obj/machinery/atmospherics/components/binary/volume_pump/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency @@ -76,7 +72,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/components/binary/volume_pump/proc/broadcast_status() if(!radio_connection) - return 0 + return var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -91,8 +87,6 @@ Thus, the two variables affect pump operation are set in New(): ) radio_connection.post_signal(src, signal) - return 1 - /obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -116,14 +110,12 @@ Thus, the two variables affect pump operation are set in New(): if(..()) return var/turf/T = get_turf(src) - //var/area/A = get_area(src) + var/area/A = get_area(src) switch(action) if("power") on = !on - investigate_log("Volume Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS) - message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]") - + investigate_log("Volume Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) + message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]") . = TRUE if("rate") var/rate = params["rate"] @@ -139,14 +131,13 @@ Thus, the two variables affect pump operation are set in New(): . = TRUE if(.) transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE) - investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS) - message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]") + investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) + message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]") update_icon() /obj/machinery/atmospherics/components/binary/volume_pump/receive_signal(datum/signal/signal) if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) - return 0 + return var/old_on = on //for logging @@ -169,22 +160,18 @@ Thus, the two variables affect pump operation are set in New(): broadcast_status() update_icon() - return /obj/machinery/atmospherics/components/binary/volume_pump/power_change() ..() update_icon() /obj/machinery/atmospherics/components/binary/volume_pump/can_unwrench(mob/user) - if(..()) - var/turf/T = get_turf(src) - //var/area/A = get_area(src) - if(!(stat & NOPOWER) && on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - investigate_log("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS) - message_admins("Volume Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]") - log_admin("[key_name(usr)] unwrenched a volume pump at [x], [y], [z]") - - return 1 - + . = ..() + var/area/A = get_area(src) + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE + else + investigate_log("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS) + message_admins("Volume Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(usr)] at [A]") + return diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index 87edfe8d11..c777e5fe17 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -2,7 +2,7 @@ name = "gas filter" icon_state = "filter_off" density = FALSE - can_unwrench = 1 + can_unwrench = TRUE var/on = FALSE var/target_pressure = ONE_ATMOSPHERE var/filter_type = "" @@ -11,7 +11,7 @@ /obj/machinery/atmospherics/components/trinary/filter/flipped icon_state = "filter_off_f" - flipped = 1 + flipped = TRUE // These two filter types have critical_machine flagged to on and thus causes the area they are in to be exempt from the Grid Check event. @@ -43,27 +43,21 @@ ..() /obj/machinery/atmospherics/components/trinary/filter/update_icon_nopipes() - - if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3) + if(on && NODE1 && NODE2 && NODE3 && is_operational()) icon_state = "filter_on[flipped?"_f":""]" return - icon_state = "filter_off[flipped?"_f":""]" /obj/machinery/atmospherics/components/trinary/filter/power_change() var/old_stat = stat ..() - if(stat & NOPOWER) - on = FALSE - if(old_stat != stat) + if(stat != old_stat) update_icon() /obj/machinery/atmospherics/components/trinary/filter/process_atmos() ..() - if(!on) - return 0 - if(!(NODE1 && NODE2 && NODE3)) - return 0 + if(!on || !(NODE1 && NODE2 && NODE3) || !is_operational()) + return var/datum/gas_mixture/air1 = AIR1 var/datum/gas_mixture/air2 = AIR2 @@ -73,7 +67,7 @@ if(output_starting_pressure >= target_pressure) //No need to mix if target is already full! - return 1 + return //Calculate necessary moles to transfer using PV=nRT @@ -113,8 +107,6 @@ update_parents() - return 1 - /obj/machinery/atmospherics/components/trinary/filter/atmosinit() set_frequency(frequency) return ..() @@ -167,3 +159,10 @@ investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS) . = TRUE update_icon() + +/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user) + . = ..() + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE + diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm index 8c2622bb42..cb515ec75f 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm @@ -3,7 +3,7 @@ density = FALSE name = "gas mixer" - can_unwrench = 1 + can_unwrench = TRUE var/on = FALSE @@ -15,7 +15,7 @@ /obj/machinery/atmospherics/components/trinary/mixer/flipped icon_state = "mixer_off_f" - flipped = 1 + flipped = TRUE /obj/machinery/atmospherics/components/trinary/mixer/update_icon() cut_overlays() @@ -29,18 +29,15 @@ return ..() /obj/machinery/atmospherics/components/trinary/mixer/update_icon_nopipes() - if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3) + if(on && NODE1 && NODE2 && NODE3 && is_operational()) icon_state = "mixer_on[flipped?"_f":""]" return - icon_state = "mixer_off[flipped?"_f":""]" /obj/machinery/atmospherics/components/trinary/mixer/power_change() var/old_stat = stat ..() - if(stat & NOPOWER) - on = FALSE - if(old_stat != stat) + if(stat != old_stat) update_icon() /obj/machinery/atmospherics/components/trinary/mixer/New() @@ -51,10 +48,8 @@ /obj/machinery/atmospherics/components/trinary/mixer/process_atmos() ..() - if(!on) - return 0 - if(!(NODE1 && NODE2 && NODE3)) - return 0 + if(!on || !(NODE1 && NODE2 && NODE3) && !is_operational()) + return var/datum/gas_mixture/air1 = AIR1 var/datum/gas_mixture/air2 = AIR2 @@ -64,7 +59,7 @@ if(output_starting_pressure >= target_pressure) //No need to mix if target is already full! - return 1 + return //Calculate necessary moles to transfer using PV=nRT @@ -114,7 +109,7 @@ var/datum/pipeline/parent3 = PARENT3 parent3.update = TRUE - return TRUE + return /obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) @@ -167,4 +162,12 @@ node1_concentration = max(0, min(1, node1_concentration - value)) investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", INVESTIGATE_ATMOS) . = TRUE - update_icon() \ No newline at end of file + update_icon() + + +/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user) + . = ..() + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE + diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm b/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm index 199d1907d8..14495cd237 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/trinary_devices.dm @@ -6,7 +6,7 @@ device_type = TRINARY layer = GAS_FILTER_LAYER - var/flipped = 0 + var/flipped = FALSE /obj/machinery/atmospherics/components/trinary/SetInitDirections() switch(dir) @@ -44,4 +44,4 @@ Housekeeping and pipe network stuff node1_connect = turn(node1_connect, 180) node3_connect = turn(node3_connect, 180) - return list(node1_connect, node2_connect, node3_connect) \ No newline at end of file + return list(node1_connect, node2_connect, node3_connect) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 4583680d13..2e0d1f3805 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -115,7 +115,7 @@ occupant_overlay.dir = SOUTH occupant_overlay.pixel_y = 22 - if(on && is_operational() && !running_bob_anim) + if(on && !running_bob_anim && is_operational()) icon_state = "pod-on" running_bob_anim = TRUE run_bob_anim(TRUE, occupant_overlay) @@ -349,7 +349,7 @@ data["cellTemperature"] = round(air1.temperature, 1) data["isBeakerLoaded"] = beaker ? TRUE : FALSE - var beakerContents = list() + var/beakerContents = list() if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) for(var/datum/reagent/R in beaker.reagents.reagent_list) beakerContents += list(list("name" = R.name, "volume" = R.volume)) @@ -378,6 +378,8 @@ if("ejectbeaker") if(beaker) beaker.forceMove(loc) + if(Adjacent(usr) && !issilicon(usr)) + usr.put_in_hands(beaker) beaker = null . = TRUE update_icon() @@ -394,4 +396,11 @@ /obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes() return 0 //you can't see the pipe network when inside a cryo cell. +/obj/machinery/atmospherics/components/unary/cryo_cell/return_temperature() + var/datum/gas_mixture/G = AIR1 + + if(G.total_moles() > 10) + return G.temperature + return ..() + #undef CRYOMOBS diff --git a/code/modules/atmospherics/machinery/components/unary_devices/generator_input.dm b/code/modules/atmospherics/machinery/components/unary_devices/generator_input.dm index 5ed771d41c..a1a67e2542 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/generator_input.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/generator_input.dm @@ -10,12 +10,7 @@ var/update_cycle /obj/machinery/atmospherics/components/unary/generator_input/update_icon() - if(NODE1) - icon_state = "intact" - else - icon_state = "exposed" - - return + icon_state = NODE1 ? "intact" : "exposed" /obj/machinery/atmospherics/components/unary/generator_input/proc/return_exchange_air() return AIR1 diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm index 30ff1ebc30..ee6e31175b 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm @@ -5,7 +5,7 @@ name = "heat exchanger" desc = "Exchanges heat between two input gases. Setup for fast heat transfer" - can_unwrench = 1 + can_unwrench = TRUE layer = LOW_OBJ_LAYER @@ -20,8 +20,6 @@ else icon_state = "he_exposed" - return - /obj/machinery/atmospherics/components/unary/heat_exchanger/atmosinit() if(!partner) var/partner_connect = turn(dir,180) @@ -36,11 +34,8 @@ /obj/machinery/atmospherics/components/unary/heat_exchanger/process_atmos() ..() - if(!partner) - return 0 - - if(SSair.times_fired <= update_cycle) - return 0 + if(!partner || SSair.times_fired <= update_cycle) + return update_cycle = SSair.times_fired partner.update_cycle = SSair.times_fired @@ -67,5 +62,3 @@ if(abs(other_old_temperature-partner_air_contents.temperature) > 1) partner.update_parents() - - return 1 diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm index 0bf467f234..d46d5b47a0 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -30,7 +30,7 @@ if(showpipe) add_overlay(getpipeimage(icon, "inje_cap", initialize_directions)) - if(!NODE1 || !on || stat & (NOPOWER|BROKEN)) + if(!NODE1 || !on || !is_operational()) icon_state = "inje_off" return @@ -47,8 +47,8 @@ ..() injecting = 0 - if(!on || stat & (NOPOWER|BROKEN)) - return 0 + if(!on || !is_operational()) + return var/datum/gas_mixture/air_contents = AIR1 @@ -62,11 +62,9 @@ update_parents() - return 1 - /obj/machinery/atmospherics/components/unary/outlet_injector/proc/inject() - if(on || injecting || stat & (NOPOWER|BROKEN)) - return 0 + if(on || injecting || !is_operational()) + return var/datum/gas_mixture/air_contents = AIR1 @@ -91,7 +89,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector/proc/broadcast_status() if(!radio_connection) - return 0 + return var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -108,8 +106,6 @@ radio_connection.post_signal(src, signal) - return 1 - /obj/machinery/atmospherics/components/unary/outlet_injector/atmosinit() set_frequency(frequency) broadcast_status() @@ -117,7 +113,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector/receive_signal(datum/signal/signal) if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) - return 0 + return if("power" in signal.data) on = text2num(signal.data["power"]) @@ -139,8 +135,6 @@ broadcast_status() return //do not update_icon - //log_admin("DEBUG \[[world.timeofday]\]: outlet_injector/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") - //return spawn(2) broadcast_status() update_icon() @@ -188,9 +182,8 @@ broadcast_status() /obj/machinery/atmospherics/components/unary/outlet_injector/can_unwrench(mob/user) - if(..()) - if (!(stat & NOPOWER|BROKEN) && on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - return 1 + . = ..() + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/oxygen_generator.dm b/code/modules/atmospherics/machinery/components/unary_devices/oxygen_generator.dm index 65f2c37ac7..e31d1efa96 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/oxygen_generator.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/oxygen_generator.dm @@ -19,7 +19,7 @@ if(showpipe) add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions)) //it works for now - if(!NODE1 || !on || stat & BROKEN) + if(!NODE1 || !on || !is_operational()) icon_state = "o2gen_off" return diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index 7dd6d62314..e17a2f796c 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -3,7 +3,7 @@ desc = "For connecting portables devices related to atmospherics control." icon = 'icons/obj/atmospherics/components/unary_devices.dmi' icon_state = "connector_map" //Only for mapping purposes, so mappers can see direction - can_unwrench = 1 + can_unwrench = TRUE var/obj/machinery/portable_atmospherics/connected_device use_power = NO_POWER_USE level = 0 @@ -29,11 +29,10 @@ return ..() /obj/machinery/atmospherics/components/unary/portables_connector/can_unwrench(mob/user) - if(..()) - if(connected_device) - to_chat(user, "You cannot unwrench [src], detach [connected_device] first!") - else - return 1 + . = ..() + if(. && connected_device) + to_chat(user, "You cannot unwrench [src], detach [connected_device] first!") + return FALSE /obj/machinery/atmospherics/components/unary/portables_connector/portableConnectorReturnAir() return connected_device.portableConnectorReturnAir() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 6ea8b717bf..17fa3b2cdf 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -39,7 +39,6 @@ icon_state = icon_state_on else icon_state = initial(icon_state) - return /obj/machinery/atmospherics/components/unary/thermomachine/update_icon_nopipes() cut_overlays() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index f52d2d9b2b..df44b4ca9e 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -10,7 +10,7 @@ desc = "Has a valve and pump attached to it." icon_state = "vent_map" use_power = IDLE_POWER_USE - can_unwrench = 1 + can_unwrench = TRUE welded = FALSE level = 1 layer = GAS_SCRUBBER_LAYER @@ -92,7 +92,7 @@ icon_state = "vent_welded" return - if(!NODE1 || !on || stat & (NOPOWER|BROKEN)) + if(!NODE1 || !on || !is_operational()) icon_state = "vent_off" return @@ -103,12 +103,12 @@ /obj/machinery/atmospherics/components/unary/vent_pump/process_atmos() ..() - if(stat & (NOPOWER|BROKEN)) + if(!is_operational()) return - if (!NODE1) + if(!NODE1) on = FALSE if(!on || welded) - return 0 + return var/datum/gas_mixture/air_contents = AIR1 var/datum/gas_mixture/environment = loc.return_air() @@ -150,8 +150,6 @@ air_update_turf() update_parents() - return 1 - //Radio remote control /obj/machinery/atmospherics/components/unary/vent_pump/proc/set_frequency(new_frequency) @@ -162,7 +160,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/proc/broadcast_status() if(!radio_connection) - return 0 + return var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -189,8 +187,6 @@ radio_connection.post_signal(src, signal, radio_filter_out) - return 1 - /obj/machinery/atmospherics/components/unary/vent_pump/atmosinit() //some vents work his own spesial way @@ -202,11 +198,11 @@ ..() /obj/machinery/atmospherics/components/unary/vent_pump/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) + if(!is_operational()) return //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/components/unary/vent_pump/receive_signal([signal.debug_print()])") if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) - return 0 + return if("purge" in signal.data) pressure_checks &= ~EXT_BOUND @@ -257,7 +253,6 @@ //log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") broadcast_status() update_icon() - return /obj/machinery/atmospherics/components/unary/vent_pump/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/weldingtool)) @@ -266,7 +261,8 @@ playsound(loc, WT.usesound, 40, 1) to_chat(user, "You begin welding the vent...") if(do_after(user, 20*W.toolspeed, target = src)) - if(!src || !WT.isOn()) return + if(!src || !WT.isOn()) + return playsound(src.loc, 'sound/items/welder2.ogg', 50, 1) if(!welded) user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.") @@ -282,11 +278,10 @@ return ..() /obj/machinery/atmospherics/components/unary/vent_pump/can_unwrench(mob/user) - if(..()) - if(!(stat & NOPOWER) && on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - return 1 + . = ..() + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE /obj/machinery/atmospherics/components/unary/vent_pump/examine(mob/user) ..() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 095473c32c..d92b061cec 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -8,7 +8,7 @@ use_power = IDLE_POWER_USE idle_power_usage = 10 active_power_usage = 60 - can_unwrench = 1 + can_unwrench = TRUE welded = FALSE level = 1 layer = GAS_SCRUBBER_LAYER @@ -17,12 +17,12 @@ var/on = FALSE var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing - var/scrub_CO2 = 1 - var/scrub_Toxins = 0 - var/scrub_N2O = 0 - var/scrub_BZ = 0 - var/scrub_Freon = 0 - var/scrub_WaterVapor = 0 + var/scrub_CO2 = TRUE + var/scrub_Toxins = FALSE + var/scrub_N2O = FALSE + var/scrub_BZ = FALSE + var/scrub_Freon = FALSE + var/scrub_WaterVapor = FALSE var/volume_rate = 200 @@ -58,12 +58,8 @@ return ..() /obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power() - if(!powered(power_channel)) - return 0 - if(!on || welded) - return 0 - if(stat & (NOPOWER|BROKEN)) - return 0 + if(!on || welded || !is_operational() || !powered(power_channel)) + return FALSE var/amount = idle_power_usage @@ -86,7 +82,7 @@ if(widenet) amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2)) use_power(amount, power_channel) - return 1 + return TRUE /obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes() cut_overlays() @@ -97,7 +93,7 @@ icon_state = "scrub_welded" return - if(!NODE1 || !on || stat & (NOPOWER|BROKEN)) + if(!NODE1 || !on || !is_operational()) icon_state = "scrub_off" return @@ -113,7 +109,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status() if(!radio_connection) - return 0 + return FALSE var/datum/signal/signal = new signal.transmission_method = 1 //radio signal @@ -143,7 +139,7 @@ radio_connection.post_signal(src, signal, radio_filter_out) - return 1 + return TRUE /obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit() radio_filter_in = frequency==initial(frequency)?(GLOB.RADIO_FROM_AIRALARM):null @@ -156,20 +152,21 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos() ..() - if(stat & (NOPOWER|BROKEN)) - return - if (!NODE1) + if(!is_operational()) + return FALSE + if(!NODE1) on = FALSE if(!on || welded) - return 0 + return FALSE scrub(loc) if(widenet) - for (var/turf/tile in adjacent_turfs) + for(var/turf/tile in adjacent_turfs) scrub(tile) + return TRUE /obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile) - if (!istype(tile)) - return 0 + if(!istype(tile)) + return FALSE var/datum/gas_mixture/environment = tile.return_air() var/datum/gas_mixture/air_contents = AIR1 @@ -189,8 +186,8 @@ //Take a gas sample var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) //Nothing left to remove from the tile - if (isnull(removed)) - return + if(isnull(removed)) + return FALSE var/list/removed_gases = removed.gases //Filter it @@ -199,39 +196,39 @@ filtered_out.temperature = removed.temperature if(scrub_Toxins && removed_gases["plasma"]) - filtered_out.assert_gas("plasma") + filtered_out.add_gas("plasma") filtered_gases["plasma"][MOLES] = removed_gases["plasma"][MOLES] removed.gases["plasma"][MOLES] = 0 if(scrub_CO2 && removed_gases["co2"]) - filtered_out.assert_gas("co2") - filtered_out.gases["co2"][MOLES] = removed_gases["co2"][MOLES] - removed.gases["co2"][MOLES] = 0 + filtered_out.add_gas("co2") + filtered_gases["co2"][MOLES] = removed_gases["co2"][MOLES] + removed_gases["co2"][MOLES] = 0 if(removed_gases["agent_b"]) - filtered_out.assert_gas("agent_b") - filtered_out.gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES] - removed.gases["agent_b"][MOLES] = 0 + filtered_out.add_gas("agent_b") + filtered_gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES] + removed_gases["agent_b"][MOLES] = 0 if(scrub_N2O && removed_gases["n2o"]) - filtered_out.assert_gas("n2o") - filtered_out.gases["n2o"][MOLES] = removed_gases["n2o"][MOLES] - removed.gases["n2o"][MOLES] = 0 + filtered_out.add_gas("n2o") + filtered_gases["n2o"][MOLES] = removed_gases["n2o"][MOLES] + removed_gases["n2o"][MOLES] = 0 if(scrub_BZ && removed_gases["bz"]) - filtered_out.assert_gas("bz") - filtered_out.gases["bz"][MOLES] = removed_gases["bz"][MOLES] - removed.gases["bz"][MOLES] = 0 + filtered_out.add_gas("bz") + filtered_gases["bz"][MOLES] = removed_gases["bz"][MOLES] + removed_gases["bz"][MOLES] = 0 if(scrub_Freon && removed_gases["freon"]) - filtered_out.assert_gas("freon") - filtered_out.gases["freon"][MOLES] = removed_gases["freon"][MOLES] - removed.gases["freon"][MOLES] = 0 + filtered_out.add_gas("freon") + filtered_gases["freon"][MOLES] = removed_gases["freon"][MOLES] + removed_gases["freon"][MOLES] = 0 if(scrub_WaterVapor && removed_gases["water_vapor"]) - filtered_out.assert_gas("water_vapor") - filtered_out.gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES] - removed.gases["water_vapor"][MOLES] = 0 + filtered_out.add_gas("water_vapor") + filtered_gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES] + removed_gases["water_vapor"][MOLES] = 0 removed.garbage_collect() @@ -242,8 +239,8 @@ tile.air_update_turf() else //Just siphoning all air - if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE) - return + if(air_contents.return_pressure()>=50*ONE_ATMOSPHERE) + return FALSE var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) @@ -254,7 +251,7 @@ update_parents() - return 1 + return TRUE //There is no easy way for an object to be notified of changes to atmos can pass flags_1 @@ -273,7 +270,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) + if(!is_operational()) return if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) return 0 @@ -363,11 +360,10 @@ return ..() /obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user) - if(..()) - if (!(stat & NOPOWER) && on) - to_chat(user, "You cannot unwrench [src], turn it off first!") - else - return 1 + . = ..() + if(. && on && is_operational()) + to_chat(user, "You cannot unwrench [src], turn it off first!") + return FALSE /obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through() return !welded diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 67b1d0d569..11a7881a98 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -5,7 +5,7 @@ var/list/obj/machinery/atmospherics/pipe/members var/list/obj/machinery/atmospherics/components/other_atmosmch - var/update = 1 + var/update = TRUE /datum/pipeline/New() other_airs = list() @@ -25,7 +25,7 @@ /datum/pipeline/process() if(update) - update = 0 + update = FALSE reconcile_air() update = air.react() @@ -114,6 +114,7 @@ other_airs.Add(E.other_airs) E.members.Cut() E.other_atmosmch.Cut() + update = TRUE qdel(E) /obj/machinery/atmospherics/proc/addMember(obj/machinery/atmospherics/A) @@ -195,7 +196,7 @@ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) air.temperature -= heat/total_heat_capacity - update = 1 + update = TRUE /datum/pipeline/proc/return_air() . = other_airs + air diff --git a/code/modules/awaymissions/super_secret_room.dm b/code/modules/awaymissions/super_secret_room.dm index 5d26e34054..fa9aff7f43 100644 --- a/code/modules/awaymissions/super_secret_room.dm +++ b/code/modules/awaymissions/super_secret_room.dm @@ -9,10 +9,13 @@ var/times_spoken_to = 0 var/list/shenanigans = list() -/obj/structure/speaking_tile/New() - var/savefile/S = new /savefile("data/npc_saves/Poly.sav") - S["phrases"] >> shenanigans - ..() +/obj/structure/speaking_tile/Initialize() + . = ..() + var/json_file = file("data/npc_saves/Poly.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + shenanigans = json["phrases"] /obj/structure/speaking_tile/interact(mob/user) if(!isliving(user) || speaking) @@ -118,4 +121,4 @@ ..() /obj/effect/landmark/error - name = "error" + name = "error" \ No newline at end of file diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index ba536acdac..c5b180d8a1 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -1643,7 +1643,11 @@ /obj/item/toy/talking/griffin, /obj/item/toy/nuke, /obj/item/toy/minimeteor, - /obj/item/toy/carpplushie, + /obj/item/toy/plush/carpplushie, + /obj/item/toy/plush/lizardplushie, + /obj/item/toy/plush/snakeplushie, + /obj/item/toy/plush/nukeplushie, + /obj/item/toy/plush/slimeplushie, /obj/item/coin/antagtoken, /obj/item/stack/tile/fakespace/loaded, /obj/item/gun/ballistic/shotgun/toy/crossbow, diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm index e10f089eb8..bf3a1f28e0 100644 --- a/code/modules/clothing/shoes/bananashoes.dm +++ b/code/modules/clothing/shoes/bananashoes.dm @@ -5,59 +5,39 @@ desc = "Lost prototype of advanced clown tech. Powered by bananium, these shoes leave a trail of chaos in their wake." icon_state = "clown_prototype_off" var/on = FALSE - var/datum/material_container/bananium actions_types = list(/datum/action/item_action/toggle) -/obj/item/clothing/shoes/clown_shoes/banana_shoes/New() - ..() - bananium = new/datum/material_container(src,list(MAT_BANANIUM),200000) +/obj/item/clothing/shoes/clown_shoes/banana_shoes/Initialize() + . = ..() + AddComponent(/datum/component/material_container, list(MAT_BANANIUM), 200000, TRUE) + AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 75) /obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action() + . = ..() if(on) - if(footstep > 1)//honks when its on - playsound(src, 'sound/items/bikehorn.ogg', 75, 1) - footstep = 0 - else - footstep++ - new/obj/item/grown/bananapeel/specialpeel(get_step(src,turn(usr.dir, 180))) //honk + GET_COMPONENT(bananium, /datum/component/material_container) bananium.use_amount_type(100, MAT_BANANIUM) if(bananium.amount(MAT_BANANIUM) < 100) on = !on flags_1 &= ~NOSLIP_1 update_icon() to_chat(loc, "You ran out of bananium!") - else - ..() /obj/item/clothing/shoes/clown_shoes/banana_shoes/attack_self(mob/user) + GET_COMPONENT(bananium, /datum/component/material_container) var/sheet_amount = bananium.retrieve_all() if(sheet_amount) to_chat(user, "You retrieve [sheet_amount] sheets of bananium from the prototype shoes.") else to_chat(user, "You cannot retrieve any bananium from the prototype shoes.") -/obj/item/clothing/shoes/clown_shoes/banana_shoes/attackby(obj/item/O, mob/user, params) - if(!bananium.get_item_material_amount(O)) - to_chat(user, "This item has no bananium!") - return - if(!user.dropItemToGround(O)) - to_chat(user, "You can't drop [O]!") - return - - var/bananium_amount = bananium.insert_item(O) - if(bananium_amount) - to_chat(user, "You insert [O] into the prototype shoes.") - qdel(O) - else - to_chat(user, "You are unable to insert more bananium!") - /obj/item/clothing/shoes/clown_shoes/banana_shoes/examine(mob/user) ..() - var/ban_amt = bananium.amount(MAT_BANANIUM) - to_chat(user, "The shoes are [on ? "enabled" : "disabled"]. There is [ban_amt ? ban_amt : "no"] bananium left.") + to_chat(user, "The shoes are [on ? "enabled" : "disabled"]") /obj/item/clothing/shoes/clown_shoes/banana_shoes/ui_action_click(mob/user) + GET_COMPONENT(bananium, /datum/component/material_container) if(bananium.amount(MAT_BANANIUM)) on = !on update_icon() diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index c0ac24c1cc..081362ee9d 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -1,4 +1,5 @@ /obj/item/clothing/shoes/proc/step_action() //this was made to rewrite clown shoes squeaking + SendSignal(COMSIG_SHOES_STEP_ACTION) /obj/item/clothing/shoes/suicide_act(mob/user) user.visible_message("[user] is bashing [user.p_their()] own head in with [src]! Ain't that a kick in the head?") @@ -79,15 +80,11 @@ item_state = "clown_shoes" slowdown = SHOES_SLOWDOWN+1 item_color = "clown" - var/footstep = 1 //used for squeeks whilst walking pockets = /obj/item/storage/internal/pocket/shoes/clown -/obj/item/clothing/shoes/clown_shoes/step_action() - if(footstep > 1) - playsound(src, "clownstep", 50, 1) - footstep = 0 - else - footstep++ +/obj/item/clothing/shoes/clown_shoes/Initialize() + . = ..() + AddComponent(/datum/component/squeak, list('sound/effects/clownstep1.ogg'=1,'sound/effects/clownstep2.ogg'=1), 50) /obj/item/clothing/shoes/clown_shoes/jester name = "jester shoes" diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 217644c4ae..65a78d0ef0 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -204,9 +204,9 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON -/datum/crafting_recipe/meteorshot - name = "Meteorshot Shell" - result = /obj/item/ammo_casing/shotgun/meteorshot +/datum/crafting_recipe/meteorslug + name = "Meteorslug Shell" + result = /obj/item/ammo_casing/shotgun/meteorslug reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /obj/item/rcd_ammo = 1, /obj/item/stock_parts/manipulator = 2) @@ -228,7 +228,7 @@ /datum/crafting_recipe/dragonsbreath name = "Dragonsbreath Shell" - result = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath + result = /obj/item/ammo_casing/shotgun/dragonsbreath reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /datum/reagent/phosphorus = 5) tools = list(/obj/item/screwdriver) time = 5 @@ -270,17 +270,6 @@ category = CAT_WEAPONRY subcategory = CAT_AMMO -/datum/crafting_recipe/improvisedslugoverload - name = "Overload Improvised Shell" - result = /obj/item/ammo_casing/shotgun/improvised/overload - reqs = list(/obj/item/ammo_casing/shotgun/improvised = 1, - /datum/reagent/blackpowder = 10, - /datum/reagent/toxin/plasma = 20) - tools = list(/obj/item/screwdriver) - time = 5 - category = CAT_WEAPONRY - subcategory = CAT_AMMO - /datum/crafting_recipe/laserslug name = "Laser Slug Shell" result = /obj/item/ammo_casing/shotgun/laserslug diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index c5a9c1a142..bc2b3c2666 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -88,7 +88,7 @@ ..() if(FESTIVE_SEASON in SSevents.holidays) new tree(get_turf(src)) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/xmastree/rdrod name = "festivus pole spawner" diff --git a/code/modules/events/wizard/magicarp.dm b/code/modules/events/wizard/magicarp.dm index 3d0461d3cf..cc632d9c87 100644 --- a/code/modules/events/wizard/magicarp.dm +++ b/code/modules/events/wizard/magicarp.dm @@ -43,7 +43,7 @@ /mob/living/simple_animal/hostile/carp/ranged/Initialize() projectiletype = pick(allowed_projectile_types) - ..() + . = ..() /mob/living/simple_animal/hostile/carp/ranged/chaos name = "chaos magicarp" diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm index 2415f08d6d..71ff26a17e 100644 --- a/code/modules/holiday/easter.dm +++ b/code/modules/holiday/easter.dm @@ -126,7 +126,7 @@ /obj/item/toy/foamblade, /obj/item/toy/prize/ripley, /obj/item/toy/prize/honk, - /obj/item/toy/carpplushie, + /obj/item/toy/plush/carpplushie, /obj/item/toy/redbutton, /obj/item/clothing/head/collectable/rabbitears) new won(where) diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm index b8fe3e777a..c8e9235646 100644 --- a/code/modules/holiday/holidays.dm +++ b/code/modules/holiday/holidays.dm @@ -485,7 +485,6 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and begin_day += 31 begin_month-- //begins in march, ends in april -// to_chat(world, "Easter calculates to be on [begin_day] of [begin_month] ([days_early] early) to [end_day] of [end_month] ([days_extra] extra) for 20[yy]") return ..() /datum/holiday/easter/celebrate() diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 11eca212ae..17d626b3a0 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -14,8 +14,8 @@ name = "bookcase" icon = 'icons/obj/library.dmi' icon_state = "bookempty" - anchored = FALSE - density = TRUE + anchored = FALSE + density = TRUE opacity = 0 resistance_flags = FLAMMABLE max_integrity = 200 @@ -25,12 +25,12 @@ /obj/structure/bookcase/Initialize(mapload) - ..() + . = ..() if(!mapload) return state = 2 icon_state = "book-0" - anchored = TRUE + anchored = TRUE for(var/obj/item/I in loc) if(istype(I, /obj/item/book)) I.loc = src @@ -44,7 +44,7 @@ playsound(loc, I.usesound, 100, 1) if(do_after(user, 20*I.toolspeed, target = src)) to_chat(user, "You wrench the frame into place.") - anchored = TRUE + anchored = TRUE state = 1 if(istype(I, /obj/item/crowbar)) playsound(loc, I.usesound, 100, 1) @@ -63,7 +63,7 @@ if(istype(I, /obj/item/wrench)) playsound(loc, I.usesound, 100, 1) to_chat(user, "You unwrench the frame.") - anchored = FALSE + anchored = FALSE state = 0 if(2) @@ -317,4 +317,4 @@ to_chat(user, "Computer has been associated with this unit.") else to_chat(user, "No associated computer found. Only local scans will function properly.") - to_chat(user, "\n") + to_chat(user, "\n") \ No newline at end of file diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm index 3c44dc28ea..769c9ac66b 100644 --- a/code/modules/library/random_books.dm +++ b/code/modules/library/random_books.dm @@ -1,18 +1,18 @@ /obj/item/book/manual/random/Initialize() - . = ..() + ..() var/static/banned_books = list(/obj/item/book/manual/random, /obj/item/book/manual/nuclear, /obj/item/book/manual/wiki) var/newtype = pick(subtypesof(/obj/item/book/manual) - banned_books) new newtype(loc) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/item/book/random var/amount = 1 var/category = null /obj/item/book/random/Initialize() - . = ..() + ..() create_random_books(amount, src.loc, TRUE, category) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/item/book/random/triple amount = 3 diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 10512aa5a2..4db42b6933 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -83,7 +83,7 @@ new /obj/item/clothing/suit/hooded/ian_costume(src) if(67 to 68) for(var/i in 1 to rand(4, 7)) - var /newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace) + var/newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace) new newitem(src) if(69 to 70) for(var/i in 1 to 5) diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 8428036860..0927a0ba88 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -66,7 +66,6 @@ density = TRUE anchored = TRUE var/obj/machinery/mineral/CONSOLE = null - var/datum/material_container/materials var/on = FALSE var/selected_material = MAT_METAL var/selected_alloy = null @@ -75,12 +74,11 @@ /obj/machinery/mineral/processing_unit/Initialize() . = ..() proximity_monitor = new(src, 1) - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), INFINITY) files = new /datum/research/smelter(src) /obj/machinery/mineral/processing_unit/Destroy() CONSOLE = null - QDEL_NULL(materials) QDEL_NULL(files) return ..() @@ -89,6 +87,7 @@ process_ore(AM) /obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/ore/O) + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!materials.has_space(material_amount)) unload_mineral(O) @@ -100,6 +99,7 @@ /obj/machinery/mineral/processing_unit/proc/get_machine_data() var/dat = "Smelter control console

" + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] dat += "[M.name]: [M.amount] cm³" @@ -165,6 +165,7 @@ continue*/ /obj/machinery/mineral/processing_unit/proc/smelt_ore() + GET_COMPONENT(materials, /datum/component/material_container) var/datum/material/mat = materials.materials[selected_material] if(mat) var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT) @@ -187,6 +188,7 @@ on = FALSE return + GET_COMPONENT(materials, /datum/component/material_container) materials.use_amount(alloy.materials, amount) generate_mineral(alloy.build_path) @@ -197,6 +199,7 @@ var/build_amount = SMELT_AMOUNT + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] @@ -214,6 +217,7 @@ unload_mineral(O) /obj/machinery/mineral/processing_unit/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index abead3ab9a..38e02474f4 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -22,17 +22,15 @@ var/list/ore_values = list(MAT_GLASS = 1, MAT_METAL = 1, MAT_PLASMA = 15, MAT_SILVER = 16, MAT_GOLD = 18, MAT_TITANIUM = 30, MAT_URANIUM = 30, MAT_DIAMOND = 50, MAT_BLUESPACE = 50, MAT_BANANIUM = 60) var/message_sent = FALSE var/list/ore_buffer = list() - var/datum/material_container/materials var/datum/research/files var/obj/item/disk/design_disk/inserted_disk /obj/machinery/mineral/ore_redemption/Initialize() . = ..() - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) files = new /datum/research/smelter(src) /obj/machinery/mineral/ore_redemption/Destroy() - QDEL_NULL(materials) QDEL_NULL(files) return ..() @@ -57,6 +55,7 @@ if(O && O.refined_type) points += O.points * point_upgrade + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!material_amount) @@ -75,6 +74,7 @@ var/build_amount = 0 + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] var/datum/material/redemption_mat = materials.materials[mat_id] @@ -110,6 +110,7 @@ var/has_minerals = FALSE + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT @@ -148,6 +149,7 @@ /obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params) if(exchange_parts(user, W)) return + GET_COMPONENT(materials, /datum/component/material_container) if(default_pry_open(W)) materials.retrieve_all() return @@ -181,16 +183,10 @@ if(user.transferItemToLoc(W, src)) inserted_disk = W return TRUE - - if(istype(W, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/S = W - var/inserted = materials.insert_stack(S, S.amount) - to_chat(user, "You add [inserted] [S] sheets to \the [src].") - return - return ..() /obj/machinery/mineral/ore_redemption/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -213,6 +209,7 @@ data["claimedPoints"] = inserted_id.mining_points data["materials"] = list() + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/sheet_amount = M.amount ? M.amount / MINERAL_MATERIAL_AMOUNT : "0" @@ -236,6 +233,7 @@ /obj/machinery/mineral/ore_redemption/ui_act(action, params) if(..()) return + GET_COMPONENT(materials, /datum/component/material_container) switch(action) if("Eject") if(!inserted_id) diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index e48db7c6fd..1a4e4c5ed1 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -1,107 +1,103 @@ -/**********************Mint**************************/ - - -/obj/machinery/mineral/mint - name = "coin press" - icon = 'icons/obj/economy.dmi' - icon_state = "coinpress0" +/**********************Mint**************************/ + + +/obj/machinery/mineral/mint + name = "coin press" + icon = 'icons/obj/economy.dmi' + icon_state = "coinpress0" density = TRUE anchored = TRUE - var/datum/material_container/materials - var/newCoins = 0 //how many coins the machine made in it's last load + var/newCoins = 0 //how many coins the machine made in it's last load var/processing = FALSE - var/chosen = MAT_METAL //which material will be used to make coins - var/coinsToProduce = 10 - speed_process = 1 - - + var/chosen = MAT_METAL //which material will be used to make coins + var/coinsToProduce = 10 + speed_process = 1 + + /obj/machinery/mineral/mint/Initialize() . = ..() - materials = new /datum/material_container(src, - list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), - max_amt = MINERAL_MATERIAL_AMOUNT*50) - -/obj/machinery/mineral/mint/Destroy() - QDEL_NULL(materials) - return ..() - -/obj/machinery/mineral/mint/process() - var/turf/T = get_step(src, input_dir) - if(!T) - return - - for(var/obj/item/stack/sheet/O in T) - materials.insert_stack(O, O.amount) - -/obj/machinery/mineral/mint/attack_hand(mob/user) - var/dat = "Coin Press
" - - for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - if(!M.amount && chosen != mat_id) - continue - dat += "
[M.name] amount: [M.amount] cm3 " - if (chosen == mat_id) - dat += "Chosen" - else - dat += "Choose" - - var/datum/material/M = materials.materials[chosen] - - dat += "

Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.
" - dat += "-10 " - dat += "-5 " - dat += "-1 " - dat += "+1 " - dat += "+5 " - dat += "+10 " - - dat += "

In total this machine produced [newCoins] coins." - dat += "
Make coins" - user << browse(dat, "window=mint") - -/obj/machinery/mineral/mint/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(processing==1) - to_chat(usr, "The machine is processing.") - return - if(href_list["choose"]) - if(materials.materials[href_list["choose"]]) - chosen = href_list["choose"] - if(href_list["chooseAmt"]) - coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) - if(href_list["makeCoins"]) - var/temp_coins = coinsToProduce + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), MINERAL_MATERIAL_AMOUNT * 50) + +/obj/machinery/mineral/mint/process() + var/turf/T = get_step(src, input_dir) + if(!T) + return + + GET_COMPONENT(materials, /datum/component/material_container) + for(var/obj/item/stack/sheet/O in T) + materials.insert_stack(O, O.amount) + +/obj/machinery/mineral/mint/attack_hand(mob/user) + var/dat = "Coin Press
" + + GET_COMPONENT(materials, /datum/component/material_container) + for(var/mat_id in materials.materials) + var/datum/material/M = materials.materials[mat_id] + if(!M.amount && chosen != mat_id) + continue + dat += "
[M.name] amount: [M.amount] cm3 " + if (chosen == mat_id) + dat += "Chosen" + else + dat += "Choose" + + var/datum/material/M = materials.materials[chosen] + + dat += "

Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.
" + dat += "-10 " + dat += "-5 " + dat += "-1 " + dat += "+1 " + dat += "+5 " + dat += "+10 " + + dat += "

In total this machine produced [newCoins] coins." + dat += "
Make coins" + user << browse(dat, "window=mint") + +/obj/machinery/mineral/mint/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(processing==1) + to_chat(usr, "The machine is processing.") + return + GET_COMPONENT(materials, /datum/component/material_container) + if(href_list["choose"]) + if(materials.materials[href_list["choose"]]) + chosen = href_list["choose"] + if(href_list["chooseAmt"]) + coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) + if(href_list["makeCoins"]) + var/temp_coins = coinsToProduce processing = TRUE - icon_state = "coinpress1" - var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 - var/datum/material/M = materials.materials[chosen] - if(!M || !M.coin_type) - updateUsrDialog() - return - - while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen)) - create_coins(M.coin_type) - coinsToProduce-- - newCoins++ - src.updateUsrDialog() - sleep(5) - - icon_state = "coinpress0" + icon_state = "coinpress1" + var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 + var/datum/material/M = materials.materials[chosen] + if(!M || !M.coin_type) + updateUsrDialog() + return + + while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen)) + create_coins(M.coin_type) + coinsToProduce-- + newCoins++ + src.updateUsrDialog() + sleep(5) + + icon_state = "coinpress0" processing = FALSE - coinsToProduce = temp_coins - src.updateUsrDialog() - return - -/obj/machinery/mineral/mint/proc/create_coins(P) - var/turf/T = get_step(src,output_dir) - if(T) - var/obj/item/O = new P(src) - var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T) - if(!M) - M = new /obj/item/storage/bag/money(src) - unload_mineral(M) + coinsToProduce = temp_coins + src.updateUsrDialog() + return + +/obj/machinery/mineral/mint/proc/create_coins(P) + var/turf/T = get_step(src,output_dir) + if(T) + var/obj/item/O = new P(src) + var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T) + if(!M) + M = new /obj/item/storage/bag/money(src) + unload_mineral(M) O.loc = M \ No newline at end of file diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 97a5cb8486..c1dd6a662e 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -329,6 +329,9 @@ if(SSshuttle.arrivals.damaged && config.arrivals_shuttle_require_safe_latejoin) src << alert("The arrivals shuttle is currently malfunctioning! You cannot join.") return FALSE + + if(config.arrivals_shuttle_require_undocked) + SSshuttle.arrivals.RequireUndocked(src) arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL //Remove the player from the join queue if he was in one and reset the timer diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 9eb16d74e2..1022719805 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -711,9 +711,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp update_icon() /mob/dead/observer/canUseTopic(atom/movable/AM,be_close = FALSE) - if(check_rights(R_ADMIN, 0)) - return 1 - return + return IsAdminGhost(usr) /mob/dead/observer/is_literate() return 1 diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 48ce6e5e7b..170cf57d95 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -40,7 +40,7 @@ create_internal_organs() - ..() + . = ..() /mob/living/carbon/alien/create_internal_organs() internal_organs += new /obj/item/organ/brain/alien diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index 9e79ec1259..b18aaacfeb 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -8,7 +8,7 @@ /mob/living/carbon/alien/humanoid/drone/Initialize() AddAbility(new/obj/effect/proc_holder/alien/evolve(null)) - ..() + . = ..() /mob/living/carbon/alien/humanoid/drone/create_internal_organs() diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm index 71619ff9a4..404d285b25 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm @@ -13,7 +13,7 @@ AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src)) AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve()) - ..() + . = ..() /mob/living/carbon/alien/humanoid/royal/praetorian/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/large @@ -48,4 +48,4 @@ return 1 else to_chat(user, "We already have an alive queen.") - return 0 + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index 2988e9b3bf..c0577c0d61 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -8,7 +8,7 @@ /mob/living/carbon/alien/humanoid/sentinel/Initialize() AddAbility(new /obj/effect/proc_holder/alien/sneak) - ..() + . = ..() /mob/living/carbon/alien/humanoid/sentinel/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel @@ -18,4 +18,4 @@ /mob/living/carbon/alien/humanoid/sentinel/movement_delay() - . = ..() + . = ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index ed4a20a91a..0a325521b0 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -18,12 +18,13 @@ var/drooling = 0 //For Neruotoxic spit overlays bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien, /obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien) + devourable = TRUE //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/humanoid/Initialize() AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null)) - ..() + . = ..() /mob/living/carbon/alien/humanoid/movement_delay() . = ..() @@ -42,7 +43,7 @@
"} for(var/i in 1 to held_items.len) var/obj/item/I = get_item_for_held_index(i) - dat += "
[get_held_index_name(i)]:[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "Empty"]" + dat += "
[get_held_index_name(i)]:[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "Empty"]" dat += "
Empty Pouches" if(handcuffed) @@ -120,4 +121,4 @@ /mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath) if(breath && breath.total_moles() > 0 && !sneaking) playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5) - ..() + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 61c78c87a8..101f1495e2 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -4,7 +4,7 @@ icon_state = "larva0" pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_SMALL - density = FALSE + density = FALSE maxHealth = 25 health = 25 @@ -22,7 +22,7 @@ AddAbility(new/obj/effect/proc_holder/alien/hide(null)) AddAbility(new/obj/effect/proc_holder/alien/larva_evolve(null)) - ..() + . = ..() /mob/living/carbon/alien/larva/create_internal_organs() internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny @@ -65,4 +65,4 @@ /mob/living/carbon/alien/larva/stripPanelEquip(obj/item/what, mob/who) to_chat(src, "You don't have the dexterity to do this!") - return + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 717c5478a5..4109166ebd 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -297,6 +297,10 @@ /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) + if(I.being_removed) + to_chat(src, "You're already attempting to remove [I]!") + return + I.being_removed = TRUE breakouttime = I.breakouttime var/displaytime = breakouttime / 600 if(!cuff_break) @@ -318,6 +322,7 @@ else if(cuff_break == INSTANT_CUFFBREAK) clear_cuffs(I, cuff_break) + I.being_removed = FALSE /mob/living/carbon/proc/uncuff() if (handcuffed) diff --git a/code/modules/mob/living/carbon/human/interactive.dm b/code/modules/mob/living/carbon/human/interactive.dm index 6add1cb80c..91921f386d 100644 --- a/code/modules/mob/living/carbon/human/interactive.dm +++ b/code/modules/mob/living/carbon/human/interactive.dm @@ -87,12 +87,16 @@ /// SNPC voice handling /mob/living/carbon/human/interactive/proc/loadVoice() - var/json_file = file("data/npc_saves/snpc.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - knownStrings = json["knownStrings"] + if(fexists("data/npc_saves/snpc.sav")) + var/savefile/S = new /savefile("data/npc_saves/snpc.sav") + S["knownStrings"] >> knownStrings + fdel(S) + else + var/json_file = file("data/npc_saves/snpc.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + knownStrings = json["knownStrings"] if(isnull(knownStrings)) knownStrings = list() @@ -1618,4 +1622,4 @@ TRAITS |= TRAIT_ROBUST TRAITS |= TRAIT_SMART faction += "bot_power" - . = ..() + . = ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 821ed9d7a6..19fa9ce82e 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -111,6 +111,10 @@ randname += " [pick(GLOB.last_names)]" return randname + +//Called when cloning, copies some vars that should be kept +/datum/species/proc/copy_properties_from(datum/species/old_species) + return //Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced. @@ -1721,4 +1725,4 @@ #undef COLD_DAMAGE_LEVEL_1 #undef COLD_DAMAGE_LEVEL_2 -#undef COLD_DAMAGE_LEVEL_3 +#undef COLD_DAMAGE_LEVEL_3 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 18444bb366..80d64b29d4 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -7,3 +7,7 @@ mutanttongue = /obj/item/organ/tongue/abductor var/scientist = 0 // vars to not pollute spieces list with castes var/team = 1 + +/datum/species/abductor/copy_properties_from(datum/species/abductor/old_species) + scientist = old_species.scientist + team = old_species.team diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm index 7c58ecbf86..dbab6b94eb 100644 --- a/code/modules/mob/living/carbon/human/species_types/angel.dm +++ b/code/modules/mob/living/carbon/human/species_types/angel.dm @@ -18,11 +18,10 @@ if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts))) H.dna.features["wings"] = "Angel" H.update_body() - if(ishuman(H)&& !fly) + if(ishuman(H) && !fly) fly = new fly.Grant(H) - /datum/species/angel/on_species_loss(mob/living/carbon/human/H) if(fly) fly.Remove(H) @@ -66,7 +65,7 @@ /datum/action/innate/flight name = "Toggle Flight" check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN - icon_icon = 'icons/mob/actions/actions_items.dmi' + icon_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "flight" /datum/action/innate/flight/Activate() diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 3319895fe0..60f2e821f2 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -9,7 +9,6 @@ exotic_blood = "slimejelly" damage_overlay_type = "" var/datum/action/innate/regenerate_limbs/regenerate_limbs - toxic_food = NONE liked_food = MEAT /datum/species/jelly/on_species_loss(mob/living/carbon/C) @@ -60,6 +59,7 @@ name = "Regenerate Limbs" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimeheal" + icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/regenerate_limbs/IsAvailable() @@ -128,7 +128,7 @@ /datum/species/jelly/slime/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() if(ishuman(C)) -/* slime_split = new + /* slime_split = new slime_split.Grant(C) swap_body = new swap_body.Grant(C) */ @@ -140,6 +140,10 @@ C.faction |= "slime" +//If you're cloned you get your body pool back +/datum/species/jelly/slime/copy_properties_from(datum/species/jelly/slime/old_species) + bodies = old_species.bodies + /datum/species/jelly/slime/spec_life(mob/living/carbon/human/H) if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT) if(prob(5)) @@ -154,6 +158,7 @@ name = "Split Body" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimesplit" + icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/split_body/IsAvailable() @@ -220,6 +225,7 @@ name = "Swap Body" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimeswap" + icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/swap_body/Activate() @@ -326,4 +332,4 @@ M.transfer_to(dupe) dupe.visible_message("[dupe] blinks and looks \ around.", - "...and move this one instead.") + "...and move this one instead.") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 636c2b7890..5c635fb870 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -30,7 +30,7 @@ burnmod = 1.5 blacklisted = TRUE no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store) - species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR,NOHUNGER) + species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR,NOHUNGER,NO_DNA_COPY,NOTRANSSTING) mutanteyes = /obj/item/organ/eyes/night_vision/nightmare var/obj/effect/proc_holder/spell/targeted/shadowwalk/shadowwalk diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm index c6fba442de..45b4a28bb5 100644 --- a/code/modules/mob/living/carbon/human/species_types/synths.dm +++ b/code/modules/mob/living/carbon/human/species_types/synths.dm @@ -1,121 +1,121 @@ -/datum/species/synth - name = "Synth" //inherited from the real species, for health scanners and things - id = "synth" - say_mod = "beep boops" //inherited from a user's real species - sexes = 0 - species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //all of these + whatever we inherit from the real species - dangerous_existence = 1 - blacklisted = 1 - meat = null - damage_overlay_type = "synth" - limbs_id = "synth" - var/list/initial_species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //for getting these values back for assume_disguise() - var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off - var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged - -/datum/species/synth/military - name = "Military Synth" - id = "military_synth" - armor = 25 - punchdamagelow = 10 - punchdamagehigh = 19 - punchstunthreshold = 14 //about 50% chance to stun - disguise_fail_health = 50 - -/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - ..() - assume_disguise(old_species, H) - -/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(chem.id == "synthflesh") - chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little - H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) - return 1 - else - return ..() - - -/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H) - if(S && !istype(S, type)) - name = S.name - say_mod = S.say_mod - sexes = S.sexes - species_traits = initial_species_traits.Copy() - species_traits.Add(S.species_traits) - attack_verb = S.attack_verb - attack_sound = S.attack_sound - miss_sound = S.miss_sound - meat = S.meat - mutant_bodyparts = S.mutant_bodyparts.Copy() - mutant_organs = S.mutant_organs.Copy() - default_features = S.default_features.Copy() - nojumpsuit = S.nojumpsuit - no_equip = S.no_equip.Copy() - limbs_id = S.limbs_id - use_skintones = S.use_skintones - fixed_mut_color = S.fixed_mut_color - hair_color = S.hair_color - fake_species = new S.type - else - name = initial(name) - say_mod = initial(say_mod) - species_traits = initial_species_traits.Copy() - attack_verb = initial(attack_verb) - attack_sound = initial(attack_sound) - miss_sound = initial(miss_sound) - mutant_bodyparts = list() - default_features = list() - nojumpsuit = initial(nojumpsuit) - no_equip = list() - qdel(fake_species) - fake_species = null - meat = initial(meat) - limbs_id = "synth" - use_skintones = 0 - sexes = 0 - fixed_mut_color = "" - hair_color = "" - - for(var/X in H.bodyparts) //propagates the damage_overlay changes - var/obj/item/bodypart/BP = X - BP.update_limb() - H.update_body_parts() //to update limb icon cache with the new damage overlays - -//Proc redirects: -//Passing procs onto the fake_species, to ensure we look as much like them as possible - -/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour) - if(fake_species) - fake_species.handle_hair(H, forced_colour) - else - return ..() - - -/datum/species/synth/handle_body(mob/living/carbon/human/H) - if(fake_species) - fake_species.handle_body(H) - else - return ..() - - -/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) - if(fake_species) - fake_species.handle_body(H,forced_colour) - else - return ..() - - -/datum/species/synth/get_spans() - if(fake_species) - return fake_species.get_spans() - return list() - - -/datum/species/synth/handle_speech(message, mob/living/carbon/human/H) - if(H.health > disguise_fail_health) - if(fake_species) - return fake_species.handle_speech(message,H) - else - return ..() - else +/datum/species/synth + name = "Synth" //inherited from the real species, for health scanners and things + id = "synth" + say_mod = "beep boops" //inherited from a user's real species + sexes = 0 + species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //all of these + whatever we inherit from the real species + dangerous_existence = 1 + blacklisted = 1 + meat = null + damage_overlay_type = "synth" + limbs_id = "synth" + var/list/initial_species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER,NO_DNA_COPY) //for getting these values back for assume_disguise() + var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off + var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged + +/datum/species/synth/military + name = "Military Synth" + id = "military_synth" + armor = 25 + punchdamagelow = 10 + punchdamagehigh = 19 + punchstunthreshold = 14 //about 50% chance to stun + disguise_fail_health = 50 + +/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + ..() + assume_disguise(old_species, H) + +/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "synthflesh") + chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little + H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) + return 1 + else + return ..() + + +/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H) + if(S && !istype(S, type)) + name = S.name + say_mod = S.say_mod + sexes = S.sexes + species_traits = initial_species_traits.Copy() + species_traits.Add(S.species_traits) + attack_verb = S.attack_verb + attack_sound = S.attack_sound + miss_sound = S.miss_sound + meat = S.meat + mutant_bodyparts = S.mutant_bodyparts.Copy() + mutant_organs = S.mutant_organs.Copy() + default_features = S.default_features.Copy() + nojumpsuit = S.nojumpsuit + no_equip = S.no_equip.Copy() + limbs_id = S.limbs_id + use_skintones = S.use_skintones + fixed_mut_color = S.fixed_mut_color + hair_color = S.hair_color + fake_species = new S.type + else + name = initial(name) + say_mod = initial(say_mod) + species_traits = initial_species_traits.Copy() + attack_verb = initial(attack_verb) + attack_sound = initial(attack_sound) + miss_sound = initial(miss_sound) + mutant_bodyparts = list() + default_features = list() + nojumpsuit = initial(nojumpsuit) + no_equip = list() + qdel(fake_species) + fake_species = null + meat = initial(meat) + limbs_id = "synth" + use_skintones = 0 + sexes = 0 + fixed_mut_color = "" + hair_color = "" + + for(var/X in H.bodyparts) //propagates the damage_overlay changes + var/obj/item/bodypart/BP = X + BP.update_limb() + H.update_body_parts() //to update limb icon cache with the new damage overlays + +//Proc redirects: +//Passing procs onto the fake_species, to ensure we look as much like them as possible + +/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour) + if(fake_species) + fake_species.handle_hair(H, forced_colour) + else + return ..() + + +/datum/species/synth/handle_body(mob/living/carbon/human/H) + if(fake_species) + fake_species.handle_body(H) + else + return ..() + + +/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) + if(fake_species) + fake_species.handle_body(H,forced_colour) + else + return ..() + + +/datum/species/synth/get_spans() + if(fake_species) + return fake_species.get_spans() + return list() + + +/datum/species/synth/handle_speech(message, mob/living/carbon/human/H) + if(H.health > disguise_fail_health) + if(fake_species) + return fake_species.handle_speech(message,H) + else + return ..() + else return ..() diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index d11f71212c..04123102c0 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -1,3 +1,5 @@ +#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin + /datum/species/zombie // 1spooky name = "High Functioning Zombie" @@ -6,7 +8,7 @@ sexes = 0 blacklisted = 1 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie - species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT) + species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT,NOTRANSSTING) mutant_organs = list(/obj/item/organ/tongue/zombie) var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg') disliked_food = NONE @@ -20,14 +22,21 @@ armor = 20 // 120 damage to KO a zombie, which kills it speedmod = 2 mutanteyes = /obj/item/organ/eyes/night_vision/zombie + var/regen_cooldown = 0 /datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount) . = min(2, amount) +/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H) + . = ..() + if(.) + regen_cooldown = world.time + REGENERATION_DELAY + /datum/species/zombie/infectious/spec_life(mob/living/carbon/C) . = ..() C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW - C.heal_overall_damage(4,4) + if(regen_cooldown < world.time) + C.heal_overall_damage(4,4) if(prob(4)) playsound(C, pick(spooks), 50, TRUE, 10) if(C.InCritical()) @@ -56,3 +65,5 @@ sexes = 0 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie mutant_organs = list(/obj/item/organ/tongue/zombie) + +#undef REGENERATION_DELAY diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm index be716e26ba..767268f8dc 100644 --- a/code/modules/mob/living/carbon/monkey/punpun.dm +++ b/code/modules/mob/living/carbon/monkey/punpun.dm @@ -5,7 +5,7 @@ var/ancestor_chain = 1 var/relic_hat //Note: these two are paths var/relic_mask - var/memory_saved = 0 + var/memory_saved = FALSE var/list/pet_monkey_names = list("Pun Pun", "Bubbles", "Mojo", "George", "Darwin", "Aldo", "Caeser", "Kanzi", "Kong", "Terk", "Grodd", "Mala", "Bojangles", "Coco", "Able", "Baker", "Scatter", "Norbit", "Travis") var/list/rare_pet_monkey_names = list("Professor Bobo", "Deempisi's Revenge", "Furious George", "King Louie", "Dr. Zaius", "Jimmy Rustles", "Dinner", "Lanky") @@ -32,25 +32,33 @@ equip_to_slot_or_del(new relic_mask, slot_wear_mask) /mob/living/carbon/monkey/punpun/Life() - if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) - Write_Memory(0) + if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) + Write_Memory(FALSE, FALSE) + memory_saved = TRUE ..() /mob/living/carbon/monkey/punpun/death(gibbed) - if(!memory_saved || gibbed) - Write_Memory(1,gibbed) + if(!memory_saved) + Write_Memory(TRUE, gibbed) ..() /mob/living/carbon/monkey/punpun/proc/Read_Memory() - var/json_file = file("data/npc_saves/Punpun.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - ancestor_name = json["ancestor_name"] - ancestor_chain = json["ancestor_chain"] - relic_hat = json["relic_hat"] - relic_mask = json["relic_hat"] + if(fexists("data/npc_saves/Punpun.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Punpun.sav") + S["ancestor_name"] >> ancestor_name + S["ancestor_chain"] >> ancestor_chain + S["relic_hat"] >> relic_hat + S["relic_mask"] >> relic_mask + fdel("data/npc_saves/Punpun.sav") + else + var/json_file = file("data/npc_saves/Punpun.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + ancestor_name = json["ancestor_name"] + ancestor_chain = json["ancestor_chain"] + relic_hat = json["relic_hat"] + relic_mask = json["relic_hat"] /mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed) var/json_file = file("data/npc_saves/Punpun.json") @@ -60,14 +68,10 @@ file_data["ancestor_chain"] = null file_data["relic_hat"] = null file_data["relic_mask"] = null - if(dead) - file_data["ancestor_name"] = ancestor_name - file_data["ancestor_chain"] = ancestor_chain + 1 - file_data["relic_hat"] = head ? head.type : null - file_data["relic_mask"] = wear_mask ? wear_mask.type : null - if(!ancestor_name) - file_data["ancestor_name"] = name + else + file_data["ancestor_name"] = ancestor_name ? ancestor_name : name + file_data["ancestor_chain"] = dead ? ancestor_chain + 1 : ancestor_chain + file_data["relic_hat"] = head ? head.type : null + file_data["relic_mask"] = wear_mask ? wear_mask.type : null fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - if(!dead) - memory_saved = 1 \ No newline at end of file + WRITE_FILE(json_file, json_encode(file_data)) \ No newline at end of file diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index acea72e911..649e19ba29 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -544,11 +544,14 @@ if(!force_moving) ..(pressure_difference, direction, pressure_resistance_prob_delta) +/mob/living/proc/can_resist() + return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE)) + /mob/living/verb/resist() set name = "Resist" set category = "IC" - if(!isliving(src) || next_move > world.time || incapacitated(ignore_restraints = 1)) + if(!can_resist()) return changeNext_move(CLICK_CD_RESIST) @@ -709,30 +712,24 @@ floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life(). /mob/living/proc/get_temperature(datum/gas_mixture/environment) - var/loc_temp = T0C - if(istype(loc, /obj/mecha)) - var/obj/mecha/M = loc - loc_temp = M.return_temperature() - - else if(istype(loc, /obj/structure/transit_tube_pod)) - loc_temp = environment.temperature - + var/loc_temp = environment ? environment.temperature : T0C + if(isobj(loc)) + var/obj/oloc = loc + var/obj_temp = oloc.return_temperature() + if(obj_temp != null) + loc_temp = obj_temp +/* if(ismob(loc)) + var/mob/living/mloc = loc + var/mob_temp = mloc.return_temperature() + if(mloc == DEAD) + loc_temp = get_turf(loc) //wew + else + loc_temp = mob_temp +*/ +//just gunna ommit this for now, it's on the 'to figgur out' list. else if(isspaceturf(get_turf(src))) var/turf/heat_turf = get_turf(src) loc_temp = heat_turf.temperature - - else if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) - var/obj/machinery/atmospherics/components/unary/cryo_cell/C = loc - var/datum/gas_mixture/G = C.AIR1 - - if(G.total_moles() < 10) - loc_temp = environment.temperature - else - loc_temp = G.temperature - - else - loc_temp = environment.temperature - return loc_temp /mob/living/proc/get_standard_pixel_x_offset(lying = 0) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index ca0a2e8c1c..812e207249 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -114,9 +114,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) - - //to_chat(world, "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]") - for(var/x = x1; x <= x2; x += CHUNK_SIZE) for(var/y = y1; y <= y2; y += CHUNK_SIZE) if(chunkGenerated(x, y, T.z)) @@ -161,4 +158,4 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) if(cameranet.chunkGenerated(x, y, z)) var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z) usr.client.debug_variables(chunk) -*/ \ No newline at end of file +*/ diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index af6f3daf92..0024772274 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -307,6 +307,7 @@ /obj/item/device/analyzer, /obj/item/device/assembly/signaler/cyborg, /obj/item/areaeditor/blueprints/cyborg, + /obj/item/device/electroadaptive_pseudocircuit, /obj/item/stack/sheet/metal/cyborg, /obj/item/stack/sheet/glass/cyborg, /obj/item/stack/sheet/rglass/cyborg, @@ -679,4 +680,4 @@ /datum/robot_energy_storage/beacon max_energy = 30 recharge_rate = 1 - name = "Marker Beacon Storage" + name = "Marker Beacon Storage" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 4007822ebb..e6a4b978ca 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -432,7 +432,6 @@ return if(on) var/speed = (wires.is_cut(WIRE_MOTOR1) ? 0 : 1) + (wires.is_cut(WIRE_MOTOR2) ? 0 : 2) - //to_chat(world, "speed: [speed]") var/num_steps = 0 switch(speed) if(0) @@ -474,8 +473,6 @@ path -= next return if(isturf(next)) - //to_chat(world, "at ([x],[y]) moving to ([next.x],[next.y])") - if(bloodiness) var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) if(blood_DNA && blood_DNA.len) @@ -497,7 +494,6 @@ var/moved = step_towards(src, next) // attempt to move if(cell) cell.use(1) if(moved && oldloc!=loc) // successful move - //to_chat(world, "Successful move.") blockcount = 0 path -= loc @@ -508,7 +504,6 @@ else // failed to move - //to_chat(world, "Unable to move.") blockcount++ mode = BOT_BLOCKED if(blockcount == 3) @@ -528,16 +523,13 @@ return else buzz(ANNOYED) - //to_chat(world, "Bad turf.") mode = BOT_NAV return else - //to_chat(world, "No path.") mode = BOT_NAV return if(BOT_NAV) // calculate new path - //to_chat(world, "Calc new path.") mode = BOT_WAIT_FOR_NAV spawn(0) calc_path() diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 2c50c98816..772604a527 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -65,10 +65,9 @@ /mob/living/simple_animal/bot/secbot/Initialize() . = ..() icon_state = "secbot[on]" - spawn(3) - var/datum/job/detective/J = new/datum/job/detective - access_card.access += J.get_access() - prev_access = access_card.access + var/datum/job/detective/J = new/datum/job/detective + access_card.access += J.get_access() + prev_access = access_card.access //SECHUD var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED] @@ -225,21 +224,25 @@ Auto Patrol: []"}, playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2) C.visible_message("[src] is trying to put zipties on [C]!",\ "[src] is trying to put zipties on you!") - spawn(60) - if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing. - return - if(!C.handcuffed) - C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) - C.update_handcuffed() - playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - back_to_idle() + addtimer(CALLBACK(src, .proc/attempt_handcuff, C), 60) + +/mob/living/simple_animal/bot/secbot/proc/attempt_handcuff(mob/living/carbon/C) + if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing. + return + if(!C.handcuffed) + C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) + C.update_handcuffed() + playsound(src, "law", 50, 0) + back_to_idle() + +/mob/living/simple_animal/bot/secbot/proc/update_onsprite() + icon_state = "secbot[on]" /mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C) var/judgement_criteria = judgement_criteria() playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1) icon_state = "secbot-c" - spawn(2) - icon_state = "secbot[on]" + addtimer(CALLBACK(src, .proc/update_onsprite), 2) var/threat = 5 if(ishuman(C)) C.stuttering = 5 @@ -352,15 +355,13 @@ Auto Patrol: []"}, target = null last_found = world.time frustration = 0 - spawn(0) - handle_automated_action() //ensure bot quickly responds + INVOKE_ASYNC(src, .proc/handle_automated_action) /mob/living/simple_animal/bot/secbot/proc/back_to_hunt() anchored = FALSE frustration = 0 mode = BOT_HUNT - spawn(0) - handle_automated_action() //ensure bot quickly responds + INVOKE_ASYNC(src, .proc/handle_automated_action) // look for a criminal in view of the bot /mob/living/simple_animal/bot/secbot/proc/look_for_perp() @@ -385,8 +386,7 @@ Auto Patrol: []"}, playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) visible_message("[src] points at [C.name]!") mode = BOT_HUNT - spawn(0) - handle_automated_action() // ensure bot quickly responds to a perp + INVOKE_ASYNC(src, .proc/handle_automated_action) break else continue diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 49ef79a4d9..feb581e03b 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -30,6 +30,7 @@ var/mob/living/simple_animal/mouse/movement_target gold_core_spawnable = 2 devourable = TRUE + no_vore = FALSE /mob/living/simple_animal/pet/cat/Initialize() . = ..() @@ -84,7 +85,7 @@ var/list/family = list()//var restored from savefile, has count of each child type var/list/children = list()//Actual mob instances of children var/cats_deployed = 0 - var/memory_saved = 0 + var/memory_saved = FALSE /mob/living/simple_animal/pet/cat/Runtime/Initialize() if(prob(5)) @@ -99,6 +100,7 @@ Deploy_The_Cats() if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) Write_Memory() + memory_saved = TRUE ..() /mob/living/simple_animal/pet/cat/Runtime/make_babies() @@ -109,21 +111,26 @@ /mob/living/simple_animal/pet/cat/Runtime/death() if(!memory_saved) - Write_Memory(1) + Write_Memory(TRUE) ..() /mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory() - var/json_file = file("data/npc_saves/Runtime.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - family = json["family"] + if(fexists("data/npc_saves/Runtime.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Runtime.sav") + S["family"] >> family + fdel("data/npc_saves/Runtime.sav") + else + var/json_file = file("data/npc_saves/Runtime.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + family = json["family"] if(isnull(family)) family = list() /mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead) var/json_file = file("data/npc_saves/Runtime.json") + var/list/file_data = list() family = list() if(!dead) for(var/mob/living/simple_animal/pet/cat/kitten/C in children) @@ -133,9 +140,9 @@ family[C.type] += 1 else family[C.type] = 1 + file_data["family"] = family fdel(json_file) - WRITE_FILE(json_file, json_encode(family)) - memory_saved = 1 + WRITE_FILE(json_file, json_encode(file_data)) /mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats() cats_deployed = 1 diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 31c080c66c..b9b526514b 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -13,6 +13,7 @@ speak_chance = 1 turns_per_move = 10 devourable = TRUE + no_vore = FALSE //Corgis and pugs are now under one dog subtype @@ -291,7 +292,7 @@ gold_core_spawnable = 0 var/age = 0 var/record_age = 1 - var/memory_saved = 0 + var/memory_saved = FALSE var/saved_head //path /mob/living/simple_animal/pet/dog/corgi/Ian/Initialize() @@ -307,7 +308,7 @@ P.real_name = "Ian" P.gender = MALE P.desc = "It's the HoP's beloved corgi puppy." - Write_Memory(0) + Write_Memory(FALSE) qdel(src) else if(age == record_age) icon_state = "old_corgi" @@ -317,24 +318,31 @@ turns_per_move = 20 /mob/living/simple_animal/pet/dog/corgi/Ian/Life() - if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) - Write_Memory(0) + if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) + Write_Memory(FALSE) + memory_saved = TRUE ..() /mob/living/simple_animal/pet/dog/corgi/Ian/death() if(!memory_saved) - Write_Memory(1) + Write_Memory(TRUE) ..() /mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory() - var/json_file = file("data/npc_saves/Ian.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - age = json["age"] - record_age = json["record_age"] - saved_head = json["saved_head"] + if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Ian.sav") + S["age"] >> age + S["record_age"] >> record_age + S["saved_head"] >> saved_head + fdel("data/npc_saves/Ian.sav") + else + var/json_file = file("data/npc_saves/Ian.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + age = json["age"] + record_age = json["record_age"] + saved_head = json["saved_head"] if(isnull(age)) age = 0 if(isnull(record_age)) @@ -349,14 +357,18 @@ file_data["age"] = age + 1 if((age + 1) > record_age) file_data["record_age"] = record_age + 1 + else + file_data["record_age"] = record_age if(inventory_head) file_data["saved_head"] = inventory_head.type + else + file_data["saved_head"] = null else file_data["age"] = 0 + file_data["record_age"] = record_age file_data["saved_head"] = null fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) - memory_saved = 1 /mob/living/simple_animal/pet/dog/corgi/Ian/Life() ..() diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index d223984cf5..c29236c2fc 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -29,6 +29,7 @@ blood_volume = BLOOD_VOLUME_NORMAL var/obj/item/udder/udder = null devourable = TRUE + no_vore = FALSE /mob/living/simple_animal/hostile/retaliate/goat/Initialize() udder = new() @@ -119,6 +120,7 @@ gold_core_spawnable = 2 blood_volume = BLOOD_VOLUME_NORMAL devourable = TRUE + no_vore = FALSE /mob/living/simple_animal/cow/Initialize() udder = new() @@ -251,6 +253,7 @@ gold_core_spawnable = 2 var/static/chicken_count = 0 devourable = TRUE + no_vore = FALSE /mob/living/simple_animal/chicken/Initialize() . = ..() @@ -275,7 +278,6 @@ user.drop_item() qdel(O) eggsleft += rand(1, 4) - //to_chat(world, eggsleft) else to_chat(user, "[name] doesn't seem hungry!") else diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm index 22f2041d18..e7d6bfbf64 100644 --- a/code/modules/mob/living/simple_animal/friendly/fox.dm +++ b/code/modules/mob/living/simple_animal/friendly/fox.dm @@ -21,6 +21,7 @@ devourable = TRUE var/mob/living/simple_animal/mouse/movement_target var/turns_since_scan = 0 + no_vore = FALSE /mob/living/simple_animal/pet/fox/Life() //MICE! diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 6983bed378..1a7ed0261f 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -28,6 +28,7 @@ /mob/living/simple_animal/mouse/Initialize() . = ..() + AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100) if(!body_color) body_color = pick( list("brown","gray","white") ) icon_state = "mouse_[body_color]" @@ -58,7 +59,6 @@ if(!stat) var/mob/M = AM to_chat(M, "[icon2html(src, M)] Squeek!") - playsound(src, 'sound/effects/mousesqueek.ogg', 100, 1) ..() /mob/living/simple_animal/mouse/handle_automated_action() diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm index 1fa0fd53b8..6833ea83a6 100644 --- a/code/modules/mob/living/simple_animal/friendly/penguin.dm +++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm @@ -13,6 +13,7 @@ speak_chance = 1 turns_per_move = 10 icon = 'icons/mob/penguins.dmi' + no_vore = FALSE /mob/living/simple_animal/pet/penguin/emperor name = "Emperor penguin" diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index e06de7b762..fa4cefd839 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -35,6 +35,8 @@ gold_core_spawnable = 0 death_sound = 'sound/voice/hiss6.ogg' deathmessage = "lets out a waning guttural screech, green blood bubbling from its maw..." + devourable = TRUE + no_vore = FALSE /mob/living/simple_animal/hostile/alien/drone name = "alien drone" diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 1c92b6233d..6b08d041c0 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -36,6 +36,8 @@ faction = list("russian") gold_core_spawnable = 1 + devourable = TRUE + no_vore = FALSE //SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! /mob/living/simple_animal/hostile/bear/Hudson diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 9a8592e48c..fde10031d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -17,6 +17,7 @@ maxHealth = 25 health = 25 devourable = TRUE + no_vore = FALSE harm_intent_damage = 8 obj_damage = 50 diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index b697473787..e0afdefd6b 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -22,7 +22,7 @@ melee_damage_upper = 18 damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5) obj_damage = 20 - environment_smash = 2 + environment_smash = ENVIRONMENT_SMASH_WALLS attacktext = "pummels" attack_sound = 'sound/weapons/punch1.ogg' dextrous = TRUE @@ -32,7 +32,11 @@ stat_attack = UNCONSCIOUS minbodytemp = 270 maxbodytemp = 350 + unique_name = TRUE var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS] + var/oogas = 0 + devourable = TRUE + no_vore = FALSE // Gorillas like to dismember limbs from unconcious mobs. // Returns null when the target is not an unconcious carbon mob; a list of limbs (possibly empty) otherwise. @@ -49,6 +53,8 @@ return parts /mob/living/simple_animal/hostile/gorilla/AttackingTarget() + if(client) + oogaooga() var/list/parts = target_bodyparts(target) if(parts) if(!parts.len) @@ -61,7 +67,7 @@ var/mob/living/L = target if(prob(80)) var/atom/throw_target = get_edge_target_turf(L, dir) - L.throw_at(throw_target, rand(1,2), 7, src) + L.throw_at(throw_target, rand(1,2), 7, src) else L.Knockdown(20) visible_message("[src] knocks [L] down!") @@ -70,8 +76,30 @@ var/list/parts = target_bodyparts(target) return ..() && !istype(the_target, /mob/living/carbon/monkey) && (!parts || parts.len > 3) +/mob/living/simple_animal/hostile/gorilla/CanSmashTurfs(turf/T) + return iswallturf(T) + +/mob/living/simple_animal/hostile/gorilla/gib(no_brain) + if(!no_brain) + var/mob/living/brain/B = new(drop_location()) + B.name = real_name + B.real_name = real_name + if(mind) + mind.transfer_to(B) + ..() + /mob/living/simple_animal/hostile/gorilla/handle_automated_speech(override) if(speak_chance && (override || prob(speak_chance))) playsound(src, "sound/creatures/gorilla.ogg", 200) ..() +/mob/living/simple_animal/hostile/gorilla/can_use_guns(obj/item/G) + to_chat(src, "Your meaty finger is much too large for the trigger guard!") + return FALSE + + +/mob/living/simple_animal/hostile/gorilla/proc/oogaooga() + oogas++ + if(oogas >= rand(2,6)) + playsound(src, "sound/creatures/gorilla.ogg", 200) + oogas = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 866f9c995a..86fe54aaeb 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -228,6 +228,9 @@ if(!target || !CanAttack(target)) LoseTarget() return 0 + if(ismob(target.loc)) + LoseTarget() + return 0 if(target in possible_targets) if(target.z != z) LoseTarget() @@ -366,23 +369,26 @@ P.original = targeted_atom P.fire() return P - + +/mob/living/simple_animal/hostile/proc/CanSmashTurfs(turf/T) + return iswallturf(T) || ismineralturf(T) /mob/living/simple_animal/hostile/proc/DestroySurroundings() if(environment_smash) EscapeConfinement() for(var/dir in GLOB.cardinals) var/turf/T = get_step(targets_from, dir) - if(iswallturf(T) || ismineralturf(T)) + if(CanSmashTurfs(T)) if(T.Adjacent(targets_from)) T.attack_animal(src) for(var/a in T) var/atom/A = a if(!A.Adjacent(targets_from)) continue - if(is_type_in_typecache(A, environment_target_typecache)) + if(is_type_in_typecache(A, environment_target_typecache) && !A.IsObscured()) A.attack_animal(src) + /mob/living/simple_animal/hostile/proc/EscapeConfinement() if(buckled) buckled.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 1c7c5331d0..f3a398d5d9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -250,7 +250,7 @@ Difficulty: Very Hard use_power = NO_POWER_USE var/memory_saved = FALSE var/list/stored_items = list() - var/static/list/blacklist = typecacheof(list(/obj/item/spellbook)) + var/list/blacklist = list() /obj/machinery/smartfridge/black_box/update_icon() return @@ -276,6 +276,7 @@ Difficulty: Very Hard ..() if(!memory_saved && SSticker.current_state == GAME_STATE_FINISHED) WriteMemory() + memory_saved = TRUE /obj/machinery/smartfridge/black_box/proc/WriteMemory() var/json_file = file("data/npc_saves/Blackbox.json") @@ -287,15 +288,18 @@ Difficulty: Very Hard file_data["data"] = stored_items fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) - memory_saved = TRUE /obj/machinery/smartfridge/black_box/proc/ReadMemory() - var/json_file = file("data/npc_saves/Blackbox.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - stored_items = json["data"] + if(fexists("data/npc_saves/Blackbox.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") + S["stored_items"] >> stored_items + fdel("data/npc_saves/Blackbox.sav") + else + var/json_file = file("data/npc_saves/Blackbox.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + stored_items = json["data"] if(isnull(stored_items)) stored_items = list() @@ -789,4 +793,4 @@ Difficulty: Very Hard #undef ACTIVATE_WEAPON #undef ACTIVATE_MAGIC -#undef MEDAL_PREFIX +#undef MEDAL_PREFIX \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index c8272ca65e..d1ddfa9a00 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -60,6 +60,7 @@ Difficulty: Medium score_type = DRAKE_SCORE deathmessage = "collapses into a pile of bones, its flesh sloughing away." death_sound = 'sound/magic/demon_dies.ogg' + no_vore = FALSE /mob/living/simple_animal/hostile/megafauna/dragon/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon_vore.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon_vore.dm new file mode 100644 index 0000000000..898a2ad734 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon_vore.dm @@ -0,0 +1,50 @@ +/mob/living/simple_animal/hostile/megafauna/dragon + vore_active = TRUE + +/mob/living/simple_animal/hostile/megafauna/dragon/Initialize() + // Create and register 'stomachs' + var/datum/belly/megafauna/dragon/maw/maw = new(src) + var/datum/belly/megafauna/dragon/gullet/gullet = new(src) + var/datum/belly/megafauna/dragon/gut/gut = new(src) + for(var/datum/belly/X in list(maw, gullet, gut)) + vore_organs[X.name] = X + // Connect 'stomachs' together + maw.transferlocation = gullet + gullet.transferlocation = gut + vore_selected = maw.name // NPC eats into maw + return ..() + +/datum/belly/megafauna/dragon + human_prey_swallow_time = 50 // maybe enough to switch targets if distracted + nonhuman_prey_swallow_time = 50 + +/datum/belly/megafauna/dragon/maw + name = "maw" + inside_flavor = "The maw of the dreaded Ash drake closes around you, engulfing you into a swelteringly hot, disgusting enviroment. The acidic saliva tingles over your form while that tongue pushes you further back...towards the dark gullet beyond." + vore_verb = "scoop" + vore_sound = 'sound/vore/pred/taurswallow.ogg' + swallow_time = 20 + escapechance = 25 + // From above, will transfer into gullet + transferchance = 25 + autotransferchance = 66 + autotransferwait = 200 + +/datum/belly/megafauna/dragon/gullet + name = "gullet" + inside_flavor = "A ripple of muscle and arching of the tongue pushes you down like any other food. No choice in the matter, you're simply consumed. The dark ambiance of the outside world is replaced with working, wet flesh. Your only light being what you brought with you." + swallow_time = 60 // costs extra time to eat directly to here + escapechance = 5 + // From above, will transfer into gut + transferchance = 25 + autotransferchance = 50 + autotransferwait = 200 + +/datum/belly/megafauna/dragon/gut + name = "stomach" + vore_capacity = 5 //I doubt this many people will actually last in the gut, but... + inside_flavor = "With a rush of burning ichor greeting you, you're introduced to the Drake's stomach. Wrinkled walls greedily grind against you, acidic slimes working into your body as you become fuel and nutriton for a superior predator. All that's left is your body's willingness to resist your destiny." + digest_mode = DM_DRAGON + digest_burn = 5 + swallow_time = 100 // costs extra time to eat directly to here + escapechance = 0 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index dfbdace1f2..5f45d47494 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -89,11 +89,15 @@ . = ..() if(. && isliving(target)) var/mob/living/L = target - if(L.stat != DEAD) - if(!client && ranged && ranged_cooldown <= world.time) - OpenFire() + if(L.stat >= SOFT_CRIT) + if(vore_active == TRUE && L.devourable == TRUE) + dragon_feeding(src,L) + else if(L.stat == DEAD) + devour(L) else - devour(L) + if(L.stat != DEAD) + if(!client && ranged && ranged_cooldown <= world.time) + OpenFire() /mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L) if(!L) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index de995f951a..af283b9139 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -31,6 +31,7 @@ var/pre_attack = 0 var/pre_attack_icon = "Goliath_preattack" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) + no_vore = FALSE /mob/living/simple_animal/hostile/asteroid/goliath/Life() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index ba2a0f3702..8c5be75684 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -60,7 +60,7 @@ cap_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) UpdateMushroomCap() health = maxHealth - ..() + . = ..() /mob/living/simple_animal/hostile/mushroom/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //Possibility to flee from a fight just to make it more visually interesting if(!retreat_distance && prob(33)) diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index fd66b8d0ae..44a0a06cdc 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -38,7 +38,7 @@ minimum_distance = 5 icon_state = "stickmanranged" icon_living = "stickmanranged" - casingtype = /obj/item/ammo_casing/c45nostamina + casingtype = /obj/item/ammo_casing/c45/nostamina projectilesound = 'sound/misc/bang.ogg' loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 7cadba01d9..11331e7ab7 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -95,7 +95,7 @@ minimum_distance = 5 icon_state = "syndicateranged" icon_living = "syndicateranged" - casingtype = /obj/item/ammo_casing/c45nostamina + casingtype = /obj/item/ammo_casing/c45/nostamina projectilesound = 'sound/weapons/gunshot_smg.ogg' loot = list(/obj/effect/gibspawner/human) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 467bd13c65..8f08742f78 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -60,6 +60,7 @@ movement_type = FLYING gold_core_spawnable = 2 devourable = TRUE + no_vore = FALSE var/parrot_damage_upper = 10 var/parrot_state = PARROT_WANDER //Hunt for a perch when created @@ -296,7 +297,7 @@ else parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell! drop_held_item(0) - if(!stat && M.a_intent == INTENT_HELP) + if(stat != DEAD && M.a_intent == INTENT_HELP) handle_automated_speech(1) //assured speak/emote return @@ -872,7 +873,7 @@ speak = list("Poly wanna cracker!", ":e Check the crystal, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS ABOUT TO DELAMINATE CALL THE SHUTTLE") gold_core_spawnable = 0 speak_chance = 3 - var/memory_saved = 0 + var/memory_saved = FALSE var/rounds_survived = 0 var/longest_survival = 0 var/longest_deathstreak = 0 @@ -903,50 +904,62 @@ rounds_survived = max(++rounds_survived,1) if(rounds_survived > longest_survival) longest_survival = rounds_survived - Write_Memory() + Write_Memory(FALSE) + memory_saved = TRUE ..() /mob/living/simple_animal/parrot/Poly/death(gibbed) if(!memory_saved) - var/go_ghost = 0 - if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666)) - go_ghost = 1 - rounds_survived = min(--rounds_survived,0) - if(rounds_survived < longest_deathstreak) - longest_deathstreak = rounds_survived - Write_Memory() - if(go_ghost) - var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc) - if(mind) - mind.transfer_to(G) - else - G.key = key + Write_Memory(TRUE) + if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666)) + var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc) + if(mind) + mind.transfer_to(G) + else + G.key = key ..(gibbed) /mob/living/simple_animal/parrot/Poly/proc/Read_Memory() - var/json_file = file("data/npc_saves/Poly.json") - if(!fexists(json_file)) - return - var/list/json = list() - json = json_decode(file2text(json_file)) - speech_buffer = json["phrases"] - rounds_survived = json["roundssurvived"] - longest_survival = json["longestsurvival"] - longest_deathstreak = json["longestdeathstreak"] + if(fexists("data/npc_saves/Poly.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Poly.sav") + S["phrases"] >> speech_buffer + S["roundssurvived"] >> rounds_survived + S["longestsurvival"] >> longest_survival + S["longestdeathstreak"] >> longest_deathstreak + fdel("data/npc_saves/Poly.sav") + else + var/json_file = file("data/npc_saves/Poly.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + speech_buffer = json["phrases"] + rounds_survived = json["roundssurvived"] + longest_survival = json["longestsurvival"] + longest_deathstreak = json["longestdeathstreak"] if(!islist(speech_buffer)) speech_buffer = list() -/mob/living/simple_animal/parrot/Poly/proc/Write_Memory() +/mob/living/simple_animal/parrot/Poly/proc/Write_Memory(dead) var/json_file = file("data/npc_saves/Poly.json") var/list/file_data = list() if(islist(speech_buffer)) file_data["phrases"] = speech_buffer - file_data["roundssurvived"] = rounds_survived - file_data["longestsurvival"] = longest_survival - file_data["longestdeathstreak"] = longest_deathstreak + if(dead) + file_data["roundssurvived"] = min(rounds_survived - 1, 0) + file_data["longestsurvival"] = longest_survival + if(rounds_survived - 1 < longest_deathstreak) + file_data["longestdeathstreak"] = rounds_survived - 1 + else + file_data["longestdeathstreak"] = longest_deathstreak + else + file_data["roundssurvived"] = rounds_survived + 1 + if(rounds_survived + 1 > longest_survival) + file_data["longestsurvival"] = rounds_survived + 1 + else + file_data["longestsurvival"] = longest_survival + file_data["longestdeathstreak"] = longest_deathstreak fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) - memory_saved = 1 /mob/living/simple_animal/parrot/Poly/ghost name = "The Ghost of Poly" @@ -958,7 +971,7 @@ butcher_results = list(/obj/item/ectoplasm = 1) /mob/living/simple_animal/parrot/Poly/ghost/Initialize() - memory_saved = 1 //At this point nothing is saved + memory_saved = TRUE //At this point nothing is saved ..() /mob/living/simple_animal/parrot/Poly/ghost/handle_automated_speech() @@ -983,4 +996,4 @@ loc = H H.ContractDisease(P) parrot_interest = null - H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!") + H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 1a14a9cd36..144fec4a4a 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -85,6 +85,8 @@ //domestication var/tame = 0 + no_vore = TRUE + /mob/living/simple_animal/Initialize() . = ..() GLOB.simple_animals += src @@ -231,7 +233,6 @@ if( abs(areatemp - bodytemperature) > 40 ) var/diff = areatemp - bodytemperature diff = diff / 5 - //to_chat(world, "changed from [bodytemperature] by [diff] to [bodytemperature + diff]") bodytemperature += diff if(!environment_is_safe(environment)) diff --git a/code/modules/mob/living/simple_animal/simple_animal_vr.dm b/code/modules/mob/living/simple_animal/simple_animal_vr.dm index 1ba77aa67f..2eca841c17 100644 --- a/code/modules/mob/living/simple_animal/simple_animal_vr.dm +++ b/code/modules/mob/living/simple_animal/simple_animal_vr.dm @@ -4,15 +4,15 @@ devourable = FALSE //insurance because who knows. var/vore_active = FALSE // If vore behavior is enabled for this mob - var/vore_capacity = 1 // The capacity (in people) this person can hold var/vore_default_mode = DM_DIGEST // Default bellymode (DM_DIGEST, DM_HOLD, DM_ABSORB) var/vore_digest_chance = 25 // Chance to switch to digest mode if resisted - var/vore_absorb_chance = 0 // Chance to switch to absorb mode if resisted var/vore_escape_chance = 25 // Chance of resisting out of mob var/vore_stomach_name // The name for the first belly if not "stomach" var/vore_stomach_flavor // The flavortext for the first belly if not the default + var/vore_fullness = 0 // How "full" the belly is (controls icons) + // Release belly contents beforey being gc'd! /mob/living/simple_animal/Destroy() @@ -22,6 +22,37 @@ prey_excludes.Cut() . = ..() + +// Update fullness based on size & quantity of belly contents +/mob/living/simple_animal/proc/update_fullness(var/atom/movable/M) + var/new_fullness = 0 + for(var/I in vore_organs) + var/datum/belly/B = vore_organs[I] + if (!(M in B.internal_contents)) + return FALSE // Nothing's inside + new_fullness += M + + vore_fullness = new_fullness + + +/mob/living/simple_animal/proc/swallow_check() + for(var/I in vore_organs) + var/datum/belly/B = vore_organs[I] + if(vore_active) + update_fullness() + if(!vore_fullness) + // Nothing + return + else + addtimer(CALLBACK(src, .proc/swallow_mob), B.swallow_time) + +/mob/living/simple_animal/proc/swallow_mob() + for(var/I in vore_organs) + var/datum/belly/B = vore_organs[I] + for(var/mob/living/M in B.internal_contents) + B.transfer_contents(M, B.transferlocation) + + /mob/living/simple_animal/death() for(var/I in vore_organs) var/datum/belly/B = vore_organs[I] @@ -69,4 +100,3 @@ "The stomach glorps and gurgles as it tries to work you into slop.") src.vore_organs[B.name] = B src.vore_selected = B.name - diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 1545bfd452..4d9fc45b1a 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -546,6 +546,35 @@ to_chat(user, "You place the power control board inside the frame.") qdel(W) + else if(istype(W, /obj/item/device/electroadaptive_pseudocircuit) && opened) + var/obj/item/device/electroadaptive_pseudocircuit/P = W + if(!has_electronics) + if(stat & BROKEN) + to_chat(user, "[src]'s frame is too damaged to support a circuit.") + return + if(!P.adapt_circuit(user, 50)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a power control board and click it into place in [src]'s guts.") + has_electronics = TRUE + locked = TRUE + else if(!cell) + if(stat & MAINT) + to_chat(user, "There's no connector for a power cell.") + return + if(!P.adapt_circuit(user, 500)) + return + var/obj/item/stock_parts/cell/crap/empty/C = new(src) + C.forceMove(src) + cell = C + chargecount = 0 + user.visible_message("[user] fabricates a weak power cell and places it into [src].", \ + "Your [P.name] whirrs with strain as you create a weak power cell and place it into [src]!") + update_icon() + else + to_chat(user, "[src] has both electronics and a cell.") + return + else if (istype(W, /obj/item/weldingtool) && opened && has_electronics==0 && !terminal) var/obj/item/weldingtool/WT = W if (WT.get_fuel() < 3) diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index b5eef4260e..6aeaff9477 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -82,24 +82,16 @@ return if(powernet) - //to_chat(world, "cold_circ and hot_circ pass") - var/datum/gas_mixture/cold_air = cold_circ.return_transfer_air() var/datum/gas_mixture/hot_air = hot_circ.return_transfer_air() - //to_chat(world, "hot_air = [hot_air]; cold_air = [cold_air];") - if(cold_air && hot_air) - //to_chat(world, "hot_air = [hot_air] temperature = [hot_air.temperature]; cold_air = [cold_air] temperature = [hot_air.temperature];") - - //to_chat(world, "coldair and hotair pass") var/cold_air_heat_capacity = cold_air.heat_capacity() var/hot_air_heat_capacity = hot_air.heat_capacity() var/delta_temperature = hot_air.temperature - cold_air.temperature - //to_chat(world, "delta_temperature = [delta_temperature]; cold_air_heat_capacity = [cold_air_heat_capacity]; hot_air_heat_capacity = [hot_air_heat_capacity]") if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0) var/efficiency = 0.65 @@ -109,13 +101,9 @@ var/heat = energy_transfer*(1-efficiency) lastgen += energy_transfer*efficiency - //to_chat(world, "lastgen = [lastgen]; heat = [heat]; delta_temperature = [delta_temperature]; hot_air_heat_capacity = [hot_air_heat_capacity]; cold_air_heat_capacity = [cold_air_heat_capacity];") - hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity - //to_chat(world, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]") - //add_avail(lastgen) This is done in process now // update icon overlays only if displayed level has changed diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index 65cce2b7c7..848d690853 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -1,100 +1,126 @@ +// .357 (Syndie Revolver) + /obj/item/ammo_casing/a357 + name = ".357 bullet casing" desc = "A .357 bullet casing." caliber = "357" - projectile_type = /obj/item/projectile/bullet + projectile_type = /obj/item/projectile/bullet/a357 + +// 7.62 (Nagant Rifle) /obj/item/ammo_casing/a762 + name = "7.62 bullet casing" desc = "A 7.62 bullet casing." icon_state = "762-casing" caliber = "a762" - projectile_type = /obj/item/projectile/bullet + projectile_type = /obj/item/projectile/bullet/a762 /obj/item/ammo_casing/a762/enchanted - projectile_type = /obj/item/projectile/bullet/weakbullet3 + projectile_type = /obj/item/projectile/bullet/a762_enchanted -/obj/item/ammo_casing/a50 - desc = "A .50AE bullet casing." - caliber = ".50" - projectile_type = /obj/item/projectile/bullet - -/obj/item/ammo_casing/c38 - desc = "A .38 bullet casing." - caliber = "38" - projectile_type = /obj/item/projectile/bullet/weakbullet2 - -/obj/item/ammo_casing/c10mm - desc = "A 10mm bullet casing." - caliber = "10mm" - projectile_type = /obj/item/projectile/bullet/midbullet3 - -/obj/item/ammo_casing/c10mm/ap - projectile_type = /obj/item/projectile/bullet/midbullet3/ap - -/obj/item/ammo_casing/c10mm/fire - projectile_type = /obj/item/projectile/bullet/midbullet3/fire - -/obj/item/ammo_casing/c10mm/hp - projectile_type = /obj/item/projectile/bullet/midbullet3/hp - -/obj/item/ammo_casing/c9mm - desc = "A 9mm bullet casing." - caliber = "9mm" - projectile_type = /obj/item/projectile/bullet/weakbullet3 - -/obj/item/ammo_casing/c9mmap - desc = "A 9mm bullet casing." - caliber = "9mm" - projectile_type =/obj/item/projectile/bullet/armourpiercing - -/obj/item/ammo_casing/c9mmtox - desc = "A 9mm bullet casing." - caliber = "9mm" - projectile_type = /obj/item/projectile/bullet/toxinbullet - -/obj/item/ammo_casing/c9mminc - desc = "A 9mm bullet casing." - caliber = "9mm" - projectile_type = /obj/item/projectile/bullet/incendiary/firebullet - -/obj/item/ammo_casing/c46x30mm - desc = "A 4.6x30mm bullet casing." - caliber = "4.6x30mm" - projectile_type = /obj/item/projectile/bullet/weakbullet3 - -/obj/item/ammo_casing/c46x30mmap - desc = "A 4.6x30mm bullet casing." - caliber = "4.6x30mm" - projectile_type =/obj/item/projectile/bullet/armourpiercing - -/obj/item/ammo_casing/c46x30mmtox - desc = "A 4.6x30mm bullet casing." - caliber = "4.6x30mm" - projectile_type = /obj/item/projectile/bullet/toxinbullet - -/obj/item/ammo_casing/c46x30mminc - desc = "A 4.6x30mm bullet casing." - caliber = "4.6x30mm" - projectile_type = /obj/item/projectile/bullet/incendiary/firebullet - -/obj/item/ammo_casing/c45 - desc = "A .45 bullet casing." - caliber = ".45" - projectile_type = /obj/item/projectile/bullet/midbullet - -/obj/item/ammo_casing/c45nostamina - desc = "A .45 bullet casing." - caliber = ".45" - projectile_type = /obj/item/projectile/bullet/midbullet3 +// 7.62x38mmR (Nagant Revolver) /obj/item/ammo_casing/n762 + name = "7.62x38mmR bullet casing" desc = "A 7.62x38mmR bullet casing." caliber = "n762" - projectile_type = /obj/item/projectile/bullet + projectile_type = /obj/item/projectile/bullet/n762 + +// .50AE (Desert Eagle) + +/obj/item/ammo_casing/a50AE + name = ".50AE bullet casing" + desc = "A .50AE bullet casing." + caliber = ".50" + projectile_type = /obj/item/projectile/bullet/a50AE + +// .38 (Detective's Gun) + +/obj/item/ammo_casing/c38 + name = ".38 bullet casing" + desc = "A .38 bullet casing." + caliber = "38" + projectile_type = /obj/item/projectile/bullet/c38 + +// 10mm (Stechkin) + +/obj/item/ammo_casing/c10mm + name = ".10mm bullet casing" + desc = "A 10mm bullet casing." + caliber = "10mm" + projectile_type = /obj/item/projectile/bullet/c10mm + +/obj/item/ammo_casing/c10mm/ap + name = ".10mm armor-piercing bullet casing" + desc = "A 10mm armor-piercing bullet casing." + projectile_type = /obj/item/projectile/bullet/c10mm_ap + +/obj/item/ammo_casing/c10mm/hp + name = ".10mm hollow-point bullet casing" + desc = "A 10mm hollow-point bullet casing." + projectile_type = /obj/item/projectile/bullet/c10mm_hp + +/obj/item/ammo_casing/c10mm/fire + name = ".10mm incendiary bullet casing" + desc = "A 10mm incendiary bullet casing." + projectile_type = /obj/item/projectile/bullet/incendiary/c10mm + +// 9mm (Stechkin APS) + +/obj/item/ammo_casing/c9mm + name = "9mm bullet casing" + desc = "A 9mm bullet casing." + caliber = "9mm" + projectile_type = /obj/item/projectile/bullet/c9mm + +/obj/item/ammo_casing/c9mm/ap + name = "9mm armor-piercing bullet casing" + desc = "A 9mm armor-piercing bullet casing." + projectile_type =/obj/item/projectile/bullet/c9mm_ap + +/obj/item/ammo_casing/c9mm/inc + name = "9mm incendiary bullet casing" + desc = "A 9mm incendiary bullet casing." + projectile_type = /obj/item/projectile/bullet/incendiary/c9mm + +// 4.6x30mm (Autorifles) + +/obj/item/ammo_casing/c46x30mm + name = "4.6x30mm bullet casing" + desc = "A 4.6x30mm bullet casing." + caliber = "4.6x30mm" + projectile_type = /obj/item/projectile/bullet/c46x30mm + +/obj/item/ammo_casing/c46x30mm/ap + name = "4.6x30mm armor-piercing bullet casing" + desc = "A 4.6x30mm armor-piercing bullet casing." + projectile_type = /obj/item/projectile/bullet/c46x30mm_ap + +/obj/item/ammo_casing/c46x30mm/inc + name = "4.6x30mm incendiary bullet casing" + desc = "A 4.6x30mm incendiary bullet casing." + projectile_type = /obj/item/projectile/bullet/incendiary/c46x30mm + +// .45 (M1911) + +/obj/item/ammo_casing/c45 + name = ".45 bullet casing" + desc = "A .45 bullet casing." + caliber = ".45" + projectile_type = /obj/item/projectile/bullet/c45 + +/obj/item/ammo_casing/c45/nostamina + projectile_type = /obj/item/projectile/bullet/c45_nostamina + +// 5.56mm (M-90gl Carbine) /obj/item/ammo_casing/a556 + name = "5.56mm bullet casing" desc = "A 5.56mm bullet casing." caliber = "a556" - projectile_type = /obj/item/projectile/bullet/heavybullet + projectile_type = /obj/item/projectile/bullet/a556 + +// 40mm (Grenade Launcher) /obj/item/ammo_casing/a40mm name = "40mm HE shell" @@ -103,148 +129,93 @@ icon_state = "40mmHE" projectile_type = /obj/item/projectile/bullet/a40mm +// .50 (Sniper) - -/////SNIPER ROUNDS - -/obj/item/ammo_casing/point50 +/obj/item/ammo_casing/p50 + name = ".50 bullet casing" desc = "A .50 bullet casing." caliber = ".50" - projectile_type = /obj/item/projectile/bullet/sniper + projectile_type = /obj/item/projectile/bullet/p50 icon_state = ".50" -/obj/item/ammo_casing/soporific +/obj/item/ammo_casing/p50/soporific + name = ".50 soporific bullet casing" desc = "A .50 bullet casing, specialised in sending the target to sleep, instead of hell." - caliber = ".50" - projectile_type = /obj/item/projectile/bullet/sniper/soporific + projectile_type = /obj/item/projectile/bullet/p50/soporific icon_state = "sleeper" -/obj/item/ammo_casing/haemorrhage - desc = "A .50 bullet casing, specialised in causing massive bloodloss." - caliber = ".50" - projectile_type = /obj/item/projectile/bullet/sniper/haemorrhage - icon_state = ".50" - -/obj/item/ammo_casing/penetrator +/obj/item/ammo_casing/p50/penetrator + name = ".50 penetrator round bullet casing" desc = "A .50 caliber penetrator round casing." - caliber = ".50" - projectile_type = /obj/item/projectile/bullet/sniper/penetrator - icon_state = ".50" + projectile_type = /obj/item/projectile/bullet/p50/penetrator -/obj/item/ammo_casing/point50/gang - desc = "A black market .50 bullet casing." - projectile_type = /obj/item/projectile/bullet/sniper/gang - -/obj/item/ammo_casing/point50/gang/sleeper - desc = "Am illegally modified tranquilizer round." - projectile_type = /obj/item/projectile/bullet/sniper/gang/sleeper - icon_state = "sleeper" - -/// SAW ROUNDS +// 1.95x129mm (SAW) /obj/item/ammo_casing/mm195x129 + name = "1.95x129mm bullet casing" desc = "A 1.95x129mm bullet casing." icon_state = "762-casing" caliber = "mm195129" - projectile_type = /obj/item/projectile/bullet/saw - -/obj/item/ammo_casing/mm195x129/bleeding - desc = "A 1.95x129mm bullet casing with specialized inner-casing, that when it makes contact with a target, releases tiny shrapnel to induce internal bleeding." - icon_state = "762-casing" - projectile_type = /obj/item/projectile/bullet/saw/bleeding - -/obj/item/ammo_casing/mm195x129/hollow - desc = "A 1.95x129mm bullet casing designed to cause more damage to unarmored targets." - projectile_type = /obj/item/projectile/bullet/saw/hollow + projectile_type = /obj/item/projectile/bullet/mm195x129 /obj/item/ammo_casing/mm195x129/ap + name = "1.95x129mm armor-piercing bullet casing" desc = "A 1.95x129mm bullet casing designed with a hardened-tipped core to help penetrate armored targets." - projectile_type = /obj/item/projectile/bullet/saw/ap + projectile_type = /obj/item/projectile/bullet/mm195x129_ap + +/obj/item/ammo_casing/mm195x129/hollow + name = "1.95x129mm hollow-point bullet casing" + desc = "A 1.95x129mm bullet casing designed to cause more damage to unarmored targets." + projectile_type = /obj/item/projectile/bullet/mm195x129_hp /obj/item/ammo_casing/mm195x129/incen + name = "1.95x129mm incendiary bullet casing" desc = "A 1.95x129mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames. " - projectile_type = /obj/item/projectile/bullet/saw/incen + projectile_type = /obj/item/projectile/bullet/incendiary/mm195x129 - - - -//SHOTGUN ROUNDS +// Shotgun /obj/item/ammo_casing/shotgun name = "shotgun slug" desc = "A 12 gauge lead slug." icon_state = "blshell" caliber = "shotgun" - projectile_type = /obj/item/projectile/bullet + projectile_type = /obj/item/projectile/bullet/shotgun_slug materials = list(MAT_METAL=4000) - -/obj/item/ammo_casing/shotgun/buckshot - name = "buckshot shell" - desc = "A 12 gauge buckshot shell." - icon_state = "gshell" - projectile_type = /obj/item/projectile/bullet/pellet - pellets = 6 - variance = 25 - -/obj/item/ammo_casing/shotgun/rubbershot - name = "rubber shot" - desc = "A shotgun casing filled with densely-packed rubber balls, used to incapacitate crowds from a distance." - icon_state = "bshell" - projectile_type = /obj/item/projectile/bullet/rpellet - pellets = 6 - variance = 25 - materials = list(MAT_METAL=4000) - - /obj/item/ammo_casing/shotgun/beanbag name = "beanbag slug" desc = "A weak beanbag slug for riot control." icon_state = "bshell" - projectile_type = /obj/item/projectile/bullet/weakbullet + projectile_type = /obj/item/projectile/bullet/shotgun_beanbag materials = list(MAT_METAL=250) +/obj/item/ammo_casing/shotgun/incendiary + name = "incendiary slug" + desc = "An incendiary-coated shotgun slug." + icon_state = "ishell" + projectile_type = /obj/item/projectile/bullet/incendiary/shotgun -/obj/item/ammo_casing/shotgun/improvised - name = "improvised shell" - desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards." - icon_state = "improvshell" - projectile_type = /obj/item/projectile/bullet/pellet/weak - materials = list(MAT_METAL=250) - pellets = 10 - variance = 25 - - -/obj/item/ammo_casing/shotgun/improvised/overload - name = "overloaded improvised shell" - desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards. This one has been packed with even more \ - propellant. It's like playing russian roulette, with a shotgun." - icon_state = "improvshell" - projectile_type = /obj/item/projectile/bullet/pellet/overload - materials = list(MAT_METAL=250) +/obj/item/ammo_casing/shotgun/dragonsbreath + name = "dragonsbreath shell" + desc = "A shotgun shell which fires a spread of incendiary pellets." + icon_state = "ishell2" + projectile_type = /obj/item/projectile/bullet/incendiary/shotgun/dragonsbreath pellets = 4 - variance = 40 - + variance = 35 /obj/item/ammo_casing/shotgun/stunslug name = "taser slug" desc = "A stunning taser slug." icon_state = "stunshell" - projectile_type = /obj/item/projectile/bullet/stunshot + projectile_type = /obj/item/projectile/bullet/shotgun_stunslug materials = list(MAT_METAL=250) - -/obj/item/ammo_casing/shotgun/meteorshot - name = "meteorshot shell" +/obj/item/ammo_casing/shotgun/meteorslug + name = "meteorslug shell" desc = "A shotgun shell rigged with CMC technology, which launches a massive slug when fired." icon_state = "mshell" - projectile_type = /obj/item/projectile/bullet/meteorshot - -/obj/item/ammo_casing/shotgun/breaching - name = "breaching shell" - desc = "An economic version of the meteorshot, utilizing similar technologies. Great for busting down doors." - icon_state = "mshell" - projectile_type = /obj/item/projectile/bullet/meteorshot/weak + projectile_type = /obj/item/projectile/bullet/shotgun_meteorslug /obj/item/ammo_casing/shotgun/pulseslug name = "pulse slug" @@ -252,27 +223,39 @@ energy blast. While the heat and power drain limit it to one use, it can still allow an operator to engage targets that ballistic ammunition \ would have difficulty with." icon_state = "pshell" - projectile_type = /obj/item/projectile/beam/pulse/shot - -/obj/item/ammo_casing/shotgun/incendiary - name = "incendiary slug" - desc = "An incendiary-coated shotgun slug." - icon_state = "ishell" - projectile_type = /obj/item/projectile/bullet/incendiary/shell + projectile_type = /obj/item/projectile/beam/pulse/shotgun /obj/item/ammo_casing/shotgun/frag12 name = "FRAG-12 slug" desc = "A high explosive breaching round for a 12 gauge shotgun." icon_state = "heshell" - projectile_type = /obj/item/projectile/bullet/frag12 + projectile_type = /obj/item/projectile/bullet/shotgun_frag12 -/obj/item/ammo_casing/shotgun/incendiary/dragonsbreath - name = "dragonsbreath shell" - desc = "A shotgun shell which fires a spread of incendiary pellets." - icon_state = "ishell2" - projectile_type = /obj/item/projectile/bullet/incendiary/shell/dragonsbreath - pellets = 4 - variance = 35 +/obj/item/ammo_casing/shotgun/buckshot + name = "buckshot shell" + desc = "A 12 gauge buckshot shell." + icon_state = "gshell" + projectile_type = /obj/item/projectile/bullet/pellet/shotgun_buckshot + pellets = 6 + variance = 25 + +/obj/item/ammo_casing/shotgun/rubbershot + name = "rubber shot" + desc = "A shotgun casing filled with densely-packed rubber balls, used to incapacitate crowds from a distance." + icon_state = "bshell" + projectile_type = /obj/item/projectile/bullet/pellet/shotgun_rubbershot + pellets = 6 + variance = 25 + materials = list(MAT_METAL=4000) + +/obj/item/ammo_casing/shotgun/improvised + name = "improvised shell" + desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards." + icon_state = "improvshell" + projectile_type = /obj/item/projectile/bullet/pellet/shotgun_improvised + materials = list(MAT_METAL=250) + pellets = 10 + variance = 25 /obj/item/ammo_casing/shotgun/ion name = "ion shell" @@ -319,4 +302,4 @@ reagents.add_reagent("spore", 6) reagents.add_reagent("mutetoxin", 6) //;HELP OPS IN MAINT reagents.add_reagent("coniine", 6) - reagents.add_reagent("sodium_thiopental", 6) + reagents.add_reagent("sodium_thiopental", 6) \ No newline at end of file diff --git a/code/modules/projectiles/ammunition/special.dm b/code/modules/projectiles/ammunition/special.dm index fa9c2ae5b0..11fd12da70 100644 --- a/code/modules/projectiles/ammunition/special.dm +++ b/code/modules/projectiles/ammunition/special.dm @@ -85,7 +85,7 @@ ..() /obj/item/ammo_casing/energy/c3dbullet - projectile_type = /obj/item/projectile/bullet/midbullet3 + projectile_type = /obj/item/projectile/bullet/c3d select_name = "spraydown" fire_sound = 'sound/weapons/gunshot_smg.ogg' e_cost = 20 diff --git a/code/modules/projectiles/boxes_magazines/external_mag.dm b/code/modules/projectiles/boxes_magazines/external_mag.dm index 525466be28..5ffe1b475a 100644 --- a/code/modules/projectiles/boxes_magazines/external_mag.dm +++ b/code/modules/projectiles/boxes_magazines/external_mag.dm @@ -1,6 +1,4 @@ - - ///////////EXTERNAL MAGAZINES//////////////// /obj/item/ammo_box/magazine/m10mm @@ -72,25 +70,16 @@ /obj/item/ammo_box/magazine/wt550m9/wtap name = "wt550 magazine (Armour Piercing 4.6x30mm)" icon_state = "46x30mmtA-20" - ammo_type = /obj/item/ammo_casing/c46x30mmap + ammo_type = /obj/item/ammo_casing/c46x30mm/ap /obj/item/ammo_box/magazine/wt550m9/wtap/update_icon() ..() icon_state = "46x30mmtA-[round(ammo_count(),4)]" -/obj/item/ammo_box/magazine/wt550m9/wttx - name = "wt550 magazine (Toxin Tipped 4.6x30mm)" - icon_state = "46x30mmtT-20" - ammo_type = /obj/item/ammo_casing/c46x30mmtox - -/obj/item/ammo_box/magazine/wt550m9/wttx/update_icon() - ..() - icon_state = "46x30mmtT-[round(ammo_count(),4)]" - /obj/item/ammo_box/magazine/wt550m9/wtic name = "wt550 magazine (Incindiary 4.6x30mm)" icon_state = "46x30mmtI-20" - ammo_type = /obj/item/ammo_casing/c46x30mminc + ammo_type = /obj/item/ammo_casing/c46x30mm/inc /obj/item/ammo_box/magazine/wt550m9/wtic/update_icon() ..() @@ -120,15 +109,11 @@ /obj/item/ammo_box/magazine/smgm9mm/ap name = "SMG magazine (Armour Piercing 9mm)" - ammo_type = /obj/item/ammo_casing/c9mmap - -/obj/item/ammo_box/magazine/smgm9mm/toxin - name = "SMG magazine (Toxin Tipped 9mm)" - ammo_type = /obj/item/ammo_casing/c9mmtox + ammo_type = /obj/item/ammo_casing/c9mm/ap /obj/item/ammo_box/magazine/smgm9mm/fire name = "SMG Magazine (Incindiary 9mm)" - ammo_type = /obj/item/ammo_casing/c9mminc + ammo_type = /obj/item/ammo_casing/c9mm/inc /obj/item/ammo_box/magazine/pistolm9mm name = "pistol magazine (9mm)" @@ -145,7 +130,7 @@ name = "SMG magazine (.45)" icon_state = "c20r45-24" origin_tech = "combat=2" - ammo_type = /obj/item/ammo_casing/c45nostamina + ammo_type = /obj/item/ammo_casing/c45/nostamina caliber = ".45" max_ammo = 24 @@ -164,7 +149,7 @@ name = "handgun magazine (.50ae)" icon_state = "50ae" origin_tech = "combat=2" - ammo_type = /obj/item/ammo_casing/a50 + ammo_type = /obj/item/ammo_casing/a50AE caliber = ".50" max_ammo = 7 multiple_sprites = 1 @@ -212,17 +197,17 @@ /obj/item/ammo_box/magazine/m12g/dragon name = "shotgun magazine (12g dragon's breath)" icon_state = "m12gf" - ammo_type = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath + ammo_type = /obj/item/ammo_casing/shotgun/dragonsbreath /obj/item/ammo_box/magazine/m12g/bioterror name = "shotgun magazine (12g bioterror)" icon_state = "m12gt" ammo_type = /obj/item/ammo_casing/shotgun/dart/bioterror -/obj/item/ammo_box/magazine/m12g/breach - name = "shotgun magazine (12g breacher slugs)" +/obj/item/ammo_box/magazine/m12g/meteor + name = "shotgun magazine (12g meteor slugs)" icon_state = "m12gbc" - ammo_type = /obj/item/ammo_casing/shotgun/breaching + ammo_type = /obj/item/ammo_casing/shotgun/meteorslug //// SNIPER MAGAZINES @@ -231,7 +216,7 @@ name = "sniper rounds (.50)" icon_state = ".50mag" origin_tech = "combat=6;syndicate=2" - ammo_type = /obj/item/ammo_casing/point50 + ammo_type = /obj/item/ammo_casing/p50 max_ammo = 6 caliber = ".50" @@ -246,37 +231,17 @@ desc = "Soporific sniper rounds, designed for happy days and dead quiet nights..." icon_state = "soporific" origin_tech = "combat=6;syndicate=3" - ammo_type = /obj/item/ammo_casing/soporific + ammo_type = /obj/item/ammo_casing/p50/soporific max_ammo = 3 caliber = ".50" -/obj/item/ammo_box/magazine/sniper_rounds/haemorrhage - name = "sniper rounds (Bleed)" - desc = "Haemorrhage sniper rounds, leaves your target in a pool of crimson pain" - icon_state = "haemorrhage" - ammo_type = /obj/item/ammo_casing/haemorrhage - max_ammo = 5 - caliber = ".50" - /obj/item/ammo_box/magazine/sniper_rounds/penetrator name = "sniper rounds (penetrator)" desc = "An extremely powerful round capable of passing straight through cover and anyone unfortunate enough to be behind it." - ammo_type = /obj/item/ammo_casing/penetrator + ammo_type = /obj/item/ammo_casing/p50/penetrator origin_tech = "combat=6;syndicate=3" max_ammo = 5 -/obj/item/ammo_box/magazine/sniper_rounds/gang - name = "black market sniper rounds (.50)" - icon_state = ".50mag" - origin_tech = "combat=6" - ammo_type = /obj/item/ammo_casing/point50/gang - -/obj/item/ammo_box/magazine/sniper_rounds/gang/sleeper - name = "illegally modified tranquilizer round" - icon_state = "soporific" - origin_tech = "combat=6" - ammo_type = /obj/item/ammo_casing/point50/gang/sleeper - //// SAW MAGAZINES /obj/item/ammo_box/magazine/mm195x129 @@ -287,11 +252,6 @@ caliber = "mm195129" max_ammo = 50 -/obj/item/ammo_box/magazine/mm195x129/bleeding - name = "box magazine (Bleeding 1.95x129mm)" - origin_tech = "combat=3" - ammo_type = /obj/item/ammo_casing/mm195x129/bleeding - /obj/item/ammo_box/magazine/mm195x129/hollow name = "box magazine (Hollow-Point 1.95x129mm)" origin_tech = "combat=3" diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 5388bf8e0a..423cd56202 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -384,11 +384,6 @@ pin = /obj/item/device/firing_pin/implant/pindicate origin_tech = "combat=7;syndicate=6" -/obj/item/gun/ballistic/automatic/sniper_rifle/gang - name = "black market sniper rifle" - desc = "A long ranged weapon that does significant damage. It is well worn from years of service." - mag_type = /obj/item/ammo_box/magazine/sniper_rounds/gang - // Old Semi-Auto Rifle // /obj/item/gun/ballistic/automatic/surplus diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 527d02e52a..a0f4712471 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -324,7 +324,6 @@ //Split Y+Pixel_Y up into list(Y, Pixel_Y) var/list/screen_loc_Y = splittext(screen_loc_params[2],":") - // to_chat(world, "X: [screen_loc_X[1]] PixelX: [screen_loc_X[2]] / Y: [screen_loc_Y[1]] PixelY: [screen_loc_Y[2]]") var/x = text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32 var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32 @@ -333,9 +332,7 @@ var/ox = round(screenview/2) - user.client.pixel_x //"origin" x var/oy = round(screenview/2) - user.client.pixel_y //"origin" y - // to_chat(world, "Pixel position: [x] [y]") angle = Atan2(y - oy, x - ox) - // to_chat(world, "Angle: [angle]") return list(angle, p_x, p_y) /obj/item/projectile/Crossed(atom/movable/AM) //A mob moving on a tile with a projectile is hit by it. diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 844a8a4662..d1d7b50cf5 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -77,7 +77,7 @@ if(isturf(target) || istype(target, /obj/structure/)) target.ex_act(EXPLODE_HEAVY) -/obj/item/projectile/beam/pulse/shot +/obj/item/projectile/beam/pulse/shotgun damage = 40 /obj/item/projectile/beam/pulse/heavy diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index d11fa850c2..6f4ae50243 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -3,105 +3,238 @@ icon_state = "bullet" damage = 60 damage_type = BRUTE - nodamage = 0 + nodamage = FALSE flag = "bullet" hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect -/obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage - damage = 5 - stamina = 80 - -/obj/item/projectile/bullet/weakbullet2 //detective revolver instastuns, but multiple shots are better for keeping punks down - damage = 15 - knockdown = 30 - stamina = 50 - -/obj/item/projectile/bullet/weakbullet3 - damage = 20 - -/obj/item/projectile/bullet/toxinbullet - damage = 15 - damage_type = TOX - -/obj/item/projectile/bullet/incendiary/firebullet - damage = 10 - -/obj/item/projectile/bullet/armourpiercing - damage = 15 - armour_penetration = 40 - -/obj/item/projectile/bullet/pellet - name = "pellet" - damage = 12.5 - /obj/item/projectile/bullet/pellet/Range() ..() damage += -0.75 if(damage < 0) qdel(src) -/obj/item/projectile/bullet/pellet/weak - damage = 6 - -/obj/item/projectile/bullet/pellet/weak/New() - range = rand(1, 8) - ..() - -/obj/item/projectile/bullet/pellet/weak/on_range() - do_sparks(1, TRUE, src) - ..() - -/obj/item/projectile/bullet/pellet/overload - damage = 3 - -/obj/item/projectile/bullet/pellet/overload/New() - range = rand(1, 10) - ..() - -/obj/item/projectile/bullet/pellet/overload/on_hit(atom/target, blocked = FALSE) - ..() - explosion(target, 0, 0, 2) - -/obj/item/projectile/bullet/pellet/overload/on_range() - explosion(src, 0, 0, 2) - do_sparks(3, TRUE, src) - ..() - -/obj/item/projectile/bullet/midbullet +/obj/item/projectile/bullet/incendiary damage = 20 - stamina = 65 //two round bursts from the c20r knocks people down + var/fire_stacks = 4 +/obj/item/projectile/bullet/incendiary/on_hit(atom/target, blocked = FALSE) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/M = target + M.adjust_fire_stacks(fire_stacks) + M.IgniteMob() -/obj/item/projectile/bullet/midbullet2 - damage = 25 +/obj/item/projectile/bullet/incendiary/Move() + . = ..() + var/turf/location = get_turf(src) + if(location) + new /obj/effect/hotspot(location) + location.hotspot_expose(700, 50, 1) -/obj/item/projectile/bullet/midbullet3 +// .357 (Syndie Revolver) + +/obj/item/projectile/bullet/a357 + name = ".357 bullet" + damage = 60 + +// 7.62 (Nagant Rifle) + +/obj/item/projectile/bullet/a762 + name = "7.62 bullet" + damage = 60 + +/obj/item/projectile/bullet/a762_enchanted + name = "enchanted 7.62 bullet" + damage = 5 + stamina = 80 + +// 7.62x38mmR (Nagant Revolver) + +/obj/item/projectile/bullet/n762 + name = "7.62x38mmR bullet" + damage = 60 + +// .50AE (Desert Eagle) + +/obj/item/projectile/bullet/a50AE + name = ".50AE bullet" + damage = 60 + +// .38 (Detective's Gun) + +/obj/item/projectile/bullet/c38 + name = ".38 bullet" + damage = 15 + knockdown = 30 + stamina = 50 + +// 10mm (Stechkin) + +/obj/item/projectile/bullet/c10mm + name = "10mm bullet" damage = 30 -/obj/item/projectile/bullet/midbullet3/hp - damage = 40 - armour_penetration = -50 - -/obj/item/projectile/bullet/midbullet3/ap +/obj/item/projectile/bullet/c10mm_ap + name = "10mm armor-piercing bullet" damage = 27 armour_penetration = 40 -/obj/item/projectile/bullet/midbullet3/fire/on_hit(atom/target, blocked = FALSE) - if(..(target, blocked)) - var/mob/living/M = target - M.adjust_fire_stacks(1) - M.IgniteMob() +/obj/item/projectile/bullet/c10mm_hp + name = "10mm hollow-point bullet" + damage = 40 + armour_penetration = -50 -/obj/item/projectile/bullet/heavybullet +/obj/item/projectile/bullet/incendiary/c10mm + name = "10mm incendiary bullet" + damage = 15 + fire_stacks = 2 + +// 9mm (Stechkin APS) + +/obj/item/projectile/bullet/c9mm + name = "9mm bullet" + damage = 20 + +/obj/item/projectile/bullet/c9mm_ap + name = "9mm armor-piercing bullet" + damage = 15 + armour_penetration = 40 + +/obj/item/projectile/bullet/incendiary/c9mm + name = "9mm incendiary bullet" + damage = 10 + fire_stacks = 1 + +// 4.6x30mm (Autorifles) + +/obj/item/projectile/bullet/c46x30mm + desc = "4.6x30mm bullet" + damage = 20 + +/obj/item/projectile/bullet/c46x30mm_ap + name = "4.6x30mm armor-piercing bullet" + damage = 15 + armour_penetration = 40 + +/obj/item/projectile/bullet/incendiary/c46x30mm + name = "4.6x30mm incendiary bullet" + damage = 10 + fire_stacks = 1 + +// .45 (M1911) + +/obj/item/projectile/bullet/c45 + name = ".45 bullet" + damage = 20 + stamina = 65 + +/obj/item/projectile/bullet/c45_nostamina + name = ".45 bullet" + damage = 20 + +// 5.56mm (M-90gl Carbine) + +/obj/item/projectile/bullet/a556 + name = "5.56mm bullet" damage = 35 -/obj/item/projectile/bullet/rpellet - damage = 3 - stamina = 25 +// 40mm (Grenade Launcher -/obj/item/projectile/bullet/stunshot //taser slugs for shotguns, nothing special - name = "stunshot" +/obj/item/projectile/bullet/a40mm + name ="40mm grenade" + desc = "USE A WEEL GUN" + icon_state= "bolter" + damage = 60 + +/obj/item/projectile/bullet/a40mm/on_hit(atom/target, blocked = FALSE) + ..() + explosion(target, -1, 0, 2, 1, 0, flame_range = 3) + return TRUE + +// .50 (Sniper) + +/obj/item/projectile/bullet/p50 + name =".50 bullet" + speed = 0 //360 alwaysscope. + damage = 70 + knockdown = 100 + dismemberment = 50 + armour_penetration = 50 + var/breakthings = TRUE + +/obj/item/projectile/bullet/p50/on_hit(atom/target, blocked = 0) + if((blocked != 100) && (!ismob(target) && breakthings)) + target.ex_act(rand(1,2)) + return ..() + +/obj/item/projectile/bullet/p50/soporific + name =".50 soporific bullet" + armour_penetration = 0 + nodamage = TRUE + dismemberment = 0 + knockdown = 0 + breakthings = FALSE + +/obj/item/projectile/bullet/p50/soporific/on_hit(atom/target, blocked = FALSE) + if((blocked != 100) && isliving(target)) + var/mob/living/L = target + L.Sleeping(400) + return ..() + +/obj/item/projectile/bullet/p50/penetrator + name =".50 penetrator bullet" + icon_state = "gauss" + name = "penetrator round" + damage = 60 + forcedodge = TRUE + dismemberment = 0 //It goes through you cleanly. + knockdown = 0 + breakthings = FALSE + +// 1.95x129mm (SAW) + +/obj/item/projectile/bullet/mm195x129 + name = "1.95x129mm bullet" + damage = 45 + armour_penetration = 5 + +/obj/item/projectile/bullet/mm195x129_ap + name = "1.95x129mm armor-piercing bullet" + damage = 40 + armour_penetration = 75 + +/obj/item/projectile/bullet/mm195x129_hp + name = "1.95x129mm hollow-point bullet" + damage = 60 + armour_penetration = -60 + +/obj/item/projectile/bullet/incendiary/mm195x129 + name = "1.95x129mm incendiary bullet" + damage = 15 + fire_stacks = 3 + +// Shotgun + +/obj/item/projectile/bullet/shotgun_slug + name = "12g shotgun slug" + damage = 60 + +/obj/item/projectile/bullet/shotgun_beanbag + name = "beanbag slug" + damage = 5 + stamina = 80 + +/obj/item/projectile/bullet/incendiary/shotgun + name = "incendiary slug" + damage = 20 + +/obj/item/projectile/bullet/incendiary/shotgun/dragonsbreath + name = "dragonsbreath pellet" + damage = 5 + +/obj/item/projectile/bullet/shotgun_stunslug + name = "stunslug" damage = 5 knockdown = 100 stutter = 5 @@ -110,47 +243,90 @@ icon_state = "spark" color = "#FFFF00" -/obj/item/projectile/bullet/incendiary/on_hit(atom/target, blocked = FALSE) - . = ..() - if(iscarbon(target)) - var/mob/living/carbon/M = target - M.adjust_fire_stacks(4) - M.IgniteMob() - - -/obj/item/projectile/bullet/incendiary/shell - name = "incendiary slug" - damage = 20 - -/obj/item/projectile/bullet/incendiary/shell/Move() - ..() - var/turf/location = get_turf(src) - if(location) - new /obj/effect/hotspot(location) - location.hotspot_expose(700, 50, 1) - -/obj/item/projectile/bullet/incendiary/shell/dragonsbreath - name = "dragonsbreath round" - damage = 5 - - -/obj/item/projectile/bullet/meteorshot - name = "meteor" +/obj/item/projectile/bullet/shotgun_meteorslug + name = "meteorslug" icon = 'icons/obj/meteor.dmi' icon_state = "dust" - damage = 30 - knockdown = 160 + damage = 20 + knockdown = 80 hitsound = 'sound/effects/meteorimpact.ogg' -/obj/item/projectile/bullet/meteorshot/weak - damage = 10 - knockdown = 80 +/obj/item/projectile/bullet/shotgun_meteorslug/on_hit(atom/target, blocked = FALSE) + . = ..() + if(ismovableatom(target)) + var/atom/movable/M = target + var/atom/throw_target = get_edge_target_turf(M, get_dir(src, get_step_away(M, src))) + M.throw_at(throw_target, 3, 2) + +/obj/item/projectile/bullet/shotgun_meteorslug/Initialize() + . = ..() + SpinAnimation() + +/obj/item/projectile/bullet/shotgun_frag12 + name ="frag12 slug" + damage = 25 + knockdown = 50 + +/obj/item/projectile/bullet/shotgun_frag12/on_hit(atom/target, blocked = FALSE) + ..() + explosion(target, -1, 0, 1) + return TRUE + +/obj/item/projectile/bullet/pellet/shotgun_buckshot + name = "buckshot pellet" + damage = 12.5 + +/obj/item/projectile/bullet/pellet/shotgun_rubbershot + damage = 3 + stamina = 25 + +/obj/item/projectile/bullet/pellet/shotgun_improvised + damage = 6 + +/obj/item/projectile/bullet/pellet/shotgun_improvised/Initialize() + . = ..() + range = rand(1, 8) + +/obj/item/projectile/bullet/pellet/shotgun_improvised/on_range() + do_sparks(1, TRUE, src) + ..() + +// Scattershot + +/obj/item/projectile/bullet/scattershot + damage = 20 + stamina = 65 + +// LMD (exosuits) + +/obj/item/projectile/bullet/lmg + damage = 20 + +// Turrets + +/obj/item/projectile/bullet/manned_turret + damage = 20 + +/obj/item/projectile/bullet/syndicate_turret + damage = 20 + +// FNX-99 (Mechs) + +/obj/item/projectile/bullet/incendiary/fnx99 + damage = 20 + +// C3D (Borgs) + +/obj/item/projectile/bullet/c3d + damage = 20 + +// Honker /obj/item/projectile/bullet/honker damage = 0 knockdown = 60 - forcedodge = 1 - nodamage = 1 + forcedodge = TRUE + nodamage = TRUE hitsound = 'sound/items/bikehorn.ogg' icon = 'icons/obj/hydroponics/harvest.dmi' icon_state = "banana" @@ -160,17 +336,7 @@ ..() SpinAnimation() -/obj/item/projectile/bullet/meteorshot/on_hit(atom/target, blocked = FALSE) - . = ..() - if(ismovableatom(target)) - var/atom/movable/M = target - var/atom/throw_target = get_edge_target_turf(M, get_dir(src, get_step_away(M, src))) - M.throw_at(throw_target, 3, 2) - -/obj/item/projectile/bullet/meteorshot/New() - ..() - SpinAnimation() - +// Mime /obj/item/projectile/bullet/mime damage = 20 @@ -181,6 +347,7 @@ var/mob/living/carbon/M = target M.silent = max(M.silent, 10) +// Darts /obj/item/projectile/bullet/dart name = "dart" @@ -210,7 +377,7 @@ ..(target, blocked) reagents.set_reacting(TRUE) reagents.handle_reactions() - return 1 + return TRUE /obj/item/projectile/bullet/dart/metalfoam/New() ..() @@ -223,18 +390,7 @@ name = "syringe" icon_state = "syringeproj" -/obj/item/projectile/bullet/neurotoxin - name = "neurotoxin spit" - icon_state = "neurotoxin" - damage = 5 - damage_type = TOX - knockdown = 100 - -/obj/item/projectile/bullet/neurotoxin/on_hit(atom/target, blocked = FALSE) - if(isalien(target)) - knockdown = 0 - nodamage = 1 - . = ..() // Execute the rest of the code. +// DNA injector /obj/item/projectile/bullet/dnainjector name = "\improper DNA injector" @@ -261,121 +417,3 @@ QDEL_NULL(injector) return ..() -//// SNIPER BULLETS - -/obj/item/projectile/bullet/sniper - speed = 0 //360 alwaysscope. - damage = 70 - knockdown = 100 - dismemberment = 50 - armour_penetration = 50 - var/breakthings = TRUE - -/obj/item/projectile/bullet/sniper/on_hit(atom/target, blocked = FALSE) - if((blocked != 100) && (!ismob(target) && breakthings)) - target.ex_act(rand(1,2)) - return ..() - -/obj/item/projectile/bullet/sniper/gang - damage = 55 - knockdown = 20 - dismemberment = 15 - armour_penetration = 25 - -/obj/item/projectile/bullet/sniper/gang/sleeper - nodamage = 1 - knockdown = 0 - dismemberment = 0 - breakthings = FALSE - -/obj/item/projectile/bullet/sniper/gang/sleeper/on_hit(atom/target, blocked = FALSE) - if((blocked != 100) && isliving(target)) - var/mob/living/L = target - L.blur_eyes(8) - if(L.staminaloss >= 40) - L.Sleeping(400) - else - L.adjustStaminaLoss(55) - return 1 - -/obj/item/projectile/bullet/sniper/soporific - armour_penetration = 0 - nodamage = 1 - dismemberment = 0 - knockdown = 0 - breakthings = FALSE - -/obj/item/projectile/bullet/sniper/soporific/on_hit(atom/target, blocked = FALSE) - if((blocked != 100) && isliving(target)) - var/mob/living/L = target - L.Sleeping(400) - return ..() - - -/obj/item/projectile/bullet/sniper/haemorrhage - armour_penetration = 15 - damage = 15 - dismemberment = 0 - knockdown = 0 - breakthings = FALSE - -/obj/item/projectile/bullet/sniper/haemorrhage/on_hit(atom/target, blocked = FALSE) - if((blocked != 100) && iscarbon(target)) - var/mob/living/carbon/C = target - C.bleed(100) - return ..() - - -/obj/item/projectile/bullet/sniper/penetrator - icon_state = "gauss" - name = "penetrator round" - damage = 60 - forcedodge = 1 - dismemberment = 0 //It goes through you cleanly. - knockdown = 0 - breakthings = FALSE - - - -//// SAW BULLETS - - -/obj/item/projectile/bullet/saw - damage = 45 - armour_penetration = 5 - -/obj/item/projectile/bullet/saw/bleeding - damage = 20 - armour_penetration = 0 - -/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = FALSE) - . = ..() - if((blocked != 100) && iscarbon(target)) - var/mob/living/carbon/C = target - C.bleed(35) - -/obj/item/projectile/bullet/saw/hollow - damage = 60 - armour_penetration = -60 - -/obj/item/projectile/bullet/saw/ap - damage = 40 - armour_penetration = 75 - -/obj/item/projectile/bullet/saw/incen - damage = 7 - armour_penetration = 0 - -/obj/item/projectile/bullet/saw/incen/Move() - ..() - var/turf/location = get_turf(src) - if(location) - new /obj/effect/hotspot(location) - location.hotspot_expose(700, 50, 1) - -/obj/item/projectile/bullet/saw/incen/on_hit(atom/target, blocked = FALSE) - . = ..() - if(iscarbon(target)) - var/mob/living/carbon/M = target - M.adjust_fire_stacks(3) - M.IgniteMob() diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index f9f7686a46..79a3d51eec 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -32,17 +32,6 @@ explosion(target, -1, 0, 2) return 1 -/obj/item/projectile/bullet/a40mm - name ="40mm grenade" - desc = "USE A WEEL GUN" - icon_state= "bolter" - damage = 60 - -/obj/item/projectile/bullet/a40mm/on_hit(atom/target, blocked = FALSE) - ..() - explosion(target, -1, 0, 2, 1, 0, flame_range = 3) - return 1 - /obj/item/projectile/bullet/a84mm name ="anti-armour rocket" desc = "USE A WEEL GUN" @@ -184,16 +173,6 @@ qdel(src) gun.create_portal(src, get_turf(src)) -/obj/item/projectile/bullet/frag12 - name ="explosive slug" - damage = 25 - knockdown = 50 - -/obj/item/projectile/bullet/frag12/on_hit(atom/target, blocked = FALSE) - ..() - explosion(target, -1, 0, 1) - return 1 - /obj/item/projectile/plasma name = "plasma blast" icon_state = "plasmacutter" @@ -616,3 +595,19 @@ /obj/item/projectile/hallucination/death/hal_apply_effect() new /datum/hallucination/death(hal_target, TRUE) + +// Neurotoxin + +/obj/item/projectile/bullet/neurotoxin + name = "neurotoxin spit" + icon_state = "neurotoxin" + damage = 5 + damage_type = TOX + knockdown = 100 + +/obj/item/projectile/bullet/neurotoxin/on_hit(atom/target, blocked = FALSE) + if(isalien(target)) + knockdown = 0 + nodamage = TRUE + return ..() + diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index ad339b8e39..9bcd909faf 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -671,7 +671,6 @@ for(var/reagent in cached_reagents) var/datum/reagent/R = reagent if(R.id == reagent_id) - //to_chat(world, "proffering a data-carrying reagent ([reagent_id])") return R.data /datum/reagents/proc/set_data(reagent_id, new_data) @@ -679,7 +678,6 @@ for(var/reagent in cached_reagents) var/datum/reagent/R = reagent if(R.id == reagent_id) - //to_chat(world, "reagent data set ([reagent_id])") R.data = new_data /datum/reagents/proc/copy_data(datum/reagent/current_reagent) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 538ae996ea..ec4a1f58f8 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -112,8 +112,8 @@ data["maxEnergy"] = cell.maxcharge * powerefficiency data["isBeakerLoaded"] = beaker ? 1 : 0 - var beakerContents[0] - var beakerCurrentVolume = 0 + var/beakerContents[0] + var/beakerCurrentVolume = 0 if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) for(var/datum/reagent/R in beaker.reagents.reagent_list) beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... @@ -129,7 +129,7 @@ data["beakerMaxVolume"] = null data["beakerTransferAmounts"] = null - var chemicals[0] + var/chemicals[0] var/is_hallucinating = FALSE if(user.hallucinating()) is_hallucinating = TRUE diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 802e4c70ca..c6a01bc45f 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -133,13 +133,13 @@ data["pillBotMaxContent"] = bottle.storage_slots - var beakerContents[0] + var/beakerContents[0] if(beaker) for(var/datum/reagent/R in beaker.reagents.reagent_list) beakerContents.Add(list(list("name" = R.name, "id" = R.id, "volume" = R.volume))) // list in a list because Byond merges the first list... data["beakerContents"] = beakerContents - var bufferContents[0] + var/bufferContents[0] if(reagents.total_volume) for(var/datum/reagent/N in reagents.reagent_list) bufferContents.Add(list(list("name" = N.name, "id" = N.id, "volume" = N.volume))) // ^ diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index a370ce2de9..6e02cc5696 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -160,8 +160,8 @@ cube.Expand() // Dehydrated carp - else if(istype(O, /obj/item/toy/carpplushie/dehy_carp)) - var/obj/item/toy/carpplushie/dehy_carp/dehy = O + else if(istype(O, /obj/item/toy/plush/carpplushie/dehy_carp)) + var/obj/item/toy/plush/carpplushie/dehy_carp/dehy = O dehy.Swell() // Makes a carp else if(istype(O, /obj/item/stack/sheet/hairlesshide)) @@ -1576,13 +1576,13 @@ /datum/reagent/magillitis name = "Magillitis" id = "magillitis" - description = "An experimental serum which causes rapid muscular growth in basic primates. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas." + description = "An experimental serum which causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas." reagent_state = LIQUID color = "#00f041" /datum/reagent/magillitis/on_mob_life(mob/living/carbon/M) ..() - if(ismonkey(M) && current_cycle >= 10) + if((ismonkey(M) || ishuman(M)) && current_cycle >= 10) return M.gorillize() /datum/reagent/growthserum diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm index ba106e8cd3..9321595a8d 100644 --- a/code/modules/reagents/reagent_containers/patch.dm +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -13,6 +13,14 @@ /obj/item/reagent_containers/pill/patch/afterattack(obj/target, mob/user , proximity) return // thanks inheritance again +/obj/item/reagent_containers/pill/patch/attack(mob/living/L, mob/user) + if(ishuman(L)) + var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected)) + if(affecting.status != BODYPART_ORGANIC) + to_chat(user, "Medicine won't work on a robotic limb!") + return + ..() + /obj/item/reagent_containers/pill/patch/canconsume(mob/eater, mob/user) if(!iscarbon(eater)) return 0 diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index ad2345afe5..f9a2c0d63c 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -11,7 +11,6 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). container_type = OPENCONTAINER_1 circuit = /obj/item/circuitboard/machine/circuit_imprinter - var/datum/material_container/materials var/efficiency_coeff var/list/categories = list( @@ -29,20 +28,18 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). ) /obj/machinery/r_n_d/circuit_imprinter/Initialize() - materials = new(src, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE)) + AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) create_reagents(0) return ..() -/obj/machinery/r_n_d/circuit_imprinter/Destroy() - QDEL_NULL(materials) - return ..() - /obj/machinery/r_n_d/circuit_imprinter/RefreshParts() reagents.maximum_volume = 0 for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.maximum_volume += G.volume G.reagents.trans_to(src, G.reagents.total_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = 0 for(var/obj/item/stock_parts/matter_bin/M in component_parts) materials.max_amount += M.rating * 75000 @@ -59,6 +56,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/circuit_imprinter/proc/check_mat(datum/design/being_built, M) // now returns how many times the item can be built with the material var/list/all_materials = being_built.reagents_list + being_built.materials + GET_COMPONENT(materials, /datum/component/material_container) var/A = materials.amount(M) if(!A) A = reagents.get_reagent_amount(M) @@ -69,6 +67,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/circuit_imprinter/on_deconstruction() for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -77,52 +76,20 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). linked_console.linked_imprinter = null ..() -/obj/machinery/r_n_d/circuit_imprinter/Insert_Item(obj/item/O, mob/user) - - if(istype(O, /obj/item/stack/sheet)) - . = 1 - if(!is_insertion_ready(user)) +/obj/machinery/r_n_d/circuit_imprinter/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) return - var/sheet_material = materials.get_item_material_amount(O) - if(!sheet_material) - return - - if(!materials.has_space(sheet_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - var/obj/item/stack/sheet/stack = O - var/amount = round(input("How many sheets do you want to add?") as num)//No decimals - if(!in_range(src, stack) || !user.Adjacent(src)) - return - var/amount_inserted = materials.insert_stack(O,amount) - if(!amount_inserted) - return 1 + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + use_power(MINERAL_MATERIAL_AMOUNT / 10) else - use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10))) - to_chat(user, "You add [amount_inserted] sheets to the [src.name].") - updateUsrDialog() - - else if(istype(O, /obj/item/ore/bluespace_crystal)) //Bluespace crystals can be either a stack or an item - . = 1 - if(!is_insertion_ready(user)) - return - var/bs_material = materials.get_item_material_amount(O) - if(!bs_material) - return - - if(!materials.has_space(bs_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - materials.insert_item(O) - use_power(MINERAL_MATERIAL_AMOUNT/10) - to_chat(user, "You add [O] to the [src.name].") - qdel(O) - updateUsrDialog() - - else if(user.a_intent != INTENT_HARM) - to_chat(user, "You cannot insert this item into the [name]!") - return 1 - else - return 0 \ No newline at end of file + var/obj/item/stack/S = lit + stack_name = initial(S.name) + use_power(max(1000, (MINERAL_MATERIAL_AMOUNT * M.last_amount_inserted / 10))) + add_overlay("protolathe_[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "protolathe_[stack_name]"), 10) diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index a03b8c8127..89adfe8edc 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -203,13 +203,6 @@ materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_GLASS = 1000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtic -/datum/design/mag_oldsmg/tx_mag - name = "WT-550 Auto Gun Uranium Magazine (4.6x30mm TX)" - desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Auto Rifle" - id = "mag_oldsmg_tx" - materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_URANIUM = 2000) - build_path = /obj/item/ammo_box/magazine/wt550m9/wttx - /datum/design/stunshell name = "Stun Shell" desc = "A stunning shell for a shotgun." diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index cbbb73652b..4d8938b1b8 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -418,8 +418,9 @@ if(exp == SCANTYPE_OBLITERATE) visible_message("[exp_on] activates the crushing mechanism, [exp_on] is destroyed!") if(linked_console.linked_lathe) + GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe) for(var/material in exp_on.materials) - linked_console.linked_lathe.materials.insert_amount( min((linked_console.linked_lathe.materials.max_amount - linked_console.linked_lathe.materials.total_amount), (exp_on.materials[material])), material) + linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material) if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!") new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src)))) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 7a18a5e630..88c902a70d 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -14,7 +14,6 @@ Note: Must be placed west/left of and R&D console to function. container_type = OPENCONTAINER_1 circuit = /obj/item/circuitboard/machine/protolathe - var/datum/material_container/materials var/efficiency_coeff var/list/categories = list( @@ -34,11 +33,9 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/Initialize() create_reagents(0) - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE)) - return ..() - -/obj/machinery/r_n_d/protolathe/Destroy() - QDEL_NULL(materials) + AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) return ..() /obj/machinery/r_n_d/protolathe/RefreshParts() @@ -47,6 +44,7 @@ Note: Must be placed west/left of and R&D console to function. reagents.maximum_volume += G.volume G.reagents.trans_to(src, G.reagents.total_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = 0 for(var/obj/item/stock_parts/matter_bin/M in component_parts) materials.max_amount += M.rating * 75000 @@ -59,6 +57,7 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/proc/check_mat(datum/design/being_built, M) // now returns how many times the item can be built with the material var/list/all_materials = being_built.reagents_list + being_built.materials + GET_COMPONENT(materials, /datum/component/material_container) var/A = materials.amount(M) if(!A) A = reagents.get_reagent_amount(M) @@ -69,6 +68,7 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/on_deconstruction() for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -77,63 +77,20 @@ Note: Must be placed west/left of and R&D console to function. linked_console.linked_lathe = null ..() -/obj/machinery/r_n_d/protolathe/Insert_Item(obj/item/O, mob/user) - - if(istype(O, /obj/item/stack/sheet)) - . = 1 - if(!is_insertion_ready(user)) +/obj/machinery/r_n_d/protolathe/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) return - var/sheet_material = materials.get_item_material_amount(O) - if(!sheet_material) - return - - if(!materials.has_space(sheet_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - var/obj/item/stack/sheet/stack = O - var/amount = round(input("How many sheets do you want to add?") as num)//No decimals - if(!in_range(src, stack) || !user.Adjacent(src)) - return - var/amount_inserted = materials.insert_stack(O,amount) - if(!amount_inserted) - return 1 + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + use_power(MINERAL_MATERIAL_AMOUNT / 10) else - var/stack_name = stack.name - busy = TRUE - use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10))) - to_chat(user, "You add [amount_inserted] sheets to the [src.name].") - add_overlay("protolathe_[stack_name]") - sleep(10) - cut_overlay("protolathe_[stack_name]") - busy = FALSE - updateUsrDialog() - - else if(istype(O, /obj/item/ore/bluespace_crystal)) //Bluespace crystals can be either a stack or an item - . = 1 - if(!is_insertion_ready(user)) - return - var/bs_material = materials.get_item_material_amount(O) - if(!bs_material) - return - - if(!materials.has_space(bs_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - materials.insert_item(O) - busy = TRUE - use_power(MINERAL_MATERIAL_AMOUNT/10) - to_chat(user, "You add [O] to the [src.name].") - qdel(O) - add_overlay("protolathe_bluespace") - sleep(10) - cut_overlay("protolathe_bluespace") - busy = FALSE - updateUsrDialog() - - else if(user.a_intent != INTENT_HARM) - to_chat(user, "You cannot insert this item into the [name]!") - return 1 - else - return 0 + var/obj/item/stack/S = lit + stack_name = initial(S.name) + use_power(max(1000, (MINERAL_MATERIAL_AMOUNT * M.last_amount_inserted / 10))) + add_overlay("protolathe_[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "protolathe_[stack_name]"), 10) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 2f60e280ec..ee2cba39fd 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -169,6 +169,15 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. var/temp_screen = text2num(href_list["menu"]) screen = temp_screen + + + var/datum/component/material_container/linked_materials + if(linked_lathe) + linked_materials = linked_lathe.GetComponent(/datum/component/material_container) + + var/datum/component/material_container/imprinter_materials + if(linked_imprinter) + imprinter_materials = linked_imprinter.GetComponent(/datum/component/material_container) if(href_list["category"]) selected_category = href_list["category"] @@ -315,7 +324,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any. for(var/material in linked_destroy.loaded_item.materials) - linked_lathe.materials.insert_amount(min((linked_lathe.materials.max_amount - linked_lathe.materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material) + linked_materials.insert_amount(min((linked_materials.max_amount - linked_materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material) SSblackbox.add_details("item_deconstructed","[linked_destroy.loaded_item.type]") linked_destroy.loaded_item = null for(var/obj/I in linked_destroy.contents) @@ -421,7 +430,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/MAT in being_built.materials) efficient_mats[MAT] = being_built.materials[MAT]*coeff - if(!linked_lathe.materials.has_materials(efficient_mats, amount)) + if(!linked_materials.has_materials(efficient_mats, amount)) linked_lathe.say("Not enough materials to complete prototype.") enough_materials = 0 g2g = 0 @@ -433,7 +442,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, g2g = 0 if(enough_materials) - linked_lathe.materials.use_amount(efficient_mats, amount) + linked_materials.use_amount(efficient_mats, amount) for(var/R in being_built.reagents_list) linked_lathe.reagents.remove_reagent(R, being_built.reagents_list[R]*coeff) @@ -497,7 +506,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/MAT in being_built.materials) efficient_mats[MAT] = being_built.materials[MAT]/coeff - if(!linked_imprinter.materials.has_materials(efficient_mats)) + if(!imprinter_materials.has_materials(efficient_mats)) linked_imprinter.say("Not enough materials to complete prototype.") enough_materials = 0 g2g = 0 @@ -509,7 +518,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, g2g = 0 if(enough_materials) - linked_imprinter.materials.use_amount(efficient_mats) + imprinter_materials.use_amount(efficient_mats) for(var/R in being_built.reagents_list) linked_imprinter.reagents.remove_reagent(R, being_built.reagents_list[R]/coeff) @@ -536,7 +545,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, linked_lathe.reagents.clear_reagents() else if(href_list["ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material - linked_lathe.materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["ejectsheet"]) + linked_materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["ejectsheet"]) //Circuit Imprinter Materials else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it) @@ -546,7 +555,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, linked_imprinter.reagents.clear_reagents() else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the imprinter to eject a sheet of material - linked_imprinter.materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["imprinter_ejectsheet"]) + imprinter_materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["imprinter_ejectsheet"]) else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with. @@ -634,6 +643,14 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(linked_imprinter == null) screen = 4.0 + + var/datum/component/material_container/linked_materials + if(linked_lathe) + linked_materials = linked_lathe.GetComponent(/datum/component/material_container) + + var/datum/component/material_container/imprinter_materials + if(linked_imprinter) + imprinter_materials = linked_imprinter.GetComponent(/datum/component/material_container) switch(screen) //////////////////////R&D CONSOLE SCREENS////////////////// @@ -823,7 +840,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Material Storage" dat += "Chemical Storage
" dat += "

Protolathe Menu:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" dat += "\ @@ -841,7 +858,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Protolathe Menu" dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" var/coeff = linked_lathe.efficiency_coeff @@ -879,7 +896,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Protolathe Menu" dat += "

Search results:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" var/coeff = linked_lathe.efficiency_coeff @@ -916,8 +933,8 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(!linked_lathe) dat += "ERROR: Protolathe connection failed." else - for(var/mat_id in linked_lathe.materials.materials) - var/datum/material/M = linked_lathe.materials.materials[mat_id] + for(var/mat_id in linked_materials.materials) + var/datum/material/M = linked_materials.materials[mat_id] dat += "* [M.amount] of [M.name]: " if(M.amount >= MINERAL_MATERIAL_AMOUNT) dat += "Eject " if(M.amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " @@ -944,7 +961,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Material Storage" dat += "Chemical Storage
" dat += "

Circuit Imprinter Menu:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" dat += "\ @@ -961,7 +978,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Circuit Imprinter Menu" dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" var/coeff = linked_imprinter.efficiency_coeff @@ -991,7 +1008,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Circuit Imprinter Menu" dat += "

Search results:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" var/coeff = linked_imprinter.efficiency_coeff @@ -1028,8 +1045,8 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(!linked_imprinter) dat += "ERROR: Protolathe connection failed." else - for(var/mat_id in linked_imprinter.materials.materials) - var/datum/material/M = linked_imprinter.materials.materials[mat_id] + for(var/mat_id in imprinter_materials.materials) + var/datum/material/M = imprinter_materials.materials[mat_id] dat += "* [M.amount] of [M.name]: " if(M.amount >= MINERAL_MATERIAL_AMOUNT) dat += "Eject " if(M.amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 79fc4078f8..0b3c930962 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -168,7 +168,7 @@ var/sentience_type = SENTIENCE_ORGANIC /obj/item/slimepotion/sentience/afterattack(mob/living/M, mob/user) - if(being_used || !ismob(M)) + if(being_used || !ismob(M) || !user.Adjacent(M)) return if(!isanimal(M) || M.ckey) //only works on animals that aren't player controlled to_chat(user, "[M] is already too intelligent for this to work!") diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm index 71a0d89f16..4e5c0605e2 100644 --- a/code/modules/spells/spell_types/mime.dm +++ b/code/modules/spells/spell_types/mime.dm @@ -1,140 +1,280 @@ -/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall - name = "Invisible Wall" - desc = "The mime's performance transmutates into physical reality." - school = "mime" - panel = "Mime" - summon_type = list(/obj/effect/forcefield/mime) - invocation_type = "emote" - invocation_emote_self = "You form a wall in front of yourself." - summon_lifespan = 300 - charge_max = 300 - clothes_req = 0 - range = 0 - cast_sound = null - human_req = 1 - - action_icon_state = "mime" - action_background_icon_state = "bg_mime" - -/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click() - if(usr && usr.mind) - if(!usr.mind.miming) - to_chat(usr, "You must dedicate yourself to silence first.") - return - invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]." - else - invocation_type ="none" - ..() - - -/obj/effect/proc_holder/spell/targeted/mime/speak - name = "Speech" - desc = "Make or break a vow of silence." - school = "mime" - panel = "Mime" - clothes_req = 0 - human_req = 1 - charge_max = 3000 - range = -1 - include_user = 1 - - action_icon_state = "mime" - action_background_icon_state = "bg_mime" - -/obj/effect/proc_holder/spell/targeted/mime/speak/Click() - if(!usr) - return - if(!ishuman(usr)) - return - var/mob/living/carbon/human/H = usr - if(H.mind.miming) - still_recharging_msg = "You can't break your vow of silence that fast!" - else - still_recharging_msg = "You'll have to wait before you can give your vow of silence again!" - ..() - -/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr) - for(var/mob/living/carbon/human/H in targets) - H.mind.miming=!H.mind.miming - if(H.mind.miming) - to_chat(H, "You make a vow of silence.") - else - to_chat(H, "You break your vow of silence.") - -// These spells can only be gotten from the "Guide for Advanced Mimery series" for Mime Traitors. - -/obj/effect/proc_holder/spell/targeted/forcewall/mime - name = "Invisible Blockade" - desc = "Form an invisible three tile wide blockade." - wall_type = /obj/effect/forcefield/mime/advanced - invocation_type = "emote" - invocation_emote_self = "You form a blockade in front of yourself." - charge_max = 600 - sound = null - clothes_req = 0 - range = -1 - include_user = 1 - - action_icon_state = "mime" - action_background_icon_state = "bg_mime" - -/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click() - if(usr && usr.mind) - if(!usr.mind.miming) - to_chat(usr, "You must dedicate yourself to silence first.") - return - invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]." - else - invocation_type ="none" - ..() - -/obj/effect/proc_holder/spell/aimed/finger_guns - name = "Finger Guns" - desc = "Shoot a mimed bullet from your fingers that stuns and does some damage." - school = "mime" - panel = "Mime" - charge_max = 300 - clothes_req = 0 - invocation_type = "emote" - invocation_emote_self = "You fire your finger gun!" - range = 20 - projectile_type = /obj/item/projectile/bullet/weakbullet2 - projectile_amount = 3 - sound = null - active_msg = "You draw your fingers!" - deactive_msg = "You put your fingers at ease. Another time." - active = FALSE - - action_icon_state = "mime" - action_background_icon_state = "bg_mime" - base_icon_state = "mime" - - -/obj/effect/proc_holder/spell/aimed/finger_guns/Click() - var/mob/living/carbon/human/owner = usr - if(owner.incapacitated()) - to_chat(owner, "You can't properly point your fingers while incapacitated.") - return - if(usr && usr.mind) - if(!usr.mind.miming) - to_chat(usr, "You must dedicate yourself to silence first.") - return - invocation = "[usr.real_name] fires [usr.p_their()] finger gun!" - else - invocation_type ="none" - ..() - - -/obj/item/spellbook/oneuse/mimery_blockade - spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime - spellname = "" - name = "Guide to Advanced Mimery Vol 1" - desc = "The pages don't make any sound when turned." - icon_state ="bookmime" - -/obj/item/spellbook/oneuse/mimery_guns - spell = /obj/effect/proc_holder/spell/aimed/finger_guns - spellname = "" - name = "Guide to Advanced Mimery Vol 2" - desc = "There aren't any words written..." - icon_state ="bookmime" +/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall + name = "Invisible Wall" + desc = "The mime's performance transmutates into physical reality." + school = "mime" + panel = "Mime" + summon_type = list(/obj/effect/forcefield/mime) + invocation_type = "emote" + invocation_emote_self = "You form a wall in front of yourself." + summon_lifespan = 300 + charge_max = 300 + clothes_req = 0 + range = 0 + cast_sound = null + human_req = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click() + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]." + else + invocation_type ="none" + ..() + + +/obj/effect/proc_holder/spell/targeted/mime/speak + name = "Speech" + desc = "Make or break a vow of silence." + school = "mime" + panel = "Mime" + clothes_req = 0 + human_req = 1 + charge_max = 3000 + range = -1 + include_user = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/targeted/mime/speak/Click() + if(!usr) + return + if(!ishuman(usr)) + return + var/mob/living/carbon/human/H = usr + if(H.mind.miming) + still_recharging_msg = "You can't break your vow of silence that fast!" + else + still_recharging_msg = "You'll have to wait before you can give your vow of silence again!" + ..() + +/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr) + for(var/mob/living/carbon/human/H in targets) + H.mind.miming=!H.mind.miming + if(H.mind.miming) + to_chat(H, "You make a vow of silence.") + else + to_chat(H, "You break your vow of silence.") + +// These spells can only be gotten from the "Guide for Advanced Mimery series" for Mime Traitors. + +/obj/effect/proc_holder/spell/targeted/forcewall/mime + name = "Invisible Blockade" + desc = "Form an invisible three tile wide blockade." + wall_type = /obj/effect/forcefield/mime/advanced + invocation_type = "emote" + invocation_emote_self = "You form a blockade in front of yourself." + charge_max = 600 + sound = null + clothes_req = 0 + range = -1 + include_user = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click() + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]." + else + invocation_type ="none" + ..() + +/obj/effect/proc_holder/spell/aimed/finger_guns + name = "Finger Guns" + desc = "Shoot a mimed bullet from your fingers that stuns and does some damage." + school = "mime" + panel = "Mime" + charge_max = 300 + clothes_req = 0 + invocation_type = "emote" + invocation_emote_self = "You fire your finger gun!" + range = 20 + projectile_type = /obj/item/projectile/bullet/mime + projectile_amount = 3 + sound = null + active_msg = "You draw your fingers!" + deactive_msg = "You put your fingers at ease. Another time." + active = FALSE + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + base_icon_state = "mime" + + +/obj/effect/proc_holder/spell/aimed/finger_guns/Click() + var/mob/living/carbon/human/owner = usr + if(owner.incapacitated()) + to_chat(owner, "You can't properly point your fingers while incapacitated.") + return + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] fires [usr.p_their()] finger gun!" + else + invocation_type ="none" + ..() + + +/obj/item/spellbook/oneuse/mimery_blockade + spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime + spellname = "" + name = "Guide to Advanced Mimery Vol 1" + desc = "The pages don't make any sound when turned." + icon_state ="bookmime" + +/obj/item/spellbook/oneuse/mimery_guns + spell = /obj/effect/proc_holder/spell/aimed/finger_guns + spellname = "" + name = "Guide to Advanced Mimery Vol 2" + desc = "There aren't any words written..." + icon_state ="bookmime" +/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall + name = "Invisible Wall" + desc = "The mime's performance transmutates into physical reality." + school = "mime" + panel = "Mime" + summon_type = list(/obj/effect/forcefield/mime) + invocation_type = "emote" + invocation_emote_self = "You form a wall in front of yourself." + summon_lifespan = 300 + charge_max = 300 + clothes_req = 0 + range = 0 + cast_sound = null + human_req = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click() + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]." + else + invocation_type ="none" + ..() + + +/obj/effect/proc_holder/spell/targeted/mime/speak + name = "Speech" + desc = "Make or break a vow of silence." + school = "mime" + panel = "Mime" + clothes_req = 0 + human_req = 1 + charge_max = 3000 + range = -1 + include_user = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/targeted/mime/speak/Click() + if(!usr) + return + if(!ishuman(usr)) + return + var/mob/living/carbon/human/H = usr + if(H.mind.miming) + still_recharging_msg = "You can't break your vow of silence that fast!" + else + still_recharging_msg = "You'll have to wait before you can give your vow of silence again!" + ..() + +/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr) + for(var/mob/living/carbon/human/H in targets) + H.mind.miming=!H.mind.miming + if(H.mind.miming) + to_chat(H, "You make a vow of silence.") + else + to_chat(H, "You break your vow of silence.") + +// These spells can only be gotten from the "Guide for Advanced Mimery series" for Mime Traitors. + +/obj/effect/proc_holder/spell/targeted/forcewall/mime + name = "Invisible Blockade" + desc = "Form an invisible three tile wide blockade." + wall_type = /obj/effect/forcefield/mime/advanced + invocation_type = "emote" + invocation_emote_self = "You form a blockade in front of yourself." + charge_max = 600 + sound = null + clothes_req = 0 + range = -1 + include_user = 1 + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click() + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]." + else + invocation_type ="none" + ..() + +/obj/effect/proc_holder/spell/aimed/finger_guns + name = "Finger Guns" + desc = "Shoot a mimed bullet from your fingers that stuns and does some damage." + school = "mime" + panel = "Mime" + charge_max = 300 + clothes_req = 0 + invocation_type = "emote" + invocation_emote_self = "You fire your finger gun!" + range = 20 + projectile_type = /obj/item/projectile/bullet/mime + projectile_amount = 3 + sound = null + active_msg = "You draw your fingers!" + deactive_msg = "You put your fingers at ease. Another time." + active = FALSE + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + base_icon_state = "mime" + + +/obj/effect/proc_holder/spell/aimed/finger_guns/Click() + var/mob/living/carbon/human/owner = usr + if(owner.incapacitated()) + to_chat(owner, "You can't properly point your fingers while incapacitated.") + return + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] fires [usr.p_their()] finger gun!" + else + invocation_type ="none" + ..() + + +/obj/item/spellbook/oneuse/mimery_blockade + spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime + spellname = "" + name = "Guide to Advanced Mimery Vol 1" + desc = "The pages don't make any sound when turned." + icon_state ="bookmime" + +/obj/item/spellbook/oneuse/mimery_guns + spell = /obj/effect/proc_holder/spell/aimed/finger_guns + spellname = "" + name = "Guide to Advanced Mimery Vol 2" + desc = "There aren't any words written..." + icon_state ="bookmime" diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index f8388a5dab..d1699cb257 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -50,11 +50,11 @@ return S /obj/item/organ/heart/on_life() - if(owner.client) + if(owner.client && beating) var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE) - var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE) var/mob/living/carbon/H = owner + if(H.health <= HEALTH_THRESHOLD_CRIT && beat != BEAT_SLOW) beat = BEAT_SLOW H.playsound_local(get_turf(H), slowbeat,40,0, channel = CHANNEL_HEARTBEAT) diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm index 1f57ac93ce..38720f81a0 100644 --- a/code/modules/uplink/uplink_item.dm +++ b/code/modules/uplink/uplink_item.dm @@ -165,7 +165,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. /datum/uplink_item/nukeoffer/sniper name = "Sniper bundle" desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, a hollow-point \ - haemorrhage magazine, a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie." + a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie." item = /obj/item/storage/briefcase/sniperbundle cost = 20 // normally 26 @@ -449,11 +449,11 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. item = /obj/item/ammo_box/magazine/m12g/dragon include_modes = list(/datum/game_mode/nuclear) -/datum/uplink_item/ammo/shotgun/breach - name = "12g Breaching Shells" - desc = "An economic variant of the CMC meteorshot slugs, not as effective for knocking \ - down targets, but still great for blasting airlocks off their frames." - item = /obj/item/ammo_box/magazine/m12g/breach +/datum/uplink_item/ammo/shotgun/meteor + name = "12g Meteorslug Shells" + desc = "An alternative 8-round meteorslug magazine for use in the Bulldog shotgun. \ + Great for blasting airlocks off their frames." + item = /obj/item/ammo_box/magazine/m12g/meteor include_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/ammo/shotgun/bag @@ -488,12 +488,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. By the time you need to use this, you'll already be on a pile of corpses." item = /obj/item/ammo_box/magazine/mm195x129 -/datum/uplink_item/ammo/machinegun/bleeding - name = "1.95x129mm (Bleeding) Box Magazine" - desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with special properties \ - to induce internal bleeding on targets." - item = /obj/item/ammo_box/magazine/mm195x129/bleeding - /datum/uplink_item/ammo/machinegun/hollow name = "1.95x129mm (Hollow-Point) Box Magazine" desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \ @@ -527,12 +521,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. item = /obj/item/ammo_box/magazine/sniper_rounds/soporific cost = 6 -/datum/uplink_item/ammo/sniper/haemorrhage - name = ".50 Haemorrhage Magazine" - desc = "A 5-round magazine of haemorrhage ammo designed for use with .50 sniper rifles; causes heavy bleeding \ - in the target." - item = /obj/item/ammo_box/magazine/sniper_rounds/haemorrhage - /datum/uplink_item/ammo/sniper/penetrator name = ".50 Penetrator Magazine" desc = "A 5-round magazine of penetrator ammo designed for use with .50 sniper rifles. \ @@ -710,7 +698,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. name = "Dehydrated Space Carp" desc = "Looks like a plush toy carp, but just add water and it becomes a real-life space carp! Activate in \ your hand before use so it knows not to kill you." - item = /obj/item/toy/carpplushie/dehy_carp + item = /obj/item/toy/plush/carpplushie/dehy_carp cost = 1 /datum/uplink_item/stealthy_weapons/soap_clusterbang @@ -1313,7 +1301,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. /datum/uplink_item/role_restricted/magillitis_serum name = "Magillitis Serum Autoinjector" - desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in basic primates." + desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas." item = /obj/item/reagent_containers/hypospray/magillitis cost = 15 restricted_roles = list("Geneticist", "Chief Medical Officer") diff --git a/code/modules/vore/eating/belly_vr.dm b/code/modules/vore/eating/belly_vr.dm index 1a181efa58..4262d9fecd 100644 --- a/code/modules/vore/eating/belly_vr.dm +++ b/code/modules/vore/eating/belly_vr.dm @@ -15,7 +15,7 @@ var/vore_verb = "ingest" // Verb for eating with this in messages var/human_prey_swallow_time = 10 SECONDS // Time in deciseconds to swallow /mob/living/carbon/human var/nonhuman_prey_swallow_time = 5 SECONDS // Time in deciseconds to swallow anything else - var/emoteTime = 300 // How long between stomach emotes at prey + var/emoteTime = 30 SECONDS // How long between stomach emotes at prey var/digest_brute = 0 // Brute damage per tick in digestion mode var/digest_burn = 1 // Burn damage per tick in digestion mode var/digest_tickrate = 9 // Modulus this of air controller tick number to iterate gurgles on @@ -25,15 +25,21 @@ var/digestchance = 0 // % Chance of stomach beginning to digest if prey struggles // var/silenced = FALSE // Will the heartbeat/fleshy internal loop play? var/escapechance = 0 // % Chance of prey beginning to escape if prey struggles. - var/transferchance = 0 // % Chance of prey being - var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone. + var/datum/belly/transferlocation = null // Location that the prey is released if they struggle and get dropped off. - var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest. + var/transferchance = 0 // % Chance of prey being transferred to transfer location when resisting + var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location + var/autotransferwait = 10 // Time between trying to transfer. + var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone. + + var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest. var/tmp/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY) // Possible digest modes - var/tmp/mob/living/owner // The mob whose belly this is. - var/tmp/list/internal_contents = list() // People/Things you've eaten into this belly! - var/tmp/is_full // Flag for if digested remeans are present. (for disposal messages) - var/tmp/emotePend = FALSE // If there's already a spawned thing counting for the next emote + var/tmp/mob/living/owner // The mob whose belly this is. + var/tmp/list/internal_contents = list() // People/Things you've eaten into this belly! + var/tmp/is_full // Flag for if digested remeans are present. (for disposal messages) + var/tmp/emotePend = FALSE // If there's already a spawned thing counting for the next emote + var/swallow_time = 10 SECONDS // for mob transfering automation + var/vore_capacity = 1 // The capacity (in people) this person can hold // Don't forget to watch your commas at the end of each line if you change these. var/list/struggle_messages_outside = list( @@ -153,8 +159,41 @@ // if(B.silenced == FALSE) //this needs more testing later prey << sound('sound/vore/prey/loop.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_PREYLOOP) + // Handle prey messages if(inside_flavor) to_chat(prey, "[src.inside_flavor]") + if(isliving(prey)) + var/mob/living/M = prey + if(can_taste && M.get_taste_message(0)) + to_chat(owner, "[M] tastes of [M.get_taste_message(0)].") + + // Setup the autotransfer checks if needed + if(transferlocation && autotransferchance > 0) + addtimer(CALLBACK(src, /datum/belly/.proc/check_autotransfer, prey), autotransferwait) + +/datum/belly/proc/check_autotransfer(var/mob/prey) + // Some sanity checks + if(transferlocation && (autotransferchance > 0) && (prey in internal_contents)) + if(prob(autotransferchance)) + // Double check transferlocation isn't insane + if(verify_transferlocation()) + transfer_contents(prey, transferlocation) + else + // Didn't transfer, so wait before retrying + addtimer(CALLBACK(src, /datum/belly/.proc/check_autotransfer, prey), autotransferwait) + +/datum/belly/proc/verify_transferlocation() + for(var/I in owner.vore_organs) + var/datum/belly/B = owner.vore_organs[I] + if(B == transferlocation) + return TRUE + + for(var/I in owner.vore_organs) + var/datum/belly/B = owner.vore_organs[I] + if(B.name == transferlocation.name) + transferlocation = B + return TRUE + return FALSE // Get the line that should show up in Examine message if the owner of this belly // is examined. By making this a proc, we not only take advantage of polymorphism, @@ -323,23 +362,9 @@ return else if(prob(transferchance) && istype(transferlocation)) //Next, let's have it see if they end up getting into an even bigger mess then when they started. - var/location_found = FALSE - var/name_found = FALSE - for(var/I in owner.vore_organs) - var/datum/belly/B = owner.vore_organs[I] - if(B == transferlocation) - location_found = TRUE - break + var/location_ok = verify_transferlocation() - if(!location_found) - for(var/I in owner.vore_organs) - var/datum/belly/B = owner.vore_organs[I] - if(B.name == transferlocation.name) - name_found = TRUE - transferlocation = B - break - - if(!location_found && !name_found) + if(!location_ok) to_chat(owner, "Something went wrong with your belly transfer settings.") transferlocation = null return @@ -358,18 +383,14 @@ to_chat(R, "But make no progress in escaping [owner]'s [name].") to_chat(owner, "But appears to be unable to make any progress in escaping your [name].") return + //Transfers contents from one belly to another /datum/belly/proc/transfer_contents(var/atom/movable/content, var/datum/belly/target, silent = 0) if(!(content in internal_contents)) return internal_contents.Remove(content) - target.internal_contents.Add(content) - if(isliving(content)) - var/mob/living/M = content - if(target.inside_flavor) - to_chat(M, "[target.inside_flavor]") - if(target.can_taste && M.get_taste_message(0)) - to_chat(owner, "[M] tastes of [M.get_taste_message(0)].") + // Re-use nom_mob + target.nom_mob(content, target.owner) if(!silent) for(var/mob/hearer in range(1,owner)) hearer << sound(target.vore_sound,volume=80) @@ -398,6 +419,8 @@ dupe.escapechance = escapechance dupe.transferchance = transferchance dupe.transferlocation = transferlocation + dupe.autotransferchance = autotransferchance + dupe.autotransferwait = autotransferwait //// Object-holding variables //struggle_messages_outside - strings diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index 901c1ca56f..ba5fa1e295 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -91,3 +91,53 @@ playsound(get_turf(owner),"digest_pred",35,0,-6,0,channel=CHANNEL_PRED) M.stop_sound_channel(CHANNEL_PRED) M.playsound_local(get_turf(M), null, 45, S = prey_gurgle) + + +//////////////////////////DM_DRAGON ///////////////////////////////////// +//because dragons need snowflake guts + if(digest_mode == DM_DRAGON) + for (var/mob/living/M in internal_contents) + if(prob(25)) + M.stop_sound_channel(CHANNEL_PRED) + playsound(get_turf(owner),"digest_pred",50,0,-6,0,channel=CHANNEL_PRED) + M.stop_sound_channel(CHANNEL_PRED) + M.playsound_local(get_turf(M), null, 45, S = prey_gurgle) + + //No digestion protection for megafauna. + + //Person just died in guts! + if(M.stat == DEAD) + var/digest_alert_owner = pick(digest_messages_owner) + var/digest_alert_prey = pick(digest_messages_prey) + + //Replace placeholder vars + digest_alert_owner = replacetext(digest_alert_owner,"%pred",owner) + digest_alert_owner = replacetext(digest_alert_owner,"%prey",M) + digest_alert_owner = replacetext(digest_alert_owner,"%belly",lowertext(name)) + + digest_alert_prey = replacetext(digest_alert_prey,"%pred",owner) + digest_alert_prey = replacetext(digest_alert_prey,"%prey",M) + digest_alert_prey = replacetext(digest_alert_prey,"%belly",lowertext(name)) + + //Send messages + to_chat(owner, "[digest_alert_owner]") + to_chat(M, "[digest_alert_prey]") + M.visible_message("You watch as [owner]'s guts loudly rumble as it finishes off a meal.") + + M.stop_sound_channel(CHANNEL_PRED) + playsound(get_turf(owner),"death_pred",45,0,-6,0,channel=CHANNEL_PRED) + M.stop_sound_channel(CHANNEL_PRED) + M.playsound_local(get_turf(M), null, 45, S = prey_digest) + M.spill_organs(FALSE,TRUE,TRUE) + M << sound(null, repeat = 0, wait = 0, volume = 80, channel = CHANNEL_PREYLOOP) + digestion_death(M) + owner.update_icons() + continue + + + // Deal digestion damage (and feed the pred) + if(!(M.status_flags & GODMODE)) + M.adjustFireLoss(digest_burn) + M.adjustToxLoss(4) // something something plasma based acids + M.adjustCloneLoss(3) // eventually this'll kill you if you're healing everything else, you nerds. + return \ No newline at end of file diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 60206a43f1..d50cdebf45 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -121,6 +121,42 @@ var/belly = input("Choose Belly") in pred.vore_organs return perform_the_nom(user, prey, pred, belly) +//Dragon noms need to be faster +/mob/living/proc/dragon_feeding(var/mob/living/user, var/mob/living/prey) + var/belly = user.vore_selected + return perform_dragon(user, prey, user, belly) + +/mob/living/proc/perform_dragon(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/belly, swallow_time = 20) + //Sanity + if(!user || !prey || !pred || !belly || !(belly in pred.vore_organs)) + return + + // The belly selected at the time of noms + var/datum/belly/belly_target = pred.vore_organs[belly] + var/attempt_msg = "ERROR: Vore message couldn't be created. Notify a dev. (at)" + var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)" + + // Prepare messages + if(user == pred) //Feeding someone to yourself + attempt_msg = text("[] starts to [] [] into their []!",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + success_msg = text("[] manages to [] [] into their []!",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name)) + + // Announce that we start the attempt! + user.visible_message(attempt_msg) + + if(!do_mob(src, user, swallow_time)) // one second should be good enough, right? + return FALSE // Prey escaped (or user disabled) before timer expired. + + // If we got this far, nom successful! Announce it! + user.visible_message(success_msg) + playsound(user, belly_target.vore_sound, 100, 1) + + // Actually shove prey into the belly. + belly_target.nom_mob(prey, user) + if (pred == user) + message_admins("[key_name(pred)] ate [key_name(prey)].") + log_attack("[key_name(pred)] ate [key_name(prey)]") + return TRUE // // Master vore proc that actually does vore procedures // @@ -250,6 +286,7 @@ if(M.loc != src) B.internal_contents.Remove(M) + // OOC Escape code for pref-breaking or AFK preds // /mob/living/proc/escapeOOC() diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index ebbc2f371c..0f01a4c9e3 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -27,7 +27,7 @@ // /datum/vore_look var/datum/belly/selected - var/show_interacts = FALSE + var/show_interacts = TRUE var/datum/browser/popup var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action. diff --git a/config/game_options.txt b/config/game_options.txt index 7d12225f47..b609f8b582 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -98,6 +98,9 @@ PROBABILITY DEVIL_AGENTS 0 ## You probably want to keep sandbox off by default for secret and random. PROBABILITY SANDBOX 0 +## Percent weight reductions for three of the most recent modes + +REPEATED_MODE_ADJUST 45 30 10 ## Toggles for continuous modes. ## Modes that aren't continuous will end the instant all antagonists are dead. @@ -486,6 +489,9 @@ Space_Budget 16 ## Must be at least 30 to not break parallax I recommended at least 55 to be visually/aurally appropriate ARRIVALS_SHUTTLE_DOCK_WINDOW 55 +## Uncomment to require the arrivals shuttle to be in flight (if it can fly) before late join players can join +#ARRIVALS_SHUTTLE_REQUIRE_UNDOCKED + ## Uncomment to prevent late join players from spawning if the arrivals shuttle is depressurized #ARRIVALS_SHUTTLE_REQUIRE_SAFE_LATEJOIN diff --git a/html/ban.png b/html/ban.png new file mode 100644 index 0000000000..54f68f4770 Binary files /dev/null and b/html/ban.png differ diff --git a/html/changelog.css b/html/changelog.css index b83a8d4f56..031c1e42c0 100644 --- a/html/changelog.css +++ b/html/changelog.css @@ -20,6 +20,11 @@ a img {border:none;} .imagedel {background-image:url(image-minus.png)} .spellcheck {background-image:url(spell-check.png)} .experiment {background-image:url(burn-exclamation.png)} +.refactor {background-image:url(burn-exclamation.png)} +.code_imp {background-image:url(coding.png)} +.config {background-image:url(chrome_wrench.png)} +.admin {background-image:url(ban.png)} +.server {background-image:url(hard-hat-exclamation.png)} .balance {background-image:url(scales.png)} .sansserif {font-family:Tahoma,sans-serif;font-size:12px;} .commit {margin-bottom:20px;font-size:100%;font-weight:normal;} diff --git a/html/changelogs/AutoChangeLog-pr-2573.yml b/html/changelogs/AutoChangeLog-pr-2573.yml new file mode 100644 index 0000000000..1bc36f7ec4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2573.yml @@ -0,0 +1,4 @@ +author: "Pubby" +delete-after: True +changes: + - rscdel: "The multiverse sword is toast" diff --git a/html/changelogs/AutoChangeLog-pr-2860.yml b/html/changelogs/AutoChangeLog-pr-2860.yml new file mode 100644 index 0000000000..cf46c2fb7d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2860.yml @@ -0,0 +1,4 @@ +author: "Pubby" +delete-after: True +changes: + - bugfix: "Atmos pipenets are less glitchy" diff --git a/html/changelogs/AutoChangeLog-pr-2865.yml b/html/changelogs/AutoChangeLog-pr-2865.yml new file mode 100644 index 0000000000..d45e9014b9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2865.yml @@ -0,0 +1,4 @@ +author: "PopNotes" +delete-after: True +changes: + - imageadd: "Airlocks animate faster. This doesn't change the time it takes to pass through an airlock, but it does visually match up much better so you don't just appear to glide through the airlock while it's half-open." diff --git a/html/changelogs/AutoChangeLog-pr-2866.yml b/html/changelogs/AutoChangeLog-pr-2866.yml new file mode 100644 index 0000000000..5561bc972a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2866.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "Several new plushie dolls are now available in toy crates." diff --git a/html/changelogs/AutoChangeLog-pr-2868.yml b/html/changelogs/AutoChangeLog-pr-2868.yml new file mode 100644 index 0000000000..ccadb2ab1e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2868.yml @@ -0,0 +1,5 @@ +author: "Poojawa" +delete-after: True +changes: + - rscadd: "Ash Drakes can actually devour you now. Must have devourment on to actually get eaten, else it'll gib you outright as normal." + - rscadd: "Ash Drake digestion will drop your brain in addition to your equipment. Something something reasons. Don't mind the funny smell." diff --git a/html/changelogs/AutoChangeLog-pr-2872.yml b/html/changelogs/AutoChangeLog-pr-2872.yml new file mode 100644 index 0000000000..ff61e5dbd0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2872.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - balance: "Knockdown and unconcious now let you regenerate stamina damage." + - rscadd: "Sleeping regenerates more stamina damage." diff --git a/html/changelogs/AutoChangeLog-pr-2875.yml b/html/changelogs/AutoChangeLog-pr-2875.yml new file mode 100644 index 0000000000..b76b1f78f7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2875.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - rscadd: "Engineering cyborgs now have an item called the \"electroadaptive pseudocircuit\" (technobabble not included) that they can use in place of a circuit for the purposes of building alarms, APCs, and firelocks." diff --git a/html/changelogs/AutoChangeLog-pr-2877.yml b/html/changelogs/AutoChangeLog-pr-2877.yml new file mode 100644 index 0000000000..523acefc54 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2877.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - balance: "Magillitis will now ALSO affect humans." diff --git a/html/changelogs/AutoChangeLog-pr-2878.yml b/html/changelogs/AutoChangeLog-pr-2878.yml new file mode 100644 index 0000000000..f2d10a7b30 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2878.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - tweak: "Gorillas will now drop their brain when gibbed or butchered." diff --git a/html/changelogs/AutoChangeLog-pr-2886.yml b/html/changelogs/AutoChangeLog-pr-2886.yml new file mode 100644 index 0000000000..75edb3a080 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2886.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - bugfix: "Admin ghosts can no longer unintentionally make a mess of things." diff --git a/html/changelogs/AutoChangeLog-pr-2887.yml b/html/changelogs/AutoChangeLog-pr-2887.yml new file mode 100644 index 0000000000..fd7d73182a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2887.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Mice spawning finds the station z level properly" diff --git a/html/changelogs/AutoChangeLog-pr-2897.yml b/html/changelogs/AutoChangeLog-pr-2897.yml new file mode 100644 index 0000000000..9cce393643 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2897.yml @@ -0,0 +1,4 @@ +author: "Robustin" +delete-after: True +changes: + - balance: "A zombie's automatic self-healing is stopped for 6 seconds after taking damage." diff --git a/html/changelogs/AutoChangeLog-pr-2904.yml b/html/changelogs/AutoChangeLog-pr-2904.yml new file mode 100644 index 0000000000..dbcf3ed59e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2904.yml @@ -0,0 +1,4 @@ +author: "More Robust Than You" +delete-after: True +changes: + - tweak: "Taking the beaker out of a cryotube now tries to put it into your hand" diff --git a/html/chrome-wrench.png b/html/chrome-wrench.png new file mode 100644 index 0000000000..a64f202074 Binary files /dev/null and b/html/chrome-wrench.png differ diff --git a/html/coding.png b/html/coding.png new file mode 100644 index 0000000000..887d6b5068 Binary files /dev/null and b/html/coding.png differ diff --git a/html/create_object.html b/html/create_object.html index 44bf7667aa..619da3ec47 100644 --- a/html/create_object.html +++ b/html/create_object.html @@ -26,7 +26,8 @@ - + /* hreftokenfield */ + Type
Offset: diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 70f994cdbe..92a74b0afa 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index f7c8e1b8dc..ddad48cfb3 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 752a0a00ec..dfb51a9caa 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/doors/airlocks/centcom/centcom.dmi b/icons/obj/doors/airlocks/centcom/centcom.dmi index ee263cf1b7..c034f8e282 100644 Binary files a/icons/obj/doors/airlocks/centcom/centcom.dmi and b/icons/obj/doors/airlocks/centcom/centcom.dmi differ diff --git a/icons/obj/doors/airlocks/centcom/overlays.dmi b/icons/obj/doors/airlocks/centcom/overlays.dmi index 7650312e8f..7ec3486053 100644 Binary files a/icons/obj/doors/airlocks/centcom/overlays.dmi and b/icons/obj/doors/airlocks/centcom/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/clockwork/overlays.dmi b/icons/obj/doors/airlocks/clockwork/overlays.dmi index b46cc5b191..b34b73fb4e 100644 Binary files a/icons/obj/doors/airlocks/clockwork/overlays.dmi and b/icons/obj/doors/airlocks/clockwork/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi b/icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi index 2da7c0e4e0..cad0fe0ed0 100644 Binary files a/icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi and b/icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi differ diff --git a/icons/obj/doors/airlocks/cult/runed/cult.dmi b/icons/obj/doors/airlocks/cult/runed/cult.dmi index cbb125b112..1ed0d58dc4 100644 Binary files a/icons/obj/doors/airlocks/cult/runed/cult.dmi and b/icons/obj/doors/airlocks/cult/runed/cult.dmi differ diff --git a/icons/obj/doors/airlocks/cult/runed/overlays.dmi b/icons/obj/doors/airlocks/cult/runed/overlays.dmi index a8d6e7dfff..19920538d9 100644 Binary files a/icons/obj/doors/airlocks/cult/runed/overlays.dmi and b/icons/obj/doors/airlocks/cult/runed/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/cult/unruned/cult.dmi b/icons/obj/doors/airlocks/cult/unruned/cult.dmi index b57167633a..83c052c413 100644 Binary files a/icons/obj/doors/airlocks/cult/unruned/cult.dmi and b/icons/obj/doors/airlocks/cult/unruned/cult.dmi differ diff --git a/icons/obj/doors/airlocks/cult/unruned/overlays.dmi b/icons/obj/doors/airlocks/cult/unruned/overlays.dmi index bfbbccf5d7..5fb77f2676 100644 Binary files a/icons/obj/doors/airlocks/cult/unruned/overlays.dmi and b/icons/obj/doors/airlocks/cult/unruned/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/external/external.dmi b/icons/obj/doors/airlocks/external/external.dmi index 4b0461ed59..12b3f26d1e 100644 Binary files a/icons/obj/doors/airlocks/external/external.dmi and b/icons/obj/doors/airlocks/external/external.dmi differ diff --git a/icons/obj/doors/airlocks/external/overlays.dmi b/icons/obj/doors/airlocks/external/overlays.dmi index 5bfa24a6be..1dde58ab5a 100644 Binary files a/icons/obj/doors/airlocks/external/overlays.dmi and b/icons/obj/doors/airlocks/external/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/glass_large/glass_large.dmi b/icons/obj/doors/airlocks/glass_large/glass_large.dmi index 91ae217562..9dbcb9d0f1 100644 Binary files a/icons/obj/doors/airlocks/glass_large/glass_large.dmi and b/icons/obj/doors/airlocks/glass_large/glass_large.dmi differ diff --git a/icons/obj/doors/airlocks/glass_large/overlays.dmi b/icons/obj/doors/airlocks/glass_large/overlays.dmi index 8d9b561ca3..f85a73d8e7 100644 Binary files a/icons/obj/doors/airlocks/glass_large/overlays.dmi and b/icons/obj/doors/airlocks/glass_large/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/hatch/centcom.dmi b/icons/obj/doors/airlocks/hatch/centcom.dmi index b83f0e29a6..bf48f8bdd6 100644 Binary files a/icons/obj/doors/airlocks/hatch/centcom.dmi and b/icons/obj/doors/airlocks/hatch/centcom.dmi differ diff --git a/icons/obj/doors/airlocks/hatch/maintenance.dmi b/icons/obj/doors/airlocks/hatch/maintenance.dmi index 99f66007bd..ab5a192647 100644 Binary files a/icons/obj/doors/airlocks/hatch/maintenance.dmi and b/icons/obj/doors/airlocks/hatch/maintenance.dmi differ diff --git a/icons/obj/doors/airlocks/hatch/overlays.dmi b/icons/obj/doors/airlocks/hatch/overlays.dmi index 45f18136da..e41af3e44c 100644 Binary files a/icons/obj/doors/airlocks/hatch/overlays.dmi and b/icons/obj/doors/airlocks/hatch/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/highsec/highsec.dmi b/icons/obj/doors/airlocks/highsec/highsec.dmi index 566270b827..a43dce6a62 100644 Binary files a/icons/obj/doors/airlocks/highsec/highsec.dmi and b/icons/obj/doors/airlocks/highsec/highsec.dmi differ diff --git a/icons/obj/doors/airlocks/highsec/overlays.dmi b/icons/obj/doors/airlocks/highsec/overlays.dmi index 48248f3299..2a6868c34b 100644 Binary files a/icons/obj/doors/airlocks/highsec/overlays.dmi and b/icons/obj/doors/airlocks/highsec/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/shuttle/overlays.dmi b/icons/obj/doors/airlocks/shuttle/overlays.dmi index ccdcb15a64..50b2e25d8f 100644 Binary files a/icons/obj/doors/airlocks/shuttle/overlays.dmi and b/icons/obj/doors/airlocks/shuttle/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/shuttle/shuttle.dmi b/icons/obj/doors/airlocks/shuttle/shuttle.dmi index 2b897ebedc..0e05597163 100644 Binary files a/icons/obj/doors/airlocks/shuttle/shuttle.dmi and b/icons/obj/doors/airlocks/shuttle/shuttle.dmi differ diff --git a/icons/obj/doors/airlocks/station/atmos.dmi b/icons/obj/doors/airlocks/station/atmos.dmi index 21fe5d2aab..896eb91b22 100644 Binary files a/icons/obj/doors/airlocks/station/atmos.dmi and b/icons/obj/doors/airlocks/station/atmos.dmi differ diff --git a/icons/obj/doors/airlocks/station/bananium.dmi b/icons/obj/doors/airlocks/station/bananium.dmi index 2183a376f6..76aab35068 100644 Binary files a/icons/obj/doors/airlocks/station/bananium.dmi and b/icons/obj/doors/airlocks/station/bananium.dmi differ diff --git a/icons/obj/doors/airlocks/station/command.dmi b/icons/obj/doors/airlocks/station/command.dmi index 90b3e4238d..d29c1fd0b3 100644 Binary files a/icons/obj/doors/airlocks/station/command.dmi and b/icons/obj/doors/airlocks/station/command.dmi differ diff --git a/icons/obj/doors/airlocks/station/diamond.dmi b/icons/obj/doors/airlocks/station/diamond.dmi index a701df40d3..1c30830644 100644 Binary files a/icons/obj/doors/airlocks/station/diamond.dmi and b/icons/obj/doors/airlocks/station/diamond.dmi differ diff --git a/icons/obj/doors/airlocks/station/engineering.dmi b/icons/obj/doors/airlocks/station/engineering.dmi index 816a84538c..8fe1bf98d1 100644 Binary files a/icons/obj/doors/airlocks/station/engineering.dmi and b/icons/obj/doors/airlocks/station/engineering.dmi differ diff --git a/icons/obj/doors/airlocks/station/freezer.dmi b/icons/obj/doors/airlocks/station/freezer.dmi index 5aacef29f7..f2f741347b 100644 Binary files a/icons/obj/doors/airlocks/station/freezer.dmi and b/icons/obj/doors/airlocks/station/freezer.dmi differ diff --git a/icons/obj/doors/airlocks/station/gold.dmi b/icons/obj/doors/airlocks/station/gold.dmi index 40ce583de5..490eefeeb9 100644 Binary files a/icons/obj/doors/airlocks/station/gold.dmi and b/icons/obj/doors/airlocks/station/gold.dmi differ diff --git a/icons/obj/doors/airlocks/station/maintenance.dmi b/icons/obj/doors/airlocks/station/maintenance.dmi index 4b046afd7b..38d1b7142f 100644 Binary files a/icons/obj/doors/airlocks/station/maintenance.dmi and b/icons/obj/doors/airlocks/station/maintenance.dmi differ diff --git a/icons/obj/doors/airlocks/station/maintenanceexternal.dmi b/icons/obj/doors/airlocks/station/maintenanceexternal.dmi index 4323cf944e..a380d89584 100644 Binary files a/icons/obj/doors/airlocks/station/maintenanceexternal.dmi and b/icons/obj/doors/airlocks/station/maintenanceexternal.dmi differ diff --git a/icons/obj/doors/airlocks/station/medical.dmi b/icons/obj/doors/airlocks/station/medical.dmi index f7cb5be24e..bd354690c5 100644 Binary files a/icons/obj/doors/airlocks/station/medical.dmi and b/icons/obj/doors/airlocks/station/medical.dmi differ diff --git a/icons/obj/doors/airlocks/station/mining.dmi b/icons/obj/doors/airlocks/station/mining.dmi index 23dee39ef6..07e8fc32e2 100644 Binary files a/icons/obj/doors/airlocks/station/mining.dmi and b/icons/obj/doors/airlocks/station/mining.dmi differ diff --git a/icons/obj/doors/airlocks/station/overlays.dmi b/icons/obj/doors/airlocks/station/overlays.dmi index a489f40be9..b1e4f9aeab 100644 Binary files a/icons/obj/doors/airlocks/station/overlays.dmi and b/icons/obj/doors/airlocks/station/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/station/plasma.dmi b/icons/obj/doors/airlocks/station/plasma.dmi index eae1601ed3..99d44ef862 100644 Binary files a/icons/obj/doors/airlocks/station/plasma.dmi and b/icons/obj/doors/airlocks/station/plasma.dmi differ diff --git a/icons/obj/doors/airlocks/station/public.dmi b/icons/obj/doors/airlocks/station/public.dmi index 0449817360..efb4600adb 100644 Binary files a/icons/obj/doors/airlocks/station/public.dmi and b/icons/obj/doors/airlocks/station/public.dmi differ diff --git a/icons/obj/doors/airlocks/station/research.dmi b/icons/obj/doors/airlocks/station/research.dmi index e2a834d133..0f49927db0 100644 Binary files a/icons/obj/doors/airlocks/station/research.dmi and b/icons/obj/doors/airlocks/station/research.dmi differ diff --git a/icons/obj/doors/airlocks/station/sandstone.dmi b/icons/obj/doors/airlocks/station/sandstone.dmi index ccedcac9d4..ef61df4c5c 100644 Binary files a/icons/obj/doors/airlocks/station/sandstone.dmi and b/icons/obj/doors/airlocks/station/sandstone.dmi differ diff --git a/icons/obj/doors/airlocks/station/science.dmi b/icons/obj/doors/airlocks/station/science.dmi index a3aa87c5a6..53a9f42c06 100644 Binary files a/icons/obj/doors/airlocks/station/science.dmi and b/icons/obj/doors/airlocks/station/science.dmi differ diff --git a/icons/obj/doors/airlocks/station/security.dmi b/icons/obj/doors/airlocks/station/security.dmi index c6f01195ab..fd330c30f5 100644 Binary files a/icons/obj/doors/airlocks/station/security.dmi and b/icons/obj/doors/airlocks/station/security.dmi differ diff --git a/icons/obj/doors/airlocks/station/silver.dmi b/icons/obj/doors/airlocks/station/silver.dmi index d3308eb8cd..e7e6672fbf 100644 Binary files a/icons/obj/doors/airlocks/station/silver.dmi and b/icons/obj/doors/airlocks/station/silver.dmi differ diff --git a/icons/obj/doors/airlocks/station/uranium.dmi b/icons/obj/doors/airlocks/station/uranium.dmi index eda814f97e..ac8c6d0611 100644 Binary files a/icons/obj/doors/airlocks/station/uranium.dmi and b/icons/obj/doors/airlocks/station/uranium.dmi differ diff --git a/icons/obj/doors/airlocks/station/virology.dmi b/icons/obj/doors/airlocks/station/virology.dmi index 79ac14dffc..b90e9cf29c 100644 Binary files a/icons/obj/doors/airlocks/station/virology.dmi and b/icons/obj/doors/airlocks/station/virology.dmi differ diff --git a/icons/obj/doors/airlocks/station/wood.dmi b/icons/obj/doors/airlocks/station/wood.dmi index ae34e82743..7b7df10329 100644 Binary files a/icons/obj/doors/airlocks/station/wood.dmi and b/icons/obj/doors/airlocks/station/wood.dmi differ diff --git a/icons/obj/doors/airlocks/station2/glass.dmi b/icons/obj/doors/airlocks/station2/glass.dmi index 69f97ceb2a..94d7ed7429 100644 Binary files a/icons/obj/doors/airlocks/station2/glass.dmi and b/icons/obj/doors/airlocks/station2/glass.dmi differ diff --git a/icons/obj/doors/airlocks/station2/overlays.dmi b/icons/obj/doors/airlocks/station2/overlays.dmi index d265abd26e..4cb389cbf2 100644 Binary files a/icons/obj/doors/airlocks/station2/overlays.dmi and b/icons/obj/doors/airlocks/station2/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/vault/overlays.dmi b/icons/obj/doors/airlocks/vault/overlays.dmi index db39b53fb6..f18346acf6 100644 Binary files a/icons/obj/doors/airlocks/vault/overlays.dmi and b/icons/obj/doors/airlocks/vault/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/vault/vault.dmi b/icons/obj/doors/airlocks/vault/vault.dmi index 8281d3cd5a..d2ef5d4e46 100644 Binary files a/icons/obj/doors/airlocks/vault/vault.dmi and b/icons/obj/doors/airlocks/vault/vault.dmi differ diff --git a/icons/obj/doors/doorint.dmi b/icons/obj/doors/doorint.dmi index e48b91da16..2abe5c7956 100644 Binary files a/icons/obj/doors/doorint.dmi and b/icons/obj/doors/doorint.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index d2d93afac0..c24f7c4c16 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi new file mode 100644 index 0000000000..f0eb817549 Binary files /dev/null and b/icons/obj/plushes.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index f2176c395d..d5cae1db93 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/sound/items/toysqueak1.ogg b/sound/items/toysqueak1.ogg new file mode 100644 index 0000000000..e64a6fb179 Binary files /dev/null and b/sound/items/toysqueak1.ogg differ diff --git a/sound/items/toysqueak2.ogg b/sound/items/toysqueak2.ogg new file mode 100644 index 0000000000..fddf1edfb9 Binary files /dev/null and b/sound/items/toysqueak2.ogg differ diff --git a/sound/items/toysqueak3.ogg b/sound/items/toysqueak3.ogg new file mode 100644 index 0000000000..338f4d8aa9 Binary files /dev/null and b/sound/items/toysqueak3.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 7c8358bba4..21a9ce81bd 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -263,7 +263,6 @@ #include "code\datums\hud.dm" #include "code\datums\map_config.dm" #include "code\datums\martial.dm" -#include "code\datums\material_container.dm" #include "code\datums\mind.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\mutations.dm" @@ -286,7 +285,9 @@ #include "code\datums\antagonists\ninja.dm" #include "code\datums\components\archaeology.dm" #include "code\datums\components\component.dm" +#include "code\datums\components\material_container.dm" #include "code\datums\components\slippery.dm" +#include "code\datums\components\squeek.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" #include "code\datums\diseases\anxiety.dm" @@ -798,6 +799,7 @@ #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\paiwire.dm" #include "code\game\objects\items\pinpointer.dm" +#include "code\game\objects\items\plushes.dm" #include "code\game\objects\items\pneumaticCannon.dm" #include "code\game\objects\items\powerfist.dm" #include "code\game\objects\items\RCD.dm" @@ -829,6 +831,7 @@ #include "code\game\objects\items\devices\camera_bug.dm" #include "code\game\objects\items\devices\chameleonproj.dm" #include "code\game\objects\items\devices\doorCharge.dm" +#include "code\game\objects\items\devices\electroadaptive_pseudocircuit.dm" #include "code\game\objects\items\devices\flashlight.dm" #include "code\game\objects\items\devices\forcefieldprojector.dm" #include "code\game\objects\items\devices\geiger_counter.dm" @@ -1823,6 +1826,7 @@ #include "code\modules\mob\living\simple_animal\hostile\megafauna\bubblegum.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\colossus.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\dragon.dm" +#include "code\modules\mob\living\simple_animal\hostile\megafauna\dragon_vore.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\hierophant.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\legion.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\megafauna.dm" diff --git a/tools/CreditsTool/CreditsTool.csproj b/tools/CreditsTool/CreditsTool.csproj new file mode 100644 index 0000000000..68187a0815 --- /dev/null +++ b/tools/CreditsTool/CreditsTool.csproj @@ -0,0 +1,47 @@ + + + + + Debug + AnyCPU + {BA95D3D9-1940-4183-8563-BE617D752D0B} + Exe + CreditsTool + CreditsTool + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/CreditsTool/CreditsTool.exe b/tools/CreditsTool/CreditsTool.exe new file mode 100644 index 0000000000..da0187aaf7 Binary files /dev/null and b/tools/CreditsTool/CreditsTool.exe differ diff --git a/tools/CreditsTool/Program.cs b/tools/CreditsTool/Program.cs new file mode 100644 index 0000000000..d5dd162412 --- /dev/null +++ b/tools/CreditsTool/Program.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Web.Script.Serialization; + +namespace CreditsTool +{ + class Program + { + const string ConfigPath = "remappings.txt"; + const string OutputLocation = "./credit_pngs"; + const int world_icon_size = 32; + //this downloads all the user images of contributors of a passed github repository + //usage ./CreditsTool [authToken (helps with github rate limiter)] + static void Main(string[] args) + { + if (args.Length < 2) + { + Console.WriteLine("Usage: ./CreditsTool.exe [authToken]"); + return; + } + + if (Directory.Exists(OutputLocation)) + { + Console.WriteLine(String.Format("Aborted: {0} exists!", OutputLocation)); + return; + } + Directory.CreateDirectory(OutputLocation); + + string repoOwner = args[0], + repoName = args[1], + authToken = args.Length > 2 ? args[2] : null; + + Console.WriteLine("Querying contributors API..."); + + var FirstResponse = GetPageResponse(repoOwner, repoName, authToken, 1); + + Console.WriteLine("Collecting avatar URLs..."); + + var LoginAvatars = new Dictionary(); + //now list the things we want: avatar urls and logins + foreach (var I in LoadPages(FirstResponse, repoOwner, repoName, authToken)) { + var avurl = (string)I["avatar_url"]; + LoginAvatars.Add((string)I["login"], String.Format("{0}{1}s={2}", avurl, avurl.Contains("?") ? "&" : "?", world_icon_size)); + } + + Console.WriteLine(String.Format("Collected info for {0} contributors.", LoginAvatars.Count)); + + Console.WriteLine("Remapping github logins..."); + + var remaps = LoadConfig(); + + Console.WriteLine(String.Format("Downloading and converting avatars to {0} (this will take a while)...", OutputLocation)); + + using (var client = new WebClient()) + { + var count = 0; + foreach (var I in LoginAvatars) + { + var writtenFilename = I.Key; + if (remaps.TryGetValue(writtenFilename, out string tmp)) + { + if (tmp == "__REMOVE__") + continue; + writtenFilename = tmp; + } + using (var stream = new MemoryStream(client.DownloadData(I.Value))) + using (var originalBMP = new Bitmap(stream)) + { + if (originalBMP.Width == world_icon_size && originalBMP.Height == world_icon_size) //no need to resize + SaveBMP(originalBMP, writtenFilename); + else + using (var resizedBMP = new Bitmap(originalBMP, new Size(world_icon_size, world_icon_size))) + SaveBMP(resizedBMP, writtenFilename); + } + Console.WriteLine(String.Format("Done {0}.png! {1}%", writtenFilename, (int)((((float)(count + 1)) / LoginAvatars.Count) * 100))); + ++count; + } + } + } + + static void SaveBMP(Bitmap bmp, string writtenFilename) + { + bmp.Save(String.Format("{0}{1}{2}.png", OutputLocation, Path.DirectorySeparatorChar, writtenFilename), ImageFormat.Png); + } + + static IDictionary LoadConfig() + { + var result = new Dictionary(); + if (File.Exists(ConfigPath)) + foreach (var I in File.ReadAllLines(ConfigPath)) + if (!String.IsNullOrWhiteSpace(I) && I[0] != '#') + { + var splits = new List(I.Split(' ')); + if (splits.Count >= 1 && !String.IsNullOrEmpty(splits[1])) + { + var key = splits[0]; + splits.RemoveAt(0); + result.Add(key, String.Join(" ", splits)); + } + } + return result; + } + + static IEnumerable> LoadPages(WebResponse firstResponse, string repoOwner, string repoName, string authToken) + { + int numPages = GetNumPagesOfContributors(firstResponse); + Console.WriteLine(String.Format("Downloading {0} pages of contributor info...", numPages)); + //load and combine json for all pages + var jss = new JavaScriptSerializer(); + using (var sr = new StreamReader(firstResponse.GetResponseStream())) + foreach (var J in jss.Deserialize>>(sr.ReadToEnd())) + yield return J; + + //skip the first + for (var I = 2; I <= numPages; ++I) + using (var sr = new StreamReader(GetPageResponse(repoOwner, repoName, authToken, I).GetResponseStream())) + foreach (var J in jss.Deserialize>>(sr.ReadToEnd())) + yield return J; + } + + static int GetNumPagesOfContributors(WebResponse response) + { + var splits = response.Headers["Link"].Split(','); + foreach (var I in splits) + if (I.Contains("rel=\"last\"")) //our boy + { + var pagestrIndex = I.IndexOf("&page=") + 6; + var closingIndex = I.IndexOf('>', pagestrIndex + 1); + var thedroidswerelookingfor = I.Substring(pagestrIndex, closingIndex - pagestrIndex); + return Convert.ToInt32(thedroidswerelookingfor); + } + return 1; + } + + static WebResponse GetPageResponse(string repoOwner, string repoName, string authToken, int pageNumber) + { + HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(String.Format("https://api.github.com/repos/{0}/{1}/contributors?per_page=100&page={2}", repoOwner, repoName, pageNumber)); + httpWebRequest.Method = WebRequestMethods.Http.Get; + httpWebRequest.Accept = "application/json"; + httpWebRequest.UserAgent = "tgstation-13-credits-tool"; + if (authToken != null) + httpWebRequest.Headers.Add(String.Format("Authorization: token {0}", authToken)); + return httpWebRequest.GetResponse(); + } + } +} diff --git a/tools/CreditsTool/UpdateCreditsDMI.sh b/tools/CreditsTool/UpdateCreditsDMI.sh new file mode 100644 index 0000000000..89d24e1e8f --- /dev/null +++ b/tools/CreditsTool/UpdateCreditsDMI.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +#If you hit github's rate limit, add a 3rd parameter here that is a github personal access token +./CreditsTool tgstation tgstation + +rm ../../icons/credits.dmi + +for filename in credit_pngs/*.png; do + realname=$(basename "$filename") + java -jar ../dmitool/dmitool.jar import ../../icons/credits.dmi "${realname%.*}" "$filename" +done + +rm -rf credit_pngs diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index dde21e4f43..4e20a7e902 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -15,10 +15,8 @@ */ -//CONFIG START (all defaults are random examples, do change them) -//Use single quotes for config options that are strings. +//CONFIGS ARE IN SECRET.PHP, THESE ARE JUST DEFAULTS! -//These are all default settings that are described in secret.php $hookSecret = '08ajh0qj93209qj90jfq932j32r'; $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; $repoOwnerAndName = "tgstation/tgstation"; @@ -33,6 +31,7 @@ $maintainer_team_id = 133041; $validation = "org"; $validation_count = 1; $tracked_branch = 'master'; +$require_changelogs = false; require_once 'secret.php'; @@ -43,6 +42,7 @@ set_error_handler(function($severity, $message, $file, $line) { set_exception_handler(function($e) { header('HTTP/1.1 500 Internal Server Error'); echo "Error on line {$e->getLine()}: " . htmlSpecialChars($e->getMessage()); + file_put_contents('htwebhookerror.log', "Error on line {$e->getLine()}: " . $e->getMessage(), FILE_APPEND); die(); }); $rawPost = NULL; @@ -96,6 +96,16 @@ switch (strtolower($_SERVER['HTTP_X_GITHUB_EVENT'])) { case 'pull_request': handle_pr($payload); break; + case 'pull_request_review': + if($payload['action'] == 'submitted'){ + $lower_state = strtolower($payload['review']['state']); + if(($lower_state == 'approved' || $lower_state == 'changes_requested') && is_maintainer($payload, $payload['review']['user']['login'])){ + $lower_association = strtolower($payload['review']['author_association']); + if($lower_association == 'member' || $lower_association == 'contributor' || $lower_association == 'owner') + remove_ready_for_review($payload); + } + } + break; default: header('HTTP/1.0 404 Not Found'); echo "Event:$_SERVER[HTTP_X_GITHUB_EVENT] Payload:\n"; @@ -103,36 +113,87 @@ switch (strtolower($_SERVER['HTTP_X_GITHUB_EVENT'])) { die(); } -//rip bs-12 -function tag_pr($payload, $opened) { +function apisend($url, $method = 'GET', $content = NULL) { global $apiKey; - - //We need to reget the pull_request part of the payload to actually see the mergeable field populated - //http://stackoverflow.com/questions/30619549/why-does-github-api-return-an-unknown-mergeable-state-in-a-pull-request + if (is_array($content)) + $content = json_encode($content); + $scontext = array('http' => array( - 'method' => 'GET', + 'method' => $method, 'header' => "Content-type: application/json\r\n". 'Authorization: token ' . $apiKey, 'ignore_errors' => true, 'user_agent' => 'tgstation13.org-Github-Automation-Tools' )); + if ($content) + $scontext['http']['content'] = $content; + + return file_get_contents($url, false, stream_context_create($scontext)); +} +function validate_user($payload) { + global $validation, $validation_count; + $query = array(); + if (empty($validation)) + $validation = 'org'; + switch (strtolower($validation)) { + case 'disable': + return TRUE; + case 'repo': + $query['repo'] = $payload['pull_request']['base']['repo']['full_name']; + break; + default: + $query['user'] = $payload['pull_request']['base']['repo']['owner']['login']; + break; + } + $query['author'] = $payload['pull_request']['user']['login']; + $query['is'] = 'merged'; + $querystring = ''; + foreach($query as $key => $value) + $querystring .= ($querystring == '' ? '' : '+') . urlencode($key) . ':' . urlencode($value); + $res = apisend('https://api.github.com/search/issues?q='.$querystring); + $res = json_decode($res, TRUE); + return $res['total_count'] >= (int)$validation_count; + +} +function get_labels($payload){ + $url = $payload['pull_request']['issue_url'] . '/labels'; + $existing_labels = json_decode(apisend($url), true); + $existing = array(); + foreach($existing_labels as $label) + $existing[] = $label['name']; + return $existing; +} + +function check_tag_and_replace($payload, $title_tag, $label, &$array_to_add_label_to){ + $title = $payload['pull_request']['title']; + if(stripos($title, $title_tag) !== FALSE){ + $array_to_add_label_to[] = $label; + $title = trim(str_ireplace($title_tag, '', $title)); + apisend($payload['pull_request']['url'], 'PATCH', array('title' => $title)); + return true; + } + return false; +} + +//rip bs-12 +function tag_pr($payload, $opened) { + //get the mergeable state $url = $payload['pull_request']['url']; - $payload['pull_request'] = json_decode(file_get_contents($url, false, stream_context_create($scontext)), true); + $payload['pull_request'] = json_decode(apisend($url), TRUE); if($payload['pull_request']['mergeable'] == null) { //STILL not ready. Give it a bit, then try one more time sleep(10); - $payload['pull_request'] = json_decode(file_get_contents($url, false, stream_context_create($scontext)), true); + $payload['pull_request'] = json_decode(apisend($url), TRUE); } $tags = array(); $title = $payload['pull_request']['title']; if($opened) { //you only have one shot on these ones so as to not annoy maintainers - $tags = checkchangelog($payload, true, false); + $tags = checkchangelog($payload, false); - $lowertitle = strtolower($title); - if(strpos($lowertitle, 'refactor') !== FALSE) + if(strpos(strtolower($title), 'refactor') !== FALSE) $tags[] = 'Refactor'; if(strpos(strtolower($title), 'revert') !== FALSE || strpos(strtolower($title), 'removes') !== FALSE) @@ -148,7 +209,7 @@ function tag_pr($payload, $opened) { $tags[] = 'Merge Conflict'; $treetags = array('_maps' => 'Map Edit', 'tools' => 'Tools', 'SQL' => 'SQL'); - $addonlytags = array('icons' => 'Sprites', 'sounds' => 'Sound'); + $addonlytags = array('icons' => 'Sprites', 'sounds' => 'Sound', 'config' => 'Config Update'); foreach($treetags as $tree => $tag) if(has_tree_been_edited($payload, $tree)) $tags[] = $tag; @@ -158,21 +219,14 @@ function tag_pr($payload, $opened) { if(has_tree_been_edited($payload, $tree)) $tags[] = $tag; - //only maintners should be able to remove these - if(strpos($lowertitle, '[dnm]') !== FALSE) - $tags[] = 'Do Not Merge'; - - if(strpos($lowertitle, '[wip]') !== FALSE) - $tags[] = 'Work In Progress'; + check_tag_and_replace($payload, '[dnm]', 'Do Not Merge', $tags); + if(!check_tag_and_replace($payload, '[wip]', 'Work In Progress', $tags)) + check_tag_and_replace($payload, '[ready]', 'Work In Progress', $remove); $url = $payload['pull_request']['issue_url'] . '/labels'; - $existing_labels = file_get_contents($url, false, stream_context_create($scontext)); - $existing_labels = json_decode($existing_labels, true); + $existing = get_labels($payload); - $existing = array(); - foreach($existing_labels as $label) - $existing[] = $label['name']; $tags = array_merge($tags, $existing); $tags = array_unique($tags); $tags = array_diff($tags, $remove); @@ -181,27 +235,153 @@ function tag_pr($payload, $opened) { foreach($tags as $t) $final[] = $t; - $scontext['http']['method'] = 'PUT'; - $scontext['http']['content'] = json_encode($final); - echo file_get_contents($url, false, stream_context_create($scontext)); + echo apisend($url, 'PUT', $final); + + return $final; +} + +function remove_ready_for_review($payload, $labels = null){ + if($labels == null) + $labels = get_labels($payload); + $index = array_search('Ready for Review', $labels); + if($index !== FALSE) + unset($labels[$index]); + $url = $payload['pull_request']['issue_url'] . '/labels'; + apisend($url, 'PUT', $labels); +} + +function dismiss_review($payload, $id, $reason){ + $content = array('message' => $reason); + apisend($payload['pull_request']['url'] . '/reviews/' . $id . '/dismissals', 'PUT', $content); +} + +function get_reviews($payload){ + return json_decode(apisend($payload['pull_request']['url'] . '/reviews'), true); +} + +function check_ready_for_review($payload, $labels = null){ + $r4rlabel = 'Ready for Review'; + $labels_which_should_not_be_ready = array('Do Not Merge', 'Work In Progress', 'Merge Conflict'); + $has_label_already = false; + $should_not_have_label = false; + if($labels == null) + $labels = get_labels($payload); + //if the label is already there we may need to remove it + foreach($labels as $L){ + if(in_array($L, $labels_which_should_not_be_ready)) + $should_not_have_label = true; + if($L == $r4rlabel) + $has_label_already = true; + } + + if($has_label_already && $should_not_have_label){ + remove_ready_for_review($payload, $labels, $r4rlabel); + return; + } + + //find all reviews to see if changes were requested at some point + $reviews = get_reviews($payload); + + $reviews_ids_with_changes_requested = array(); + $dismissed_an_approved_review = false; + + foreach($reviews as $R){ + $lower_association = strtolower($R['author_association']); + if($lower_association == 'member' || $lower_association == 'contributor' || $lower_association == 'owner'){ + $lower_state = strtolower($R['state']); + if($lower_state == 'changes_requested') + $reviews_ids_with_changes_requested[] = $R['id']; + else if ($lower_state == 'approved'){ + dismiss_review($payload, $R['id'], 'Out of date review'); + $dismissed_an_approved_review = true; + } + } + } + + if(!$dismissed_an_approved_review && count($reviews_ids_with_changes_requested) == 0){ + if($has_label_already) + remove_ready_for_review($payload, $labels); + return; //no need to be here + } + + if(count($reviews_ids_with_changes_requested) > 0){ + //now get the review comments for the offending reviews + + $review_comments = json_decode(apisend($payload['pull_request']['review_comments_url']), true); + + foreach($review_comments as $C){ + //make sure they are part of an offending review + if(!in_array($C['pull_request_review_id'], $reviews_ids_with_changes_requested)) + continue; + + //review comments which are outdated have a null position + if($C['position'] !== null){ + if($has_label_already) + remove_ready_for_review($payload, $labels); + return; //no need to tag + } + } + } + + //finally, add it if necessary + if(!$has_label_already){ + $labels[] = $r4rlabel; + $url = $payload['pull_request']['issue_url'] . '/labels'; + apisend($url, 'PUT', $labels); + } +} + +function check_dismiss_changelog_review($payload){ + global $require_changelog; + global $no_changelog; + + if(!$require_changelog) + return; + + if(!$no_changelog) + checkchangelog($payload, false); + + $review_message = 'Your changelog for this PR is either malformed or non-existent. Please create one to document your changes.'; + + $reviews = get_reviews($payload); + if($no_changelog){ + //check and see if we've already have this review + foreach($reviews as $R) + if($R['body'] == $review_message && strtolower($R['state']) == 'changes_requested') + return; + //otherwise make it ourself + apisend($payload['pull_request']['url'] . '/reviews', 'POST', array('body' => $review_message, 'event' => 'REQUEST_CHANGES')); + } + else + //kill previous reviews + foreach($reviews as $R) + if($R['body'] == $review_message && strtolower($R['state']) == 'changes_requested') + dismiss_review($payload, $R['id'], 'Changelog added/fixed.'); } function handle_pr($payload) { + global $no_changelog; $action = 'opened'; + $validated = validate_user($payload); switch ($payload["action"]) { case 'opened': tag_pr($payload, true); + if($no_changelog) + check_dismiss_changelog_review($payload); if(get_pr_code_friendliness($payload) < 0){ $balances = pr_balances(); $author = $payload['pull_request']['user']['login']; - if(isset($balances[$author]) && $balances[$author] < 0) + if(isset($balances[$author]) && $balances[$author] < 0 && !is_maintainer($payload, $author)) create_comment($payload, 'You currently have a negative Fix/Feature pull request delta of ' . $balances[$author] . '. Maintainers may close this PR at will. Fixing issues or improving the codebase will improve this score.'); } break; case 'edited': + check_dismiss_changelog_review($payload); case 'synchronize': - tag_pr($payload, false); + $labels = tag_pr($payload, false); + if($payload['action'] == 'synchronize') + check_ready_for_review($payload, $labels); return; case 'reopened': $action = $payload['action']; @@ -213,7 +393,7 @@ function handle_pr($payload) { else { $action = 'merged'; auto_update($payload); - checkchangelog($payload, true, true); + checkchangelog($payload, true); update_pr_balance($payload); $validated = TRUE; //pr merged events always get announced. } @@ -226,7 +406,11 @@ function handle_pr($payload) { echo "PR Announcement Halted; Secret tag detected.\n"; return; } - + if (!$validated) { + echo "PR Announcement Halted; User not validated.\n"; + return; + } + $msg = '['.$payload['pull_request']['base']['repo']['full_name'].'] Pull Request '.$action.' by '.htmlSpecialChars($payload['sender']['login']).': '.htmlSpecialChars('#'.$payload['pull_request']['number'].' '.$payload['pull_request']['user']['login'].' - '.$payload['pull_request']['title']).''; sendtoallservers('?announce='.urlencode($msg), $payload); } @@ -306,7 +490,7 @@ function is_maintainer($payload, $author){ global $maintainer_team_id; $repo_is_org = $payload['pull_request']['base']['repo']['owner']['type'] == 'Organization'; if($maintainer_team_id == null || !$repo_is_org) { - $collaburl = $payload['pull_request']['base']['repo']['collaborators_url'] . '/' . $author . '/permissions'; + $collaburl = str_replace('{/collaborator}', '/' . $author, $payload['pull_request']['base']['repo']['collaborators_url']) . '/permission'; $perms = json_decode(apisend($collaburl), true); $permlevel = $perms['permission']; return $permlevel == 'admin' || $permlevel == 'write'; @@ -314,7 +498,7 @@ function is_maintainer($payload, $author){ else { $check_url = 'https://api.github.com/teams/' . $maintainer_team_id . '/memberships/' . $author; $result = json_decode(apisend($check_url), true); - return isset($result['state']); //this field won't be here if they aren't a member + return isset($result['state']) && $result['state'] == 'active'; } } @@ -325,17 +509,17 @@ function update_pr_balance($payload) { if(!$trackPRBalance) return; $author = $payload['pull_request']['user']['login']; - if(is_maintainer($payload, $author)) //immune - return; $balances = pr_balances(); if(!isset($balances[$author])) $balances[$author] = $startingPRBalance; $friendliness = get_pr_code_friendliness($payload, $balances[$author]); $balances[$author] += $friendliness; - if($balances[$author] < 0 && $friendliness < 0) - create_comment($payload, 'Your Fix/Feature pull request delta is currently below zero (' . $balances[$author] . '). Maintainers may close future Feature/Tweak/Balance PRs. Fixing issues or helping to improve the codebase will raise this score.'); - else if($balances[$author] >= 0 && ($balances[$author] - $friendliness) < 0) - create_comment($payload, 'Your Fix/Feature pull request delta is now above zero (' . $balances[$author] . '). Feel free to make Feature/Tweak/Balance PRs.'); + if(!is_maintainer($payload, $author)){ //immune + if($balances[$author] < 0 && $friendliness < 0) + create_comment($payload, 'Your Fix/Feature pull request delta is currently below zero (' . $balances[$author] . '). Maintainers may close future Feature/Tweak/Balance PRs. Fixing issues or helping to improve the codebase will raise this score.'); + else if($balances[$author] >= 0 && ($balances[$author] - $friendliness) < 0) + create_comment($payload, 'Your Fix/Feature pull request delta is now above zero (' . $balances[$author] . '). Feel free to make Feature/Tweak/Balance PRs.'); + } $balances_file = fopen(pr_balance_json_path(), 'w'); fwrite($balances_file, json_encode($balances)); fclose($balances_file); @@ -372,10 +556,9 @@ function has_tree_been_edited($payload, $tree){ return $github_diff !== FALSE && strpos($github_diff, 'diff --git a/' . $tree) !== FALSE; } -function checkchangelog($payload, $merge = false, $compile = true) { - global $apiKey; - if (!$merge) - return; +$no_changelog = false; +function checkchangelog($payload, $compile = true) { + global $no_changelog; if (!isset($payload['pull_request']) || !isset($payload['pull_request']['body'])) { return; } @@ -449,10 +632,6 @@ function checkchangelog($payload, $merge = false, $compile = true) { $currentchangelogblock[] = array('type' => 'bugfix', 'body' => $item); } break; - case 'wip': - if($item != 'added a few works in progress') - $currentchangelogblock[] = array('type' => 'wip', 'body' => $item); - break; case 'rsctweak': case 'tweaks': case 'tweak': @@ -510,11 +689,6 @@ function checkchangelog($payload, $merge = false, $compile = true) { $currentchangelogblock[] = array('type' => 'spellcheck', 'body' => $item); } break; - case 'experimental': - case 'experiment': - if($item != 'added an experimental thingy') - $currentchangelogblock[] = array('type' => 'experiment', 'body' => $item); - break; case 'balance': case 'rebalance': if($item != 'rebalanced something'){ @@ -525,6 +699,35 @@ function checkchangelog($payload, $merge = false, $compile = true) { case 'tgs': $currentchangelogblock[] = array('type' => 'tgs', 'body' => $item); break; + case 'code_imp': + case 'code': + if($item != 'changed some code'){ + $tags[] = 'Code Improvement'; + $currentchangelogblock[] = array('type' => 'code_imp', 'body' => $item); + } + break; + case 'refactor': + if($item != 'refactored some code'){ + $tags[] = 'Refactor'; + $currentchangelogblock[] = array('type' => 'refactor', 'body' => $item); + } + break; + case 'config': + if($item != 'changed some config setting'){ + $tags[] = 'Config Update'; + $currentchangelogblock[] = array('type' => 'config', 'body' => $item); + } + break; + case 'admin': + if($item != 'messed with admin stuff'){ + $tags[] = 'Administration'; + $currentchangelogblock[] = array('type' => 'admin', 'body' => $item); + } + break; + case 'server': + if($item != 'something server ops should know') + $currentchangelogblock[] = array('type' => 'server', 'body' => $item); + break; default: //we add it to the last changelog entry as a separate line if (count($currentchangelogblock) > 0) @@ -533,7 +736,10 @@ function checkchangelog($payload, $merge = false, $compile = true) { } } - if (!count($changelogbody) || !$compile) + if(!count($changelogbody)) + $no_changelog = true; + + if ($no_changelog || !$compile) return $tags; $file = 'author: "'.trim(str_replace(array("\\", '"'), array("\\\\", "\\\""), $username)).'"'."\n"; @@ -550,17 +756,9 @@ function checkchangelog($payload, $merge = false, $compile = true) { 'message' => 'Automatic changelog generation for PR #'.$payload['pull_request']['number'].' [ci skip]', 'content' => base64_encode($file) ); - $scontext = array('http' => array( - 'method' => 'PUT', - 'header' => - "Content-type: application/json\r\n". - 'Authorization: token ' . $apiKey, - 'content' => json_encode($content), - 'ignore_errors' => true, - 'user_agent' => 'tgstation13.org-Github-Automation-Tools' - )); + $filename = '/html/changelogs/AutoChangeLog-pr-'.$payload['pull_request']['number'].'.yml'; - echo file_get_contents($payload['pull_request']['base']['repo']['url'].'/contents'.$filename, false, stream_context_create($scontext)); + echo apisend($payload['pull_request']['base']['repo']['url'].'/contents'.$filename, 'PUT', $content); } function sendtoallservers($str, $payload = null) { diff --git a/tools/WebhookProcessor/secret.php b/tools/WebhookProcessor/secret.php index abea10564f..93c9b318f6 100644 --- a/tools/WebhookProcessor/secret.php +++ b/tools/WebhookProcessor/secret.php @@ -8,6 +8,7 @@ $hookSecret = '08ajh0qj93209qj90jfq932j32r'; //Api key for pushing changelogs. +//This requires the public_repo (or repo for private repositories) and read:org permissions $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; //Used to prevent potential RCEs @@ -47,3 +48,6 @@ $validation = "org"; //how many merged prs must they have under the rules above to have their pr announced to the game servers. $validation_count = 1; + +//enforce changelogs on PRs +$require_changelogs = false; diff --git a/tools/ss13_genchangelog.py b/tools/ss13_genchangelog.py index c4e22014df..c7a31325b1 100644 --- a/tools/ss13_genchangelog.py +++ b/tools/ss13_genchangelog.py @@ -57,7 +57,12 @@ validPrefixes = [ 'spellcheck', 'experiment', 'tgs', - 'balance' + 'balance', + 'code_imp', + 'refactor', + 'config', + 'admin', + 'server' ] def dictToTuples(inp): diff --git a/tools/travis/before_build_byond.sh b/tools/travis/before_build_byond.sh index af7dc3cc66..8cfe0a1cf6 100755 --- a/tools/travis/before_build_byond.sh +++ b/tools/travis/before_build_byond.sh @@ -5,6 +5,10 @@ set -e if [ "$BUILD_TOOLS" = true ]; then exit 0 fi; +echo "Combining maps for building" +if [ "$DM_MAPFILE" = "loadallmaps" ]; then + python tools/travis/template_dm_generator.py +fi; if [ -d "$HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin" ]; then diff --git a/tools/travis/before_build_tools.sh b/tools/travis/before_build_tools.sh index 50167e1262..2329de82b2 100755 --- a/tools/travis/before_build_tools.sh +++ b/tools/travis/before_build_tools.sh @@ -5,6 +5,3 @@ if [ "$BUILD_TOOLS" = true ]; then cd tgui && source ~/.nvm/nvm.sh && npm install && cd .. fi; -if [ "$DM_MAPFILE" = "loadallmaps" ]; then - python tools/travis/template_dm_generator.py -fi; diff --git a/tools/travis/build_tools.sh b/tools/travis/build_tools.sh index 6aba5da538..2e9810b470 100755 --- a/tools/travis/build_tools.sh +++ b/tools/travis/build_tools.sh @@ -7,5 +7,6 @@ if [ "$BUILD_TOOLS" = true ]; then md5sum -c - <<< "49bc6b1b9ed56c83cceb6674bd97cb34 *html/changelogs/example.yml"; cd tgui && source ~/.nvm/nvm.sh && gulp && cd ..; + php5.6 -l tools/WebhookProcessor/github_webhook_processor.php; python tools/ss13_genchangelog.py html/changelog.html html/changelogs; fi;