diff --git a/_maps/map_files/NSVBlueshift/Blueshift.dmm b/_maps/map_files/NSVBlueshift/Blueshift.dmm index b4c280df87a..33b1872f727 100644 --- a/_maps/map_files/NSVBlueshift/Blueshift.dmm +++ b/_maps/map_files/NSVBlueshift/Blueshift.dmm @@ -18359,7 +18359,7 @@ /obj/item/clothing/suit/jacket/letterman_syndie, /obj/item/clothing/suit/jacket/miljacket, /obj/item/clothing/suit/jacket/leather, -/obj/item/clothing/suit/croptop, +/obj/item/clothing/suit/jacket/croptop, /turf/open/floor/iron/dark, /area/station/common/tailoring) "dwK" = ( diff --git a/_maps/safehouses/ancientmilsim_nova.dmm b/_maps/safehouses/ancientmilsim_nova.dmm index 4b00bcb4370..015646aa8fb 100644 --- a/_maps/safehouses/ancientmilsim_nova.dmm +++ b/_maps/safehouses/ancientmilsim_nova.dmm @@ -4,33 +4,32 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/virtual_domain/safehouse) "b" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /obj/structure/closet/crate/secure/weapon, -/obj/item/storage/pouch/medical/firstaid/stabilizer, -/obj/item/storage/pouch/ammo, -/obj/item/clothing/head/helmet/hecu, -/obj/item/clothing/suit/armor/vest/hecu, +/obj/item/storage/medkit/combat_surgeon/stocked, +/obj/item/storage/medkit/civil_defense/stocked, +/obj/item/clothing/glasses/hud/health/night, +/obj/item/storage/belt/military/assault, /obj/item/storage/box/survival/syndie, -/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/clothing/head/helmet/sf_peacekeeper, +/obj/item/clothing/suit/armor/sf_peacekeeper, /obj/item/knife/combat, -/obj/item/gun/ballistic/automatic/pistol/sol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, -/obj/item/storage/belt/military/assault/hecu, +/obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, -/obj/item/stack/medical/mesh/bloody, -/obj/item/stack/medical/suture/bloody, -/obj/item/clothing/gloves/military, -/obj/item/clothing/glasses/hud/health/night, +/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/gun/ballistic/automatic/pistol/sol, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/sand/volcanic, /turf/open/floor/iron, /area/virtual_domain/safehouse) "e" = ( @@ -131,29 +130,27 @@ /turf/open/floor/iron, /area/virtual_domain/safehouse) "G" = ( -/obj/effect/turf_decal/stripes/end, -/obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate/secure/weapon, -/obj/item/storage/pouch/medical/firstaid/stabilizer, -/obj/item/storage/pouch/ammo, -/obj/item/clothing/head/helmet/hecu, -/obj/item/clothing/suit/armor/vest/hecu, +/obj/item/storage/medkit/combat_surgeon/stocked, +/obj/item/storage/medkit/civil_defense/stocked, +/obj/item/clothing/glasses/hud/health/night, +/obj/item/storage/belt/military/assault, /obj/item/storage/box/survival/syndie, -/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/clothing/head/helmet/sf_peacekeeper, +/obj/item/clothing/suit/armor/sf_peacekeeper, /obj/item/knife/combat, -/obj/item/gun/ballistic/automatic/pistol/sol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, -/obj/item/storage/belt/military/assault/hecu, +/obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, -/obj/item/stack/medical/mesh/bloody, -/obj/item/stack/medical/suture/bloody, -/obj/item/clothing/gloves/military, -/obj/item/clothing/glasses/hud/health/night, +/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/gun/ballistic/automatic/pistol/sol, +/obj/effect/turf_decal/stripes/end, +/obj/effect/turf_decal/sand/volcanic, /turf/open/floor/iron, /area/virtual_domain/safehouse) "H" = ( @@ -170,7 +167,6 @@ }, /obj/effect/decal/cleanable/dirt, /obj/machinery/computer{ - dir = 2; name = "hovercraft console"; icon_screen = "shuttle"; desc = "An armored hovercraft control computer. Doesn't work anymore... who would've thought." @@ -223,26 +219,24 @@ }, /obj/effect/turf_decal/sand/volcanic, /obj/structure/closet/crate/secure/weapon, -/obj/item/storage/pouch/medical/firstaid/loaded, -/obj/item/storage/pouch/medical/loaded, -/obj/item/clothing/head/helmet/hecu, -/obj/item/clothing/suit/armor/vest/hecu, +/obj/item/storage/medkit/combat_surgeon/stocked, +/obj/item/storage/medkit/civil_defense/stocked, +/obj/item/clothing/glasses/hud/health/night, +/obj/item/storage/belt/military/assault, /obj/item/storage/box/survival/syndie, -/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/clothing/head/helmet/sf_peacekeeper, +/obj/item/clothing/suit/armor/sf_peacekeeper, /obj/item/knife/combat, -/obj/item/gun/ballistic/automatic/pistol/sol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol, -/obj/item/storage/belt/military/assault/hecu, +/obj/item/ammo_box/magazine/c35sol_pistol, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, /obj/item/ammo_box/magazine/c35sol_pistol/stendo, -/obj/item/stack/medical/mesh/bloody, -/obj/item/stack/medical/suture/bloody, -/obj/item/clothing/gloves/military, -/obj/item/clothing/glasses/hud/health/night, +/obj/item/gun/ballistic/automatic/sol_smg, +/obj/item/gun/ballistic/automatic/pistol/sol, /turf/open/floor/iron, /area/virtual_domain/safehouse) diff --git a/_maps/shuttles/cargo_birdshot.dmm b/_maps/shuttles/cargo_birdshot.dmm index 4706a71d082..a0cc7901c18 100644 --- a/_maps/shuttles/cargo_birdshot.dmm +++ b/_maps/shuttles/cargo_birdshot.dmm @@ -69,9 +69,6 @@ }, /turf/open/floor/mineral/titanium, /area/shuttle/supply) -"t" = ( -/turf/closed/wall/mineral/titanium/nosmooth, -/area/shuttle/supply) "w" = ( /obj/effect/turf_decal/stripes/box, /obj/machinery/conveyor{ @@ -247,7 +244,7 @@ T X W Z -t +T M J w @@ -289,7 +286,7 @@ T R m i -t +T P e I diff --git a/_maps/templates/battlecruiser_starfury.dmm b/_maps/templates/battlecruiser_starfury.dmm index 672cc444fbd..cc2abc8c5d9 100644 --- a/_maps/templates/battlecruiser_starfury.dmm +++ b/_maps/templates/battlecruiser_starfury.dmm @@ -5791,9 +5791,6 @@ }, /turf/open/floor/iron/dark, /area/shuttle/sbc_starfury) -"ZF" = ( -/turf/closed/wall/mineral/plastitanium/nosmooth, -/area/shuttle/sbc_starfury) "ZK" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5974,7 +5971,7 @@ cH ow ae ae -ZF +ac aa aa aa @@ -6110,7 +6107,7 @@ cH Zl ae ae -ZF +ac aa aa aa @@ -8014,7 +8011,7 @@ cH vC ae ae -ZF +ac aa aa aa @@ -8150,7 +8147,7 @@ cH xI ae ae -ZF +ac aa aa aa diff --git a/_maps/virtual_domains/ancientmilsim_nova.dmm b/_maps/virtual_domains/ancientmilsim_nova.dmm index 15a7366f67a..d380fd85b4c 100644 --- a/_maps/virtual_domains/ancientmilsim_nova.dmm +++ b/_maps/virtual_domains/ancientmilsim_nova.dmm @@ -195,7 +195,7 @@ /area/virtual_domain/ancient_milsim/snpc_garage) "gL" = ( /obj/structure/table, -/obj/item/grenade/chem_grenade/clf3, +/obj/item/grenade/stingbang, /turf/open/floor/plating, /area/virtual_domain/ancient_milsim/janitor) "gP" = ( @@ -1709,7 +1709,7 @@ /turf/open/floor/iron, /area/virtual_domain/ancient_milsim/snpc_cafe) "Vr" = ( -/obj/item/ammo_box/magazine/lanca, +/obj/item/ammo_box/magazine/wylom, /turf/open/misc/grass/planet/ancient_milsim, /area/virtual_domain/ancient_milsim/loot_camp) "VA" = ( @@ -4625,7 +4625,7 @@ Uz (49,1,1) = {" Uz Vl -Vr +Vl Vl Vl Vl @@ -4682,7 +4682,7 @@ Uz "} (50,1,1) = {" Uz -Vl +Vr wz Vl Vl diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index eeac64d4bca..ee2d52ce8b9 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -95,6 +95,7 @@ #define SECHUD_BARTENDER "hudbartender" #define SECHUD_BITRUNNER "hudbitrunner" #define SECHUD_BOTANIST "hudbotanist" +#define SECHUD_BRIDGE_ASSISTANT "hudbridgeassistant" #define SECHUD_CAPTAIN "hudcaptain" #define SECHUD_CARGO_TECHNICIAN "hudcargotechnician" #define SECHUD_CHAPLAIN "hudchaplain" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index 3c7399d98fa..41c2b4b7459 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -84,6 +84,9 @@ /// (new_name, old_name) #define COMSIG_GLOB_STATION_NAME_CHANGED "!station_name_changed" +/// Global signal sent before we decide what job everyone has +#define COMSIG_GLOB_PRE_JOBS_ASSIGNED "!pre_roles_assigned" + /// global signal when a global nullrod type is picked #define COMSIG_GLOB_NULLROD_PICKED "!nullrod_picked" diff --git a/code/__DEFINES/external_organs.dm b/code/__DEFINES/external_organs.dm index da8c4ddc272..07a329677fe 100644 --- a/code/__DEFINES/external_organs.dm +++ b/code/__DEFINES/external_organs.dm @@ -8,3 +8,7 @@ ///Tail wagging #define WAG_ABLE (1<<0) #define WAG_WAGGING (1<<1) + +/// Tail spine defines +#define SPINE_KEY_LIZARD "lizard" +#define SPINE_KEY_VOX "vox" // NOVA EDIT ADDITION diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 4b625097d23..46d3f1a83e6 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -48,6 +48,7 @@ #define JOB_RESEARCH_DIRECTOR "Research Director" #define JOB_CHIEF_ENGINEER "Chief Engineer" #define JOB_CHIEF_MEDICAL_OFFICER "Chief Medical Officer" +#define JOB_BRIDGE_ASSISTANT "Bridge Assistant" //Silicon #define JOB_AI "AI" #define JOB_CYBORG "Cyborg" @@ -76,10 +77,11 @@ #define JOB_SCIENTIST "Scientist" #define JOB_ROBOTICIST "Roboticist" #define JOB_GENETICIST "Geneticist" -#define JOB_SCIENCE_GUARD "Science Guard" +#define JOB_SCIENCE_GUARD "Science Guard" // NOVA EDIT ADDITION //Supply #define JOB_QUARTERMASTER "Quartermaster" #define JOB_CARGO_TECHNICIAN "Cargo Technician" +#define JOB_CARGO_GORILLA "Cargo Gorilla" #define JOB_SHAFT_MINER "Shaft Miner" #define JOB_BITRUNNER "Bitrunner" #define JOB_CUSTOMS_AGENT "Customs Agent" // NOVA EDIT ADDITION @@ -145,50 +147,52 @@ #define JOB_DISPLAY_ORDER_ASSISTANT 1 #define JOB_DISPLAY_ORDER_CAPTAIN 2 #define JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL 3 -#define JOB_DISPLAY_ORDER_BARTENDER 4 -#define JOB_DISPLAY_ORDER_BOTANIST 5 -#define JOB_DISPLAY_ORDER_COOK 6 -#define JOB_DISPLAY_ORDER_JANITOR 7 -#define JOB_DISPLAY_ORDER_CLOWN 8 -#define JOB_DISPLAY_ORDER_MIME 9 -#define JOB_DISPLAY_ORDER_CURATOR 10 -#define JOB_DISPLAY_ORDER_LAWYER 11 -#define JOB_DISPLAY_ORDER_CHAPLAIN 12 -#define JOB_DISPLAY_ORDER_PSYCHOLOGIST 13 -#define JOB_DISPLAY_ORDER_AI 14 -#define JOB_DISPLAY_ORDER_CYBORG 15 -#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 16 -#define JOB_DISPLAY_ORDER_STATION_ENGINEER 17 -#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 18 -#define JOB_DISPLAY_ORDER_QUARTERMASTER 19 -#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 20 -#define JOB_DISPLAY_ORDER_SHAFT_MINER 21 -#define JOB_DISPLAY_ORDER_BITRUNNER 22 -#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 23 -#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 24 -#define JOB_DISPLAY_ORDER_PARAMEDIC 25 -#define JOB_DISPLAY_ORDER_CHEMIST 26 -#define JOB_DISPLAY_ORDER_VIROLOGIST 27 -#define JOB_DISPLAY_ORDER_CORONER 28 -#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 29 -#define JOB_DISPLAY_ORDER_SCIENTIST 30 -#define JOB_DISPLAY_ORDER_ROBOTICIST 31 -#define JOB_DISPLAY_ORDER_GENETICIST 32 -#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 33 -#define JOB_DISPLAY_ORDER_WARDEN 34 -#define JOB_DISPLAY_ORDER_DETECTIVE 35 -#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 36 -#define JOB_DISPLAY_ORDER_PRISONER 37 -#define JOB_DISPLAY_ORDER_SECURITY_MEDIC 38 //NOVA EDIT ADDITON -#define JOB_DISPLAY_ORDER_CORRECTIONS_OFFICER 39 //NOVA EDIT ADDITON -#define JOB_DISPLAY_ORDER_NANOTRASEN_CONSULTANT 40 //NOVA EDIT ADDITON -#define JOB_DISPLAY_ORDER_BLUESHIELD 41 //NOVA EDIT ADDITON -#define JOB_DISPLAY_ORDER_ORDERLY 42 //NOVA EDIT ADDITION -#define JOB_DISPLAY_ORDER_SCIENCE_GUARD 43 //NOVA EDIT ADDITION -#define JOB_DISPLAY_ORDER_BOUNCER 44 //NOVA EDIT ADDITION -#define JOB_DISPLAY_ORDER_ENGINEER_GUARD 45 //NOVA EDIT ADDITION -#define JOB_DISPLAY_ORDER_CUSTOMS_AGENT 46 //NOVA EDIT ADDITION -#define JOB_DISPLAY_ORDER_EXP_CORPS 47 //NOVA EDIT ADDITON +#define JOB_DISPLAY_ORDER_BRIDGE_ASSISTANT 4 +#define JOB_DISPLAY_ORDER_BARTENDER 5 +#define JOB_DISPLAY_ORDER_BOTANIST 6 +#define JOB_DISPLAY_ORDER_COOK 7 +#define JOB_DISPLAY_ORDER_JANITOR 8 +#define JOB_DISPLAY_ORDER_CLOWN 9 +#define JOB_DISPLAY_ORDER_MIME 10 +#define JOB_DISPLAY_ORDER_CURATOR 11 +#define JOB_DISPLAY_ORDER_LAWYER 12 +#define JOB_DISPLAY_ORDER_CHAPLAIN 13 +#define JOB_DISPLAY_ORDER_PSYCHOLOGIST 14 +#define JOB_DISPLAY_ORDER_AI 15 +#define JOB_DISPLAY_ORDER_CYBORG 16 +#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 17 +#define JOB_DISPLAY_ORDER_STATION_ENGINEER 18 +#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 19 +#define JOB_DISPLAY_ORDER_QUARTERMASTER 20 +#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 21 +#define JOB_DISPLAY_ORDER_SHAFT_MINER 22 +#define JOB_DISPLAY_ORDER_BITRUNNER 23 +#define JOB_DISPLAY_ORDER_CARGO_GORILLA 24 +#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 25 +#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 26 +#define JOB_DISPLAY_ORDER_PARAMEDIC 27 +#define JOB_DISPLAY_ORDER_CHEMIST 28 +#define JOB_DISPLAY_ORDER_VIROLOGIST 29 +#define JOB_DISPLAY_ORDER_CORONER 30 +#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 31 +#define JOB_DISPLAY_ORDER_SCIENTIST 32 +#define JOB_DISPLAY_ORDER_ROBOTICIST 33 +#define JOB_DISPLAY_ORDER_GENETICIST 34 +#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 35 +#define JOB_DISPLAY_ORDER_WARDEN 36 +#define JOB_DISPLAY_ORDER_DETECTIVE 37 +#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 38 +#define JOB_DISPLAY_ORDER_PRISONER 39 +#define JOB_DISPLAY_ORDER_SECURITY_MEDIC 40 //NOVA EDIT ADDITON +#define JOB_DISPLAY_ORDER_CORRECTIONS_OFFICER 41 //NOVA EDIT ADDITON +#define JOB_DISPLAY_ORDER_NANOTRASEN_CONSULTANT 42 //NOVA EDIT ADDITON +#define JOB_DISPLAY_ORDER_BLUESHIELD 43 //NOVA EDIT ADDITON +#define JOB_DISPLAY_ORDER_ORDERLY 44 //NOVA EDIT ADDITION +#define JOB_DISPLAY_ORDER_SCIENCE_GUARD 45 //NOVA EDIT ADDITION +#define JOB_DISPLAY_ORDER_BOUNCER 46 //NOVA EDIT ADDITION +#define JOB_DISPLAY_ORDER_ENGINEER_GUARD 47 //NOVA EDIT ADDITION +#define JOB_DISPLAY_ORDER_CUSTOMS_AGENT 48 //NOVA EDIT ADDITION +#define JOB_DISPLAY_ORDER_EXP_CORPS 49 //NOVA EDIT ADDITON #define DEPARTMENT_UNASSIGNED "No Department" diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 5b82fa07e89..76ea6b5910b 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -87,6 +87,7 @@ #define ROLE_SLAUGHTER_DEMON "Slaughter Demon" #define ROLE_WIZARD_APPRENTICE "apprentice" #define ROLE_SYNDICATE_MONKEY "Syndicate Monkey Agent" +#define ROLE_CONTRACTOR_SUPPORT "Contractor Support Unit" //Spawner roles #define ROLE_ANCIENT_CREW "Ancient Crew" diff --git a/code/__DEFINES/station.dm b/code/__DEFINES/station.dm index ddaa82daffc..5a04961429f 100644 --- a/code/__DEFINES/station.dm +++ b/code/__DEFINES/station.dm @@ -2,12 +2,17 @@ #define STATION_TRAIT_NEUTRAL 2 #define STATION_TRAIT_NEGATIVE 3 -/// For traits that shouldn't be selected, like abstract types (wow) -#define STATION_TRAIT_ABSTRACT (1<<0) +///Defines for the cost of different station traits. This one is the default. +#define STATION_TRAIT_COST_FULL 1 +///Cost for smaller traits that could fly under the radar, and are only minorly negative/positive if not neutral. +#define STATION_TRAIT_COST_LOW 0.5 +///Cost for very little, and mainly neutral traits that hardly amount to anything really that interesting. +#define STATION_TRAIT_COST_MINIMAL 0.3 + /// Only run on planet stations -#define STATION_TRAIT_PLANETARY (1<<1) +#define STATION_TRAIT_PLANETARY (1<<0) /// Only run on space stations -#define STATION_TRAIT_SPACE_BOUND (1<<2) +#define STATION_TRAIT_SPACE_BOUND (1<<1) /// Not restricted by space or planet, can always just happen #define STATION_TRAIT_MAP_UNRESTRICTED STATION_TRAIT_PLANETARY | STATION_TRAIT_SPACE_BOUND diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 8f7fab41367..b79fe449c16 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -4,8 +4,8 @@ // BEGIN TRAIT DEFINES /* - *Remember to update _globalvars/traits.dm if you're adding/removing/renaming traits. - */ +Remember to update _globalvars/traits.dm if you're adding/removing/renaming traits. +*/ //mob traits /// Forces the user to stay unconscious. @@ -829,6 +829,9 @@ /// Similar trait given to temporary bodies inhabited by players #define TRAIT_TEMPORARY_BODY "temporary_body" +/// Trait given to objects with the wallmounted component +#define TRAIT_WALLMOUNTED "wallmounted" + /// Trait given to mechs that can have orebox functionality on movement #define TRAIT_OREBOX_FUNCTIONAL "orebox_functional" diff --git a/code/__DEFINES/~nova_defines/mobs.dm b/code/__DEFINES/~nova_defines/mobs.dm index 2943a1b5e3c..a040ec993d7 100644 --- a/code/__DEFINES/~nova_defines/mobs.dm +++ b/code/__DEFINES/~nova_defines/mobs.dm @@ -32,3 +32,4 @@ #define BODYPART_ICON_SYNTHMAMMAL 'modular_nova/modules/bodyparts/icons/synthmammal_parts_greyscale.dmi' #define BODYPART_ICON_IPC 'modular_nova/modules/bodyparts/icons/ipc_parts.dmi' #define BODYPART_ICON_SYNTHLIZARD 'modular_nova/modules/bodyparts/icons/synthliz_parts_greyscale.dmi' +#define BODYPART_ICON_SNAIL 'modular_nova/modules/bodyparts/icons/snail_parts_greyscale.dmi' diff --git a/code/__HELPERS/announcements.dm b/code/__HELPERS/announcements.dm index 7a27be43a75..d8653a2eb05 100644 --- a/code/__HELPERS/announcements.dm +++ b/code/__HELPERS/announcements.dm @@ -16,8 +16,8 @@ * * play_sound - if TRUE, play a sound with the announcement (based on player option) * * sound_override - optional, override the default announcement sound * * sender_override - optional, modifies the sender of the announcement - * * encode_title - if TRUE, the title will be HTML encoded - * * encode_text - if TRUE, the text will be HTML encoded + * * encode_title - if TRUE, the title will be HTML encoded (escaped) + * * encode_text - if TRUE, the text will be HTML encoded (escaped) */ /proc/send_ooc_announcement( @@ -28,7 +28,7 @@ sound_override = 'sound/misc/bloop.ogg', sender_override = "Server Admin Announcement", encode_title = TRUE, - encode_text = TRUE, + encode_text = FALSE, ) if(isnull(text)) return diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 408852af459..1e447ac1470 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -28,6 +28,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, GLOB.animated_spines_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tail_spines, GLOB.tail_spines_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, GLOB.caps_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings, GLOB.moth_wings_list) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 1fceed44004..a26ff1752f2 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -26,6 +26,7 @@ GLOBAL_LIST_EMPTY(snouts_list) GLOBAL_LIST_EMPTY(horns_list) GLOBAL_LIST_EMPTY(frills_list) GLOBAL_LIST_EMPTY(spines_list) +GLOBAL_LIST_EMPTY(tail_spines_list) GLOBAL_LIST_EMPTY(legs_list) GLOBAL_LIST_EMPTY(animated_spines_list) diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index 8ac2f0d3ddf..b77942bad87 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -107,6 +107,7 @@ GLOBAL_LIST_EMPTY(generic_event_spawns) /// essentially allowing a user to override generic job spawnpoints with a specific one GLOBAL_LIST_EMPTY(jobspawn_overrides) +GLOBAL_LIST_EMPTY(gorilla_start) GLOBAL_LIST_EMPTY(wizardstart) GLOBAL_LIST_EMPTY(nukeop_start) GLOBAL_LIST_EMPTY(nukeop_leader_start) diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index bc195bcf5f4..c51fbaa9eb7 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -25,6 +25,7 @@ GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1. GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt")) GLOBAL_LIST_INIT(cyberauth_names, world.file2list("strings/names/cyberauth.txt")) GLOBAL_LIST_INIT(syndicate_monkey_names, world.file2list("strings/names/syndicate_monkey.txt")) +GLOBAL_LIST_INIT(cargorilla_names, world.file2list("strings/names/cargorilla.txt")) GLOBAL_LIST_INIT(guardian_first_names, world.file2list("strings/names/guardian_descriptions.txt")) GLOBAL_LIST_INIT(guardian_tech_surnames, world.file2list("strings/names/guardian_gamepieces.txt")) GLOBAL_LIST_INIT(guardian_fantasy_surnames, world.file2list("strings/names/guardian_tarot.txt")) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 41169dfc600..6435db5ff3a 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -99,6 +99,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( /datum/wound = list( "TRAIT_WOUND_SCANNED" = TRAIT_WOUND_SCANNED, ), + /obj = list( + "TRAIT_WALLMOUNTED" = TRAIT_WALLMOUNTED, + ), /mob = list( "TRAIT_ABDUCTOR_SCIENTIST_TRAINING" = TRAIT_ABDUCTOR_SCIENTIST_TRAINING, "TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING, diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index aceb360c953..f18f44c2ecb 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -270,6 +270,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( combo_display = null //NOVA EDIT START - SKYRAT HUD + ammo_counter = null wanted_lvl = null // NOVA EDIT END - SKYRAT HUD diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 86735de1127..9cdf936fde0 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -1,38 +1,65 @@ -/* NOVA EDIT REMOVAL - Custom HTML Lobby Screen #define SHUTTER_MOVEMENT_DURATION 0.4 SECONDS #define SHUTTER_WAIT_DURATION 0.2 SECONDS +/// Maximum number of station trait buttons we will display, please think hard before creating scenarios where there are more than this +#define MAX_STATION_TRAIT_BUTTONS_VERTICAL 3 /datum/hud/new_player ///Whether the menu is currently on the client's screen or not var/menu_hud_status = TRUE /datum/hud/new_player/New(mob/owner) - ..() + . = ..() - if(!owner || !owner.client) + if (!owner || !owner.client) return - if(owner.client.interviewee) + if (owner.client.interviewee) return var/list/buttons = subtypesof(/atom/movable/screen/lobby) - for(var/button_type in buttons) - var/atom/movable/screen/lobby/lobbyscreen = new button_type(our_hud = src) + for (var/atom/movable/screen/lobby/lobbyscreen as anything in buttons) + if (!initial(lobbyscreen.always_available)) + continue + lobbyscreen = new lobbyscreen(our_hud = src) lobbyscreen.SlowInit() static_inventory += lobbyscreen - if(!lobbyscreen.always_shown) + if (!lobbyscreen.always_shown) lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_COLLAPSED, TYPE_PROC_REF(/atom/movable/screen/lobby, collapse_button)) lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_EXPANDED, TYPE_PROC_REF(/atom/movable/screen/lobby, expand_button)) - if(istype(lobbyscreen, /atom/movable/screen/lobby/button)) + if (istype(lobbyscreen, /atom/movable/screen/lobby/button)) var/atom/movable/screen/lobby/button/lobby_button = lobbyscreen lobby_button.owner = REF(owner) + add_station_trait_buttons() + +/// Display buttons for relevant station traits +/datum/hud/new_player/proc/add_station_trait_buttons() + if (!mymob?.client || mymob.client.interviewee || !length(GLOB.lobby_station_traits)) + return + var/buttons_created = 0 + var/y_offset = 397 + var/y_button_offset = 27 + for (var/datum/station_trait/trait as anything in GLOB.lobby_station_traits) + if (!trait.can_display_lobby_button(mymob.client)) + continue + var/atom/movable/screen/lobby/button/sign_up/sign_up_button = new(our_hud = src) + sign_up_button.SlowInit() + sign_up_button.owner = REF(mymob) + sign_up_button.screen_loc = offset_to_screen_loc(233, y_offset, mymob.client.view) + y_offset += y_button_offset + static_inventory += sign_up_button + trait.setup_lobby_button(sign_up_button) + buttons_created++ + if (buttons_created >= MAX_STATION_TRAIT_BUTTONS_VERTICAL) + return /atom/movable/screen/lobby plane = SPLASHSCREEN_PLANE layer = LOBBY_MENU_LAYER screen_loc = "TOP,CENTER" - ///Whether this HUD element can be hidden from the client's "screen" (moved off-screen) or not + /// Whether this HUD element can be hidden from the client's "screen" (moved off-screen) or not var/always_shown = FALSE + /// If true we will create this button every time the HUD is generated + var/always_available = TRUE ///Set the HUD in New, as lobby screens are made before Atoms are Initialized. /atom/movable/screen/lobby/New(loc, datum/hud/our_hud, ...) @@ -84,7 +111,7 @@ return flick("[base_icon_state]_pressed", src) update_appearance(UPDATE_ICON) - SEND_SOUND(hud.mymob, sound('modular_nova/master_files/sound/effects/save.ogg')) //NOVA EDIT ADDITION + SEND_SOUND(hud.mymob, sound('modular_nova/master_files/sound/effects/save.ogg')) // NOVA EDIT ADDITION return TRUE /atom/movable/screen/lobby/button/MouseEntered(location,control,params) @@ -184,12 +211,6 @@ return var/mob/dead/new_player/new_player = hud.mymob - // NOVA EDIT BEGIN - if(!is_admin(new_player.client) && length_char(new_player.client?.prefs?.read_preference(/datum/preference/text/flavor_text)) < FLAVOR_TEXT_CHAR_REQUIREMENT) - to_chat(new_player, span_notice("You need at least [FLAVOR_TEXT_CHAR_REQUIREMENT] characters of flavor text to ready up for the round. You have [length_char(new_player.client.prefs.read_preference(/datum/preference/text/flavor_text))] characters.")) - return - // NOVA EDIT END - ready = !ready if(ready) new_player.ready = PLAYER_READY_TO_PLAY @@ -253,18 +274,13 @@ to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len].")) return - // NOVA EDIT BEGIN - if(length_char(new_player.client.prefs.read_preference(/datum/preference/text/flavor_text)) <= FLAVOR_TEXT_CHAR_REQUIREMENT) - to_chat(new_player, span_notice("You need at least [FLAVOR_TEXT_CHAR_REQUIREMENT] characters of flavor text to join the round. You have [length_char(new_player.client.prefs.read_preference(/datum/preference/text/flavor_text))] characters.")) - return - // NOVA EDIT END - if(!LAZYACCESS(params2list(params), CTRL_CLICK)) GLOB.latejoin_menu.ui_interact(new_player) else to_chat(new_player, span_warning("Opening emergency fallback late join menu! If THIS doesn't show, ahelp immediately!")) GLOB.latejoin_menu.fallback_ui(new_player) + /atom/movable/screen/lobby/button/join/proc/show_join_button() SIGNAL_HANDLER set_button_status(TRUE) @@ -413,6 +429,23 @@ var/mob/dead/new_player/new_player = hud.mymob new_player.handle_player_polling() +/// A generic "sign up" button used by station traits +/atom/movable/screen/lobby/button/sign_up + icon = 'icons/hud/lobby/signup_button.dmi' + icon_state = "signup" + base_icon_state = "signup" + always_available = FALSE + +/atom/movable/screen/lobby/button/sign_up/MouseEntered(location, control, params) + . = ..() + if(QDELETED(src) || !desc) + return + openToolTip(usr, tip_src = src, params = params, title = name, content = desc,) + +/atom/movable/screen/lobby/button/sign_up/MouseExited() + . = ..() + closeToolTip(usr) + /atom/movable/screen/lobby/button/collapse name = "Collapse Lobby Menu" icon = 'icons/hud/lobby/collapse_expand.dmi' @@ -540,5 +573,4 @@ #undef SHUTTER_MOVEMENT_DURATION #undef SHUTTER_WAIT_DURATION - -*/ // NOVA EDIT END +#undef MAX_STATION_TRAIT_BUTTONS_VERTICAL diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 372a32b3c68..ce5c97a63c7 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -55,6 +55,10 @@ /atom/movable/screen/proc/component_click(atom/movable/screen/component_button/component, params) return +/// Returns the mob this is being displayed to, if any +/atom/movable/screen/proc/get_mob() + return hud?.mymob + /atom/movable/screen/text icon = null icon_state = null diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index fd6a5ecf9a5..9c84fcc2c1e 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -935,6 +935,9 @@ SUBSYSTEM_DEF(dynamic) stack_trace("Invalid dynamic configuration variable [variable] in [ruleset.ruletype] [ruleset.name].") continue ruleset.vars[variable] = rule_conf[variable] + ruleset.restricted_roles |= SSstation.antag_restricted_roles + if(length(ruleset.protected_roles)) //if we care to protect any role, we should protect station trait roles too + ruleset.protected_roles |= SSstation.antag_protected_roles if(CONFIG_GET(flag/protect_roles_from_antagonist)) ruleset.restricted_roles |= ruleset.protected_roles if(CONFIG_GET(flag/protect_assistant_from_antagonist)) diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 4a8345728e5..d2a374f39cd 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -94,6 +94,18 @@ SUBSYSTEM_DEF(job) set_overflow_role(CONFIG_GET(string/overflow_job)) // this must always go after load_jobs_from_config() due to how the legacy systems operate, this always takes precedent. return SS_INIT_SUCCESS +/// Returns a list of jobs that we are allowed to fuck with during random events +/datum/controller/subsystem/job/proc/get_valid_overflow_jobs() + var/static/list/overflow_jobs + if (!isnull(overflow_jobs)) + return overflow_jobs + + overflow_jobs = list() + for (var/datum/job/check_job in joinable_occupations) + if (!check_job.allow_bureaucratic_error) + continue + overflow_jobs += check_job + return overflow_jobs /datum/controller/subsystem/job/proc/set_overflow_role(new_overflow_role) var/datum/job/new_overflow = ispath(new_overflow_role) ? GetJobType(new_overflow_role) : GetJob(new_overflow_role) diff --git a/code/controllers/subsystem/processing/station.dm b/code/controllers/subsystem/processing/station.dm index b30a276fc36..00c9d14a845 100644 --- a/code/controllers/subsystem/processing/station.dm +++ b/code/controllers/subsystem/processing/station.dm @@ -11,6 +11,10 @@ PROCESSING_SUBSYSTEM_DEF(station) var/list/selectable_traits_by_types = list(STATION_TRAIT_POSITIVE = list(), STATION_TRAIT_NEUTRAL = list(), STATION_TRAIT_NEGATIVE = list()) ///Currently active announcer. Starts as a type but gets initialized after traits are selected var/datum/centcom_announcer/announcer = /datum/centcom_announcer/default + ///A list of trait roles that should be protected from antag + var/list/antag_protected_roles = list() + ///A list of trait roles that should never be able to roll antag + var/list/antag_restricted_roles = list() /datum/controller/subsystem/processing/station/Initialize() @@ -18,6 +22,7 @@ PROCESSING_SUBSYSTEM_DEF(station) // Autowiki also wants consistent outputs, for example making sure the vending machine page always reports the normal products #if !defined(UNIT_TESTS) && !defined(AUTOWIKI) SetupTraits() + display_lobby_traits() #endif announcer = new announcer() //Initialize the station's announcer datum @@ -57,7 +62,7 @@ PROCESSING_SUBSYSTEM_DEF(station) setup_trait(trait_typepath) continue - if(initial(trait_typepath.trait_flags) & STATION_TRAIT_ABSTRACT) + if(initial(trait_typepath.abstract_type) == trait_typepath) continue //Dont add abstract ones to it if(!(initial(trait_typepath.trait_flags) & STATION_TRAIT_PLANETARY) && SSmapping.is_planetary()) // we're on a planet but we can't do planet ;_; @@ -96,3 +101,12 @@ PROCESSING_SUBSYSTEM_DEF(station) for(var/i in trait_instance.blacklist) var/datum/station_trait/trait_to_remove = i selectable_traits_by_types[initial(trait_to_remove.trait_type)] -= trait_to_remove + +/// Update station trait lobby buttons for clients who joined before we initialised this subsystem +/datum/controller/subsystem/processing/station/proc/display_lobby_traits() + for (var/mob/dead/new_player/player as anything in GLOB.new_player_list) + var/datum/hud/new_player/observer_hud = player.hud_used + if (!istype(observer_hud)) + continue + observer_hud.add_station_trait_buttons() + observer_hud.show_hud(observer_hud.hud_version) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 75b51b2babc..add23ac91b2 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -249,6 +249,7 @@ SUBSYSTEM_DEF(ticker) var/can_continue = FALSE can_continue = SSdynamic.pre_setup() //Choose antagonists CHECK_TICK + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PRE_JOBS_ASSIGNED, src) can_continue = can_continue && SSjob.DivideOccupations() //Distribute jobs CHECK_TICK diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index d235b4d50ab..c1ff66dcfa9 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -48,10 +48,10 @@ charging += charger actively_moving = FALSE SEND_SIGNAL(owner, COMSIG_STARTED_CHARGE) - RegisterSignal(charger, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump), TRUE) - RegisterSignal(charger, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move), TRUE) - RegisterSignal(charger, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved), TRUE) - RegisterSignal(charger, COMSIG_LIVING_DEATH, PROC_REF(charge_end)) + RegisterSignal(charger, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump), override = TRUE) + RegisterSignal(charger, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move), override = TRUE) + RegisterSignal(charger, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved), override = TRUE) + RegisterSignal(charger, COMSIG_LIVING_DEATH, PROC_REF(charge_end), override = TRUE) charger.setDir(dir) do_charge_indicator(charger, target) @@ -62,9 +62,9 @@ var/datum/move_loop/new_loop = SSmove_manager.home_onto(charger, target, delay = charge_speed, timeout = time_to_hit, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) if(!new_loop) return - RegisterSignal(new_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) - RegisterSignal(new_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) - RegisterSignal(new_loop, COMSIG_QDELETING, PROC_REF(charge_end)) + RegisterSignal(new_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move), override = TRUE) + RegisterSignal(new_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move), override = TRUE) + RegisterSignal(new_loop, COMSIG_QDELETING, PROC_REF(charge_end), override = TRUE) // Yes this is disgusting. But we need to queue this stuff, and this code just isn't setup to support that right now. So gotta do it with sleeps sleep(time_to_hit + charge_speed) diff --git a/code/datums/components/ghost_direct_control.dm b/code/datums/components/ghost_direct_control.dm index 83c893b6dca..a131a2d3ca7 100644 --- a/code/datums/components/ghost_direct_control.dm +++ b/code/datums/components/ghost_direct_control.dm @@ -30,7 +30,7 @@ src.ban_type = ban_type src.assumed_control_message = assumed_control_message || "You are [parent]!" src.extra_control_checks = extra_control_checks - src.after_assumed_control= after_assumed_control + src.after_assumed_control = after_assumed_control var/mob/mob_parent = parent LAZYADD(GLOB.joinable_mobs[format_text("[initial(mob_parent.name)]")], mob_parent) @@ -42,9 +42,10 @@ . = ..() RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, PROC_REF(on_ghost_clicked)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) + RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(on_login)) /datum/component/ghost_direct_control/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_EXAMINE)) + UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_EXAMINE, COMSIG_MOB_LOGIN)) return ..() /datum/component/ghost_direct_control/Destroy(force) @@ -140,3 +141,8 @@ to_chat(new_body, span_boldnotice(assumed_control_message)) after_assumed_control?.Invoke(harbinger) qdel(src) + +/// When someone else assumes control via some other means, get rid of our component +/datum/component/ghost_direct_control/proc/on_login() + SIGNAL_HANDLER + qdel(src) diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm index f2b4ce9e923..fc7e42c6c43 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -459,15 +459,15 @@ if(MATERIAL_INSERT_ITEM_SUCCESS) //no problems full item was consumed if(chat_data["stack"]) var/sheets = min(count, amount) //minimum between sheets inserted vs sheets consumed(values differ for alloys) - to_chat(user, span_notice("[sheets > 1 ? sheets : ""] [item_name][sheets > 1 ? "'s" : ""] was consumed by [parent]")) + to_chat(user, span_notice("[sheets > 1 ? sheets : ""] [item_name][sheets > 1 ? "s were" : " was"] added to [parent].")) else - to_chat(user, span_notice("[count > 1 ? count : ""] [item_name][count > 1 ? "'s" : ""] worth [amount] sheets of material was consumed by [parent]")) + to_chat(user, span_notice("[count > 1 ? count : ""] [item_name][count > 1 ? "s" : ""], worth [amount] sheets, [count > 1 ? "were" : "was"] added to [parent].")) if(MATERIAL_INSERT_ITEM_NO_SPACE) //no space - to_chat(user, span_warning("[parent] has no space to accept [item_name]")) + to_chat(user, span_warning("[parent] has no space to accept [item_name]!")) if(MATERIAL_INSERT_ITEM_NO_MATS) //no materials inside these items - to_chat(user, span_warning("[count > 1 ? count : ""] [item_name][count > 1 ? "'s" : ""] has no materials to be accepted by [parent]")) + to_chat(user, span_warning("[item_name][count > 1 ? "s have" : " has"] no materials that can be accepted by [parent]!")) if(MATERIAL_INSERT_ITEM_FAILURE) //could be because the material type was not accepted or other stuff - to_chat(user, span_warning("[count > 1 ? count : ""] [item_name][count > 1 ? "'s" : ""] was rejected by [parent]")) + to_chat(user, span_warning("[item_name][count > 1 ? "s were" : " was"] rejected by [parent]!")) /// Proc that allows players to fill the parent with mats /datum/component/material_container/proc/on_attackby(datum/source, obj/item/weapon, mob/living/user) diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index 6d033469cc2..464f1a58a07 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -173,17 +173,25 @@ /datum/component/two_handed/proc/wield(mob/living/carbon/user) if(wielded) return + var/atom/atom_parent = parent + if(HAS_TRAIT(user, TRAIT_NO_TWOHANDING)) + if(require_twohands) + atom_parent.balloon_alert(user, "too weak to wield!") + user.dropItemToGround(parent, force = TRUE) + else + atom_parent.balloon_alert(user, "too weak to wield with both hands!") + return if(user.get_inactive_held_item()) if(require_twohands) - to_chat(user, span_notice("[parent] is too cumbersome to carry in one hand!")) - user.dropItemToGround(parent, force=TRUE) + atom_parent.balloon_alert(user, "can't carry in one hand!") + user.dropItemToGround(parent, force = TRUE) else - to_chat(user, span_warning("You need your other hand to be empty!")) + atom_parent.balloon_alert(user, "holding something in other hand!") return if(user.usable_hands < 2) if(require_twohands) user.dropItemToGround(parent, force=TRUE) - to_chat(user, span_warning("You don't have enough intact hands.")) + atom_parent.balloon_alert(user, "not enough hands!") return // wield update status diff --git a/code/datums/components/wall_mounted.dm b/code/datums/components/wall_mounted.dm index 62af35dc974..a10fb246833 100644 --- a/code/datums/components/wall_mounted.dm +++ b/code/datums/components/wall_mounted.dm @@ -16,12 +16,14 @@ on_drop = on_drop_callback /datum/component/wall_mounted/RegisterWithParent() + ADD_TRAIT(parent, TRAIT_WALLMOUNTED, REF(src)) RegisterSignal(hanging_wall_turf, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(hanging_wall_turf, COMSIG_TURF_CHANGE, PROC_REF(on_turf_changing)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_linked_destroyed)) /datum/component/wall_mounted/UnregisterFromParent() + REMOVE_TRAIT(parent, TRAIT_WALLMOUNTED, REF(src)) UnregisterSignal(hanging_wall_turf, list(COMSIG_ATOM_EXAMINE, COMSIG_TURF_CHANGE)) UnregisterSignal(parent, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED)) hanging_wall_turf = null diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 6ea1a8121f0..0938ab66d1f 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -66,7 +66,8 @@ if(!forced) if(!check_teleport_valid(teleatom, destination, channel)) - teleatom.balloon_alert(teleatom, "something holds you back!") + if(ismob(teleatom)) + teleatom.balloon_alert(teleatom, "something holds you back!") return FALSE if(isobserver(teleatom)) diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index 72a23adf768..ea46cc91319 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -203,6 +203,28 @@ ) job = /datum/job/botanist +/datum/id_trim/job/bridge_assistant + assignment = "Bridge Assistant" + trim_state = "trim_assistant" + department_color = COLOR_COMMAND_BLUE + subdepartment_color = COLOR_COMMAND_BLUE + sechud_icon_state = SECHUD_BRIDGE_ASSISTANT + minimal_access = list( + ACCESS_COMMAND, + ACCESS_EVA, + ACCESS_GATEWAY, + ACCESS_MAINT_TUNNELS, + ACCESS_RC_ANNOUNCE, + ACCESS_TELEPORTER, + ACCESS_WEAPONS, + ) + extra_access = list() + template_access = list( + ACCESS_CAPTAIN, + ACCESS_CHANGE_IDS, + ) + job = /datum/job/bridge_assistant + /datum/id_trim/job/captain assignment = "Captain" intern_alt_name = "Captain-in-Training" diff --git a/code/datums/quirks/positive_quirks/spacer.dm b/code/datums/quirks/positive_quirks/spacer.dm index 83157352901..641c010407a 100644 --- a/code/datums/quirks/positive_quirks/spacer.dm +++ b/code/datums/quirks/positive_quirks/spacer.dm @@ -13,7 +13,7 @@ quirk_flags = QUIRK_CHANGES_APPEARANCE //NOVA EDIT CHANGE - ORIGINAL: quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_CHANGES_APPEARANCE medical_record_text = "Patient is well-adapted to non-terrestrial environments." mail_goodies = list( - /obj/item/storage/pill_bottle/ondansetron, + /obj/item/reagent_containers/hypospray/medipen/deforest/psifinil, // NOVA EDIT CHANGE - ORIGINAL: /obj/item/storage/pill_bottle/ondansetron, /obj/item/reagent_containers/pill/gravitum, ) /// How high spacers get bumped up to @@ -63,10 +63,10 @@ you are awarded with a 25% hazard pay bonus due to your [on_a_planet ? "station" : "occupational"] assignment.")) // Supply them with some patches to help out on their new assignment - var/obj/item/storage/pill_bottle/ondansetron/disgust_killers = new() - disgust_killers.desc += " Best to take one when travelling to a planet's surface." + var/obj/item/storage/medkit/civil_defense/comfort/stocked/disgust_killers = new() // NOVA EDIT CHANGE - a custom deforest cheesekit filled with much better meds - ORIGINAL: var/obj/item/storage/pill_bottle/ondansetron/disgust_killers = new() + //disgust_killers.desc += " Best to take one when travelling to a planet's surface." NOVA EDIT REMOVAL - remove extra blurb, unneeded if(quirk_holder.equip_to_slot_if_possible(disgust_killers, ITEM_SLOT_BACKPACK, qdel_on_fail = TRUE, initial = TRUE, indirect_action = TRUE)) - to_chat(quirk_holder, span_info("You have[isnull(spacer_account) ? " " : " also "]been given some anti-emetic patches to assist in adjusting to planetary gravity.")) + to_chat(quirk_holder, span_info("You have[isnull(spacer_account) ? " " : " also "]been given a kit of symptom-alleviating autoinjectors to aid in adjusting to planetary gravity.")) // NOVA EDIT CHANGE - rewords to make sense - ORIGINAL: to_chat(quirk_holder, span_info("You have[isnull(spacer_account) ? " " : " also "]been given some anti-emetic patches to assist in adjusting to planetary gravity.")) /datum/quirk/spacer_born/remove() UnregisterSignal(quirk_holder, COMSIG_MOVABLE_Z_CHANGED) diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index febd6374f7f..1ba59b72d86 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -174,3 +174,36 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) target.rank = assignment target.trim = trim + +/datum/manifest/ui_state(mob/user) + return GLOB.always_state + +/datum/manifest/ui_status(mob/user, datum/ui_state/state) + return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user) || user.client?.holder) ? UI_INTERACTIVE : UI_CLOSE + +/datum/manifest/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "CrewManifest") + ui.open() + +/datum/manifest/ui_data(mob/user) + var/list/positions = list() + for(var/datum/job_department/department as anything in SSjob.joinable_departments) + var/open = 0 + var/list/exceptions = list() + for(var/datum/job/job as anything in department.department_jobs) + if(job.total_positions == -1) + exceptions += job.title + continue + var/open_slots = job.total_positions - job.current_positions + if(open_slots < 1) + continue + open += open_slots + positions[department.department_name] = list("exceptions" = exceptions, "open" = open) + + return list( + "manifest" = get_manifest(), + "positions" = positions + ) + diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 02e12504576..4ce7cb55177 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -1756,9 +1756,12 @@ /datum/sprite_accessory/tails em_block = TRUE + /// Describes which tail spine sprites to use, if any. + var/spine_key = NONE /datum/sprite_accessory/tails/lizard icon = 'icons/mob/human/species/lizard/lizard_tails.dmi' + spine_key = SPINE_KEY_LIZARD /datum/sprite_accessory/tails/lizard/smooth name = "Smooth" @@ -1779,6 +1782,7 @@ /datum/sprite_accessory/tails/lizard/short name = "Short" icon_state = "short" + spine_key = NONE /datum/sprite_accessory/tails/human/cat name = "Cat" @@ -2091,6 +2095,10 @@ icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE +/datum/sprite_accessory/tail_spines + icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' + em_block = TRUE + /datum/sprite_accessory/spines/none name = "None" icon_state = "none" @@ -2099,6 +2107,10 @@ name = "None" icon_state = "none" +/datum/sprite_accessory/tail_spines/none + name = "None" + icon_state = "none" + /datum/sprite_accessory/spines/short name = "Short" icon_state = "short" @@ -2107,6 +2119,10 @@ name = "Short" icon_state = "short" +/datum/sprite_accessory/tail_spines/short + name = "Short" + icon_state = "short" + /datum/sprite_accessory/spines/shortmeme name = "Short + Membrane" icon_state = "shortmeme" @@ -2115,6 +2131,10 @@ name = "Short + Membrane" icon_state = "shortmeme" +/datum/sprite_accessory/tail_spines/shortmeme + name = "Short + Membrane" + icon_state = "shortmeme" + /datum/sprite_accessory/spines/long name = "Long" icon_state = "long" @@ -2123,6 +2143,10 @@ name = "Long" icon_state = "long" +/datum/sprite_accessory/tail_spines/long + name = "Long" + icon_state = "long" + /datum/sprite_accessory/spines/longmeme name = "Long + Membrane" icon_state = "longmeme" @@ -2131,6 +2155,10 @@ name = "Long + Membrane" icon_state = "longmeme" +/datum/sprite_accessory/tail_spines/longmeme + name = "Long + Membrane" + icon_state = "longmeme" + /datum/sprite_accessory/spines/aquatic name = "Aquatic" icon_state = "aqua" @@ -2139,6 +2167,10 @@ name = "Aquatic" icon_state = "aqua" +/datum/sprite_accessory/tail_spines/aquatic + name = "Aquatic" + icon_state = "aqua" + /datum/sprite_accessory/legs //legs are a special case, they aren't actually sprite_accessories but are updated with them. icon = null //These datums exist for selecting legs on preference, and little else em_block = TRUE diff --git a/code/datums/station_traits/_station_trait.dm b/code/datums/station_traits/_station_trait.dm index 8e8303c0366..7130f1c896b 100644 --- a/code/datums/station_traits/_station_trait.dm +++ b/code/datums/station_traits/_station_trait.dm @@ -1,3 +1,6 @@ +/// Station traits displayed in the lobby +GLOBAL_LIST_EMPTY(lobby_station_traits) + ///Base class of station traits. These are used to influence rounds in one way or the other by influencing the levers of the station. /datum/station_trait ///Name of the trait @@ -8,6 +11,8 @@ var/trait_processes = FALSE ///Chance relative to other traits of its type to be picked var/weight = 10 + ///The cost of the trait, which is removed from the budget. + var/cost = STATION_TRAIT_COST_FULL ///Whether this trait is always enabled; generally used for debugging var/force = FALSE ///Does this trait show in the centcom report? @@ -22,10 +27,16 @@ var/trait_flags = STATION_TRAIT_MAP_UNRESTRICTED /// Whether or not this trait can be reverted by an admin var/can_revert = TRUE + /// If set to true we'll show a button on the lobby to notify people about this trait + var/sign_up_button = FALSE + /// Lobby buttons controlled by this trait + var/list/lobby_buttons = list() /// The ID that we look for in dynamic.json. Not synced with 'name' because I can already see this go wrong var/dynamic_threat_id /// If ran during dynamic, do we reduce the total threat? Will be overriden by config if set var/threat_reduction = 0 + /// Trait should not be instantiated in a round if its type matches this type + var/abstract_type = /datum/station_trait /datum/station_trait/New() . = ..() @@ -34,7 +45,8 @@ if(threat_reduction) GLOB.dynamic_station_traits[src] = threat_reduction - + if(sign_up_button) + GLOB.lobby_station_traits += src if(trait_processes) START_PROCESSING(SSstation, src) if(trait_to_give) @@ -43,14 +55,10 @@ /datum/station_trait/Destroy() SSstation.station_traits -= src GLOB.dynamic_station_traits.Remove(src) + destroy_lobby_buttons() return ..() -/// Proc ran when round starts. Use this for roundstart effects. -/datum/station_trait/proc/on_round_start() - SIGNAL_HANDLER - return - -///type of info the centcom report has on this trait, if any. +/// Returns the type of info the centcom report has on this trait, if any. /datum/station_trait/proc/get_report() return "[name] - [report_message]" @@ -64,7 +72,7 @@ qdel(src) -///Called by decals if they can be colored, to see if we got some cool colors for them. Only takes the first station trait +/// Called by decals if they can be colored, to see if we got some cool colors for them. Only takes the first station trait /proc/request_station_colors(atom/thing_to_color, pattern) for(var/datum/station_trait/trait in SSstation.station_traits) var/decal_color = trait.get_decal_color(thing_to_color, pattern || PATTERN_DEFAULT) @@ -72,6 +80,50 @@ return decal_color return null -///Return a color for the decals, if any +/// Return a color for the decals, if any /datum/station_trait/proc/get_decal_color(thing_to_color, pattern) return + +/// Return TRUE if we want to show a lobby button, by default we assume we don't want it after the round begins +/datum/station_trait/proc/can_display_lobby_button(client/player) + return sign_up_button && !SSticker.HasRoundStarted() + +/// Apply any additional handling we need to our lobby button +/datum/station_trait/proc/setup_lobby_button(atom/movable/screen/lobby/button/sign_up/lobby_button) + SHOULD_CALL_PARENT(TRUE) + lobby_buttons |= lobby_button + RegisterSignal(lobby_button, COMSIG_ATOM_UPDATE_ICON, PROC_REF(on_lobby_button_update_icon)) + RegisterSignal(lobby_button, COMSIG_CLICK, PROC_REF(on_lobby_button_click)) + RegisterSignal(lobby_button, COMSIG_QDELETING, PROC_REF(on_lobby_button_destroyed)) + lobby_button.update_appearance(UPDATE_ICON) + +/// Called when our lobby button is clicked on +/datum/station_trait/proc/on_lobby_button_click(atom/movable/screen/lobby/button/sign_up/lobby_button, location, control, params, mob/dead/new_player/user) + SIGNAL_HANDLER + return + +/// Called when our lobby button tries to update its appearance +/datum/station_trait/proc/on_lobby_button_update_icon(atom/movable/screen/lobby/button/sign_up/lobby_button, updates) + SIGNAL_HANDLER + return + +/// Don't hold references to deleted buttons +/datum/station_trait/proc/on_lobby_button_destroyed(atom/movable/screen/lobby/button/sign_up/lobby_button) + SIGNAL_HANDLER + lobby_buttons -= lobby_button + +/// Proc ran when round starts. Use this for roundstart effects. By default we clean up our buttons here. +/datum/station_trait/proc/on_round_start() + SIGNAL_HANDLER + destroy_lobby_buttons() + +/// Remove all of our active lobby buttons +/datum/station_trait/proc/destroy_lobby_buttons() + for (var/atom/movable/screen/button as anything in lobby_buttons) + var/mob/hud_owner = button.get_mob() + qdel(button) + if (QDELETED(hud_owner)) + continue + var/datum/hud/using_hud = hud_owner.hud_used + using_hud?.show_hud(using_hud?.hud_version) + lobby_buttons = list() diff --git a/code/datums/station_traits/job_traits.dm b/code/datums/station_traits/job_traits.dm new file mode 100644 index 00000000000..8dea2f96bbf --- /dev/null +++ b/code/datums/station_traits/job_traits.dm @@ -0,0 +1,169 @@ +#define CAN_ROLL_ALWAYS 1 //always can roll for antag +#define CAN_ROLL_PROTECTED 2 //can roll if config lets protected roles roll +#define CAN_ROLL_NEVER 3 //never roll antag + +/** + * A station trait which enables a temporary job + * Generally speaking these should always all be mutually exclusive, don't have too many at once + */ +/datum/station_trait/job + sign_up_button = TRUE + abstract_type = /datum/station_trait/job + /// What tooltip to show on the button + var/button_desc = "Sign up to gain some kind of unusual job, not available in most rounds." + /// Can this job roll antag? + var/can_roll_antag = CAN_ROLL_ALWAYS + /// How many positions to spawn? + var/position_amount = 1 + /// Type of job to enable + var/datum/job/job_to_add = /datum/job/clown + /// Who signed up to this in the lobby + var/list/lobby_candidates + +/datum/station_trait/job/New() + . = ..() + switch(can_roll_antag) + if(CAN_ROLL_PROTECTED) + SSstation.antag_protected_roles += job_to_add::title + if(CAN_ROLL_NEVER) + SSstation.antag_restricted_roles += job_to_add::title + blacklist += subtypesof(/datum/station_trait/job) - type // All but ourselves + RegisterSignal(SSdcs, COMSIG_GLOB_PRE_JOBS_ASSIGNED, PROC_REF(pre_jobs_assigned)) + +/datum/station_trait/job/setup_lobby_button(atom/movable/screen/lobby/button/sign_up/lobby_button) + RegisterSignal(lobby_button, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_lobby_button_update_overlays)) + lobby_button.desc = button_desc + return ..() + +/datum/station_trait/job/on_lobby_button_click(atom/movable/screen/lobby/button/sign_up/lobby_button, location, control, params, mob/dead/new_player/user) + if (LAZYFIND(lobby_candidates, user)) + LAZYREMOVE(lobby_candidates, user) + else + LAZYADD(lobby_candidates, user) + +/datum/station_trait/job/on_lobby_button_update_icon(atom/movable/screen/lobby/button/sign_up/lobby_button, updates) + if (LAZYFIND(lobby_candidates, lobby_button.get_mob())) + lobby_button.base_icon_state = "signup_on" + else + lobby_button.base_icon_state = "signup" + +/// Add an overlay based on whether you are actively signed up for this role +/datum/station_trait/job/proc/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays) + SIGNAL_HANDLER + overlays += LAZYFIND(lobby_candidates, lobby_button.get_mob()) ? "tick" : "cross" + +/// Called before we start assigning roles, assign ours first +/datum/station_trait/job/proc/pre_jobs_assigned() + SIGNAL_HANDLER + sign_up_button = FALSE + destroy_lobby_buttons() + for (var/mob/dead/new_player/signee as anything in lobby_candidates) + if (isnull(signee) || !signee.client || !signee.mind || signee.ready != PLAYER_READY_TO_PLAY) + LAZYREMOVE(lobby_candidates, signee) + if (!LAZYLEN(lobby_candidates)) + on_failed_assignment() + return // Nobody signed up :( + for(var/_ in 1 to position_amount) + var/mob/dead/new_player/picked_player = pick_n_take(lobby_candidates) + picked_player.mind.assigned_role = new job_to_add() + lobby_candidates = null + +/// Called if we didn't assign a role before the round began, we add it to the latejoin menu instead +/datum/station_trait/job/proc/on_failed_assignment() + var/datum/job/our_job = SSjob.GetJob(job_to_add::title) + our_job.total_positions = position_amount + +/datum/station_trait/job/can_display_lobby_button(client/player) + var/datum/job/our_job = SSjob.GetJob(job_to_add::title) + return our_job.player_old_enough(player) && ..() + +/// Adds a gorilla to the cargo department, replacing the sloth and the mech +/datum/station_trait/job/cargorilla + name = "Cargo Gorilla" + button_desc = "Sign up to become the Cargo Gorilla, a peaceful shepherd of boxes." + weight = 1 + show_in_report = FALSE // Selective attention test. Did you spot the gorilla? + can_roll_antag = CAN_ROLL_NEVER + job_to_add = /datum/job/cargo_gorilla + +/datum/station_trait/job/cargorilla/New() + . = ..() + RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(replace_cargo)) + +/datum/station_trait/job/cargorilla/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays) + . = ..() + overlays += LAZYFIND(lobby_candidates, lobby_button.get_mob()) ? "gorilla_on" : "gorilla_off" + +/// Remove the cargo equipment and personnel that are being replaced by a gorilla. +/datum/station_trait/job/cargorilla/proc/replace_cargo(datum/source) + SIGNAL_HANDLER + var/mob/living/basic/sloth/cargo_sloth = GLOB.cargo_sloth + if(isnull(cargo_sloth)) + lobby_candidates = list() + destroy_lobby_buttons() // Sorry folks + sign_up_button = FALSE + return + + // hmm our sloth looks funny today + qdel(cargo_sloth) + // monkey carries the crates, the age of robot is over + if(GLOB.cargo_ripley) + qdel(GLOB.cargo_ripley) + +/datum/station_trait/job/bridge_assistant + name = "Bridge Assistant" + button_desc = "Sign up to become the Bridge Assistant and watch over the Bridge." + weight = 2 + report_message = "We have installed a Bridge Assistant on your station." + show_in_report = TRUE + can_roll_antag = CAN_ROLL_PROTECTED + job_to_add = /datum/job/bridge_assistant + +/datum/station_trait/job/bridge_assistant/New() + . = ..() + RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(add_coffeemaker)) + +/datum/station_trait/job/bridge_assistant/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays) + . = ..() + overlays += "bridge_assistant" + +/// Creates a coffeemaker in the bridge, if we don't have one yet. +/datum/station_trait/job/bridge_assistant/proc/add_coffeemaker(datum/source) + SIGNAL_HANDLER + var/area/bridge = GLOB.areas_by_type[/area/station/command/bridge] + if(isnull(bridge)) //no bridge, what will he assist? + return + var/list/possible_coffeemaker_positions = list(/area/station/command/bridge, /area/station/command/meeting_room) + var/list/coffeemakers = SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/coffeemaker) + for(var/obj/machinery/coffeemaker as anything in coffeemakers) //don't spawn a coffeemaker if there is already one on the bridge + if(is_type_in_list(get_area(coffeemaker), possible_coffeemaker_positions)) + return + var/list/tables = list() + for(var/turf/area_turf as anything in bridge.get_turfs_from_all_zlevels()) + var/obj/structure/table/table = locate() in area_turf + if(isnull(table)) + continue + if(area_turf.is_blocked_turf(ignore_atoms = list(table))) //don't spawn a coffeemaker on a fax machine or smth + continue + tables += table + if(!length(tables)) + return + var/picked_table = pick_n_take(tables) + var/picked_turf = get_turf(picked_table) + if(length(tables)) + var/another_table = pick(tables) + for(var/obj/thing_on_table in picked_turf) //if there's paper bins or other shit on the table, get that off + if(thing_on_table == picked_table) + continue + if(HAS_TRAIT(thing_on_table, TRAIT_WALLMOUNTED) || (thing_on_table.flags_1 & ON_BORDER_1) || thing_on_table.layer < TABLE_LAYER) + continue + if(thing_on_table.invisibility || !thing_on_table.alpha || !thing_on_table.mouse_opacity) + continue + thing_on_table.forceMove(get_turf(another_table)) + new /obj/machinery/coffeemaker/impressa(picked_turf) + new /obj/item/reagent_containers/cup/coffeepot(picked_turf) + new /obj/item/storage/box/coffeepack(picked_turf) + +#undef CAN_ROLL_ALWAYS +#undef CAN_ROLL_PROTECTED +#undef CAN_ROLL_NEVER diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 87e521b9533..5858f34aeab 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -147,7 +147,7 @@ /datum/station_trait/overflow_job_bureaucracy/proc/set_overflow_job_override(datum/source) SIGNAL_HANDLER - var/datum/job/picked_job = pick(SSjob.joinable_occupations) + var/datum/job/picked_job = pick(SSjob.get_valid_overflow_jobs()) chosen_job_name = lowertext(picked_job.title) // like Chief Engineers vs like chief engineers SSjob.set_overflow_role(picked_job.type) @@ -278,7 +278,7 @@ name = "Random Event Modifier" report_message = "A random event has been modified this shift! Someone forgot to set this!" show_in_report = TRUE - trait_flags = STATION_TRAIT_ABSTRACT + abstract_type = /datum/station_trait/random_event_weight_modifier weight = 0 /// The path to the round_event_control that we modify. @@ -301,7 +301,6 @@ name = "Ionic Stormfront" report_message = "An ionic stormfront is passing over your station's system. Expect an increased likelihood of ion storms afflicting your station's silicon units." trait_type = STATION_TRAIT_NEGATIVE - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 3 event_control_path = /datum/round_event_control/ion_storm weight_multiplier = 2 @@ -310,7 +309,6 @@ name = "Radiation Stormfront" report_message = "A radioactive stormfront is passing through your station's system. Expect an increased likelihood of radiation storms passing over your station, as well the potential for multiple radiation storms to occur during your shift." trait_type = STATION_TRAIT_NEGATIVE - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 2 event_control_path = /datum/round_event_control/radiation_storm weight_multiplier = 1.5 @@ -320,7 +318,6 @@ name = "Dust Stormfront" report_message = "The space around your station is clouded by heavy pockets of space dust. Expect an increased likelyhood of space dust storms damaging the station hull." trait_type = STATION_TRAIT_NEGATIVE - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 2 event_control_path = /datum/round_event_control/meteor_wave/dust_storm weight_multiplier = 2 @@ -448,7 +445,7 @@ ///Station traits that influence the space background and apply some unique effects! /datum/station_trait/nebula name = "Nebula" - trait_flags = STATION_TRAIT_ABSTRACT + abstract_type = /datum/station_trait/nebula weight = 0 show_in_report = TRUE @@ -469,7 +466,7 @@ ///Station nebula that incur some sort of effect if no shielding is created /datum/station_trait/nebula/hostile - trait_flags = STATION_TRAIT_ABSTRACT + abstract_type = /datum/station_trait/nebula/hostile trait_processes = TRUE ///Intensity of the nebula @@ -699,7 +696,7 @@ ///Starts a storm on roundstart /datum/station_trait/storm - trait_flags = STATION_TRAIT_ABSTRACT + abstract_type = /datum/station_trait/storm var/datum/weather/storm_type /datum/station_trait/storm/on_round_start() diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index 96c33259152..dd940b3b821 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -2,7 +2,7 @@ name = "Bananium Shipment" trait_type = STATION_TRAIT_NEUTRAL weight = 5 - report_message = "Rumors has it that the clown planet has been sending support packages to clowns in this system" + report_message = "Rumors has it that the clown planet has been sending support packages to clowns in this system." trait_to_give = STATION_TRAIT_BANANIUM_SHIPMENTS /datum/station_trait/unnatural_atmosphere @@ -10,7 +10,7 @@ trait_type = STATION_TRAIT_NEUTRAL weight = 5 show_in_report = TRUE - report_message = "System's local planet has irregular atmospherical properties" + report_message = "System's local planet has irregular atmospherical properties." trait_to_give = STATION_TRAIT_UNNATURAL_ATMOSPHERE // This station trait modifies the atmosphere, which is too far past the time admins are able to revert it @@ -142,60 +142,6 @@ var/new_colored_assistant_type = pick(subtypesof(/datum/colored_assistant) - get_configured_colored_assistant_type()) GLOB.colored_assistant = new new_colored_assistant_type -/datum/station_trait/cargorilla - name = "Cargo Gorilla" - trait_type = STATION_TRAIT_NEUTRAL - weight = 1 - show_in_report = FALSE // Selective attention test. Did you spot the gorilla? - - /// The gorilla we created, we only hold this ref until the round starts. - var/mob/living/basic/gorilla/cargorilla/cargorilla - -/datum/station_trait/cargorilla/New() - . = ..() - RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(replace_cargo)) - -/// Replace some cargo equipment and 'personnel' with a gorilla. -/datum/station_trait/cargorilla/proc/replace_cargo(datum/source) - SIGNAL_HANDLER - - var/mob/living/basic/sloth/cargo_sloth = GLOB.cargo_sloth - if(isnull(cargo_sloth)) - return - - cargorilla = new(cargo_sloth.loc) - cargorilla.name = cargo_sloth.name - // We do a poll on roundstart, don't let ghosts in early - INVOKE_ASYNC(src, PROC_REF(make_id_for_gorilla)) - // hm our sloth looks funny today - qdel(cargo_sloth) - - // monkey carries the crates, the age of robot is over - if(GLOB.cargo_ripley) - qdel(GLOB.cargo_ripley) - -/// Makes an ID card for the gorilla -/datum/station_trait/cargorilla/proc/make_id_for_gorilla() - var/obj/item/card/id/advanced/cargo_gorilla/gorilla_id = new(cargorilla.loc) - gorilla_id.registered_name = cargorilla.name - gorilla_id.update_label() - - cargorilla.put_in_hands(gorilla_id, del_on_fail = TRUE) - -/datum/station_trait/cargorilla/on_round_start() - if(!cargorilla) - return - - addtimer(CALLBACK(src, PROC_REF(get_ghost_for_gorilla), cargorilla), 12 SECONDS) // give ghosts a bit of time to funnel in - cargorilla = null - -/// Get us a ghost for the gorilla. -/datum/station_trait/cargorilla/proc/get_ghost_for_gorilla(mob/living/basic/gorilla/cargorilla/gorilla) - if(QDELETED(gorilla)) - return - - gorilla.poll_for_gorilla() - /datum/station_trait/birthday name = "Employee Birthday" trait_type = STATION_TRAIT_NEUTRAL @@ -252,7 +198,7 @@ /datum/station_trait/birthday/proc/announce_birthday() - report_message = "We here at Nanotrasen would all like to wish [birthday_person ? birthday_person_name : "Employee Name"] a very happy birthday" + report_message = "We here at Nanotrasen would all like to wish [birthday_person ? birthday_person_name : "Employee Name"] a very happy birthday." priority_announce("Happy birthday to [birthday_person ? birthday_person_name : "Employee Name"]! Nanotrasen wishes you a very happy [birthday_person ? thtotext(birthday_person.age + 1) : "255th"] birthday.") if(birthday_person) playsound(birthday_person, 'sound/items/party_horn.ogg', 50) diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index fb740dbaf0b..0f470dd893b 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -100,7 +100,7 @@ name = "deathrattled department" trait_type = STATION_TRAIT_POSITIVE show_in_report = TRUE - trait_flags = STATION_TRAIT_ABSTRACT + abstract_type = /datum/station_trait/deathrattle_department blacklist = list(/datum/station_trait/deathrattle_all) var/department_to_apply_to @@ -128,49 +128,42 @@ /datum/station_trait/deathrattle_department/service name = "Deathrattled Service" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_SERVICE department_name = "Service" /datum/station_trait/deathrattle_department/cargo name = "Deathrattled Cargo" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_CARGO department_name = "Cargo" /datum/station_trait/deathrattle_department/engineering name = "Deathrattled Engineering" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_ENGINEERING department_name = "Engineering" /datum/station_trait/deathrattle_department/command name = "Deathrattled Command" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_COMMAND department_name = "Command" /datum/station_trait/deathrattle_department/science name = "Deathrattled Science" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_SCIENCE department_name = "Science" /datum/station_trait/deathrattle_department/security name = "Deathrattled Security" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_SECURITY department_name = "Security" /datum/station_trait/deathrattle_department/medical name = "Deathrattled Medical" - trait_flags = STATION_TRAIT_MAP_UNRESTRICTED weight = 1 department_to_apply_to = DEPARTMENT_BITFLAG_MEDICAL department_name = "Medical" diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 2e655018517..18d710ca0d3 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -129,8 +129,7 @@ if(0) to_chat(victim, span_deadsay("The last of the nerve endings in your [limb.plaintext_zone] wither away, as the infection completely paralyzes your joint connector.")) threshold_penalty = 120 // piss easy to destroy - var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone) - victim.gain_trauma(sepsis) + set_disabling(TRUE) /datum/wound/burn/flesh/get_wound_description(mob/user) if(strikes_to_lose_limb <= 0) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a71c479811f..04895e528ae 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1092,7 +1092,7 @@ skill_modifier = user.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) if(user.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_JOURNEYMAN && prob(user.mind.get_skill_modifier(/datum/skill/mining, SKILL_PROBS_MODIFIER))) // we check if the skill level is greater than Journeyman and then we check for the probality for that specific level. - mineral_scan_pulse(get_turf(user), SKILL_LEVEL_JOURNEYMAN - 2) //SKILL_LEVEL_JOURNEYMAN = 3 So to get range of 1+ we have to subtract 2 from it,. + mineral_scan_pulse(get_turf(user), SKILL_LEVEL_JOURNEYMAN - 2, scanner = src) //SKILL_LEVEL_JOURNEYMAN = 3 So to get range of 1+ we have to subtract 2 from it,. delay *= toolspeed * skill_modifier diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index bc331db0775..0acbed5540c 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -190,6 +190,26 @@ to_preload += /obj/item/extinguisher/mini return to_preload +/obj/item/storage/belt/utility/full/inducer/PopulateContents() + SSwardrobe.provide_type(/obj/item/screwdriver, src) + SSwardrobe.provide_type(/obj/item/wrench, src) + SSwardrobe.provide_type(/obj/item/weldingtool, src) + SSwardrobe.provide_type(/obj/item/crowbar/red, src) + SSwardrobe.provide_type(/obj/item/wirecutters, src) + SSwardrobe.provide_type(/obj/item/multitool, src) + SSwardrobe.provide_type(/obj/item/inducer, src) + +/obj/item/storage/belt/utility/full/inducer/get_types_to_preload() + var/list/to_preload = list() //Yes this is a pain. Yes this is the point + to_preload += /obj/item/screwdriver + to_preload += /obj/item/wrench + to_preload += /obj/item/weldingtool + to_preload += /obj/item/crowbar + to_preload += /obj/item/wirecutters + to_preload += /obj/item/multitool + to_preload += /obj/item/inducer + return to_preload + /obj/item/storage/belt/utility/syndicate preload = FALSE diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 0eeb8ee15b2..e2038cb623b 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -118,6 +118,12 @@ /obj/structure/bed/medical/AltClick(mob/user) . = ..() + if(!can_interact(user)) + return + + if(has_buckled_mobs() && (user in buckled_mobs)) + return + anchored = !anchored balloon_alert(user, "brakes [anchored ? "applied" : "released"]") update_appearance() diff --git a/code/game/turfs/closed/wall/mineral_walls.dm b/code/game/turfs/closed/wall/mineral_walls.dm index 23e9a2cf775..b42e194ffcf 100644 --- a/code/game/turfs/closed/wall/mineral_walls.dm +++ b/code/game/turfs/closed/wall/mineral_walls.dm @@ -270,11 +270,6 @@ base_icon_state = "shuttle_wall" smoothing_flags = SMOOTH_BITMASK -/turf/closed/wall/mineral/titanium/nosmooth - icon = 'icons/turf/shuttle.dmi' - icon_state = "wall" - smoothing_flags = NONE - /turf/closed/wall/mineral/titanium/overspace icon_state = "map-overspace" smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS @@ -332,11 +327,6 @@ base_icon_state = "plastitanium_wall" smoothing_flags = SMOOTH_BITMASK -/turf/closed/wall/mineral/plastitanium/nosmooth - icon = 'icons/turf/shuttle.dmi' - icon_state = "wall" - smoothing_flags = NONE - /turf/closed/wall/mineral/plastitanium/overspace icon_state = "map-overspace" smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm index 3172e5a9e56..20926fe9d32 100644 --- a/code/game/turfs/closed/wall/reinf_walls.dm +++ b/code/game/turfs/closed/wall/reinf_walls.dm @@ -253,11 +253,6 @@ base_icon_state = "plastitanium_wall" smoothing_flags = SMOOTH_BITMASK -/turf/closed/wall/r_wall/syndicate/nosmooth - icon = 'icons/turf/shuttle.dmi' - icon_state = "wall" - smoothing_flags = NONE - /turf/closed/wall/r_wall/syndicate/overspace icon_state = "map-overspace" smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm index 445097e8bef..5ea2e227750 100644 --- a/code/modules/admin/verbs/list_exposer.dm +++ b/code/modules/admin/verbs/list_exposer.dm @@ -51,12 +51,7 @@ if(!SSticker.HasRoundStarted()) tgui_alert(usr, "The game hasn't started yet!") return - var/data = "Showing Crew Manifest.
" - data += "" - for(var/datum/record/crew/entry in GLOB.manifest.general) - data += "" - data += "
NamePosition
[entry.name][entry.rank][entry.rank != entry.trim ? " ([entry.trim])" : ""]
" - usr << browse(data, "window=manifest;size=440x410") + GLOB.manifest.ui_interact(usr) /datum/admins/proc/output_ai_laws() var/law_bound_entities = 0 diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index 6ff809b59cb..9ef40a9cebf 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -332,7 +332,15 @@ return to_chat(user, span_notice("You activate [src] and wait for confirmation.")) - var/list/baddie_candidates = SSpolling.poll_ghost_candidates("Do you want to play as a [role_to_play]?", check_jobban = poll_role_check, role = poll_role_check, poll_time = 10 SECONDS, ignore_category = poll_ignore_category, pic_source = src, role_name_text = role_to_play) + var/list/baddie_candidates = SSpolling.poll_ghost_candidates( + "Do you want to play as a [role_to_play]?", + check_jobban = poll_role_check, + role = poll_role_check, + poll_time = 10 SECONDS, + ignore_category = poll_ignore_category, + pic_source = src, + role_name_text = role_to_play, + ) if(!LAZYLEN(baddie_candidates)) to_chat(user, span_warning(fail_text)) return @@ -359,7 +367,7 @@ else spawned_mob.forceMove(locate(1,1,1)) - antag_datum = new() + op_mind.add_antag_datum(antag_datum) if(ishuman(spawned_mob)) var/mob/living/carbon/human/human_mob = spawned_mob @@ -373,6 +381,21 @@ spawned_mob.forceMove(pod) new /obj/effect/pod_landingzone(get_turf(src), pod) +/obj/item/antag_spawner/loadout/contractor + name = "contractor support beacon" + desc = "A beacon sold to the most prestigeous syndicate members, a single-use radio for calling immediate backup." + icon = 'icons/obj/devices/voice.dmi' + icon_state = "nukietalkie" + outfit = /datum/outfit/contractor_partner + use_subtypes = FALSE + antag_datum = /datum/antagonist/traitor/contractor_support + poll_ignore_category = ROLE_TRAITOR + role_to_play = ROLE_CONTRACTOR_SUPPORT + +/obj/item/antag_spawner/loadout/contractor/do_special_things(mob/living/carbon/human/contractor_support, mob/user) + to_chat(contractor_support, "\n[span_alertwarning("[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.")]") + to_chat(contractor_support, "[span_alertwarning("Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.")]") + /obj/item/antag_spawner/loadout/monkey_man name = "monkey agent beacon" desc = "Call up some backup from ARC for monkey mayhem." diff --git a/code/modules/antagonists/traitor/contractor/contract_teammate.dm b/code/modules/antagonists/traitor/contractor/contract_teammate.dm index 47a3c704194..54fc958c1f8 100644 --- a/code/modules/antagonists/traitor/contractor/contract_teammate.dm +++ b/code/modules/antagonists/traitor/contractor/contract_teammate.dm @@ -1,35 +1,8 @@ -///Spawns a contractor partner to a spawning user, with a given key to assign to the new player. -/proc/spawn_contractor_partner(mob/living/user, key) - var/mob/living/carbon/human/partner = new() - var/datum/outfit/contractor_partner/partner_outfit = new() - - partner_outfit.equip(partner) - - var/obj/structure/closet/supplypod/arrival_pod = new(null, STYLE_SYNDICATE) - arrival_pod.explosionSize = list(0,0,0,1) - arrival_pod.bluespace = TRUE - - var/turf/free_location = find_obstruction_free_location(2, user) - - // We really want to send them - if we can't find a nice location just land it on top of them. - if (!free_location) - free_location = get_turf(user) - - partner.forceMove(arrival_pod) - partner.ckey = key - - /// We give a reference to the mind that'll be the support unit - var/datum/antagonist/traitor/contractor_support/new_datum = partner.mind.make_contractor_support() // NOVA EDIT CHANGE - ORIGINAL: var/datum/antagonist/traitor/contractor_support/new_datum = partner.mind.add_antag_datum(/datum/antagonist/traitor/contractor_support) - - to_chat(partner, "\n[span_alertwarning("[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.")]") - to_chat(partner, "[span_alertwarning("Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.")]") - - new /obj/effect/pod_landingzone(free_location, arrival_pod) - return new_datum - /// Support unit gets it's own very basic antag datum for admin logging. /datum/antagonist/traitor/contractor_support name = "Contractor Support Unit" + job_rank = ROLE_CONTRACTOR_SUPPORT + employer = "Contractor Support Unit" show_in_roundend = FALSE give_objectives = TRUE give_uplink = FALSE diff --git a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm index 775841e977f..e14b454526b 100644 --- a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm @@ -107,16 +107,15 @@ if(opfor_data.contractor_hub.current_contract == src) // NOVA EDIT CHANGE - ORIGINAL: if(traitor_data.uplink_handler.contractor_hub.current_contract == src) opfor_data.contractor_hub.current_contract = null // NOVA EDIT CHANGE - ORIGINAL: traitor_data.uplink_handler.contractor_hub.current_contract = null - if(iscarbon(person_sent)) - for(var/obj/item/person_contents in person_sent.gather_belongings()) - if(ishuman(person_sent)) - var/mob/living/carbon/human/human_sent = person_sent - if(person_contents == human_sent.w_uniform) - continue //So all they're left with are shoes and uniform. - if(person_contents == human_sent.shoes) - continue - person_sent.transferItemToLoc(person_contents) - victim_belongings.Add(WEAKREF(person_contents)) + for(var/obj/item/person_contents as anything in person_sent.gather_belongings()) + if(ishuman(person_sent)) + var/mob/living/carbon/human/human_sent = person_sent + if(person_contents == human_sent.w_uniform) + continue //So all they're left with are shoes and uniform. + if(person_contents == human_sent.shoes) + continue + person_sent.transferItemToLoc(person_contents) + victim_belongings.Add(WEAKREF(person_contents)) var/obj/structure/closet/supplypod/extractionpod/pod = source // Handle the pod returning diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 4b5332140d7..1d2551b0917 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -34,7 +34,7 @@ ///if TRUE, this traitor will always get hijacking as their final objective var/is_hijacker = FALSE - ///the name of the antag flavor this traitor has. + ///the name of the antag flavor this traitor has, set in Traitor's setup if not preset. var/employer ///assoc list of strings set up after employer is given @@ -188,22 +188,23 @@ return ..() /datum/antagonist/traitor/proc/pick_employer() - var/faction = prob(75) ? FLAVOR_FACTION_SYNDICATE : FLAVOR_FACTION_NANOTRASEN - var/list/possible_employers = list() - - possible_employers.Add(GLOB.syndicate_employers, GLOB.nanotrasen_employers) - - if(istype(ending_objective, /datum/objective/hijack)) - possible_employers -= GLOB.normal_employers - else //escape or martyrdom - possible_employers -= GLOB.hijack_employers - - switch(faction) - if(FLAVOR_FACTION_SYNDICATE) - possible_employers -= GLOB.nanotrasen_employers - if(FLAVOR_FACTION_NANOTRASEN) - possible_employers -= GLOB.syndicate_employers - employer = pick(possible_employers) + if(!employer) + var/faction = prob(75) ? FLAVOR_FACTION_SYNDICATE : FLAVOR_FACTION_NANOTRASEN + var/list/possible_employers = list() + + possible_employers.Add(GLOB.syndicate_employers, GLOB.nanotrasen_employers) + + if(istype(ending_objective, /datum/objective/hijack)) + possible_employers -= GLOB.normal_employers + else //escape or martyrdom + possible_employers -= GLOB.hijack_employers + + switch(faction) + if(FLAVOR_FACTION_SYNDICATE) + possible_employers -= GLOB.nanotrasen_employers + if(FLAVOR_FACTION_NANOTRASEN) + possible_employers -= GLOB.syndicate_employers + employer = pick(possible_employers) traitor_flavor = strings(TRAITOR_FLAVOR_FILE, employer) /// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack. @@ -308,6 +309,7 @@ data["allies"] = traitor_flavor["allies"] data["goal"] = traitor_flavor["goal"] data["has_uplink"] = uplink ? TRUE : FALSE + data["given_uplink"] = give_uplink if(uplink) data["uplink_intro"] = traitor_flavor["uplink"] data["uplink_unlock_info"] = uplink.unlock_text diff --git a/code/modules/bitrunning/job.dm b/code/modules/bitrunning/job.dm index 57581753c0f..1e749a3c7a5 100644 --- a/code/modules/bitrunning/job.dm +++ b/code/modules/bitrunning/job.dm @@ -29,7 +29,7 @@ /obj/item/food/cornchips/blue = 1, ) rpg_title = "Recluse" - job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + job_flags = STATION_JOB_FLAGS /datum/outfit/job/bitrunner name = "Bitrunner" diff --git a/code/modules/client/preferences/middleware/jobs.dm b/code/modules/client/preferences/middleware/jobs.dm index a7261bbaf17..27c6b033f38 100644 --- a/code/modules/client/preferences/middleware/jobs.dm +++ b/code/modules/client/preferences/middleware/jobs.dm @@ -53,6 +53,8 @@ var/list/jobs = list() for (var/datum/job/job as anything in SSjob.joinable_occupations) + if (job.job_flags & JOB_LATEJOIN_ONLY) + continue var/datum/job_department/department_type = job.department_for_prefs || job.departments_list?[1] if (isnull(department_type)) stack_trace("[job] does not have a department set, yet is a joinable occupation!") @@ -118,6 +120,8 @@ var/list/job_required_experience = list() for (var/datum/job/job as anything in SSjob.all_occupations) + if (job.job_flags & JOB_LATEJOIN_ONLY) + continue var/required_playtime_remaining = job.required_playtime_remaining(user.client) if (required_playtime_remaining) job_required_experience[job.title] = list( diff --git a/code/modules/clothing/outfits/plasmaman.dm b/code/modules/clothing/outfits/plasmaman.dm index a422d2d736e..40d7cfa888e 100644 --- a/code/modules/clothing/outfits/plasmaman.dm +++ b/code/modules/clothing/outfits/plasmaman.dm @@ -288,3 +288,10 @@ uniform = /obj/item/clothing/under/plasmaman/bitrunner gloves = /obj/item/clothing/gloves/color/plasmaman/black head = /obj/item/clothing/head/helmet/space/plasmaman/bitrunner + +/datum/outfit/plasmaman/bridge_assistant + name = "Bridge Assistant Plasmaman" + + uniform = /obj/item/clothing/under/plasmaman //call me when this is gags and not 10 million new assets + gloves = /obj/item/clothing/gloves/color/plasmaman/black + head = /obj/item/clothing/head/helmet/space/plasmaman diff --git a/code/modules/events/bureaucratic_error.dm b/code/modules/events/bureaucratic_error.dm index 578adc9be30..db6371d6498 100644 --- a/code/modules/events/bureaucratic_error.dm +++ b/code/modules/events/bureaucratic_error.dm @@ -13,21 +13,17 @@ priority_announce("A recent bureaucratic error in the Organic Resources Department may result in personnel shortages in some departments and redundant staffing in others.", "Paperwork Mishap Alert") /datum/round_event/bureaucratic_error/start() - var/list/jobs = SSjob.joinable_occupations.Copy() - /* - if(prob(33)) // Only allows latejoining as a single role. Add latejoin AI bluespace pods for fun later. + var/list/jobs = SSjob.get_valid_overflow_jobs() + /* NOVA EDIT REMOVAL START - No more locking off jobs + if(prob(33)) // Only allows latejoining as a single role. var/datum/job/overflow = pick_n_take(jobs) overflow.spawn_positions = -1 overflow.total_positions = -1 // Ensures infinite slots as this role. Assistant will still be open for those that cant play it. for(var/job in jobs) var/datum/job/current = job - if(!current.allow_bureaucratic_error) - continue current.total_positions = 0 - else // Adds/removes a random amount of job slots from all jobs. - */ // NOVA EDIT REMOVAL - no more locking off jobs + return + */ // NOVA EDIT REMOVAL END + // Adds/removes a random amount of job slots from all jobs. for(var/datum/job/current as anything in jobs) - if(!current.allow_bureaucratic_error) - continue - var/ran = rand(1,4) // NOVA EDIT - no more locking off jobs - current.total_positions = max(current.total_positions + ran, 0) + current.total_positions = max(current.total_positions + rand(1,4), 0) // NOVA EDIT - no more locking off jobs - ORIGINAL: current.total_positions = max(current.total_positions + rand(-2,4), 0) diff --git a/code/modules/food_and_drinks/recipes/soup_mixtures.dm b/code/modules/food_and_drinks/recipes/soup_mixtures.dm index 7a80f291b87..312d3731864 100644 --- a/code/modules/food_and_drinks/recipes/soup_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/soup_mixtures.dm @@ -1228,7 +1228,6 @@ ) results = list( /datum/reagent/consumable/nutriment/soup/oatmeal = 20, - /datum/reagent/consumable/milk = 12, /datum/reagent/consumable/nutriment/vitamin = 8, ) percentage_of_nutriment_converted = 0 // Oats have barely any nutrients diff --git a/code/modules/jobs/job_types/cargo_gorilla.dm b/code/modules/jobs/job_types/cargo_gorilla.dm new file mode 100644 index 00000000000..96a79e3a4d3 --- /dev/null +++ b/code/modules/jobs/job_types/cargo_gorilla.dm @@ -0,0 +1,50 @@ +/datum/job/cargo_gorilla + title = JOB_CARGO_GORILLA + description = "Assist the supply department by moving freight and disposing of unwanted fruits." + department_head = list(JOB_QUARTERMASTER) + faction = FACTION_STATION + total_positions = 0 + spawn_positions = 0 + supervisors = SUPERVISOR_QM + spawn_type = /mob/living/basic/gorilla/cargorilla + config_tag = "CARGO_GORILLA" + random_spawns_possible = FALSE + display_order = JOB_DISPLAY_ORDER_CARGO_GORILLA + departments_list = list(/datum/job_department/cargo) + mail_goodies = list( + /obj/item/food/grown/banana = 1, + ) + rpg_title = "Beast of Burden" + allow_bureaucratic_error = FALSE + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_NEW_PLAYER_JOINABLE | JOB_EQUIP_RANK | JOB_CANNOT_OPEN_SLOTS | JOB_HIDE_WHEN_EMPTY | JOB_LATEJOIN_ONLY + +/datum/job/cargo_gorilla/get_roundstart_spawn_point() + if (length(GLOB.gorilla_start)) + return pick(GLOB.gorilla_start) + return ..() + +/datum/job/cargo_gorilla/get_spawn_mob(client/player_client, atom/spawn_point) + if (!player_client) + return + var/mob/living/the_big_man = new spawn_type(get_turf(spawn_point)) + the_big_man.fully_replace_character_name(the_big_man.real_name, pick(GLOB.cargorilla_names)) + return the_big_man + +/datum/job/cargo_gorilla/after_spawn(mob/living/spawned, client/player_client) + . = ..() + // Gorilla with a wage, what's he buyin? + var/datum/bank_account/bank_account = new(spawned.real_name, src) + bank_account.payday(STARTING_PAYCHECKS, TRUE) + bank_account.replaceable = FALSE + spawned.add_mob_memory(/datum/memory/key/account, remembered_id = bank_account.account_id) + + var/obj/item/card/id/advanced/cargo_gorilla/gorilla_id = new(spawned.loc) + gorilla_id.registered_name = spawned.name + gorilla_id.update_label() + gorilla_id.registered_account = bank_account + bank_account.bank_cards += gorilla_id + spawned.put_in_hands(gorilla_id, del_on_fail = TRUE) + + to_chat(spawned, span_boldnotice("You are Cargorilla, a pacifist friend of the station and carrier of freight.")) + to_chat(spawned, span_notice("You can pick up crates by clicking on them, and drop them by clicking on the ground.")) + spawned.mind.special_role = "Cargorilla" diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm index 8a58dc233a7..bd0c3a3ed27 100644 --- a/code/modules/jobs/job_types/prisoner.dm +++ b/code/modules/jobs/job_types/prisoner.dm @@ -23,7 +23,7 @@ family_heirlooms = list(/obj/item/pen/blue) rpg_title = "Defeated Miniboss" - job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | JOB_CANNOT_OPEN_SLOTS & ~JOB_REOPEN_ON_ROUNDSTART_LOSS /datum/job/prisoner/New() . = ..() diff --git a/code/modules/jobs/job_types/station_trait/bridge_assistant.dm b/code/modules/jobs/job_types/station_trait/bridge_assistant.dm new file mode 100644 index 00000000000..b1ae57de1ff --- /dev/null +++ b/code/modules/jobs/job_types/station_trait/bridge_assistant.dm @@ -0,0 +1,80 @@ +/datum/job/bridge_assistant + title = JOB_BRIDGE_ASSISTANT + description = "Watch over the Bridge, command its consoles, and spend your days brewing coffee for higher-ups." + auto_deadmin_role_flags = DEADMIN_POSITION_HEAD //not really a head but close enough + department_head = list(JOB_CAPTAIN) + faction = FACTION_STATION + total_positions = 0 + spawn_positions = 0 + supervisors = "the Captain, and in non-Bridge related situations the other heads" + minimal_player_age = 7 + exp_requirements = 300 + exp_required_type = EXP_TYPE_CREW + exp_granted_type = EXP_TYPE_CREW + config_tag = "BRIDGE_ASSISTANT" + + outfit = /datum/outfit/job/bridge_assistant + plasmaman_outfit = /datum/outfit/plasmaman/bridge_assistant + + paycheck = PAYCHECK_CREW + paycheck_department = ACCOUNT_CIV + + liver_traits = list(TRAIT_PRETENDER_ROYAL_METABOLISM) + + display_order = JOB_DISPLAY_ORDER_BRIDGE_ASSISTANT + departments_list = list(/datum/job_department/command) + + family_heirlooms = list(/obj/item/banner/command/mundane) + + mail_goodies = list( + /obj/item/storage/fancy/cigarettes = 1, + /obj/item/pen/fountain = 1, + ) + rpg_title = "Royal Guard" + allow_bureaucratic_error = FALSE + job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS + ignore_human_authority = TRUE + +/datum/job/bridge_assistant/after_spawn(mob/living/spawned, client/player_client) + . = ..() + ADD_TRAIT(spawned, TRAIT_NO_TWOHANDING, JOB_TRAIT) + +/datum/job/bridge_assistant/get_roundstart_spawn_point() + var/list/chair_turfs = list() + var/list/possible_turfs = list() + var/area/bridge = GLOB.areas_by_type[/area/station/command/bridge] + if(isnull(bridge)) + return ..() //if no bridge, spawn on the arrivals shuttle (but also what the fuck) + for (var/list/zlevel_turfs as anything in bridge.get_zlevel_turf_lists()) + for (var/turf/possible_turf as anything in zlevel_turfs) + if(possible_turf.is_blocked_turf()) + continue + if(locate(/obj/structure/chair) in possible_turf) + chair_turfs += possible_turf + continue + possible_turfs += possible_turf + if(length(chair_turfs)) + return pick(chair_turfs) //prioritize turfs with a chair + if(length(possible_turfs)) + return pick(possible_turfs) //if none, just pick a random turf in the bridge + return ..() //if the bridge has no turfs, spawn on the arrivals shuttle + +/datum/outfit/job/bridge_assistant + name = "Bridge Assistant" + jobtype = /datum/job/bridge_assistant + + id_trim = /datum/id_trim/job/bridge_assistant + backpack_contents = list( + /obj/item/modular_computer/pda/bridge_assistant = 1, + ) + + uniform = /obj/item/clothing/under/trek/command/next + neck = /obj/item/clothing/neck/large_scarf/blue + belt = /obj/item/storage/belt/utility/full/inducer + ears = /obj/item/radio/headset/headset_com + glasses = /obj/item/clothing/glasses/sunglasses + gloves = /obj/item/clothing/gloves/fingerless + head = /obj/item/clothing/head/soft/black + shoes = /obj/item/clothing/shoes/laceup + l_pocket = /obj/item/gun/energy/e_gun/mini + r_pocket = /obj/item/assembly/flash/handheld diff --git a/code/modules/jobs/job_types/station_trait/cargo_gorilla.dm b/code/modules/jobs/job_types/station_trait/cargo_gorilla.dm new file mode 100644 index 00000000000..87363bf9b7b --- /dev/null +++ b/code/modules/jobs/job_types/station_trait/cargo_gorilla.dm @@ -0,0 +1,50 @@ +/datum/job/cargo_gorilla + title = JOB_CARGO_GORILLA + description = "Assist the supply department by moving freight and disposing of unwanted fruits." + department_head = list(JOB_QUARTERMASTER) + faction = FACTION_STATION + total_positions = 0 + spawn_positions = 0 + supervisors = SUPERVISOR_QM + spawn_type = /mob/living/basic/gorilla/cargorilla + config_tag = "CARGO_GORILLA" + random_spawns_possible = FALSE + display_order = JOB_DISPLAY_ORDER_CARGO_GORILLA + departments_list = list(/datum/job_department/cargo) + mail_goodies = list( + /obj/item/food/grown/banana = 1, + ) + rpg_title = "Beast of Burden" + allow_bureaucratic_error = FALSE + job_flags = STATION_TRAIT_JOB_FLAGS | JOB_ANNOUNCE_ARRIVAL | JOB_NEW_PLAYER_JOINABLE | JOB_EQUIP_RANK + +/datum/job/cargo_gorilla/get_roundstart_spawn_point() + if (length(GLOB.gorilla_start)) + return pick(GLOB.gorilla_start) + return ..() + +/datum/job/cargo_gorilla/get_spawn_mob(client/player_client, atom/spawn_point) + if (!player_client) + return + var/mob/living/the_big_man = new spawn_type(get_turf(spawn_point)) + the_big_man.fully_replace_character_name(the_big_man.real_name, pick(GLOB.cargorilla_names)) + return the_big_man + +/datum/job/cargo_gorilla/after_spawn(mob/living/spawned, client/player_client) + . = ..() + // Gorilla with a wage, what's he buyin? + var/datum/bank_account/bank_account = new(spawned.real_name, src) + bank_account.payday(STARTING_PAYCHECKS, TRUE) + bank_account.replaceable = FALSE + spawned.add_mob_memory(/datum/memory/key/account, remembered_id = bank_account.account_id) + + var/obj/item/card/id/advanced/cargo_gorilla/gorilla_id = new(spawned.loc) + gorilla_id.registered_name = spawned.name + gorilla_id.update_label() + gorilla_id.registered_account = bank_account + bank_account.bank_cards += gorilla_id + spawned.put_in_hands(gorilla_id, del_on_fail = TRUE) + + to_chat(spawned, span_boldnotice("You are Cargorilla, a pacifist friend of the station and carrier of freight.")) + to_chat(spawned, span_notice("You can pick up crates by clicking on them, and drop them by clicking on the ground.")) + spawned.mind.special_role = "Cargorilla" diff --git a/code/modules/mining/boulder_processing/_boulder_processing.dm b/code/modules/mining/boulder_processing/_boulder_processing.dm index 5cf9544141a..daa6620a233 100644 --- a/code/modules/mining/boulder_processing/_boulder_processing.dm +++ b/code/modules/mining/boulder_processing/_boulder_processing.dm @@ -211,7 +211,7 @@ if(!is_type_in_list(possible_mat, processable_materials)) continue var/quantity = chosen_boulder.custom_materials[possible_mat] - points_held = round((points_held + (quantity * possible_mat.points_per_unit)) * MINING_POINT_MACHINE_MULTIPLIER) // put point total here into machine + points_held = round(points_held + (quantity * possible_mat.points_per_unit * MINING_POINT_MACHINE_MULTIPLIER)) // put point total here into machine processable_ores += possible_mat processable_ores[possible_mat] = quantity chosen_boulder.custom_materials -= possible_mat //Remove it from the boulder now that it's tracked diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm index 7ef529af133..55a0ab44949 100644 --- a/code/modules/mining/equipment/mineral_scanner.dm +++ b/code/modules/mining/equipment/mineral_scanner.dm @@ -71,7 +71,6 @@ var/vents_nearby = FALSE var/undiscovered = FALSE var/radar_volume = 30 - scanner.transform = matrix() for(var/turf/closed/mineral/mineral in RANGE_TURFS(range, T)) if(mineral.scan_state) minerals += mineral diff --git a/code/modules/mob/dead/crew_manifest.dm b/code/modules/mob/dead/crew_manifest.dm deleted file mode 100644 index 6a2c84622a2..00000000000 --- a/code/modules/mob/dead/crew_manifest.dm +++ /dev/null @@ -1,38 +0,0 @@ -/datum/crew_manifest - -/datum/crew_manifest/ui_state(mob/user) - return GLOB.always_state - -/datum/crew_manifest/ui_status(mob/user, datum/ui_state/state) - return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user)) ? UI_INTERACTIVE : UI_CLOSE - -/datum/crew_manifest/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if (!ui) - ui = new(user, src, "CrewManifest") - ui.open() - -/datum/crew_manifest/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - -/datum/crew_manifest/ui_data(mob/user) - var/list/positions = list() - for(var/datum/job_department/department as anything in SSjob.joinable_departments) - var/open = 0 - var/list/exceptions = list() - for(var/datum/job/job as anything in department.department_jobs) - if(job.total_positions == -1) - exceptions += job.title - continue - var/open_slots = job.total_positions - job.current_positions - if(open_slots < 1) - continue - open += open_slots - positions[department.department_name] = list("exceptions" = exceptions, "open" = open) - - return list( - "manifest" = GLOB.manifest.get_manifest(), - "positions" = positions - ) diff --git a/code/modules/mob/dead/new_player/latejoin_menu.dm b/code/modules/mob/dead/new_player/latejoin_menu.dm index 992f0513423..a2d68536974 100644 --- a/code/modules/mob/dead/new_player/latejoin_menu.dm +++ b/code/modules/mob/dead/new_player/latejoin_menu.dm @@ -80,6 +80,8 @@ GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new) ) if(job_availability != JOB_AVAILABLE) + if (job_datum.job_flags & JOB_HIDE_WHEN_EMPTY) + continue job_data["unavailable_reason"] = get_job_unavailable_error_message(job_availability, job_datum.title) if(job_datum.total_positions < 0) @@ -95,6 +97,7 @@ GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new) /datum/latejoin_menu/ui_static_data(mob/user) var/list/departments = list() + var/mob/dead/new_player/owner = user for(var/datum/job_department/department as anything in SSjob.joinable_departments) var/list/department_jobs = list() @@ -108,6 +111,8 @@ GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new) //Jobs under multiple departments should only be displayed if this is their first department or the command department if(LAZYLEN(job_datum.departments_list) > 1 && job_datum.departments_list[1] != department.type && !(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) continue + if((job_datum.job_flags & JOB_HIDE_WHEN_EMPTY) && owner.IsJobUnavailable(job_datum.title, latejoin = TRUE) != JOB_AVAILABLE) + continue var/list/job_data = list( "command" = !!(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND), diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index c10c027bc3d..e1033e24f35 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -338,11 +338,7 @@ return client.crew_manifest_delay = world.time + (1 SECONDS) - if(!GLOB.crew_manifest_tgui) - GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) - - - GLOB.crew_manifest_tgui.ui_interact(src) + GLOB.manifest.ui_interact(src) /mob/dead/new_player/Move() return 0 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 86c0da5acf7..0a3e0bde103 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -726,10 +726,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return client.crew_manifest_delay = world.time + (1 SECONDS) - if(!GLOB.crew_manifest_tgui) - GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) - - GLOB.crew_manifest_tgui.ui_interact(src) + GLOB.manifest.ui_interact(src) //this is called when a ghost is drag clicked to something. /mob/dead/observer/MouseDrop(atom/over) diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm index 1e17938c5fd..64cff6780df 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm @@ -158,31 +158,4 @@ ADD_TRAIT(src, TRAIT_PACIFISM, INNATE_TRAIT) AddComponent(/datum/component/crate_carrier) -/mob/living/basic/gorilla/cargorilla/death(gibbed) - var/datum/component/potential_component = GetComponent(/datum/component/ghost_direct_control) - if(!QDELETED(potential_component)) - qdel(potential_component) - return ..() - -/** - * Poll ghosts for control of the gorilla. Not added in init because we only want to poll when the round starts. - * Preferably in future we can replace this with a popup on the lobby to queue to become a gorilla. - */ -/mob/living/basic/gorilla/cargorilla/proc/poll_for_gorilla() - AddComponent(\ - /datum/component/ghost_direct_control,\ - poll_candidates = TRUE,\ - poll_length = 30 SECONDS,\ - role_name = "Cargorilla",\ - assumed_control_message = "You are Cargorilla, a pacifist friend of the station and carrier of freight.",\ - poll_ignore_key = POLL_IGNORE_CARGORILLA,\ - after_assumed_control = CALLBACK(src, PROC_REF(became_player_controlled)),\ - ) - -/// Called once a ghost assumes control -/mob/living/basic/gorilla/cargorilla/proc/became_player_controlled() - mind.set_assigned_role(SSjob.GetJobType(/datum/job/cargo_technician)) - mind.special_role = "Cargorilla" - to_chat(src, span_notice("You can pick up crates by clicking on them, and drop them by clicking on the ground.")) - #undef GORILLA_HANDS_LAYER diff --git a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm index d0355e906a7..f35f78ba80f 100644 --- a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm +++ b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm @@ -84,7 +84,7 @@ /mob/living/basic/mining/goldgrub/proc/barf_contents(gibbed) playsound(src, 'sound/effects/splat.ogg', 50, TRUE) - for(var/obj/item/ore as anything in src) + for(var/obj/item/stack/ore/ore in src) ore.forceMove(loc) if(!gibbed) visible_message(span_danger("[src] spits out its consumed ores!")) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm index 91edf40615c..7cc5ea06ad8 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -30,7 +30,7 @@ density = FALSE ai_controller = /datum/ai_controller/basic_controller/legion_brood /// Reference to a guy who made us - var/mob/living/created_by + var/datum/weakref/created_by /mob/living/basic/legion_brood/Initialize(mapload) . = ..() @@ -49,7 +49,12 @@ if (ishuman(target) && target.stat > SOFT_CRIT) infest(target) return - if (isliving(target) && faction_check_atom(target) && !istype(target, created_by?.type)) + + var/mob/living/mob_creator = created_by?.resolve() + if(isnull(mob_creator)) + created_by = null + + if (isliving(target) && faction_check_atom(target) && !istype(target, mob_creator?.type)) visible_message(span_warning("[src] melds with [target]'s flesh!")) target.apply_status_effect(/datum/status_effect/regenerative_core) new /obj/effect/temp_visual/heal(get_turf(target), COLOR_HEALING_CYAN) @@ -78,7 +83,7 @@ faction = creator.faction.Copy() else faction |= REF(creator) - created_by = creator + created_by = WEAKREF(creator) ai_controller?.set_blackboard_key(BB_LEGION_BROOD_CREATOR, creator) RegisterSignal(creator, COMSIG_QDELETING, PROC_REF(creator_destroyed)) diff --git a/code/modules/mob/living/basic/pets/sloth.dm b/code/modules/mob/living/basic/pets/sloth.dm index 0b1546ccf93..125a3a7b97d 100644 --- a/code/modules/mob/living/basic/pets/sloth.dm +++ b/code/modules/mob/living/basic/pets/sloth.dm @@ -44,11 +44,12 @@ GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) AddElement(/datum/element/ai_retaliate) AddComponent(/datum/component/tree_climber) - if(!mapload || isnull(GLOB.cargo_sloth) || !is_station_level(z)) + if(!mapload || !isnull(GLOB.cargo_sloth) || !is_station_level(z)) return // If someone adds non-cargo sloths to maps we'll have a problem but we're fine for now GLOB.cargo_sloth = src + GLOB.gorilla_start += get_turf(src) /mob/living/basic/sloth/Destroy() if(GLOB.cargo_sloth == src) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 31096fbffc7..5efce52d6e8 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -353,10 +353,7 @@ return client.crew_manifest_delay = world.time + (1 SECONDS) - if(!GLOB.crew_manifest_tgui) - GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) - - GLOB.crew_manifest_tgui.ui_interact(src) + GLOB.manifest.ui_interact(src) /mob/living/silicon/proc/set_autosay() //For allowing the AI and borgs to set the radio behavior of auto announcements (state laws, arrivals). if(!radio) diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm index 28b3da6580a..1f384878e8d 100644 --- a/code/modules/mob/mob_say.dm +++ b/code/modules/mob/mob_say.dm @@ -169,8 +169,8 @@ return message if (is_banned_from(ckey, "Emote")) return copytext(message, customsaypos + 1) - mods[MODE_CUSTOM_SAY_EMOTE] = copytext(message, 1, customsaypos) - message = copytext(message, customsaypos + 1) + mods[MODE_CUSTOM_SAY_EMOTE] = lowercase_title(copytext(message, 1, customsaypos)) // NOVA EDIT: ORIGINAL: mods[MODE_CUSTOM_SAY_EMOTE] = copytext(message, 1, customsaypos) + message = trim(copytext(message, customsaypos + 1)) //NOVA EDIT: ORIGINAL: message = copytext(message, customsaypos + 1) if (!message) mods[MODE_CUSTOM_SAY_ERASE_INPUT] = TRUE message = "an interesting thing to say" diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 80422dfc0c7..3728901352c 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -927,17 +927,16 @@ return FALSE inserted_pai = card balloon_alert(user, "inserted pai") - var/datum/action/innate/pai/messenger/messenger_ability = new(inserted_pai.pai) - messenger_ability.Grant(inserted_pai.pai) + if(inserted_pai.pai) + inserted_pai.pai.give_messenger_ability() update_appearance(UPDATE_ICON) return TRUE /obj/item/modular_computer/proc/remove_pai(mob/user) if(!inserted_pai) return FALSE - var/datum/action/innate/pai/messenger/messenger_ability = locate() in inserted_pai.pai.actions - messenger_ability.Remove(inserted_pai.pai) - qdel(messenger_ability) + if(inserted_pai.pai) + inserted_pai.pai.remove_messenger_ability() if(user) user.put_in_hands(inserted_pai) balloon_alert(user, "removed pAI") diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 31d763054b6..0d9b7167d7a 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -103,7 +103,7 @@ /obj/item/modular_computer/pda/heads/quartermaster name = "quartermaster PDA" - greyscale_config = /datum/greyscale_config/tablet/stripe_thick + greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head greyscale_colors = "#c4b787#18191e#8b4c31" inserted_item = /obj/item/pen/survival stored_paper = 20 @@ -414,7 +414,7 @@ ) /** - * No Department + * No Department/Station Trait */ /obj/item/modular_computer/pda/assistant @@ -423,6 +423,14 @@ /datum/computer_file/program/bounty_board, ) +/obj/item/modular_computer/pda/bridge_assistant + name = "bridge assistant PDA" + greyscale_colors = "#374f7e#a92323" + starting_programs = list( + /datum/computer_file/program/crew_manifest, + /datum/computer_file/program/status, + ) + /** * Non-roles */ diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index 19e00a04556..494c39eb33f 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -80,6 +80,9 @@ /// Remote signaler var/obj/item/assembly/signaler/internal/signaler + ///The messeenger ability that pAIs get when they are put in a PDA. + var/datum/action/innate/pai/messenger/messenger_ability + // Static lists /// List of all available downloads var/static/list/available_software = list( @@ -149,6 +152,7 @@ return ..(target, action_bitflags) /mob/living/silicon/pai/Destroy() + QDEL_NULL(messenger_ability) QDEL_NULL(atmos_analyzer) QDEL_NULL(hacking_cable) QDEL_NULL(instrument) @@ -203,6 +207,8 @@ /mob/living/silicon/pai/Initialize(mapload) . = ..() + if(istype(loc, /obj/item/modular_computer)) + give_messenger_ability() START_PROCESSING(SSfastprocess, src) GLOB.pai_list += src make_laws() @@ -457,3 +463,14 @@ if (new_distance < HOLOFORM_MIN_RANGE || new_distance > HOLOFORM_MAX_RANGE) return leash.set_distance(new_distance) + +///Gives the messenger ability to the pAI, creating a new one if it doesn't have one already. +/mob/living/silicon/pai/proc/give_messenger_ability() + if(!messenger_ability) + messenger_ability = new(src) + messenger_ability.Grant(src) + +///Removes the messenger ability from the pAI, but does not delete it. +/mob/living/silicon/pai/proc/remove_messenger_ability() + if(messenger_ability) + messenger_ability.Remove(src) diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm index b35f4de3fba..e712f474464 100644 --- a/code/modules/power/apc/apc_tool_act.dm +++ b/code/modules/power/apc/apc_tool_act.dm @@ -77,6 +77,7 @@ return toggle_panel_open() balloon_alert(user, "wires [panel_open ? "exposed" : "unexposed"]") + W.play_tool_sound(src) update_appearance() return diff --git a/code/modules/reagents/chemistry/equilibrium.dm b/code/modules/reagents/chemistry/equilibrium.dm index c07c349f893..d2a037f91d1 100644 --- a/code/modules/reagents/chemistry/equilibrium.dm +++ b/code/modules/reagents/chemistry/equilibrium.dm @@ -84,6 +84,8 @@ * Don't call this unless you know what you're doing, this is an internal proc */ /datum/equilibrium/proc/check_inital_conditions() + PRIVATE_PROC(TRUE) + if(QDELETED(holder)) stack_trace("an equilibrium is missing it's holder.") return FALSE @@ -95,7 +97,7 @@ return FALSE //Make sure we have the right multipler for on_reaction() - for(var/single_reagent in reaction.required_reagents) + for(var/datum/reagent/single_reagent as anything in reaction.required_reagents) multiplier = min(multiplier, holder.get_reagent_amount(single_reagent) / reaction.required_reagents[single_reagent]) multiplier = round(multiplier, CHEMICAL_QUANTISATION_LEVEL) if(!multiplier) //we have no more or very little reagents left @@ -108,7 +110,7 @@ //All checks pass. cache the product ratio if(length(reaction.results)) product_ratio = 0 - for(var/product in reaction.results) + for(var/datum/reagent/product as anything in reaction.results) product_ratio += reaction.results[product] else product_ratio = 1 @@ -123,6 +125,8 @@ * otherwise, generally, don't call this directed except internally */ /datum/equilibrium/proc/check_reagent_properties() + PRIVATE_PROC(TRUE) + //Have we exploded from on_reaction or did we run out of reagents? if(QDELETED(holder.my_atom) || !holder.reagent_list.len) return FALSE @@ -150,8 +154,10 @@ * Generally an internal proc */ /datum/equilibrium/proc/calculate_yield() + PRIVATE_PROC(TRUE) + multiplier = INFINITY - for(var/reagent in reaction.required_reagents) + for(var/datum/reagent/reagent as anything in reaction.required_reagents) multiplier = min(multiplier, holder.get_reagent_amount(reagent) / reaction.required_reagents[reagent]) multiplier = round(multiplier, CHEMICAL_QUANTISATION_LEVEL) if(!multiplier) //we have no more or very little reagents left @@ -160,14 +166,14 @@ //Incase of no reagent product if(!length(reaction.results)) step_target_vol = INFINITY - for(var/reagent in reaction.required_reagents) + for(var/datum/reagent/reagent as anything in reaction.required_reagents) step_target_vol = min(step_target_vol, multiplier * reaction.required_reagents[reagent]) return TRUE //If we have reagent products step_target_vol = 0 reacted_vol = 0 //Because volumes can be lost mid reactions - for(var/product in reaction.results) + for(var/datum/reagent/product as anything in reaction.results) step_target_vol += multiplier * reaction.results[product] reacted_vol += holder.get_reagent_amount(product) target_vol = reacted_vol + step_target_vol @@ -181,6 +187,8 @@ * step_volume_added is how much product (across all products) was added for this single step */ /datum/equilibrium/proc/check_fail_states(step_volume_added) + PRIVATE_PROC(TRUE) + //Are we overheated? if(reaction.is_cold_recipe) if(holder.chem_temp < reaction.overheat_temp && reaction.overheat_temp != NO_OVERHEAT) //This is before the process - this is here so that overly_impure and overheated() share the same code location (and therefore vars) for calls. @@ -192,7 +200,7 @@ reaction.overheated(holder, src, step_volume_added) //is our product too impure? - for(var/product in reaction.results) + for(var/datum/reagent/product as anything in reaction.results) var/datum/reagent/reagent = holder.has_reagent(product) if(!reagent) //might be missing from overheat exploding continue @@ -212,6 +220,8 @@ * * seconds_per_tick - the time between the last proc in world.time */ /datum/equilibrium/proc/deal_with_time(seconds_per_tick) + PRIVATE_PROC(TRUE) + if(seconds_per_tick > 1) time_deficit += seconds_per_tick - 1 seconds_per_tick = 1 //Lets make sure reactions aren't super speedy and blow people up from a big lag spike @@ -306,7 +316,7 @@ purity = delta_ph //Then adjust purity of result with beaker reagent purity. - purity *= reactant_purity(reaction) + purity *= average_purity() //Then adjust it from the input modifier purity *= purity_modifier @@ -324,13 +334,13 @@ //Calculate how much product to make and how much reactant to remove factors.. var/required_amount + var/pH_adjust for(var/datum/reagent/requirement as anything in reaction.required_reagents) required_amount = reaction.required_reagents[requirement] if(!holder.remove_reagent(requirement, delta_chem_factor * required_amount)) to_delete = TRUE return //Apply pH changes - var/pH_adjust if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT) pH_adjust = ((delta_chem_factor * required_amount) / target_vol) * (reaction.H_ion_release * h_ion_mod) else //Default adds pH independant of volume @@ -347,7 +357,6 @@ return //Apply pH changes - var/pH_adjust if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT) pH_adjust = (step_add / target_vol) * (reaction.H_ion_release * h_ion_mod) else @@ -386,9 +395,9 @@ to_delete = TRUE return - //end reactions faster so plumbing is faster - //length is so that plumbing is faster - but it doesn't disable competitive reactions. Basically, competitive reactions will likely reach their step target at the start, so this will disable that. We want to avoid that. But equally, we do want to full stop a holder from reacting asap so plumbing isn't waiting an tick to resolve. - if((step_add >= step_target_vol) && (length(holder.reaction_list) == 1)) + //If the volume of reagents created(total_step_added) >= volume of reagents still to be created(step_target_vol) then end + //i.e. we have created all the reagents needed for this reaction + if(total_step_added >= step_target_vol) to_delete = TRUE /* @@ -396,12 +405,14 @@ * Currently calculates it irrespective of required reagents at the start, but this should be changed if this is powergamed to required reagents * It's not currently because overly_impure affects all reagents */ -/datum/equilibrium/proc/reactant_purity(datum/chemical_reaction/C) +/datum/equilibrium/proc/average_purity() + PRIVATE_PROC(TRUE) + var/list/cached_reagents = holder.reagent_list var/num_of_reagents = cached_reagents.len if(!num_of_reagents)//I've never seen it get here with 0, but in case - it gets here when it blows up from overheat - stack_trace("No reactants found mid reaction for [C.type]. Beaker: [holder.my_atom]") + stack_trace("No reactants found mid reaction for [reaction.type]. Beaker: [holder.my_atom]") return 0 //we exploded and cleared reagents - but lets not kill the process var/cached_purity diff --git a/code/modules/reagents/withdrawal/generic_addictions.dm b/code/modules/reagents/withdrawal/generic_addictions.dm index b42345ae97d..4eabfa1095a 100644 --- a/code/modules/reagents/withdrawal/generic_addictions.dm +++ b/code/modules/reagents/withdrawal/generic_addictions.dm @@ -74,8 +74,8 @@ /datum/addiction/hallucinogens/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) . = ..() var/atom/movable/plane_master_controller/game_plane_master_controller = affected_carbon.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] - game_plane_master_controller.add_filter("hallucinogen_wave", 10, wave_filter(300, 300, 3, 0, WAVE_SIDEWAYS)) game_plane_master_controller.add_filter("hallucinogen_blur", 10, angular_blur_filter(0, 0, 3)) + game_plane_master_controller.add_filter("hallucinogen_wave", 10, wave_filter(300, 300, 3, 0, WAVE_SIDEWAYS)) /datum/addiction/hallucinogens/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index f43e33aa25a..bd063dea439 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -317,8 +317,8 @@ var/atom/movable/plane_master_controller/game_plane_master_controller = owner.hud_used?.plane_master_controllers[PLANE_MASTERS_GAME] if(!game_plane_master_controller) return FALSE - game_plane_master_controller.add_filter("psychic_wave", 10, wave_filter(240, 240, 3, 0, WAVE_SIDEWAYS)) game_plane_master_controller.add_filter("psychic_blur", 10, angular_blur_filter(0, 0, 3)) + game_plane_master_controller.add_filter("psychic_wave", 10, wave_filter(240, 240, 3, 0, WAVE_SIDEWAYS)) return TRUE /datum/status_effect/psychic_projection/on_remove() diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index c657e89cefd..2031ea4c723 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -227,7 +227,7 @@ if(bodypart_disabled) owner.set_usable_hands(owner.usable_hands - 1) if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) + to_chat(owner, span_userdanger("You lose control of your [plaintext_zone]!")) if(held_index) owner.dropItemToGround(owner.get_item_for_held_index(held_index)) else if(!bodypart_disabled) @@ -324,7 +324,7 @@ if(bodypart_disabled) owner.set_usable_hands(owner.usable_hands - 1) if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) + to_chat(owner, span_userdanger("You lose control of your [plaintext_zone]!")) if(held_index) owner.dropItemToGround(owner.get_item_for_held_index(held_index)) else if(!bodypart_disabled) @@ -443,7 +443,7 @@ if(bodypart_disabled) owner.set_usable_legs(owner.usable_legs - 1) if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) + to_chat(owner, span_userdanger("You lose control of your [plaintext_zone]!")) else if(!bodypart_disabled) owner.set_usable_legs(owner.usable_legs + 1) @@ -532,7 +532,7 @@ if(bodypart_disabled) owner.set_usable_legs(owner.usable_legs - 1) if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) + to_chat(owner, span_userdanger("You lose control of your [plaintext_zone]!")) else if(!bodypart_disabled) owner.set_usable_legs(owner.usable_legs + 1) diff --git a/code/modules/surgery/organs/external/_external_organ.dm b/code/modules/surgery/organs/external/_external_organ.dm index 5b9f9d67347..23b74ef9b4e 100644 --- a/code/modules/surgery/organs/external/_external_organ.dm +++ b/code/modules/surgery/organs/external/_external_organ.dm @@ -57,6 +57,15 @@ if(restyle_flags) RegisterSignal(src, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle)) +/obj/item/organ/external/Insert(mob/living/carbon/receiver, special, movement_flags) + . = ..() + receiver.update_body_parts() + +/obj/item/organ/external/Remove(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + if(!special) + organ_owner.update_body_parts() + /obj/item/organ/external/mob_insert(mob/living/carbon/receiver, special, movement_flags) if(!should_external_organ_apply_to(type, receiver)) stack_trace("adding a [type] to a [receiver.type] when it shouldn't be!") diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 86bc8c800a1..d632246500b 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -13,37 +13,27 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/spines - ///A two-way reference between the tail and the spines because of wagging sprites. Bruh. - var/obj/item/organ/external/tail/lizard/paired_tail - /obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, movement_flags) - . = ..() - if(.) - paired_tail = locate(/obj/item/organ/external/tail/lizard) in receiver.organs //We want specifically a lizard tail, so we don't use the slot. - paired_tail?.paired_spines = src + // If we have a tail, attempt to add a tail spines overlay + var/obj/item/organ/external/tail/our_tail = receiver.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + our_tail?.try_insert_tail_spines(our_tail.bodypart_owner) + return ..() /obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, movement_flags) - . = ..() - if(paired_tail) - paired_tail.paired_spines = null - paired_tail = null + // If we have a tail, remove any tail spines overlay + var/obj/item/organ/external/tail/our_tail = organ_owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + our_tail?.remove_tail_spines(our_tail.bodypart_owner) + return ..() -///Bodypart overlay for spines (wagging gets updated by tail) +///Bodypart overlay for spines /datum/bodypart_overlay/mutant/spines layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND feature_key = "spines" - ///Spines moth with the tail, so track it - var/wagging = FALSE /datum/bodypart_overlay/mutant/spines/get_global_feature_list() return GLOB.sprite_accessories["spines"] // NOVA EDIT - Customization - ORIGINAL: return GLOB.spines_list -/datum/bodypart_overlay/mutant/spines/get_base_icon_state() - return (wagging ? "wagging_" : "") + sprite_datum.icon_state //add the wagging tag if we be wagging - - /datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(mob/living/carbon/human/human) . = ..() if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT)) return FALSE - diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 5c620eea161..1e8cf71b5f0 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -17,6 +17,8 @@ var/wag_flags = NONE ///The original owner of this tail var/original_owner //Yay, snowflake code! + ///The overlay for tail spines, if any + var/datum/bodypart_overlay/mutant/tail_spines/tail_spines_overlay /obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() @@ -32,6 +34,42 @@ else if(type in receiver.dna.species.external_organs) receiver.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) +/obj/item/organ/external/tail/on_bodypart_insert(obj/item/bodypart/bodypart) + var/obj/item/organ/external/spines/our_spines = bodypart.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) + if(our_spines) + try_insert_tail_spines(bodypart) + return ..() + +/obj/item/organ/external/tail/on_bodypart_remove(obj/item/bodypart/bodypart) + remove_tail_spines(bodypart) + return ..() + +/// If the owner has spines and an appropriate overlay exists, add a tail spines overlay. +/obj/item/organ/external/tail/proc/try_insert_tail_spines(obj/item/bodypart/bodypart) + // Don't insert another overlay if there already is one. + if(tail_spines_overlay) + return + // If this tail doesn't have a valid set of tail spines, don't insert them + var/datum/sprite_accessory/tails/tail_sprite_datum = bodypart_overlay.sprite_datum + if(!istype(tail_sprite_datum)) + return + var/tail_spine_key = tail_sprite_datum.spine_key + if(!tail_spine_key) + return + + tail_spines_overlay = new + tail_spines_overlay.tail_spine_key = tail_spine_key + var/feature_name = bodypart.owner.dna.mutant_bodyparts["spines"][MUTANT_INDEX_NAME] // NOVA EDIT CHANGE - ORIGINAL: var/feature_name = bodypart.owner.dna.features["spines"] //tail spines don't live in DNA, but share feature names with regular spines + tail_spines_overlay.set_appearance_from_dna(bodypart.owner.dna, feature_name, feature_key = "spines") // NOVA EDIT CHANGE - ORIGINAL: tail_spines_overlay.set_appearance_from_name(feature_name) + bodypart.add_bodypart_overlay(tail_spines_overlay) + +/// If we have a tail spines overlay, delete it +/obj/item/organ/external/tail/proc/remove_tail_spines(obj/item/bodypart/bodypart) + if(!tail_spines_overlay) + return + bodypart.remove_bodypart_overlay(tail_spines_overlay) + QDEL_NULL(tail_spines_overlay) + /obj/item/organ/external/tail/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() @@ -64,6 +102,8 @@ var/datum/bodypart_overlay/mutant/tail/accessory = bodypart_overlay wag_flags |= WAG_WAGGING accessory.wagging = TRUE + if(tail_spines_overlay) //if there are spines, they should wag with the tail + tail_spines_overlay.wagging = TRUE organ_owner.update_body_parts() RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(stop_wag)) return TRUE @@ -75,6 +115,8 @@ var/datum/bodypart_overlay/mutant/tail/accessory = bodypart_overlay wag_flags &= ~WAG_WAGGING accessory.wagging = FALSE + if(tail_spines_overlay) //if there are spines, they should stop wagging with the tail + tail_spines_overlay.wagging = FALSE if(isnull(organ_owner)) return @@ -135,32 +177,7 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/tail/lizard wag_flags = WAG_ABLE - ///A reference to the paired_spines, since for some fucking reason tail spines are tied to the spines themselves. - var/obj/item/organ/external/spines/paired_spines - -/obj/item/organ/external/tail/lizard/Insert(mob/living/carbon/receiver, special, movement_flags) - . = ..() - if(.) - paired_spines = bodypart_owner.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) - paired_spines?.paired_tail = src - -/obj/item/organ/external/tail/lizard/Remove(mob/living/carbon/organ_owner, special, movement_flags) - . = ..() - if(paired_spines) - paired_spines.paired_tail = null - paired_spines = null - -/obj/item/organ/external/tail/lizard/start_wag() - if(paired_spines) - var/datum/bodypart_overlay/mutant/spines/accessory = paired_spines.bodypart_overlay - accessory.wagging = TRUE - return ..() - -/obj/item/organ/external/tail/lizard/stop_wag() - if(paired_spines) - var/datum/bodypart_overlay/mutant/spines/accessory = paired_spines.bodypart_overlay - accessory.wagging = FALSE - return ..() + //dna_block = DNA_LIZARD_TAIL_BLOCK // NOVA EDIT REMOVAL - Customization - We have our own system to handle DNA. ///Lizard tail bodypart overlay datum /datum/bodypart_overlay/mutant/tail/lizard @@ -172,3 +189,23 @@ /obj/item/organ/external/tail/lizard/fake name = "fabricated lizard tail" desc = "A fabricated severed lizard tail. This one's made of synthflesh. Probably not usable for lizard wine." + +///Bodypart overlay for tail spines. Handled by the tail - has no actual organ associated. +/datum/bodypart_overlay/mutant/tail_spines + layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND + feature_key = "tailspines" + ///Spines wag when the tail does + var/wagging = FALSE + /// Key for tail spine states, depends on the shape of the tail. Defined in the tail sprite datum. + var/tail_spine_key = NONE + +/datum/bodypart_overlay/mutant/tail_spines/get_global_feature_list() + return GLOB.sprite_accessories["tailspines"] // NOVA EDIT CHANGE - ORIGINAL: return GLOB.tail_spines_list + +/datum/bodypart_overlay/mutant/tail_spines/get_base_icon_state() + return (!isnull(tail_spine_key) ? "[tail_spine_key]_" : "") + (wagging ? "wagging_" : "") + sprite_datum.icon_state // Select the wagging state if appropriate + +/datum/bodypart_overlay/mutant/tail_spines/can_draw_on_bodypart(mob/living/carbon/human/human) + . = ..() + if(human.wear_suit && (human.wear_suit.flags_inv & HIDEJUMPSUIT)) + return FALSE diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index 884f3a9043d..a447b508c71 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -310,7 +310,7 @@ /datum/action/cooldown/golem_ore_sight/Activate(atom/target) . = ..() - mineral_scan_pulse(get_turf(target), scanner = src) + mineral_scan_pulse(get_turf(target), scanner = target) ///Robotic diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm index 757fe67d81e..22027a3cf8e 100644 --- a/code/modules/tooltip/tooltip.dm +++ b/code/modules/tooltip/tooltip.dm @@ -107,22 +107,22 @@ Notes: //Open a tooltip for user, at a location based on params //Theme is a CSS class in tooltip.html, by default this wrapper chooses a CSS class based on the user's UI_style (Midnight, Plasmafire, Retro, etc) //Includes sanity.checks -/proc/openToolTip(mob/user = null, atom/movable/tip_src = null, params = null,title = "",content = "",theme = "") - if(istype(user)) - if(user.client && user.client.tooltips) - var/ui_style = user.client?.prefs?.read_preference(/datum/preference/choiced/ui_style) - if(!theme && ui_style) - theme = lowertext(ui_style) - if(!theme) - theme = "default" - user.client.tooltips.show(tip_src, params,title,content,theme) +/proc/openToolTip(mob/user = null, atom/movable/tip_src = null, params = null, title = "", content = "", theme = "") + if(!istype(user) || !user.client?.tooltips) + return + var/ui_style = user.client?.prefs?.read_preference(/datum/preference/choiced/ui_style) + if(!theme && ui_style) + theme = lowertext(ui_style) + if(!theme) + theme = "default" + user.client.tooltips.show(tip_src, params, title, content, theme) //Arbitrarily close a user's tooltip //Includes sanity checks. /proc/closeToolTip(mob/user) - if(istype(user)) - if(user.client && user.client.tooltips) - user.client.tooltips.hide() + if(!istype(user) || !user.client?.tooltips) + return + user.client.tooltips.hide() diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_snail.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_snail.png index a9e62a2ac8d..f699cf7b702 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_snail.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_snail.png differ diff --git a/code/modules/unit_tests/station_trait_tests.dm b/code/modules/unit_tests/station_trait_tests.dm index 430e83b9af7..21173e152d7 100644 --- a/code/modules/unit_tests/station_trait_tests.dm +++ b/code/modules/unit_tests/station_trait_tests.dm @@ -6,5 +6,7 @@ for(var/datum/job/job as anything in subtypesof(/datum/job)) if(!(initial(job.job_flags) & JOB_CREW_MEMBER)) continue + if((initial(job.job_flags) & STATION_TRAIT_JOB_FLAGS) == STATION_TRAIT_JOB_FLAGS) + continue if(!(job in cyber_trait.job_to_cybernetic)) TEST_FAIL("Job [job] does not have an assigned cybernetic for [cyber_trait.type] station trait.") diff --git a/code/modules/uplink/uplink_items/contractor.dm b/code/modules/uplink/uplink_items/contractor.dm index 1364f8b088b..b774d05e59d 100644 --- a/code/modules/uplink/uplink_items/contractor.dm +++ b/code/modules/uplink/uplink_items/contractor.dm @@ -82,28 +82,9 @@ cost = 1 /datum/uplink_item/contractor/partner - name = "Reinforcements" - desc = "Upon purchase we'll contact available units in the area. Should there be an agent free, \ - we'll send them down to assist you immediately. If no units are free, we give a full refund." - item = /obj/effect/gibspawner/generic + name = "Contractor Reinforcement" + desc = "A reinforecment operative will be sent to aid you in your goals, \ + they are paid separately, and will not take a cut from your profits." + item = /obj/item/antag_spawner/loadout/contractor limited_stock = 1 cost = 2 - -/datum/uplink_item/contractor/partner/spawn_item(spawn_path, mob/user, datum/uplink_handler/uplink_handler, atom/movable/source) - to_chat(user, span_notice("The uplink vibrates quietly, connecting to nearby agents...")) - var/list/candidates = SSpolling.poll_ghost_candidates( - question = "Do you want to play as the Contractor Support Unit for [user.real_name]?", - check_jobban = ROLE_TRAITOR, - role = ROLE_TRAITOR, - poll_time = 10 SECONDS, - ignore_category = POLL_IGNORE_CONTRACTOR_SUPPORT, - pic_source = /obj/item/modular_computer/pda/syndicate_contract_uplink, - role_name_text = "contractor support unit", - ) - if(!LAZYLEN(candidates)) - to_chat(user, span_notice("No available agents at this time, please try again later.")) - limited_stock++ - return //bobux no icon - var/mob/dead/observer/selected_player = pick(candidates) - uplink_handler.contractor_hub.contractor_teammate = spawn_contractor_partner(user, selected_player.key) - return source //for log icon diff --git a/html/changelogs/AutoChangeLog-pr-1641.yml b/html/changelogs/AutoChangeLog-pr-1641.yml new file mode 100644 index 00000000000..a60b7438983 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1641.yml @@ -0,0 +1,10 @@ +author: "Paxilmaniac" +delete-after: True +changes: + - rscadd: "Cargo, and the rapid construction fabricator, are now hosts to a new source of power. The stirling generator, operating something like the old TEG, creates power from large differences in temperature. Handy!" + - rscadd: "A variety of special kitchen machines have been created for the rapid construction fabricator. While they might not perform *too* much different from their standard counterparts, they are easier to move around and can be printed whole." + - rscadd: "Three new crates have been added to cargo, each one featuring a bundle of frontier equipment. In the service tab, kits for frontier kitchens and botany chemical synthesizers can be found. In the engineering tab, the colony starter kit can be found." + - qol: "Many flatpack machines that were needlessly large have been made normal sized, meaning they fit inside of backpacks now!" + - bugfix: "A large number of flatpack machines that were missing custom materials now have them, meaning they can now be recycled as well." + - image: "New sprites for all the new machines and whatnot made by me" + - spellcheck: "Every instance of Flat-packed has been changed to Flat-Packed where appropriate" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1653.yml b/html/changelogs/AutoChangeLog-pr-1653.yml new file mode 100644 index 00000000000..12f0d258a2f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1653.yml @@ -0,0 +1,4 @@ +author: "JohnFulpWillard" +delete-after: True +changes: + - bugfix: "Moved the curator's treasure hunter fedora up by a single pixel." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1654.yml b/html/changelogs/AutoChangeLog-pr-1654.yml new file mode 100644 index 00000000000..458aab740aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1654.yml @@ -0,0 +1,5 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "reactions that create multiple reagents now terminate without looping endlessly." + - bugfix: "oatmeal reactions now terminate & produce the right quantity of results but without milk." \ No newline at end of file diff --git a/html/changelogs/archive/2024-01.yml b/html/changelogs/archive/2024-01.yml index b019e1f06d6..ba77039d595 100644 --- a/html/changelogs/archive/2024-01.yml +++ b/html/changelogs/archive/2024-01.yml @@ -820,3 +820,52 @@ been reduced to 15% from 50%. - rscadd: The messaging for both the hemophage and the victim during blood draining is now much more informative. +2024-01-24: + 00-Steven: + - sound: APCs actually play the tool sound when exposing their wires. + A.C.M.O.: + - rscadd: Added the forked cybernetic tongue to Augments+. + - rscadd: Added the robotic lizard voicebox to Augments+ and the RoboDrobe vendor. + Ghommie: + - bugfix: Goldgrubs should no longer spit out things that aren't ore (e.g. stasised + mobs from the polymorph belt). + Lutowski: + - rscadd: Fluffier than ever before, moths can now have hair & facial hair. + Nerev4r, Vol: + - rscadd: A new jacket option for Security has appeared in the loadout and their + vendors. + Paxilmaniac: + - image: A single missing frame from the prefab shutter closing animation has been + re-placed, meaning they wont vanish for 1/10 of a second whenever closing + - bugfix: Plastic wall panels, as well as prefab floor tiles have been fixed to + not eat way more materials than they should be + - rscdel: The milsim domain's one clf3 grenade is gone + - balance: The equipment that the bitrunners get in the milsim domain has been changed, + mostly to use the new-ish solfed gear rather than HECU stuff + - bugfix: The wylom in the milsim domain on the bitrunner side has been given its + actual magazines around it, rather than lanca magazines + - rscadd: Hunter shotgun slugs can now mine mineral walls, shotgun mining time baby. + - bugfix: Hunter slugs and .60 AMR ammo will now properly do extra damage to the + biotypes they are strong against. + nikothedude: + - bugfix: Synth wound oscillations will no longer cause you to reel from impacts + if there were no impacts + - balance: Synth blunt wounds are now faster to treat + - balance: Wirecutters on electrical damage have been streamlined and are always + fix 4x more than suturing + - balance: Synth wound oscillations now have a minimum of 3 seconds between each + oscillation + scriptis: + - spellcheck: iron sheets's what? + vinylspiders: + - bugfix: fixed ammo counter hud not updating for self-recharging energy weapons + - bugfix: fixes features not updating when changing character slots + yooriss: + - rscadd: A bunch of new stuff has been added to the loadout tab, such as civil + defense & frontier medkits, a ton of Kahraman frontier clothing, wheely-heels + and in-hand empty gun cases! MODlink scryers are also now available as a pocket + slot option too, so you can video-call your friends with a scarf. + - bugfix: Holobadges are now accessible from both the neck and accessory loadout + slots (since they fit in both). + - bugfix: Prisoners joining a round now properly have their implants removed as + intended. diff --git a/icons/hud/lobby/signup_button.dmi b/icons/hud/lobby/signup_button.dmi new file mode 100644 index 00000000000..a67cc558442 Binary files /dev/null and b/icons/hud/lobby/signup_button.dmi differ diff --git a/icons/mob/clothing/head/hats.dmi b/icons/mob/clothing/head/hats.dmi index 3477cb1820a..0fd0de8e425 100644 Binary files a/icons/mob/clothing/head/hats.dmi and b/icons/mob/clothing/head/hats.dmi differ diff --git a/icons/mob/huds/hud.dmi b/icons/mob/huds/hud.dmi index 3e32e17437c..3dff7642a96 100644 Binary files a/icons/mob/huds/hud.dmi and b/icons/mob/huds/hud.dmi differ diff --git a/icons/mob/human/species/lizard/lizard_spines.dmi b/icons/mob/human/species/lizard/lizard_spines.dmi index 82eb636b339..5112c8a0a6e 100644 Binary files a/icons/mob/human/species/lizard/lizard_spines.dmi and b/icons/mob/human/species/lizard/lizard_spines.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index fdf3657c9d1..6397cf6fb5b 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/modular_nova/master_files/code/_globalvars/text.dm b/modular_nova/master_files/code/_globalvars/text.dm index f730a8ff817..3517f458fea 100644 --- a/modular_nova/master_files/code/_globalvars/text.dm +++ b/modular_nova/master_files/code/_globalvars/text.dm @@ -7,3 +7,10 @@ input_text = replacetext(input_text, GLOB.noncapital_i, "I") return input_text + +/// Ensures text does not start with capital letters. +/proc/lowercase_title(input_text) + if (!input_text) + return input_text + var/start = lowertext(input_text[1]) + return splicetext(input_text, 1, 2, start) diff --git a/modular_nova/master_files/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/modular_nova/master_files/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 3fcf2bbe707..1a86afbea05 100644 --- a/modular_nova/master_files/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/modular_nova/master_files/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -27,10 +27,14 @@ * * Arguments: * * dna - The `/datum/dna` datum from which we're going to be extracting the data to set the + * * accessory_name - instead of using the name from mutant_bodyparts[feature_key][MUTANT_INDEX_NAME] you can optionally pass one explicitly + * * feature_key - same as with accessory_key, you can optionally pass a feature_key explicitly * appearance. */ -/datum/bodypart_overlay/mutant/proc/set_appearance_from_dna(datum/dna/dna) - sprite_datum = fetch_sprite_datum_from_name(dna.mutant_bodyparts[feature_key][MUTANT_INDEX_NAME]) +/datum/bodypart_overlay/mutant/proc/set_appearance_from_dna(datum/dna/dna, accessory_name, feature_key) + if(isnull(feature_key)) // if not explicitly set, just use the feature_key of the bodypart_overlay + feature_key = src.feature_key + sprite_datum = fetch_sprite_datum_from_name(accessory_name ? accessory_name : dna.mutant_bodyparts[feature_key][MUTANT_INDEX_NAME]) modsuit_affected = sprite_datum.use_custom_mod_icon draw_color = dna.mutant_bodyparts[feature_key][MUTANT_INDEX_COLOR_LIST] build_emissive_eligibility(dna.mutant_bodyparts[feature_key][MUTANT_INDEX_EMISSIVE_LIST]) diff --git a/modular_nova/master_files/code/datums/quirks/negative_quirks/narcolepsy.dm b/modular_nova/master_files/code/datums/quirks/negative_quirks/narcolepsy.dm index 424295157c8..3807f65264f 100644 --- a/modular_nova/master_files/code/datums/quirks/negative_quirks/narcolepsy.dm +++ b/modular_nova/master_files/code/datums/quirks/negative_quirks/narcolepsy.dm @@ -16,9 +16,9 @@ var/mob/living/carbon/human/user = quirk_holder user.gain_trauma(/datum/brain_trauma/severe/narcolepsy/permanent, TRAUMA_RESILIENCE_ABSOLUTE) - var/obj/item/storage/pill_bottle/prescription_stimulant/stimmies = new() + var/obj/item/storage/medkit/civil_defense/comfort/stocked/stimmies = new() if(quirk_holder.equip_to_slot_if_possible(stimmies, ITEM_SLOT_BACKPACK, qdel_on_fail = TRUE, initial = TRUE, indirect_action = TRUE)) - to_chat(quirk_holder, span_info("You have been given a bottle of mild stimulants to assist in staying awake this shift...")) + to_chat(quirk_holder, span_info("You have been given a company-issued symptom support kit containing mild stimulants to assist in staying awake this shift. Dose responsibly. Consult your allocated care provider if you experience any side-effects.")) /datum/quirk/narcolepsy/remove() . = ..() @@ -52,17 +52,3 @@ else if(drowsy && SPT_PROB(sleep_chance, seconds_per_tick)) to_chat(owner, span_warning("You fall asleep.")) owner.Sleeping(rand(20 SECONDS, 30 SECONDS)) - -/obj/item/storage/pill_bottle/prescription_stimulant - name = "bottle of prescribed stimulant pills" - desc = "A bottle of mild and medicinally approved stimulants to help prevent drowsiness." - -/obj/item/storage/pill_bottle/prescription_stimulant/PopulateContents() - for(var/i in 1 to 5) - new /obj/item/reagent_containers/pill/prescription_stimulant(src) - -/obj/item/reagent_containers/pill/prescription_stimulant - name = "prescription stimulant pill" - desc = "Used to treat symptoms of drowsiness and sudden loss of consciousness. A warning label reads: Take in moderation." - list_reagents = list(/datum/reagent/consumable/sugar = 5, /datum/reagent/medicine/synaptizine = 5, /datum/reagent/medicine/modafinil = 3) - icon_state = "pill15" diff --git a/modular_nova/master_files/code/datums/quirks/positive_quirks/spacer.dm b/modular_nova/master_files/code/datums/quirks/positive_quirks/spacer.dm new file mode 100644 index 00000000000..ac2cb947ddb --- /dev/null +++ b/modular_nova/master_files/code/datums/quirks/positive_quirks/spacer.dm @@ -0,0 +1,8 @@ +// Make spacer's gravity wellness effect visible so players know something is happening. +/datum/status_effect/spacer/gravity_wellness + alert_type = /atom/movable/screen/alert/status_effect/gravity_wellness + +/atom/movable/screen/alert/status_effect/gravity_wellness + name = "Gravity Wellness" + desc = "Your physiology thrives in low-gravity conditions: you catch your breath quicker and are more mobile." + icon_state = "negative" diff --git a/modular_nova/master_files/code/modules/antagonists/pirate/pirate_gang.dm b/modular_nova/master_files/code/modules/antagonists/pirate/pirate_gang.dm new file mode 100644 index 00000000000..fc05a926507 --- /dev/null +++ b/modular_nova/master_files/code/modules/antagonists/pirate/pirate_gang.dm @@ -0,0 +1,4 @@ +// Override for Pirates for lore or policy reasons +// Interdyne isnt a hostile faction in current lore, balance reasons aside +/datum/pirate_gang/interdyne/can_roll() + return FALSE diff --git a/modular_nova/master_files/code/modules/clothing/back/antigravityharness.dm b/modular_nova/master_files/code/modules/clothing/back/antigravityharness.dm index a75b6c1b5c8..d0f8cae6d43 100644 --- a/modular_nova/master_files/code/modules/clothing/back/antigravityharness.dm +++ b/modular_nova/master_files/code/modules/clothing/back/antigravityharness.dm @@ -101,6 +101,7 @@ user.RemoveElement(/datum/element/forced_gravity, 0) REMOVE_TRAIT(user, TRAIT_NEGATES_GRAVITY, CLOTHING_TRAIT) + var/datum/quirk/spacer_born/spacer = user.get_quirk(/datum/quirk/spacer_born) switch(target_mode) if(MODE_ANTIGRAVITY) mode = MODE_ANTIGRAVITY @@ -115,6 +116,10 @@ icon_state = ANTIGRAVITY_STATE worn_icon_state = ANTIGRAVITY_STATE + //are we a spacer? if so, let the quirk know we're back in low gravity conditions + if (!isnull(spacer)) + spacer.in_space(user) + if(MODE_EXTRAGRAVITY) mode = MODE_EXTRAGRAVITY @@ -128,6 +133,10 @@ icon_state = EXTRAGRAVITY_STATE worn_icon_state = EXTRAGRAVITY_STATE + //are we a spacer? if so, let the quirk know we're in extremely uncomfortable extragrav + if (!isnull(spacer)) + spacer.on_planet(user) + if(MODE_GRAVOFF) if(!user.has_gravity() && mode != MODE_GRAVOFF) new /obj/effect/temp_visual/mook_dust/robot(get_turf(src)) @@ -145,6 +154,10 @@ icon_state = OFF_STATE worn_icon_state = OFF_STATE + //are we a spacer? if so, make the quirk assert the correct condition based on where we are + if (!isnull(spacer)) + spacer.check_z(user) + else return FALSE @@ -153,7 +166,6 @@ return TRUE - /obj/item/gravity_harness/dropped(mob/user) . = ..() change_mode(MODE_GRAVOFF) @@ -164,6 +176,7 @@ /obj/item/gravity_harness/attack_self(mob/user) toggle_mode(user, TRUE) + /// This outputs the harness's current mode and cell charge to your status tab, so you don't need to examine it every time. /obj/item/gravity_harness/proc/get_status_tab_item(mob/living/source, list/items) SIGNAL_HANDLER diff --git a/modular_nova/master_files/code/modules/jobs/prisoner.dm b/modular_nova/master_files/code/modules/jobs/prisoner.dm new file mode 100644 index 00000000000..0b9a4c40bd2 --- /dev/null +++ b/modular_nova/master_files/code/modules/jobs/prisoner.dm @@ -0,0 +1,15 @@ +/datum/outfit/job/prisoner/post_equip(mob/living/carbon/human/new_prisoner, visualsOnly) + . = ..() + + var/implants_removed = 0 + var/implants_total = 0 + + for(var/obj/item/organ/internal/cyberimp/cybernetic in new_prisoner.organs) + implants_total += 1 + if (cybernetic.cannot_confiscate) + continue + QDEL_NULL(cybernetic) + implants_removed += 1 + + if (implants_removed >= 1) + to_chat(new_prisoner, span_warning("[(implants_total > implants_removed) ? "Some of your" : "Your"] implants have been confiscated as part of your sentence.")) diff --git a/modular_nova/master_files/code/modules/projectiles/guns/energy/recharge.dm b/modular_nova/master_files/code/modules/projectiles/guns/energy/recharge.dm new file mode 100644 index 00000000000..26fdfce3037 --- /dev/null +++ b/modular_nova/master_files/code/modules/projectiles/guns/energy/recharge.dm @@ -0,0 +1,4 @@ +// self-reloading weapons need their ammo hud updated whenever reload() is called +/obj/item/gun/energy/recharge/reload() + . = ..() + SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) diff --git a/modular_nova/master_files/code/modules/research/designs/medical_designs.dm b/modular_nova/master_files/code/modules/research/designs/medical_designs.dm index 7798c4cd43a..c2beb545386 100644 --- a/modular_nova/master_files/code/modules/research/designs/medical_designs.dm +++ b/modular_nova/master_files/code/modules/research/designs/medical_designs.dm @@ -14,3 +14,9 @@ RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_ORGANS_1, ) departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + +/datum/design/cybernetic_tongue/lizard + name = "Forked Cybernetic Tongue" + desc = "A forked cybernetic tongue." + id = "cybernetic_tongue_lizard" + build_path = /obj/item/organ/internal/tongue/lizard/cybernetic diff --git a/modular_nova/master_files/code/modules/research/techweb/all_nodes.dm b/modular_nova/master_files/code/modules/research/techweb/all_nodes.dm index 5ee944941e9..725f55c64ad 100644 --- a/modular_nova/master_files/code/modules/research/techweb/all_nodes.dm +++ b/modular_nova/master_files/code/modules/research/techweb/all_nodes.dm @@ -140,6 +140,7 @@ /datum/techweb_node/cyber_organs/New() design_ids += list( "cybernetic_tongue", + "cybernetic_tongue_lizard", ) return ..() diff --git a/modular_nova/master_files/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/modular_nova/master_files/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm new file mode 100644 index 00000000000..c17bd25da42 --- /dev/null +++ b/modular_nova/master_files/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -0,0 +1,3 @@ +/obj/item/organ/internal/cyberimp + /// If TRUE, this augment cannot be confiscated at roundstart for roles like prisoner, etc. + var/cannot_confiscate diff --git a/modular_nova/master_files/icons/hud/lobby/bottom_buttons.dmi b/modular_nova/master_files/icons/hud/lobby/bottom_buttons.dmi deleted file mode 100644 index 990a6d1bc17..00000000000 Binary files a/modular_nova/master_files/icons/hud/lobby/bottom_buttons.dmi and /dev/null differ diff --git a/modular_nova/master_files/icons/mob/64x64_lefthand.dmi b/modular_nova/master_files/icons/mob/64x64_lefthand.dmi index 70ac1d387c1..2197d194135 100644 Binary files a/modular_nova/master_files/icons/mob/64x64_lefthand.dmi and b/modular_nova/master_files/icons/mob/64x64_lefthand.dmi differ diff --git a/modular_nova/master_files/icons/mob/64x64_righthand.dmi b/modular_nova/master_files/icons/mob/64x64_righthand.dmi index f92f3e53470..aee16d66d54 100644 Binary files a/modular_nova/master_files/icons/mob/64x64_righthand.dmi and b/modular_nova/master_files/icons/mob/64x64_righthand.dmi differ diff --git a/modular_nova/master_files/icons/mob/clothing/back.dmi b/modular_nova/master_files/icons/mob/clothing/back.dmi index 4e8d6bc375f..0fd5d84f1e6 100644 Binary files a/modular_nova/master_files/icons/mob/clothing/back.dmi and b/modular_nova/master_files/icons/mob/clothing/back.dmi differ diff --git a/modular_nova/master_files/icons/mob/clothing/species/teshari/suit.dmi b/modular_nova/master_files/icons/mob/clothing/species/teshari/suit.dmi index e4db1a1654e..5420cf652e8 100644 Binary files a/modular_nova/master_files/icons/mob/clothing/species/teshari/suit.dmi and b/modular_nova/master_files/icons/mob/clothing/species/teshari/suit.dmi differ diff --git a/modular_nova/master_files/icons/mob/clothing/suits/armor.dmi b/modular_nova/master_files/icons/mob/clothing/suits/armor.dmi index 9d6de8b7cfc..fc894643f6d 100644 Binary files a/modular_nova/master_files/icons/mob/clothing/suits/armor.dmi and b/modular_nova/master_files/icons/mob/clothing/suits/armor.dmi differ diff --git a/modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi b/modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi new file mode 100644 index 00000000000..00521501d08 Binary files /dev/null and b/modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi differ diff --git a/modular_nova/master_files/icons/mob/sprite_accessory/lizard_spines.dmi b/modular_nova/master_files/icons/mob/sprite_accessory/lizard_spines.dmi deleted file mode 100644 index eaadb820ebc..00000000000 Binary files a/modular_nova/master_files/icons/mob/sprite_accessory/lizard_spines.dmi and /dev/null differ diff --git a/modular_nova/master_files/icons/mob/sprite_accessory/vox_spines.dmi b/modular_nova/master_files/icons/mob/sprite_accessory/vox_spines.dmi index 10547f6db8d..d446399dc93 100644 Binary files a/modular_nova/master_files/icons/mob/sprite_accessory/vox_spines.dmi and b/modular_nova/master_files/icons/mob/sprite_accessory/vox_spines.dmi differ diff --git a/modular_nova/master_files/icons/obj/clothing/suits/armor.dmi b/modular_nova/master_files/icons/obj/clothing/suits/armor.dmi index 948d2d783ed..bbc57992f1e 100644 Binary files a/modular_nova/master_files/icons/obj/clothing/suits/armor.dmi and b/modular_nova/master_files/icons/obj/clothing/suits/armor.dmi differ diff --git a/modular_nova/master_files/icons/obj/clothing/suits/jacket.dmi b/modular_nova/master_files/icons/obj/clothing/suits/jacket.dmi new file mode 100644 index 00000000000..ace9238ecd2 Binary files /dev/null and b/modular_nova/master_files/icons/obj/clothing/suits/jacket.dmi differ diff --git a/modular_nova/master_files/icons/obj/kinetic_glaive.dmi b/modular_nova/master_files/icons/obj/kinetic_glaive.dmi index ae0bbdb0625..407ae6bf135 100644 Binary files a/modular_nova/master_files/icons/obj/kinetic_glaive.dmi and b/modular_nova/master_files/icons/obj/kinetic_glaive.dmi differ diff --git a/modular_nova/modules/GAGS/greyscale_configs.dm b/modular_nova/modules/GAGS/greyscale_configs.dm index 7134068f9a0..390c7baeae4 100644 --- a/modular_nova/modules/GAGS/greyscale_configs.dm +++ b/modular_nova/modules/GAGS/greyscale_configs.dm @@ -800,12 +800,16 @@ /datum/greyscale_config/croptop name = "Croptop Sweater" - icon_file = 'modular_nova/master_files/icons/mob/clothing/suit.dmi' + icon_file = 'modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi' json_config = 'modular_nova/modules/GAGS/json_configs/suits/croptop/croptop.json' /datum/greyscale_config/croptop/worn name = "Croptop Sweater (Worn)" - json_config = 'modular_nova/modules/GAGS/json_configs/suits/croptop/croptop_worn.json' + icon_file = 'modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi' + +/datum/greyscale_config/croptop/worn/teshari + name = "Croptop Sweater (Worn, Teshari)" + icon_file = 'modular_nova/master_files/icons/mob/clothing/species/teshari/suit.dmi' // TAILORED JACKET diff --git a/modular_nova/modules/GAGS/json_configs/suits/croptop/croptop_worn.json b/modular_nova/modules/GAGS/json_configs/suits/croptop/croptop_worn.json deleted file mode 100644 index 2fd05c399e1..00000000000 --- a/modular_nova/modules/GAGS/json_configs/suits/croptop/croptop_worn.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "croptop": [ - { - "type": "icon_state", - "icon_state": "croptop", - "blend_mode": "overlay", - "color_ids": [ 1 ] - } - ] -} diff --git a/modular_nova/modules/bitrunning/code/virtual_domains/ancient_milsim/outfit.dm b/modular_nova/modules/bitrunning/code/virtual_domains/ancient_milsim/outfit.dm index 1811071c5b0..e722c857862 100644 --- a/modular_nova/modules/bitrunning/code/virtual_domains/ancient_milsim/outfit.dm +++ b/modular_nova/modules/bitrunning/code/virtual_domains/ancient_milsim/outfit.dm @@ -1,13 +1,13 @@ /datum/outfit/solfed_bitrun name = "Bitrunning SolFed Marine" - uniform = /obj/item/clothing/under/rank/security/officer/hecu + uniform = /obj/item/clothing/under/sol_peacekeeper head = null - mask = /obj/item/clothing/mask/gas/hecu2 - gloves = /obj/item/clothing/gloves/combat + mask = /obj/item/clothing/mask/gas/sechailer/syndicate + gloves = /obj/item/clothing/gloves/frontier_colonist suit = null - shoes = /obj/item/clothing/shoes/combat - back = /obj/item/storage/backpack/ert/odst/hecu + shoes = /obj/item/clothing/shoes/jackboots/frontier_colonist + back = /obj/item/storage/backpack/industrial/frontier_colonist glasses = null ears = /obj/item/radio/headset/headset_faction/bowman id = /obj/item/card/id/advanced/solfed diff --git a/modular_nova/modules/bodyparts/code/moth_bodyparts.dm b/modular_nova/modules/bodyparts/code/moth_bodyparts.dm index 3f55ec93393..aab60d23281 100644 --- a/modular_nova/modules/bodyparts/code/moth_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/moth_bodyparts.dm @@ -4,7 +4,7 @@ icon_state = "moth_head_m" limb_id = SPECIES_MOTH is_dimorphic = TRUE - head_flags = HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN //what the fuck, moths have lips? + head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN //what the fuck, moths have lips? /obj/item/bodypart/chest/moth icon = BODYPART_ICON_MOTH diff --git a/modular_nova/modules/bodyparts/code/snail_bodyparts.dm b/modular_nova/modules/bodyparts/code/snail_bodyparts.dm index 9a4c166922c..b80ad943352 100644 --- a/modular_nova/modules/bodyparts/code/snail_bodyparts.dm +++ b/modular_nova/modules/bodyparts/code/snail_bodyparts.dm @@ -1,28 +1,28 @@ // MODULAR SNAIL OVERRIDES /obj/item/bodypart/head/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_DEBRAIN /obj/item/bodypart/chest/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL /obj/item/bodypart/arm/left/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL unarmed_damage_low = 1 // Roundstart Snails - Lowest possible punch damage. if this is set to 0, punches will always miss. unarmed_damage_high = 5 // Roundstart Snails - A Bit More damage. /obj/item/bodypart/arm/right/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL unarmed_damage_low = 1 unarmed_damage_high = 5 /obj/item/bodypart/leg/left/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL unarmed_damage_low = 1. unarmed_damage_high = 5 /obj/item/bodypart/leg/right/snail - icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC + icon_greyscale = BODYPART_ICON_SNAIL unarmed_damage_low = 1 unarmed_damage_high = 5 diff --git a/modular_nova/modules/bodyparts/icons/snail_parts_greyscale.dmi b/modular_nova/modules/bodyparts/icons/snail_parts_greyscale.dmi new file mode 100644 index 00000000000..0b57859dca4 Binary files /dev/null and b/modular_nova/modules/bodyparts/icons/snail_parts_greyscale.dmi differ diff --git a/modular_nova/modules/chat_colors/code/chat_color.dm b/modular_nova/modules/chat_colors/code/chat_color.dm index afbd6c61e6c..fc6f0347d8a 100644 --- a/modular_nova/modules/chat_colors/code/chat_color.dm +++ b/modular_nova/modules/chat_colors/code/chat_color.dm @@ -85,11 +85,11 @@ // There are special cases for greyscale and the red/blue/violet range if(hue == CM_COLOR_HUE_GREY) - processed_luminance = max(luminance, CM_COLOR_LUM_MIN_GREY) // greys have a higher floor on the allowed luminance value + processed_luminance = max(luminance, CM_COLOR_LUM_MIN_GREY) // greys have a lower floor on the allowed luminance value than the default else if(CM_COLOR_HUE_RANGE_UPPER > hue > CM_COLOR_HUE_RANGE_LOWER) - processed_luminance = min(luminance, CM_COLOR_LUM_MAX_DARK_RANGE) // colors in the deep reds/blues/violets range will have a slightly higher luminance floor than the rest + processed_luminance = min(luminance, CM_COLOR_LUM_MAX_DARK_RANGE) // colors in the deep reds/blues/violets range will have a slightly higher luminance floor than the default else - processed_luminance = max(luminance, CM_COLOR_LUM_MIN) // everything else gets the default + processed_luminance = max(luminance, CM_COLOR_LUM_MIN) // everything else gets the default floor // Convert it back to a hex return rgb(hue, saturation*sat_shift, processed_luminance*lum_shift, space = COLORSPACE_HSL) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/chem_machines.dm b/modular_nova/modules/colony_fabricator/code/appliances/chem_machines.dm index 63e0831f6d3..045adfc4733 100644 --- a/modular_nova/modules/colony_fabricator/code/appliances/chem_machines.dm +++ b/modular_nova/modules/colony_fabricator/code/appliances/chem_machines.dm @@ -12,10 +12,13 @@ var/static/list/synthesizable_reagents = list( /datum/reagent/water, ) + /// What this repacks into + var/repacked_type = /obj/item/flatpacked_machine/water_synth -/obj/machinery/plumbing/synthesizer/water_synth/Initialize(mapload, bolt, layer) +/obj/machinery/plumbing/synthesizer/water_synth/Initialize(mapload, bolt = FALSE, layer) . = ..() dispensable_reagents = synthesizable_reagents + AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) // Deployable item for cargo for the water synth @@ -27,6 +30,10 @@ w_class = WEIGHT_CLASS_NORMAL type_to_deploy = /obj/machinery/plumbing/synthesizer/water_synth deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) // Machine that makes botany nutrients for hydroponics farming @@ -48,10 +55,13 @@ /datum/reagent/toxin/plantbgone/weedkiller, /datum/reagent/toxin/pestkiller, ) + /// What this repacks into + var/repacked_type = /obj/item/flatpacked_machine/hydro_synth -/obj/machinery/plumbing/synthesizer/colony_hydroponics/Initialize(mapload, bolt, layer) +/obj/machinery/plumbing/synthesizer/colony_hydroponics/Initialize(mapload, bolt = FALSE, layer) . = ..() dispensable_reagents = synthesizable_reagents + AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) // Deployable item for cargo for the hydro synth @@ -63,6 +73,10 @@ w_class = WEIGHT_CLASS_NORMAL type_to_deploy = /obj/machinery/plumbing/synthesizer/colony_hydroponics deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) // Chem dispenser with a limited range of thematic reagents to dispense @@ -117,8 +131,9 @@ powerefficiency = 0.5 recharge_amount = 50 -/obj/machinery/chem_dispenser/frontier_appliance/default_deconstruction_crowbar() - return +/obj/machinery/chem_dispenser/frontier_appliance/examine(mob/user) + . = ..() + . += span_notice("It cannot be repacked, but can be deconstructed normally.") // Deployable item for cargo for the sustenance machine @@ -129,3 +144,8 @@ w_class = WEIGHT_CLASS_NORMAL type_to_deploy = /obj/machinery/chem_dispenser/frontier_appliance deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/co2_cracker.dm b/modular_nova/modules/colony_fabricator/code/appliances/co2_cracker.dm index 51901079aed..66b78ca16d8 100644 --- a/modular_nova/modules/colony_fabricator/code/appliances/co2_cracker.dm +++ b/modular_nova/modules/colony_fabricator/code/appliances/co2_cracker.dm @@ -71,10 +71,13 @@ GLOBAL_LIST_INIT(cracker_reactions, cracker_reactions_list()) working_power = 1 /// Soundloop for while the thermomachine is turned on var/datum/looping_sound/conditioner_running/soundloop + /// What this repacks into + var/repacked_type = /obj/item/flatpacked_machine/co2_cracker /obj/machinery/electrolyzer/co2_cracker/Initialize(mapload) . = ..() soundloop = new(src, FALSE) + AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) /obj/machinery/electrolyzer/co2_cracker/process_atmos() diff --git a/modular_nova/modules/colony_fabricator/code/appliances/foodricator.dm b/modular_nova/modules/colony_fabricator/code/appliances/foodricator.dm index 51274cb99a8..b707a2ec446 100644 --- a/modular_nova/modules/colony_fabricator/code/appliances/foodricator.dm +++ b/modular_nova/modules/colony_fabricator/code/appliances/foodricator.dm @@ -18,10 +18,13 @@ RND_CATEGORY_AKHTER_FOODRICATOR_UTENSILS, RND_CATEGORY_AKHTER_SEEDS, ) + /// What this repacks into + var/repacked_type = /obj/item/flatpacked_machine/organics_ration_printer /obj/machinery/biogenerator/foodricator/Initialize(mapload) . = ..() AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + AddElement(/datum/element/repackable, repacked_type, 5 SECONDS) /obj/machinery/biogenerator/foodricator/RefreshParts() . = ..() @@ -38,6 +41,7 @@ icon = 'modular_nova/modules/colony_fabricator/icons/foodricator.dmi' icon_state = "biogenerator_parts" type_to_deploy = /obj/machinery/biogenerator/foodricator + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, diff --git a/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm new file mode 100644 index 00000000000..0d79cbf2d74 --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/griddle.dm @@ -0,0 +1,38 @@ +/obj/machinery/griddle/frontier_tabletop + name = "tabletop griddle" + desc = "A griddle type slim enough to fit atop a table without much fuss. This type in particular \ + was made to be broken down into many parts and shipped across the glaxy. This makes it a favourite in \ + pop-up food stalls and colony kitchens all around." + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/griddle.dmi' + icon_state = "griddletable_off" + variant = "table" + pass_flags_self = LETPASSTHROW + pass_flags = PASSTABLE + circuit = null + // Lines up perfectly with tables when anchored on them + anchored_tabletop_offset = 3 + /// What type this repacks into + var/repacked_type = /obj/item/flatpacked_machine/frontier_griddle + +/obj/machinery/griddle/frontier_tabletop/Initialize(mapload) + . = ..() + AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) + AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + +/obj/machinery/griddle/frontier_tabletop/unanchored + anchored = FALSE + +// Deployable item for cargo + +/obj/item/flatpacked_machine/frontier_griddle + name = "flat-packed tabletop griddle" + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/griddle.dmi' + icon_state = "griddle_parts" + w_class = WEIGHT_CLASS_NORMAL + type_to_deploy = /obj/machinery/griddle/frontier_tabletop + deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm new file mode 100644 index 00000000000..8359250d438 --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/macrowave.dm @@ -0,0 +1,42 @@ +/obj/machinery/microwave/frontier_printed + desc = "A plastic-paneled microwave oven, capable of doing anything a standard microwave could do. \ + This one is special designed to be tightly packed into a shape that can be easily re-assembled \ + later from the factory. There don't seem to be included instructions on getting it folded back \ + together, though..." + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/microwave.dmi' + circuit = null + max_n_of_items = 5 + efficiency = 2 + vampire_charging_capable = TRUE + +/obj/machinery/microwave/frontier_printed/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + +/obj/machinery/microwave/frontier_printed/RefreshParts() + . = ..() + max_n_of_items = 5 + efficiency = 2 + vampire_charging_capable = TRUE + +/obj/machinery/microwave/frontier_printed/examine(mob/user) + . = ..() + . += span_notice("It cannot be repacked, but can be deconstructed normally.") + +/obj/machinery/microwave/frontier_printed/unanchored + anchored = FALSE + +// Deployable item for cargo + +/obj/item/flatpacked_machine/macrowave + name = "microwave oven parts kit" + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/microwave.dmi' + icon_state = "packed_microwave" + w_class = WEIGHT_CLASS_NORMAL + type_to_deploy = /obj/machinery/microwave/frontier_printed + deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/range.dm b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/range.dm new file mode 100644 index 00000000000..6f8c48bf789 --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/appliances/kitchen_appliances/range.dm @@ -0,0 +1,38 @@ +/obj/machinery/oven/range_frontier + name = "frontier range" + desc = "A combined oven and stove commonly seen on the frontier. Comes from the factory packed up \ + in a neatly compact format that can then be deployed into a nearly full size appliance. \ + It seems, however, that the designer forgot to include instructions on packing these things back up." + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/range.dmi' + icon_state = "range_off" + base_icon_state = "range" + pass_flags_self = PASSMACHINE|PASSTABLE|LETPASSTHROW + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 1.2 + circuit = null + +/obj/machinery/oven/range_frontier/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + AddComponent(/datum/component/stove, container_x = -3, container_y = 14) + +/obj/machinery/oven/range_frontier/examine(mob/user) + . = ..() + . += span_notice("It cannot be repacked, but can be deconstructed normally.") + +/obj/machinery/oven/range_frontier/unanchored + anchored = FALSE + +// Deployable item for cargo + +/obj/item/flatpacked_machine/frontier_range + name = "frontier range parts kit" + icon = 'modular_nova/modules/colony_fabricator/icons/kitchen_stuff/range.dmi' + icon_state = "range_packed" + w_class = WEIGHT_CLASS_NORMAL + type_to_deploy = /obj/machinery/oven/range_frontier + deploy_time = 2 SECONDS + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/space_heater.dm b/modular_nova/modules/colony_fabricator/code/appliances/space_heater.dm new file mode 100644 index 00000000000..18303a21930 --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/appliances/space_heater.dm @@ -0,0 +1,58 @@ +/obj/machinery/space_heater/wall_mounted + name = "mounted heater" + desc = "A compact heating and cooling device for small scale applications, made to mount onto walls up and out of the way. \ + Like other, more free-standing space heaters however, these still require cell power to function." + icon = 'modular_nova/modules/colony_fabricator/icons/space_heater.dmi' + anchored = TRUE + density = FALSE + circuit = null + heating_power = 20000 + efficiency = 10000 + display_panel = TRUE + /// What this repacks into when its wrenched off a wall + var/repacked_type = /obj/item/wallframe/wall_heater + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/space_heater/wall_mounted, 29) + +/obj/machinery/space_heater/wall_mounted/Initialize(mapload) + . = ..() + find_and_hang_on_wall() + AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + +/obj/machinery/space_heater/wall_mounted/RefreshParts() + . = ..() + heating_power = 20000 + efficiency = 10000 + +/obj/machinery/space_heater/wall_mounted/default_deconstruction_crowbar() + return + +/obj/machinery/space_heater/wall_mounted/default_unfasten_wrench(mob/living/user, obj/item/wrench, time) + user.balloon_alert(user, "deconstructing...") + wrench.play_tool_sound(src) + if(wrench.use_tool(src, user, 1 SECONDS)) + playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + deconstruct(TRUE) + return + +/obj/machinery/space_heater/wall_mounted/deconstruct(disassembled) + if(disassembled) + new repacked_type(drop_location()) + return ..() + +// Wallmount for creating the heaters + +/obj/item/wallframe/wall_heater + name = "unmounted wall heater" + desc = "A compact heating and cooling device for small scale applications, made to mount onto walls up and out of the way. \ + Like other, more free-standing space heaters however, these still require cell power to function." + icon = 'modular_nova/modules/colony_fabricator/icons/space_heater.dmi' + icon_state = "sheater-off" + w_class = WEIGHT_CLASS_NORMAL + result_path = /obj/machinery/space_heater/wall_mounted + pixel_shift = 29 + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1, + /datum/material/gold = SMALL_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/appliances/wind_turbine.dm b/modular_nova/modules/colony_fabricator/code/appliances/wind_turbine.dm index 1713f78a925..5f6dcfffdc8 100644 --- a/modular_nova/modules/colony_fabricator/code/appliances/wind_turbine.dm +++ b/modular_nova/modules/colony_fabricator/code/appliances/wind_turbine.dm @@ -80,6 +80,7 @@ icon = 'modular_nova/modules/colony_fabricator/icons/wind_turbine.dmi' icon_state = "turbine_packed" type_to_deploy = /obj/machinery/power/colony_wind_turbine + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, diff --git a/modular_nova/modules/colony_fabricator/code/cargo_packs.dm b/modular_nova/modules/colony_fabricator/code/cargo_packs.dm new file mode 100644 index 00000000000..9f9611b335f --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/cargo_packs.dm @@ -0,0 +1,49 @@ +// Service + +/datum/supply_pack/service/hydro_synthesizers + name = "Hydroponics Plumbing Synthesizer Pack" + desc = "Watering and feeding your plants got you down? Worry no further as this kit contains two each of water and hydroponics fertilizer synthesizers." + cost = CARGO_CRATE_VALUE * 2 + contains = list( + /obj/machinery/plumbing/synthesizer/water_synth, + /obj/machinery/plumbing/synthesizer/water_synth, + /obj/machinery/plumbing/synthesizer/colony_hydroponics, + /obj/machinery/plumbing/synthesizer/colony_hydroponics, + ) + crate_name = "hydroponics synthesizers crate" + crate_type = /obj/structure/closet/crate/hydroponics + +/datum/supply_pack/service/frontier_kitchen + name = "Frontier Kitchen Equipment" + desc = "A range of frontier appliance classics, enough to set up a functioning kitchen no matter where you are in the galaxy." + cost = CARGO_CRATE_VALUE * 5 + contains = list( + /obj/machinery/plumbing/synthesizer/water_synth, + /obj/machinery/chem_dispenser/frontier_appliance, + /obj/machinery/griddle/frontier_tabletop/unanchored, + /obj/machinery/microwave/frontier_printed/unanchored, + /obj/machinery/oven/range_frontier/unanchored, + /obj/machinery/biogenerator/foodricator, + ) + crate_name = "frontier kitchen crate" + +// Engineering + +/datum/supply_pack/engineering/colony_starter + name = "Colonization Starter Kit" + desc = "The Sol standard minimum kit for frontier colonization, contains everything you need to construct a mostly functioning colony in most places across the galaxy." + cost = CARGO_CRATE_VALUE * 11 // 6 for the lathe, 3 for the organics printer, 2 for the rest of the stuff + contains = list( + /obj/item/flatpacked_machine, + /obj/item/flatpacked_machine/organics_printer, + /obj/item/flatpacked_machine/gps_beacon, + /obj/item/stack/sheet/plastic_wall_panel/fifty, + /obj/item/stack/rods/twentyfive, + /obj/item/stack/sheet/iron/twenty, + /obj/item/flatpacked_machine/airlock_kit_manual, + /obj/item/flatpacked_machine/airlock_kit_manual, + /obj/item/wallframe/apc, + /obj/item/electronics/apc, + /obj/item/stock_parts/cell/high, + ) + crate_name = "colonization kit crate" diff --git a/modular_nova/modules/colony_fabricator/code/construction/doors.dm b/modular_nova/modules/colony_fabricator/code/construction/doors.dm index a40a15ef9e6..1fbf4dc595a 100644 --- a/modular_nova/modules/colony_fabricator/code/construction/doors.dm +++ b/modular_nova/modules/colony_fabricator/code/construction/doors.dm @@ -25,6 +25,7 @@ icon = 'modular_nova/modules/colony_fabricator/icons/doors/packed.dmi' icon_state = "shutters_parts" type_to_deploy = /obj/machinery/door/poddoor/shutters/colony_fabricator/preopen + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, @@ -50,6 +51,7 @@ icon = 'modular_nova/modules/colony_fabricator/icons/doors/packed.dmi' icon_state = "airlock_parts" type_to_deploy = /obj/machinery/door/airlock/colony_prefab + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, diff --git a/modular_nova/modules/colony_fabricator/code/construction/turfs.dm b/modular_nova/modules/colony_fabricator/code/construction/turfs.dm index c4865faa9ce..2257b6080a5 100644 --- a/modular_nova/modules/colony_fabricator/code/construction/turfs.dm +++ b/modular_nova/modules/colony_fabricator/code/construction/turfs.dm @@ -87,9 +87,6 @@ GLOBAL_LIST_INIT(plastic_wall_panel_recipes, list( merge_type = /obj/item/stack/tile/catwalk_tile/colony_lathe tile_reskin_types = null -/obj/item/stack/tile/catwalk_tile/colony_lathe/lathe_spawn - amount = 4 - /obj/item/stack/tile/iron/colony name = "prefab floor tiles" singular_name = "prefab floor tile" @@ -107,9 +104,6 @@ GLOBAL_LIST_INIT(plastic_wall_panel_recipes, list( /obj/item/stack/tile/iron/colony/white/bolts, ) -/obj/item/stack/tile/iron/colony/lathe_spawn - amount = 4 - // Grated floor tile, for seeing wires under /turf/open/floor/catwalk_floor/colony_fabricator diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/appliances.dm b/modular_nova/modules/colony_fabricator/code/design_datums/appliances.dm index f56bc6037e1..966585016f4 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/appliances.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/appliances.dm @@ -25,13 +25,10 @@ "co2_cracker", "portable_recycler", "foodricator", -<<<<<<< HEAD -======= "wall_heater", "macrowave", "frontier_range", "tabletop_griddle", ->>>>>>> 21b58a477 (makes the tabletop griddle actually printable (#583)) ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000000000000000) // God save you hidden = TRUE @@ -87,6 +84,24 @@ ) construction_time = 30 SECONDS +/// Space heater, but it mounts on walls + +/datum/design/wall_mounted_space_heater + name = "Mounted Heater" + id = "wall_heater" + build_type = COLONY_FABRICATOR + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1, + /datum/material/gold = SMALL_MATERIAL_AMOUNT, + ) + build_path = /obj/item/wallframe/wall_heater + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_ATMOS, + ) + construction_time = 30 SECONDS + // Plumbable chem machine that makes nothing but water /datum/design/water_synthesizer @@ -194,6 +209,60 @@ ) construction_time = 30 SECONDS +// Really, its just a microwave + +/datum/design/macrowave + name = "Microwave Oven" + id = "macrowave" + build_type = COLONY_FABRICATOR + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/machinery/microwave/frontier_printed/unanchored + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE, + ) + construction_time = 30 SECONDS + +// A range, but it looks cool af + +/datum/design/frontier_range + name = "Frontier Range" + id = "frontier_range" + build_type = COLONY_FABRICATOR + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/machinery/oven/range_frontier/unanchored + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE, + ) + construction_time = 1 MINUTES + +// Griddles that fit on top of any regular table + +/datum/design/tabletop_griddle + name = "Tabletop Griddle" + id = "tabletop_griddle" + build_type = COLONY_FABRICATOR + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/machinery/griddle/frontier_tabletop/unanchored + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_CATEGORY_APPLIANCES + FABRICATOR_SUBCATEGORY_SUSTENANCE, + ) + construction_time = 1 MINUTES + #undef FABRICATOR_CATEGORY_APPLIANCES #undef FABRICATOR_SUBCATEGORY_POWER #undef FABRICATOR_SUBCATEGORY_ATMOS diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/construction.dm b/modular_nova/modules/colony_fabricator/code/design_datums/construction.dm index 7e5e608aca3..2359bd2b2e0 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/construction.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/construction.dm @@ -75,13 +75,13 @@ // Fancy floor tiles /datum/design/prefab_floor_tile - name = "Prefab Floor Tile x4" + name = "Prefab Floor Tile" id = "prefab_floor_tile" build_type = COLONY_FABRICATOR materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT, + /datum/material/iron = SHEET_MATERIAL_AMOUNT / 4, ) - build_path = /obj/item/stack/tile/iron/colony/lathe_spawn + build_path = /obj/item/stack/tile/iron/colony category = list( RND_CATEGORY_INITIAL, RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES, @@ -91,13 +91,13 @@ // Fancy catwalk floor tiles /datum/design/prefab_cat_floor_tile - name = "Prefab Catwalk Plating x4" + name = "Prefab Catwalk Plating" id = "prefab_cat_floor_tile" build_type = COLONY_FABRICATOR materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT, + /datum/material/iron = SHEET_MATERIAL_AMOUNT / 4, ) - build_path = /obj/item/stack/tile/catwalk_tile/colony_lathe/lathe_spawn + build_path = /obj/item/stack/tile/catwalk_tile/colony_lathe category = list( RND_CATEGORY_INITIAL, RND_CATEGORY_CONSTRUCTION + FABRICATOR_SUBCATEGORY_STRUCTURES, @@ -107,12 +107,12 @@ // Plastic wall panels, twice the wall for the same price in plastic, efficient! /datum/design/colony_fab_plastic_wall_panel - name = "Plastic Paneling x10" + name = "Plastic Paneling" id = "colony_fab_plastic_wall_panel" build_type = COLONY_FABRICATOR materials = list( - /datum/material/plastic = SHEET_MATERIAL_AMOUNT * 5, - /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT, + /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT, ) build_path = /obj/item/stack/sheet/plastic_wall_panel/ten category = list( diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm b/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm index 47560f14e6a..b05045ed60e 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/machine_boards.dm @@ -6,10 +6,6 @@ . = ..() build_type |= COLONY_FABRICATOR -/datum/design/board/microwave/New() - . = ..() - build_type |= COLONY_FABRICATOR - /datum/design/board/processor/New() . = ..() build_type |= COLONY_FABRICATOR @@ -18,14 +14,6 @@ . = ..() build_type |= COLONY_FABRICATOR -/datum/design/board/range/New() - . = ..() - build_type |= COLONY_FABRICATOR - -/datum/design/board/griddle/New() - . = ..() - build_type |= COLONY_FABRICATOR - /datum/design/board/reagentgrinder/New() . = ..() build_type |= COLONY_FABRICATOR diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm b/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm index 92a68bade56..9d24a6d043f 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/fabricator_flag_additions/tools.dm @@ -107,3 +107,51 @@ /datum/design/spraycan/New() . = ..() build_type |= COLONY_FABRICATOR + +/datum/design/pickaxe/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/bucket/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/watering_can/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/mop/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/broom/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/tray/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/cultivator/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/plant_analyzer/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/shovel/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/spade/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/hatchet/New() + . = ..() + build_type |= COLONY_FABRICATOR + +/datum/design/secateurs/New() + . = ..() + build_type |= COLONY_FABRICATOR diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/flatpack_machines.dm b/modular_nova/modules/colony_fabricator/code/design_datums/flatpack_machines.dm index 5912a347bd2..c4305cd9935 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/flatpack_machines.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/flatpack_machines.dm @@ -33,7 +33,7 @@ // Lets the colony lathe make more colony lathes but at very hihg cost, for fun /datum/design/flatpack_colony_fabricator - name = "Flat-packed Colony Fabricator" + name = "Flat-Packed Colony Fabricator" desc = "A deployable fabricator capable of producing other flat-packed machines and other special equipment tailored for \ rapidly constructing functional structures given resources and power. While it cannot be upgraded, it can be repacked \ and moved to any location you see fit." @@ -56,7 +56,7 @@ // Solar panels and trackers /datum/design/flatpack_solar_panel - name = "Flat-packed Solar Panel" + name = "Flat-Packed Solar Panel" desc = "A deployable solar panel, able to be repacked after placement for relocation or recycling." id = "flatpack_solar_panel" build_type = COLONY_FABRICATOR @@ -72,7 +72,7 @@ construction_time = 5 SECONDS /datum/design/flatpack_solar_tracker - name = "Flat-packed Solar Tracker" + name = "Flat-Packed Solar Tracker" desc = "A deployable solar tracker, able to be repacked after placement for relocation or recycling." id = "flatpack_solar_tracker" build_type = COLONY_FABRICATOR @@ -90,7 +90,7 @@ // Arc furance /datum/design/flatpack_arc_furnace - name = "Flat-packed Arc Furnace" + name = "Flat-Packed Arc Furnace" desc = "A deployable furnace for refining ores. While slower and less safe than conventional refining methods, \ it multiplies the output of refined materials enough to still outperform simply recycling ore." id = "flatpack_arc_furnace" @@ -109,7 +109,7 @@ // Power storage structures /datum/design/flatpack_power_storage - name = "Flat-packed Stationary Battery" + name = "Flat-Packed Stationary Battery" desc = "A deployable station-scale power cell with an overall low capacity, but high input and output rate." id = "flatpack_station_battery" build_type = COLONY_FABRICATOR @@ -126,7 +126,7 @@ construction_time = 20 SECONDS /datum/design/flatpack_power_storage_large - name = "Flat-packed Large Stationary Battery" + name = "Flat-Packed Large Stationary Battery" desc = "A deployable station-scale power cell with an overall extremely high capacity, but low input and output rate." id = "flatpack_station_battery_large" build_type = COLONY_FABRICATOR @@ -166,7 +166,7 @@ // Buildable RTG that is quite radioactive /datum/design/flatpack_rtg - name = "Flat-packed Radioisotope Thermoelectric Generator" + name = "Flat-Packed Radioisotope Thermoelectric Generator" desc = "A deployable radioisotope generator capable of producing a practically free trickle of power. \ Free if you can tolerate the radiation that the machine makes while deployed, that is." id = "flatpack_rtg" @@ -187,7 +187,7 @@ // Thermomachine with decent temperature change rate, but a limited max/min temperature /datum/design/flatpack_thermomachine - name = "Flat-packed Atmospheric Temperature Regulator" + name = "Flat-Packed Atmospheric Temperature Regulator" desc = "A deployable temperature control device for use with atmospherics pipe systems. \ Limited in its temperature range, however comes with a higher than normal heat capacity." id = "flatpack_thermo" @@ -206,7 +206,7 @@ // Ore silo except it beeps /datum/design/flatpack_ore_silo - name = "Flat-packed Ore Silo" + name = "Flat-Packed Ore Silo" desc = "An all-in-one materials management solution. Connects resource-using machines \ through a network of distrobution systems." id = "flatpack_ore_silo" @@ -225,7 +225,7 @@ // Wind turbine, produces tiny amounts of power when placed outdoors in an atmosphere, but makes significantly more if there's a storm in that area /datum/design/flatpack_turbine_team_fortress_two - name = "Flat-packed Miniature Wind Turbine" + name = "Flat-Packed Miniature Wind Turbine" desc = "A deployable fabricator capable of producing other flat-packed machines and other special equipment tailored for \ rapidly constructing functional structures given resources and power. While it cannot be upgraded, it can be repacked \ and moved to any location you see fit. This one makes specialized engineering designs and tools." @@ -243,6 +243,30 @@ ) construction_time = 30 SECONDS +// Stirling generator, kinda like a TEG but on a smaller scale and producing less insane amounts of power + +/datum/design/flatpack_bootleg_teg + name = "Flat-Packed Stirling Generator" + desc = "An industrial scale stirling generator. Stirling generators operate by intaking \ + hot gasses through their inlet pipes, and being cooled by the ambient air around them. \ + The cycling compression and expansion that this creates creates power, and this one is made \ + to make power on the scale of small stations and outposts." + id = "flatpack_bootleg_teg" + build_type = COLONY_FABRICATOR + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/plasma = SHEET_MATERIAL_AMOUNT * 10, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/gold = SHEET_MATERIAL_AMOUNT * 5, + ) + build_path = /obj/item/flatpacked_machine/stirling_generator + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_CATEGORY_FLATPACK_MACHINES + FABRICATOR_SUBCATEGORY_POWER, + ) + construction_time = 2 MINUTES + #undef FABRICATOR_CATEGORY_FLATPACK_MACHINES #undef FABRICATOR_SUBCATEGORY_MANUFACTURING #undef FABRICATOR_SUBCATEGORY_POWER diff --git a/modular_nova/modules/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm b/modular_nova/modules/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm index ed1590d71b3..f64ba01c5ff 100644 --- a/modular_nova/modules/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm +++ b/modular_nova/modules/colony_fabricator/code/design_datums/rations_printer_designs/seeds.dm @@ -75,12 +75,12 @@ RND_CATEGORY_AKHTER_SEEDS, ) -/datum/design/organic_herb_seed - name = "Pack of Herb Seeds" - id = "oganic_herb_seed" +/datum/design/organic_plump_helmet + name = "Pack of Plump-Helmet Seeds" + id = "oganic_plump_helmet" build_type = BIOGENERATOR materials = list(/datum/material/biomass = 25) - build_path = /obj/item/seeds/herbs + build_path = /obj/item/seeds/plump category = list( RND_CATEGORY_INITIAL, RND_CATEGORY_AKHTER_SEEDS, diff --git a/modular_nova/modules/colony_fabricator/code/machines/arc_furnace.dm b/modular_nova/modules/colony_fabricator/code/machines/arc_furnace.dm index 7e22e231f70..f175a1c9cfb 100644 --- a/modular_nova/modules/colony_fabricator/code/machines/arc_furnace.dm +++ b/modular_nova/modules/colony_fabricator/code/machines/arc_furnace.dm @@ -169,6 +169,8 @@ where_we_spawn_air.atmos_spawn_air("co2=50;TEMP=1200") if(/obj/item/stack/sheet/mineral/titanium) where_we_spawn_air.atmos_spawn_air("n2=10;co2=10;TEMP=1200") + if(/obj/item/stack/sheet/mineral/plasma) + where_we_spawn_air.atmos_spawn_air("co2=75;TEMP=2000") else where_we_spawn_air.atmos_spawn_air("co2=20;TEMP=1200") diff --git a/modular_nova/modules/colony_fabricator/code/machines/ore_silo.dm b/modular_nova/modules/colony_fabricator/code/machines/ore_silo.dm index c06a99f40a1..8a072446591 100644 --- a/modular_nova/modules/colony_fabricator/code/machines/ore_silo.dm +++ b/modular_nova/modules/colony_fabricator/code/machines/ore_silo.dm @@ -4,12 +4,16 @@ through a network of distribution systems." icon = 'modular_nova/modules/colony_fabricator/icons/ore_silo.dmi' circuit = null - /// What this unpacks into - var/unpacked_type = /obj/item/flatpacked_machine/ore_silo + /// What this packs into + var/packed_type = /obj/item/flatpacked_machine/ore_silo /obj/machinery/ore_silo/colony_lathe/silo_log(obj/machinery/machinery_in_question, action, amount, noun, list/mats) . = ..() playsound(src, 'sound/machines/beep.ogg', 30, TRUE) + AddElement(/datum/element/repackable, packed_type, 10 SECONDS) + +/obj/machinery/ore_silo/colony_lathe/default_deconstruction_crowbar() + return // Item for deploying ore silos /obj/item/flatpacked_machine/ore_silo diff --git a/modular_nova/modules/colony_fabricator/code/machines/power_storage_unit.dm b/modular_nova/modules/colony_fabricator/code/machines/power_storage_unit.dm index 7bb15f98e8f..113e5234c4e 100644 --- a/modular_nova/modules/colony_fabricator/code/machines/power_storage_unit.dm +++ b/modular_nova/modules/colony_fabricator/code/machines/power_storage_unit.dm @@ -56,6 +56,11 @@ name = "flat-packed stationary battery" icon_state = "battery_small_packed" type_to_deploy = /obj/machinery/power/smes/battery_pack + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, + ) // Larger station batteries, hold more but have less in/output @@ -83,3 +88,8 @@ name = "flat-packed large stationary battery" icon_state = "battery_large_packed" type_to_deploy = /obj/machinery/power/smes/battery_pack/large + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 12, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/gold = SHEET_MATERIAL_AMOUNT, + ) diff --git a/modular_nova/modules/colony_fabricator/code/machines/solar_panels.dm b/modular_nova/modules/colony_fabricator/code/machines/solar_panels.dm index d8cba4dfada..98c270025de 100644 --- a/modular_nova/modules/colony_fabricator/code/machines/solar_panels.dm +++ b/modular_nova/modules/colony_fabricator/code/machines/solar_panels.dm @@ -27,6 +27,7 @@ icon_state = "solar_panel_packed" type_to_deploy = /obj/machinery/power/solar/deployable deploy_time = 2 SECONDS + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.75, /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3, @@ -61,6 +62,7 @@ icon_state = "solar_tracker_packed" type_to_deploy = /obj/machinery/power/tracker/deployable deploy_time = 3 SECONDS + w_class = WEIGHT_CLASS_NORMAL custom_materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2, /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3.5, diff --git a/modular_nova/modules/colony_fabricator/code/machines/stirling_generator.dm b/modular_nova/modules/colony_fabricator/code/machines/stirling_generator.dm new file mode 100644 index 00000000000..c7f242638ba --- /dev/null +++ b/modular_nova/modules/colony_fabricator/code/machines/stirling_generator.dm @@ -0,0 +1,138 @@ +// Stirling generator, like a miniature TEG, pipe hot air in, and keep the air around it cold + +/obj/machinery/power/stirling_generator + name = "stirling generator" + desc = "An industrial scale stirling generator. Stirling generators operate by intaking \ + hot gasses through their inlet pipes, and being cooled by the ambient air around them. \ + The cycling compression and expansion caused by this creates power, and this one is made \ + to make power on the scale of small stations and outposts." + icon = 'modular_nova/modules/colony_fabricator/icons/stirling_generator/big_generator.dmi' + icon_state = "stirling" + density = TRUE + use_power = NO_POWER_USE + circuit = null + max_integrity = 300 + armor_type = /datum/armor/unary_thermomachine + set_dir_on_move = FALSE + can_change_cable_layer = TRUE + /// Reference to the datum connector we're using to interface with the pipe network + var/datum/gas_machine_connector/connected_chamber + /// What this thing deconstructs into + var/deconstruction_type = /obj/item/flatpacked_machine/stirling_generator + /// Maximum efficient heat difference, at what heat difference does more difference stop meaning anything for power? + var/max_efficient_heat_difference = 8000 + /// Maximum power output from this machine + var/max_power_output = 100 * 1000 + /// How much power the generator is currently making + var/current_power_generation + /// Our looping fan sound that we play when turned on + var/datum/looping_sound/ore_thumper_fan/soundloop + + +/obj/machinery/power/stirling_generator/Initialize(mapload) + . = ..() + soundloop = new(src, FALSE) + connected_chamber = new(loc, src, dir, CELL_VOLUME * 0.5) + connect_to_network() + AddElement(/datum/element/repackable, deconstruction_type, 10 SECONDS) + AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) + // This is just to make sure our atmos connection spawns facing the right way + setDir(dir) + + +/obj/machinery/power/stirling_generator/examine(mob/user) + . = ..() + . += span_notice("You can use a wrench with Left-Click to rotate the generator.") + . += span_notice("It will not work in a vacuum as it must be cooled by the gas around it.") + . += span_notice("It is currently generating [current_power_generation / 1000] kW of power.") + . += span_notice("It has a maximum power output of [max_power_output / 1000] kW at a temperature difference of [max_efficient_heat_difference] K.") + + +/obj/machinery/power/stirling_generator/Destroy() + QDEL_NULL(connected_chamber) + return ..() + + +/obj/machinery/power/stirling_generator/process_atmos() + if(!powernet) + connect_to_network() + if(!powernet) + return + + var/turf/our_turf = get_turf(src) + + var/datum/gas_mixture/hot_air_from_pipe = connected_chamber.gas_connector.airs[1] + var/datum/gas_mixture/environment = our_turf.return_air() + + if(!QUANTIZE(hot_air_from_pipe.total_moles()) || !QUANTIZE(environment.total_moles())) //Don't transfer if there's no gas + return + + var/gas_temperature_delta = hot_air_from_pipe.temperature - environment.temperature + + if(!(gas_temperature_delta > 0)) + current_power_generation = 0 + return + + var/input_capacity = hot_air_from_pipe.heat_capacity() + var/output_capacity = environment.heat_capacity() + var/cooling_heat_amount = CALCULATE_CONDUCTION_ENERGY(gas_temperature_delta, input_capacity, output_capacity) + hot_air_from_pipe.temperature = max(hot_air_from_pipe.temperature - (cooling_heat_amount / input_capacity), TCMB) + + /// Takes the amount of heat moved, and divides it by the maximum temperature difference we expect, creating a number to divide power generation by + var/effective_energy_transfer = round((max_efficient_heat_difference / min(gas_temperature_delta, max_efficient_heat_difference)), 0.01) + current_power_generation = round(max_power_output / effective_energy_transfer) + + +/obj/machinery/power/stirling_generator/process() + var/power_output = round(current_power_generation) + add_avail(power_output) + var/new_icon_state = (power_output ? "stirling_on" : "stirling") + icon_state = new_icon_state + if(soundloop.is_active() && !power_output) + soundloop.stop() + else if(!soundloop.is_active() && power_output) + soundloop.start() + + +/obj/machinery/power/stirling_generator/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return + + +/obj/machinery/power/stirling_generator/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return + + +/obj/machinery/power/stirling_generator/wrench_act(mob/living/user, obj/item/tool) + return default_change_direction_wrench(user, tool) + + +/obj/machinery/power/stirling_generator/default_change_direction_wrench(mob/user, obj/item/wrench) + if(wrench.tool_behaviour != TOOL_WRENCH) + return FALSE + + wrench.play_tool_sound(src, 50) + setDir(turn(dir,-90)) + to_chat(user, span_notice("You rotate [src].")) + SEND_SIGNAL(src, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, user, wrench) + return TRUE + + +/obj/machinery/power/stirling_generator/Destroy() + QDEL_NULL(connected_chamber) + return ..() + + +// Item for creating stirling generators + +/obj/item/flatpacked_machine/stirling_generator + name = "flat-packed stirling generator" + icon = 'modular_nova/modules/colony_fabricator/icons/stirling_generator/packed_machines.dmi' + icon_state = "stirling" + type_to_deploy = /obj/machinery/power/stirling_generator + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/plasma = SHEET_MATERIAL_AMOUNT * 10, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/gold = SHEET_MATERIAL_AMOUNT * 5, + ) diff --git a/modular_nova/modules/colony_fabricator/code/machines/thermomachine.dm b/modular_nova/modules/colony_fabricator/code/machines/thermomachine.dm index 063a9f07bd5..c620a1f7423 100644 --- a/modular_nova/modules/colony_fabricator/code/machines/thermomachine.dm +++ b/modular_nova/modules/colony_fabricator/code/machines/thermomachine.dm @@ -20,7 +20,10 @@ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) flick("thermo_deploy", src) + + // Makes for certain that we are visually facing the correct way setDir(dir) + update_appearance() /obj/machinery/atmospherics/components/unary/thermomachine/deployable/RefreshParts() . = ..() diff --git a/modular_nova/modules/colony_fabricator/icons/doors/shutter.dmi b/modular_nova/modules/colony_fabricator/icons/doors/shutter.dmi index f29dc998999..f3ab4f661bd 100644 Binary files a/modular_nova/modules/colony_fabricator/icons/doors/shutter.dmi and b/modular_nova/modules/colony_fabricator/icons/doors/shutter.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/griddle.dmi b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/griddle.dmi new file mode 100644 index 00000000000..46cde00af67 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/griddle.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/microwave.dmi b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/microwave.dmi new file mode 100644 index 00000000000..00979f05eb4 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/microwave.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/range.dmi b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/range.dmi new file mode 100644 index 00000000000..1e6ed4cfa73 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/kitchen_stuff/range.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/space_heater.dmi b/modular_nova/modules/colony_fabricator/icons/space_heater.dmi new file mode 100644 index 00000000000..eda06ce46e4 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/space_heater.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/stirling_generator/big_generator.dmi b/modular_nova/modules/colony_fabricator/icons/stirling_generator/big_generator.dmi new file mode 100644 index 00000000000..d8cac6292e2 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/stirling_generator/big_generator.dmi differ diff --git a/modular_nova/modules/colony_fabricator/icons/stirling_generator/packed_machines.dmi b/modular_nova/modules/colony_fabricator/icons/stirling_generator/packed_machines.dmi new file mode 100644 index 00000000000..5b750da5151 Binary files /dev/null and b/modular_nova/modules/colony_fabricator/icons/stirling_generator/packed_machines.dmi differ diff --git a/modular_nova/modules/company_imports/code/armament_datums/akh_frontier.dm b/modular_nova/modules/company_imports/code/armament_datums/akh_frontier.dm index 290ab7386fc..d775fc4e456 100644 --- a/modular_nova/modules/company_imports/code/armament_datums/akh_frontier.dm +++ b/modular_nova/modules/company_imports/code/armament_datums/akh_frontier.dm @@ -45,6 +45,10 @@ item_type = /obj/item/wallframe/cell_charger_multi cost = PAYCHECK_CREW +/datum/armament_entry/company_import/akh_frontier/appliances/wall_heater + item_type = /obj/item/wallframe/wall_heater + cost = PAYCHECK_CREW + /datum/armament_entry/company_import/akh_frontier/appliances/water_synth item_type = /obj/item/flatpacked_machine/water_synth @@ -64,9 +68,6 @@ /datum/armament_entry/company_import/akh_frontier/deployables_misc/arc_furnace item_type = /obj/item/flatpacked_machine/arc_furnace -/datum/armament_entry/company_import/akh_frontier/deployables_misc/thermomachine - item_type = /obj/item/flatpacked_machine/thermomachine - /datum/armament_entry/company_import/akh_frontier/deployables_misc/co2_cracker item_type = /obj/item/flatpacked_machine/co2_cracker @@ -79,23 +80,18 @@ subcategory = "Deployable Power Equipment" cost = PAYCHECK_COMMAND -/datum/armament_entry/company_import/akh_frontier/deployables/solar - item_type = /obj/item/flatpacked_machine/solar - cost = PAYCHECK_CREW - -/datum/armament_entry/company_import/akh_frontier/deployables/solar_tracker - item_type = /obj/item/flatpacked_machine/solar_tracker +/datum/armament_entry/company_import/akh_frontier/deployables/turbine + item_type = /obj/item/flatpacked_machine/wind_turbine cost = PAYCHECK_CREW -/datum/armament_entry/company_import/akh_frontier/deployables/station_battery - item_type = /obj/item/flatpacked_machine/station_battery - -/datum/armament_entry/company_import/akh_frontier/deployables/big_station_battery - item_type = /obj/item/flatpacked_machine/large_station_battery - /datum/armament_entry/company_import/akh_frontier/deployables/solids_generator item_type = /obj/item/flatpacked_machine/fuel_generator +/datum/armament_entry/company_import/akh_frontier/deployables/stirling_generator + item_type = /obj/item/flatpacked_machine/stirling_generator + cost = PAYCHECK_COMMAND * 3 + /datum/armament_entry/company_import/akh_frontier/deployables/rtg item_type = /obj/item/flatpacked_machine/rtg + cost = PAYCHECK_COMMAND * 2 restricted = TRUE diff --git a/modular_nova/modules/company_imports/code/armament_datums/deforest_medical.dm b/modular_nova/modules/company_imports/code/armament_datums/deforest_medical.dm index c9bd351f5f2..874fb9a680f 100644 --- a/modular_nova/modules/company_imports/code/armament_datums/deforest_medical.dm +++ b/modular_nova/modules/company_imports/code/armament_datums/deforest_medical.dm @@ -7,6 +7,10 @@ /datum/armament_entry/company_import/deforest/first_aid_kit subcategory = "First-Aid Kits" +/datum/armament_entry/deforest/first_aid_kit/civil_defense/comfort + item_type = /obj/item/storage/medkit/civil_defense/comfort/stocked + cost = PAYCHECK_COMMAND * 2 + /datum/armament_entry/company_import/deforest/first_aid_kit/civil_defense item_type = /obj/item/storage/medkit/civil_defense/stocked cost = PAYCHECK_COMMAND * 4 diff --git a/modular_nova/modules/contractor/code/datums/contractor_items.dm b/modular_nova/modules/contractor/code/datums/contractor_items.dm index 386a306ca07..58973be6297 100644 --- a/modular_nova/modules/contractor/code/datums/contractor_items.dm +++ b/modular_nova/modules/contractor/code/datums/contractor_items.dm @@ -92,34 +92,6 @@ limited = 1 cost = 2 -/datum/contractor_item/contractor_partner/handle_purchase(datum/contractor_hub/hub, mob/living/user) - . = ..() - - if(!.) - return - to_chat(user, span_notice("The uplink vibrates quietly, connecting to nearby agents...")) - - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates( - "Do you want to play as the Contractor Support Unit for [user.real_name]?", - role = ROLE_PAI, - check_jobban = FALSE, - poll_time = 10 SECONDS, - ignore_category = POLL_IGNORE_CONTRACTOR_SUPPORT, - pic_source = user, - role_name_text = "[user.real_name]'s support", - ) - - if(LAZYLEN(candidates)) - var/mob/dead/observer/picked_obs = pick(candidates) - hub.contractor_teammate = spawn_contractor_partner(user, picked_obs.key) - else - to_chat(user, span_notice("No available agents at this time, please try again later.")) - - // refund and add the limit back. - limited += 1 - hub.contract_rep += cost - hub.purchased_items -= src - /datum/contractor_item/blackout name = "Blackout" desc = "Request Syndicate Command to distrupt the station's powernet. Disables power across the station for a short duration." diff --git a/modular_nova/modules/contractor/code/datums/mind_datum.dm b/modular_nova/modules/contractor/code/datums/mind_datum.dm deleted file mode 100644 index d95e6e524fa..00000000000 --- a/modular_nova/modules/contractor/code/datums/mind_datum.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/mind/proc/make_contractor_support() - var/contractor_support_datum = has_antag_datum(/datum/antagonist/traitor/contractor_support) - if(contractor_support_datum) - return contractor_support_datum - return add_antag_datum(/datum/antagonist/traitor/contractor_support) diff --git a/modular_nova/modules/customization/modules/client/augment/organs.dm b/modular_nova/modules/customization/modules/client/augment/organs.dm index 0384c3668d9..3d5fac41c5a 100644 --- a/modular_nova/modules/customization/modules/client/augment/organs.dm +++ b/modular_nova/modules/customization/modules/client/augment/organs.dm @@ -99,10 +99,18 @@ name = "Robotic voicebox" path = /obj/item/organ/internal/tongue/robot +/datum/augment_item/organ/tongue/robo/forked + name = "Robotic lizard voicebox" + path = /obj/item/organ/internal/tongue/lizard/robot + /datum/augment_item/organ/tongue/cybernetic name = "Cybernetic tongue" path = /obj/item/organ/internal/tongue/cybernetic +/datum/augment_item/organ/tongue/cybernetic/forked + name = "Forked cybernetic tongue" + path = /obj/item/organ/internal/tongue/lizard/cybernetic + /datum/augment_item/organ/tongue/forked name = "Forked tongue" path = /obj/item/organ/internal/tongue/lizard diff --git a/modular_nova/modules/customization/modules/clothing/suits/coats.dm b/modular_nova/modules/customization/modules/clothing/suits/coats.dm index b17ba3dd666..99f7775b3e5 100644 --- a/modular_nova/modules/customization/modules/clothing/suits/coats.dm +++ b/modular_nova/modules/customization/modules/clothing/suits/coats.dm @@ -146,25 +146,21 @@ worn_icon = 'modular_nova/master_files/icons/mob/clothing/suit.dmi' blood_overlay_type = "coat" -/obj/item/clothing/suit/croptop +/obj/item/clothing/suit/jacket/croptop name = "crop top turtleneck" - desc = "A comfy looking turtleneck that exposes your midriff, fashionable but makes the point of a sweater moot. Now with Pycroft polychromatic tech!" + desc = "A comfy looking turtleneck that exposes your midriff, fashionable but makes the point of a sweater moot." icon_state = "croptop" + icon = 'modular_nova/master_files/icons/obj/clothing/suits/jacket.dmi' + worn_icon = 'modular_nova/master_files/icons/mob/clothing/suits/jacket.dmi' + body_parts_covered = CHEST|ARMS + cold_protection = CHEST|ARMS greyscale_config = /datum/greyscale_config/croptop greyscale_config_worn = /datum/greyscale_config/croptop/worn + greyscale_config_worn_teshari = /datum/greyscale_config/croptop/worn/teshari greyscale_colors = "#1d1b1b" - body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS flags_1 = IS_PLAYER_COLORABLE_1 - icon = 'modular_nova/master_files/icons/obj/clothing/suits.dmi' - worn_icon = 'modular_nova/master_files/icons/mob/clothing/suit.dmi' supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON -/obj/item/clothing/suit/croptop/Initialize(mapload) - . = ..() - AddElement(/datum/element/gags_recolorable) - update_icon(UPDATE_OVERLAYS) - /obj/item/clothing/suit/varsity name = "varsity jacket" desc = "A simple varsity jacket with no obvious sources." diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm index 0a7d45a50fc..e9f96e84df6 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm @@ -39,16 +39,12 @@ GLOBAL_LIST_EMPTY(cached_mutant_icon_files) ///Set this to true to make an accessory appear as color customizable in preferences despite advanced color settings being off, will also prevent the accessory from being reset var/always_color_customizable - ///Whether the accessory can have a special icon_state to render, i.e. wagging tails - var/special_render_case ///Special case of whether the accessory should be shifted in the X dimension, check taur genitals for example var/special_x_dimension ///Special case of whether the accessory should have a different icon, check taur genitals for example var/special_icon_case ///Special case for MODsuit overlays var/use_custom_mod_icon - ///Special case of applying a different color - var/special_colorize ///If defined, the accessory will be only available to ckeys inside the list. ITS ASSOCIATIVE, ie. ("ckey" = TRUE). For speed var/list/ckey_whitelist ///Whether this feature is genetic, and thus modifiable by DNA consoles @@ -87,15 +83,6 @@ GLOBAL_LIST_EMPTY(cached_mutant_icon_files) /datum/sprite_accessory/proc/is_hidden(mob/living/carbon/human/owner) return FALSE -/datum/sprite_accessory/proc/get_special_render_state(mob/living/carbon/human/H) - return null - -/datum/sprite_accessory/proc/get_special_render_key(mob/living/carbon/human/owner) - return key - -/datum/sprite_accessory/proc/get_special_render_colour(mob/living/carbon/human/H, passed_state) - return null - /datum/sprite_accessory/proc/get_special_icon(mob/living/carbon/human/H, passed_state) return icon diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm index 89a0e31bbfe..2819d0a5199 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm @@ -2,8 +2,6 @@ #define TAUR_DIMENSION_X 64 /datum/sprite_accessory/genital - special_render_case = TRUE - special_colorize = TRUE var/associated_organ_slot /// If true, then there should be a variant in the icon file that's slightly pinkier to match human base colors. var/has_skintone_shading = FALSE @@ -57,15 +55,6 @@ else return TRUE -/datum/sprite_accessory/genital/get_special_render_state(mob/living/carbon/human/human) - var/obj/item/organ/external/genital/genital = human.get_organ_slot(associated_organ_slot) - return "[genital?.sprite_suffix]" - -/datum/sprite_accessory/genital/get_special_render_colour(mob/living/carbon/human/human, render_state) - var/obj/item/organ/external/genital/genital = human.get_organ_slot(associated_organ_slot) - if(genital?.uses_skin_color && HAS_TRAIT(human, TRAIT_USES_SKINTONES)) - return skintone2hex(human.skin_tone) - /datum/sprite_accessory/genital/penis icon = 'modular_nova/master_files/icons/mob/sprite_accessory/genitals/penis_onmob.dmi' organ_type = /obj/item/organ/external/genital/penis diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/spines.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/spines.dm index 51a93be25ae..4f631993af4 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/spines.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/spines.dm @@ -1,8 +1,6 @@ /datum/sprite_accessory/spines key = "spines" generic = "Spines" - icon = 'modular_nova/master_files/icons/mob/sprite_accessory/lizard_spines.dmi' - special_render_case = TRUE default_color = DEFAULT_SECONDARY recommended_species = list(SPECIES_LIZARD, SPECIES_UNATHI, SPECIES_LIZARD_ASH, SPECIES_LIZARD_SILVER) relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER) @@ -10,43 +8,39 @@ organ_type = /obj/item/organ/external/spines /datum/sprite_accessory/spines/is_hidden(mob/living/carbon/human/wearer) - var/obj/item/organ/external/tail/tail = wearer.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) - if(!wearer.w_uniform && !wearer.wear_suit) - return FALSE - // Can hide if wearing uniform - if(key in wearer.try_hide_mutant_parts) - return TRUE + if(wearer.w_uniform) + if(wearer.w_uniform.flags_inv & HIDESPINE) + return TRUE if(wearer.wear_suit) - // Exception for MODs - if(istype(wearer.wear_suit, /obj/item/clothing/suit/mod)) - return FALSE - else if(!tail \ - || (wearer.wear_suit \ - && (wearer.wear_suit.flags_inv & HIDETAIL \ - || wearer.wear_suit.flags_inv & HIDESPINE) \ - ) - ) + if(wearer.wear_suit.flags_inv & HIDESPINE) + return TRUE + if(key in wearer.try_hide_mutant_parts) return TRUE -/datum/sprite_accessory/spines/get_special_render_state(mob/living/carbon/human/H) - return icon_state + return FALSE -/datum/sprite_accessory/spines/is_hidden(mob/living/carbon/human/wearer) +/datum/sprite_accessory/tail_spines + key = "tailspines" + default_color = DEFAULT_SECONDARY + relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER) + +/datum/sprite_accessory/tail_spines/is_hidden(mob/living/carbon/human/wearer) var/list/used_in_turf = list("tail") - // Emote exception if(wearer.owned_turf?.name in used_in_turf) + // Emote exception return TRUE if(!wearer.w_uniform && !wearer.wear_suit) return FALSE - if(key in wearer.try_hide_mutant_parts) + if("spines" in wearer.try_hide_mutant_parts) + return TRUE + if("tail" in wearer.try_hide_mutant_parts) return TRUE if(wearer.wear_suit) // Exception for MODs if(istype(wearer.wear_suit, /obj/item/clothing/suit/mod)) return FALSE - // Hide accessory if flagged to do so else if(wearer.wear_suit.flags_inv & HIDETAIL) return TRUE diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm index 208fcf4b7f1..41be5d0fc3c 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -3,8 +3,6 @@ generic = "Tail" organ_type = /obj/item/organ/external/tail icon = 'modular_nova/master_files/icons/mob/sprite_accessory/tails.dmi' - special_render_case = TRUE - special_colorize = TRUE relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) genetic = TRUE /// Can we use this tail for the fluffy tail turf emote? @@ -29,9 +27,6 @@ else if(wearer.wear_suit.flags_inv & HIDETAIL) return TRUE -/datum/sprite_accessory/tails/get_special_render_state(mob/living/carbon/human/wearer) - return icon_state - /datum/sprite_accessory/tails/none name = "None" icon_state = "none" diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm index 00ef0c74826..6459c622c4f 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/vox.dm @@ -123,6 +123,7 @@ icon_state = "vox" recommended_species = list(SPECIES_VOX) organ_type = /obj/item/organ/external/tail/lizard + spine_key = SPINE_KEY_VOX //The tail markings /datum/sprite_accessory/spines/vox @@ -131,14 +132,31 @@ recommended_species = list(SPECIES_VOX) relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/tail_spines/vox + icon = 'modular_nova/master_files/icons/mob/sprite_accessory/vox_spines.dmi' + default_color = DEFAULT_TERTIARY + recommended_species = list(SPECIES_VOX) + relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) + /datum/sprite_accessory/spines/vox/vox_bands name = "Vox Bands" - icon_state = "vox_bands" + icon_state = "bands" + +/datum/sprite_accessory/tail_spines/vox/vox_bands + name = "Vox Bands" + icon_state = "bands" /datum/sprite_accessory/spines/vox/vox_tip name = "Vox Tip" - icon_state = "vox_tip" + icon_state = "tip" +/datum/sprite_accessory/tail_spines/vox/vox_tip + name = "Vox Tip" + icon_state = "tip" /datum/sprite_accessory/spines/vox/vox_stripe name = "Vox Stripe" - icon_state = "vox_stripe" + icon_state = "stripe" + +/datum/sprite_accessory/tail_spines/vox/vox_stripe + name = "Vox Stripe" + icon_state = "stripe" diff --git a/modular_nova/modules/customization/modules/surgery/organs/spines.dm b/modular_nova/modules/customization/modules/surgery/organs/spines.dm index 1849bb0a5c5..98cdd9869ee 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/spines.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/spines.dm @@ -12,12 +12,6 @@ /datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(mob/living/carbon/human/human) return !sprite_datum.is_hidden(human) -/datum/bodypart_overlay/mutant/spines/get_feature_key_for_overlay() - return (wagging ? "wagging" : "") + feature_key - -/datum/bodypart_overlay/mutant/spines/get_base_icon_state() - return sprite_datum.icon_state - /// We overwrite this just because we need to change the layer to be ever so slightly above the tails. /// It sucks, but it's the best I could do without refactoring a lot more. /datum/bodypart_overlay/mutant/spines/get_images(image_layer, obj/item/bodypart/limb) @@ -27,3 +21,21 @@ overlay.layer += SPINES_LAYER_OFFSET return returned_overlays + +/datum/bodypart_overlay/mutant/tail_spines + color_source = ORGAN_COLOR_OVERRIDE + layers = ALL_EXTERNAL_OVERLAYS + +/datum/bodypart_overlay/mutant/tail_spines/override_color(rgb_value) + return draw_color + +/datum/bodypart_overlay/mutant/tail_spines/can_draw_on_bodypart(mob/living/carbon/human/human) + return !sprite_datum.is_hidden(human) + +/datum/bodypart_overlay/mutant/tail_spines/get_images(image_layer, obj/item/bodypart/limb) + var/list/mutable_appearance/returned_overlays = ..() + + for(var/mutable_appearance/overlay in returned_overlays) + overlay.layer += SPINES_LAYER_OFFSET + + return returned_overlays diff --git a/modular_nova/modules/deforest_medical_items/code/cargo_packs.dm b/modular_nova/modules/deforest_medical_items/code/cargo_packs.dm index ab38a07a646..010aa149a73 100644 --- a/modular_nova/modules/deforest_medical_items/code/cargo_packs.dm +++ b/modular_nova/modules/deforest_medical_items/code/cargo_packs.dm @@ -8,6 +8,16 @@ /obj/item/storage/medkit/civil_defense/stocked = 5, ) +/datum/supply_pack/medical/civil_defense/comfort + name = "\improper Civil Defense Symptom Support Kit Crate" + crate_name = "civil defense symptom support kit crate" + desc = "Contains five civil defense symptom support kits stocked with three pens of psifinil and a tube containing 5 pills of alifil, two proprietary DeForest mixes designed to provide long-lasting relief from chronic disease and syndromes like gravity sickness." + access = ACCESS_MEDICAL + cost = CARGO_CRATE_VALUE * 5 // 2000 + contains = list( + /obj/item/storage/medkit/civil_defense/comfort/stocked = 5, + ) + /datum/supply_pack/medical/frontier_first_aid name = "Frontier First Aid Crate" crate_name = "frontier first aid crate" diff --git a/modular_nova/modules/deforest_medical_items/code/storage_items.dm b/modular_nova/modules/deforest_medical_items/code/storage_items.dm index b8452cfe5f2..e2e3af11c4d 100644 --- a/modular_nova/modules/deforest_medical_items/code/storage_items.dm +++ b/modular_nova/modules/deforest_medical_items/code/storage_items.dm @@ -19,6 +19,36 @@ /datum/reagent/consumable/sugar = 5, ) +// Narcolepsy quirk medicines +/obj/item/storage/pill_bottle/prescription_stimulant + name = "alifil pill bottle" + desc = "A special miniaturized pill bottle with an insert resembling a revolver cylinder, fitted for the inside of a 'civil defense'-class shell medkit. Holds five alifil pills, and is designed only to accept their proprietary DeForest(tm) shape. A big, bold yellow warning label on the side reads: 'FOLLOW DOSAGE DIRECTIONS'." + icon = 'modular_nova/modules/deforest_medical_items/icons/storage.dmi' + icon_state = "painkiller_bottle" + w_class = WEIGHT_CLASS_TINY // this is fine because we hard limit what can go in this thing + +/obj/item/storage/pill_bottle/prescription_stimulant/Initialize(mapload) + . = ..() + // Make sure we can only hold alifil pills since this is nested inside a symptom support kit + atom_storage.max_slots = 5 + atom_storage.set_holdable(list( + /obj/item/reagent_containers/pill/prescription_stimulant, + )) + +/obj/item/storage/pill_bottle/prescription_stimulant/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/reagent_containers/pill/prescription_stimulant(src) + +/obj/item/reagent_containers/pill/prescription_stimulant + name = "alifil pill" + desc = "Used to treat symptoms of drowsiness and sudden loss of consciousness. Contains a mix of sugar, synaptizine and modafinil. A warning label reads: Take in moderation." + icon_state = "pill15" + list_reagents = list( + /datum/reagent/consumable/sugar = 5, + /datum/reagent/medicine/synaptizine = 5, + /datum/reagent/medicine/modafinil = 3 + ) + // Pre-packed civil defense medkit, with items to heal low damages inside /obj/item/storage/medkit/civil_defense name = "civil defense medical kit" @@ -37,6 +67,7 @@ atom_storage.max_slots = 4 atom_storage.set_holdable(list( /obj/item/reagent_containers/hypospray/medipen, + /obj/item/storage/pill_bottle/prescription_stimulant, )) /obj/item/storage/medkit/civil_defense/stocked @@ -50,6 +81,21 @@ ) generate_items_inside(items_inside,src) +// Variant on the civil defense medkit for spacer planetside personnel (or other people suffering from chronic illnesses) +/obj/item/storage/medkit/civil_defense/comfort + name = "civil defense symptom support kit" + desc = "A small, pocket-sized kit that can typically only fit autoinjectors in it. This variant on the classic 'cheese' civil defense kit contains supplies to address hindering symptomatic burden associated with common chronic diseases or adaptation syndromes, such as gravity sickness." + icon_state = "symptom_kit" + +/obj/item/storage/medkit/civil_defense/comfort/stocked + +/obj/item/storage/medkit/civil_defense/comfort/stocked/PopulateContents() + var/static/items_inside = list( + /obj/item/reagent_containers/hypospray/medipen/deforest/psifinil = 3, + /obj/item/storage/pill_bottle/prescription_stimulant = 1, + ) + generate_items_inside(items_inside, src) + // Pre-packed frontier medkit, with supplies to repair most common frontier health issues /obj/item/storage/medkit/frontier name = "frontier medical kit" diff --git a/modular_nova/modules/deforest_medical_items/icons/storage.dmi b/modular_nova/modules/deforest_medical_items/icons/storage.dmi index 516e7cd30a7..5335ffddda0 100644 Binary files a/modular_nova/modules/deforest_medical_items/icons/storage.dmi and b/modular_nova/modules/deforest_medical_items/icons/storage.dmi differ diff --git a/modular_nova/modules/gunhud/code/gun_hud.dm b/modular_nova/modules/gunhud/code/gun_hud.dm index e323026cb0b..b9f8886b572 100644 --- a/modular_nova/modules/gunhud/code/gun_hud.dm +++ b/modular_nova/modules/gunhud/code/gun_hud.dm @@ -33,6 +33,8 @@ var/oth_h ///This is the custom indicator sprite that will appear in the box at the bottom of the ammo hud, use this for something like semi/auto toggle on a gun. var/indicator + // is the ui on or off? + var/on ///This proc simply resets the hud to standard and removes it from the players visible hud. /atom/movable/screen/ammo_counter/proc/turn_off() @@ -45,10 +47,12 @@ oth_h = "" indicator = "" update_appearance() + on = FALSE ///This proc turns the hud on, but does not set it to anything other than the currently set values /atom/movable/screen/ammo_counter/proc/turn_on() invisibility = 0 + on = TRUE ///This is the main proc for altering the hud's appeareance, it controls the setting of the overlays. Use the OTH and below variables to set it accordingly. /atom/movable/screen/ammo_counter/proc/set_hud(_backing_color, _oth_o, _oth_t, _oth_h, _indicator, _oth_backing = "oth_light") diff --git a/modular_nova/modules/gunhud/code/gun_hud_component.dm b/modular_nova/modules/gunhud/code/gun_hud_component.dm index 54b8122fb10..33a2a686aab 100644 --- a/modular_nova/modules/gunhud/code/gun_hud_component.dm +++ b/modular_nova/modules/gunhud/code/gun_hud_component.dm @@ -1,5 +1,8 @@ /datum/component/ammo_hud + /// The ammo counter screen object itself var/atom/movable/screen/ammo_counter/hud + /// A weakref to the mob who currently owns the hud + var/datum/weakref/current_hud_owner /datum/component/ammo_hud/Initialize() . = ..() @@ -19,15 +22,17 @@ if(H.is_holding(parent)) if(H.hud_used) hud = H.hud_used.ammo_counter - RegisterSignal(user, COMSIG_QDELETING, PROC_REF(turn_off)) - turn_on() + if(!hud.on) // make sure we're not already turned on + current_hud_owner = WEAKREF(user) + RegisterSignal(user, COMSIG_QDELETING, PROC_REF(turn_off)) + turn_on() else - UnregisterSignal(user, COMSIG_QDELETING) turn_off() /datum/component/ammo_hud/proc/turn_on() SIGNAL_HANDLER + RegisterSignal(hud, COMSIG_QDELETING, PROC_REF(turn_off)) RegisterSignals(parent, list(COMSIG_PREQDELETED, COMSIG_ITEM_DROPPED), PROC_REF(turn_off)) RegisterSignals(parent, list(COMSIG_UPDATE_AMMO_HUD, COMSIG_GUN_CHAMBER_PROCESSED), PROC_REF(update_hud)) @@ -38,11 +43,19 @@ SIGNAL_HANDLER UnregisterSignal(parent, list(COMSIG_PREQDELETED, COMSIG_ITEM_DROPPED, COMSIG_UPDATE_AMMO_HUD, COMSIG_GUN_CHAMBER_PROCESSED)) + var/mob/living/carbon/human/current_owner = current_hud_owner?.resolve() + if(isnull(current_owner)) + current_hud_owner = null + else + UnregisterSignal(current_owner, COMSIG_QDELETING) if(hud) hud.turn_off() + UnregisterSignal(hud, COMSIG_QDELETING) hud = null + current_hud_owner = null + /// Returns get_ammo() with the appropriate args passed to it - some guns like the revolver and bow are special cases /datum/component/ammo_hud/proc/get_accurate_ammo_count(obj/item/gun/ballistic/the_gun) // fucking revolvers indeed - do not count empty or chambered rounds for the display HUD diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_accessory.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_accessory.dm index addd37faf58..05a1051ec6f 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_accessory.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_accessory.dm @@ -75,6 +75,16 @@ GLOBAL_LIST_INIT(loadout_accessory, generate_loadout_items(/datum/loadout_item/a item_path = /obj/item/clothing/accessory/armband/deputy/lopland restricted_roles = list(JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_CORRECTIONS_OFFICER) +/datum/loadout_item/accessory/holobadge + name = "Holobadge" + item_path = /obj/item/clothing/accessory/badge/holo + restricted_roles = list(JOB_SECURITY_OFFICER, JOB_DETECTIVE, JOB_WARDEN, JOB_HEAD_OF_SECURITY) + +/datum/loadout_item/accessory/holobadge/lanyard + name = "Holobadge with Lanyard" + item_path = /obj/item/clothing/accessory/badge/holo/cord + restricted_roles = list(JOB_SECURITY_OFFICER, JOB_DETECTIVE, JOB_WARDEN, JOB_HEAD_OF_SECURITY) + /datum/loadout_item/accessory/armband_security_deputy name = "Security Deputy Armband" item_path = /obj/item/clothing/accessory/armband/deputy diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_heads.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_heads.dm index 40ab19257ea..472325aa505 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_heads.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_heads.dm @@ -129,6 +129,14 @@ GLOBAL_LIST_INIT(loadout_helmets, generate_loadout_items(/datum/loadout_item/hea name = "Mothic Softcap" item_path = /obj/item/clothing/head/mothcap +/datum/loadout_item/head/frontiercap + name = "Frontier Cap" + item_path = /obj/item/clothing/head/soft/frontier_colonist + +/datum/loadout_item/head/frontiercap/medic + name = "Frontier Medical Cap" + item_path = /obj/item/clothing/head/soft/frontier_colonist/medic + /* * FEDORAS */ diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_inhands.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_inhands.dm index 7d3cb8ff756..51ad30f2881 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_inhands.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_inhands.dm @@ -43,6 +43,18 @@ GLOBAL_LIST_INIT(loadout_inhand_items, generate_loadout_items(/datum/loadout_ite name = "Secure Briefcase" item_path = /obj/item/storage/briefcase/secure +/datum/loadout_item/inhand/guncase_large + name = "Black Empty Gun Case (Large)" + item_path = /obj/item/storage/toolbox/guncase/nova/empty + +/datum/loadout_item/inhand/guncase_large/yellow + name = "Yellow Empty Gun Case (Large)" + item_path = /obj/item/storage/toolbox/guncase/nova/carwo_large_case/empty + +/datum/loadout_item/inhand/guncase_small + name = "Black Empty Gun Case (Small)" + item_path = /obj/item/storage/toolbox/guncase/nova/pistol/empty + /datum/loadout_item/inhand/skub name = "Skub" item_path = /obj/item/skub diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_neck.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_neck.dm index df9f0c69c27..bb8d4a3e326 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_neck.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_neck.dm @@ -287,16 +287,6 @@ GLOBAL_LIST_INIT(loadout_necks, generate_loadout_items(/datum/loadout_item/neck) name = "MODlink Scryer" item_path = /obj/item/clothing/neck/link_scryer/loaded -/datum/loadout_item/neck/holobadge - name = "Holobadge" - item_path = /obj/item/clothing/accessory/badge/holo - restricted_roles = list(JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_CORRECTIONS_OFFICER) - -/datum/loadout_item/neck/holobadge_cord - name = "Holobadge with Lanyard" - item_path = /obj/item/clothing/accessory/badge/holo/cord - restricted_roles = list(JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_CORRECTIONS_OFFICER) - /* * DONATOR */ diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_pocket.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_pocket.dm index da283f05b73..13cc3d67dd1 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_pocket.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_pocket.dm @@ -117,6 +117,10 @@ GLOBAL_LIST_INIT(loadout_pocket_items, generate_loadout_items(/datum/loadout_ite name = "Personal AI Device" item_path = /obj/item/pai_card +/datum/loadout_item/pocket_items/link_scryer + name = "MODlink Scryer" + item_path = /obj/item/clothing/neck/link_scryer/loaded + /datum/loadout_item/pocket_items/cigarettes name = "Cigarette Pack" item_path = /obj/item/storage/fancy/cigarettes @@ -201,6 +205,14 @@ GLOBAL_LIST_INIT(loadout_pocket_items, generate_loadout_items(/datum/loadout_ite name = "First-Aid Kit" item_path = /obj/item/storage/medkit/regular +/datum/loadout_item/pocket_items/deforest_cheesekit + name = "Civil Defense Medical Kit" + item_path = /obj/item/storage/medkit/civil_defense/stocked + +/datum/loadout_item/pocket_items/deforest_frontiermedkit + name = "Frontier Medical Kit" + item_path = /obj/item/storage/medkit/frontier/stocked + /datum/loadout_item/pocket_items/ingredients name = "Wildcard Ingredient Box" item_path = /obj/item/storage/box/ingredients/wildcard diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_shoes.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_shoes.dm index 71d665a904e..8f630213683 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_shoes.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_shoes.dm @@ -42,6 +42,10 @@ GLOBAL_LIST_INIT(loadout_shoes, generate_loadout_items(/datum/loadout_item/shoes name = "Recolorable Jackboots" item_path = /obj/item/clothing/shoes/jackboots/recolorable +/datum/loadout_item/shoes/jackboots/frontier + name = "Heavy Frontier Boots" + item_path = /obj/item/clothing/shoes/jackboots/frontier_colonist + /* * MISC BOOTS */ @@ -219,6 +223,10 @@ GLOBAL_LIST_INIT(loadout_shoes, generate_loadout_items(/datum/loadout_item/shoes name = "Roller Skates" item_path = /obj/item/clothing/shoes/wheelys/rollerskates +/datum/loadout_item/shoes/wheelys + name = "Wheely-Heels" + item_path = /obj/item/clothing/shoes/wheelys + /datum/loadout_item/shoes/jingleshoes name = "Jester Shoes" item_path = /obj/item/clothing/shoes/jester_shoes diff --git a/modular_nova/modules/loadouts/loadout_items/loadout_datum_suit.dm b/modular_nova/modules/loadouts/loadout_items/loadout_datum_suit.dm index c3ad43d7ca1..962e2ffcebf 100644 --- a/modular_nova/modules/loadouts/loadout_items/loadout_datum_suit.dm +++ b/modular_nova/modules/loadouts/loadout_items/loadout_datum_suit.dm @@ -347,7 +347,7 @@ GLOBAL_LIST_INIT(loadout_exosuits, generate_loadout_items(/datum/loadout_item/su /datum/loadout_item/suit/croptop name = "Crop Top Turtleneck" - item_path = /obj/item/clothing/suit/croptop + item_path = /obj/item/clothing/suit/jacket/croptop /* * FLANNELS @@ -390,6 +390,10 @@ GLOBAL_LIST_INIT(loadout_exosuits, generate_loadout_items(/datum/loadout_item/su name = "Blue Trenchcoat" item_path = /obj/item/clothing/suit/frenchtrench +/datum/loadout_item/suit/frontiertrench + name = "Frontier Trenchcoat" + item_path = /obj/item/clothing/suit/jacket/frontier_colonist + /datum/loadout_item/suit/cossak name = "Ukrainian Coat" item_path = /obj/item/clothing/suit/cossack @@ -430,6 +434,14 @@ GLOBAL_LIST_INIT(loadout_exosuits, generate_loadout_items(/datum/loadout_item/su name = "Colourable Leather Jacket" item_path = /obj/item/clothing/suit/jacket/leather/colourable +/datum/loadout_item/suit/frontierjacket/short + name = "Frontier Jacket (Short)" + item_path = /obj/item/clothing/suit/jacket/frontier_colonist/short + +/datum/loadout_item/suit/frontierjacket/short/medical + name = "Frontier Medical Jacket (Short)" + item_path = /obj/item/clothing/suit/jacket/frontier_colonist/medical + /datum/loadout_item/suit/woolcoat name = "Leather Overcoat" item_path = /obj/item/clothing/suit/woolcoat @@ -607,6 +619,15 @@ GLOBAL_LIST_INIT(loadout_exosuits, generate_loadout_items(/datum/loadout_item/su item_path = /obj/item/clothing/suit/british_officer restricted_roles = list(JOB_WARDEN, JOB_DETECTIVE, JOB_SECURITY_OFFICER, JOB_HEAD_OF_SECURITY, JOB_CORRECTIONS_OFFICER) +/datum/loadout_item/suit/peacekeeper_jacket + name = "Peacekeeper Jacket" + item_path = /obj/item/clothing/suit/armor/vest/peacekeeper/jacket + restricted_roles = list(JOB_WARDEN, JOB_DETECTIVE, JOB_SECURITY_OFFICER, JOB_HEAD_OF_SECURITY, JOB_CORRECTIONS_OFFICER) + +/datum/loadout_item/suit/peacekeeper_jacket/badge + name = "Badged Peacekeeper Jacket" + item_path = /obj/item/clothing/suit/armor/vest/peacekeeper/jacket/badge + /datum/loadout_item/suit/offdep_jacket name = "Off-Department Jacket" item_path = /obj/item/clothing/suit/toggle/jacket/assistant diff --git a/modular_nova/modules/loadouts/loadout_items/under/loadout_datum_under.dm b/modular_nova/modules/loadouts/loadout_items/under/loadout_datum_under.dm index 1142a669374..f25ac98a40c 100644 --- a/modular_nova/modules/loadouts/loadout_items/under/loadout_datum_under.dm +++ b/modular_nova/modules/loadouts/loadout_items/under/loadout_datum_under.dm @@ -51,6 +51,10 @@ GLOBAL_LIST_INIT(loadout_miscunders, generate_loadout_items(/datum/loadout_item/ item_path = /obj/item/clothing/under/color/jumpskirt/random additional_tooltip_contents = list(TOOLTIP_RANDOM_COLOR) +/datum/loadout_item/under/jumpsuit/frontier + name = "Frontier Jumpsuit" + item_path = /obj/item/clothing/under/frontier_colonist + /datum/loadout_item/under/jumpsuit/rainbow name = "Rainbow Jumpsuit" item_path = /obj/item/clothing/under/color/rainbow diff --git a/modular_nova/modules/mapping/code/spaceship_turfs.dm b/modular_nova/modules/mapping/code/spaceship_turfs.dm index cef19636158..52f2d75a350 100644 --- a/modular_nova/modules/mapping/code/spaceship_turfs.dm +++ b/modular_nova/modules/mapping/code/spaceship_turfs.dm @@ -14,10 +14,6 @@ icon_state = "map-shuttle_nd" smoothing_flags = SMOOTH_BITMASK -/turf/closed/wall/mineral/titanium/spaceship/nosmooth - icon_state = "ship_walls-0" - smoothing_flags = NONE - /turf/closed/wall/mineral/titanium/spaceship/overspace icon_state = "map-overspace" smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS diff --git a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm index 66cbbb510b2..92f74d8b508 100644 --- a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm +++ b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm @@ -89,6 +89,8 @@ var/last_time_victim_moved = 0 processes = TRUE + /// Whenever an oscillation is triggered by movement, we wait 4 seconds before trying to do another. + COOLDOWN_DECLARE(movement_stagger_cooldown) /datum/wound_pregen_data/blunt_metal abstract = TRUE @@ -249,7 +251,7 @@ message += "!" self_message += "! You might be able to avoid an aftershock by stopping and waiting..." - if (isnull(attack_direction)) + if (isnull(attack_direction) && !isnull(attacking_item)) attack_direction = get_dir(victim, attacking_item) if (!isnull(attack_direction) && prob(stagger_score * stagger_movement_chance_ratio)) @@ -359,9 +361,10 @@ overall_mult *= get_buckled_movement_consequence_mult(victim.buckled) - if (limb.body_zone == BODY_ZONE_CHEST) + if (limb.body_zone == BODY_ZONE_CHEST && COOLDOWN_FINISHED(src, movement_stagger_cooldown)) var/stagger_chance = chest_movement_stagger_chance * overall_mult if (prob(stagger_chance)) + COOLDOWN_START(src, movement_stagger_cooldown, 4 SECONDS) stagger(base_movement_stagger_score, shake_duration = base_stagger_movement_shake_duration, from_movement = TRUE, shift = movement_stagger_shift, knockdown_ratio = stagger_aftershock_knockdown_movement_ratio) last_time_victim_moved = world.time diff --git a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm index 9cd2ae0adbb..19541a4dc8e 100644 --- a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm +++ b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm @@ -43,7 +43,7 @@ var/delay_mult = 1 if (user == victim) - delay_mult *= 3 + delay_mult *= 2 if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) delay_mult *= 0.5 @@ -56,7 +56,7 @@ victim.visible_message(span_notice("[user] begins fastening the screws of [their_or_other] [limb.plaintext_zone]..."), \ span_notice("You begin fastening the screws of [your_or_other] [limb.plaintext_zone]...")) - if (!screwdriver_tool.use_tool(target = victim, user = user, delay = (10 SECONDS * delay_mult), volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if (!screwdriver_tool.use_tool(target = victim, user = user, delay = (6 SECONDS * delay_mult), volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return victim.visible_message(span_green("[user] finishes fastening [their_or_other] [limb.plaintext_zone]!"), \ diff --git a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm index 68bac1fe12b..1dd35f14bed 100644 --- a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm +++ b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm @@ -32,7 +32,7 @@ chest_attacked_stagger_chance_ratio = 5 chest_attacked_stagger_mult = 3 - chest_movement_stagger_chance = 3 + chest_movement_stagger_chance = 2 stagger_aftershock_knockdown_ratio = 0.3 stagger_aftershock_knockdown_movement_ratio = 0.2 diff --git a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm index 14f6f30a2af..e30c4aeed1c 100644 --- a/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm +++ b/modular_nova/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm @@ -38,7 +38,7 @@ status_effect_type = /datum/status_effect/wound/blunt/robotic/critical treatable_tools = list(TOOL_WELDER, TOOL_CROWBAR) - base_movement_stagger_score = 55 + base_movement_stagger_score = 50 base_aftershock_camera_shake_duration = 1.75 SECONDS base_aftershock_camera_shake_strength = 1 @@ -46,7 +46,7 @@ chest_attacked_stagger_chance_ratio = 6.5 chest_attacked_stagger_mult = 4 - chest_movement_stagger_chance = 14 + chest_movement_stagger_chance = 8 aftershock_stopped_moving_score_mult = 0.3 @@ -117,7 +117,7 @@ if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) delay_mult *= 0.75 - if(!do_after(user, 8 SECONDS, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if(!do_after(user, 4 SECONDS, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return mold_metal(user) return TRUE @@ -213,7 +213,7 @@ if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) delay_mult *= 0.75 - if (!welder.use_tool(target = victim, user = user, delay = 10 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if (!welder.use_tool(target = victim, user = user, delay = 7 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return TRUE var/wound_path = /datum/wound/burn/robotic/overheat/severe @@ -249,11 +249,11 @@ var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") var/your_or_other = (user == victim ? "your" : "[victim]'s") - var/base_time = 10 SECONDS + var/base_time = 7 SECONDS var/delay_mult = 1 var/knows_wires = FALSE if (victim == user) - delay_mult *= 3 // real slow + delay_mult *= 2 if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) delay_mult *= 0.75 if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) @@ -335,7 +335,7 @@ delay_mult /= treating_plunger.plunge_mod - if (!treating_plunger.use_tool(target = victim, user = user, delay = 8 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if (!treating_plunger.use_tool(target = victim, user = user, delay = 6 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return TRUE var/success_chance = 80 diff --git a/modular_nova/modules/medical/code/wounds/synth/blunt/secures_internals.dm b/modular_nova/modules/medical/code/wounds/synth/blunt/secures_internals.dm index d4483dafb0b..e15dd40ba1d 100644 --- a/modular_nova/modules/medical/code/wounds/synth/blunt/secures_internals.dm +++ b/modular_nova/modules/medical/code/wounds/synth/blunt/secures_internals.dm @@ -340,14 +340,14 @@ var/delay_mult = 1 if (victim == user) - delay_mult *= 0.5 + delay_mult *= 1.5 if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) delay_mult *= 0.75 user.visible_message(span_danger("[user] begins hastily applying [gel] to [victim]'s [limb.plaintext_zone]..."), span_warning("You begin hastily applying [gel] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone], disregarding the acidic effect it seems to have on the metal...")) - if (!do_after(user, (8 SECONDS * delay_mult), target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if (!do_after(user, (6 SECONDS * delay_mult), target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return TRUE gel.use(1) diff --git a/modular_nova/modules/medical/code/wounds/synth/robotic_pierce.dm b/modular_nova/modules/medical/code/wounds/synth/robotic_pierce.dm index 09cc878afd4..501c0391063 100644 --- a/modular_nova/modules/medical/code/wounds/synth/robotic_pierce.dm +++ b/modular_nova/modules/medical/code/wounds/synth/robotic_pierce.dm @@ -41,7 +41,7 @@ process_shock_spark_count_max = 1 process_shock_spark_count_min = 1 - wirecut_repair_percent = 0.065 // not even faster at this point + wirecut_repair_percent = 0.104 wire_repair_percent = 0.026 initial_sparks_amount = 1 @@ -84,7 +84,7 @@ process_shock_spark_count_max = 2 process_shock_spark_count_min = 1 - wirecut_repair_percent = 0.068 + wirecut_repair_percent = 0.08 wire_repair_percent = 0.02 initial_sparks_amount = 3 @@ -129,7 +129,7 @@ process_shock_spark_count_max = 3 process_shock_spark_count_min = 2 - wirecut_repair_percent = 0.067 + wirecut_repair_percent = 0.072 wire_repair_percent = 0.018 initial_sparks_amount = 8 diff --git a/modular_nova/modules/medical/code/wounds/synth/robotic_slash.dm b/modular_nova/modules/medical/code/wounds/synth/robotic_slash.dm index f01e90a8b47..b6b0216ef72 100644 --- a/modular_nova/modules/medical/code/wounds/synth/robotic_slash.dm +++ b/modular_nova/modules/medical/code/wounds/synth/robotic_slash.dm @@ -326,12 +326,12 @@ var/change = (processing_full_shock_threshold * wire_repair_percent) * ELECTRICAL_DAMAGE_SUTURE_WIRE_HEALING_AMOUNT_MULT var/delay_mult = 1 if (user == victim) - delay_mult *= 1.5 + delay_mult *= 1.4 if (is_suture) - delay_mult *= 2 + delay_mult *= 1.5 var/obj/item/stack/medical/suture/suture_item = suturing_item var/obj/item/stack/medical/suture/base_suture = /obj/item/stack/medical/suture - change += (suture_item.heal_brute - initial(base_suture.heal_brute)) + change = max(change - (suture_item.heal_brute - initial(base_suture.heal_brute)), 0.00001) // as this is the trauma treatment, there are less bonuses // if youre doing this, youre probably doing this on-the-spot @@ -342,7 +342,7 @@ if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) delay_mult *= 0.8 if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) - change *= 1.2 + change *= 1.5 var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") var/your_or_other = (user == victim ? "your" : "[victim]'s") @@ -385,17 +385,15 @@ var/change = (processing_full_shock_threshold * wirecut_repair_percent) var/delay_mult = 1 if (user == victim) - delay_mult *= 2.5 + delay_mult *= 2 if (is_retractor) delay_mult *= 2 - change *= 0.8 var/knows_wires = FALSE if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) - delay_mult *= 0.9 - change *= 1.7 + delay_mult *= 0.3 knows_wires = TRUE else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) - change *= 1.35 + delay_mult *= 0.6 knows_wires = TRUE if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) if (knows_wires) @@ -403,7 +401,7 @@ else delay_mult *= 0.75 if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) - delay_mult *= 0.8 + change *= 1.5 var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") var/your_or_other = (user == victim ? "your" : "[victim]'s") @@ -518,7 +516,7 @@ process_shock_spark_count_max = 1 process_shock_spark_count_min = 1 - wirecut_repair_percent = 0.085 // not even faster at this point + wirecut_repair_percent = 0.14 wire_repair_percent = 0.035 initial_sparks_amount = 1 @@ -561,7 +559,7 @@ process_shock_spark_count_max = 2 process_shock_spark_count_min = 1 - wirecut_repair_percent = 0.1 + wirecut_repair_percent = 0.128 wire_repair_percent = 0.032 initial_sparks_amount = 3 @@ -581,7 +579,7 @@ name = "Systemic Fault" desc = "A significant portion of the power distribution network has been cut open, resulting in massive power loss and runaway electrocution." occur_text = "lets out a violent \"zhwarp\" sound as angry electric arcs attack the surrounding air" - examine_desc = "has lots of wires mauled wires sticking out" + examine_desc = "has lots of mauled wires sticking out" treat_text = "Immediate securing via gauze, followed by emergency cable replacement and securing via wirecutters or retractor. \ If the fault has become uncontrollable, extreme heat therapy is recommended." diff --git a/modular_nova/modules/modular_implants/code/nifs.dm b/modular_nova/modules/modular_implants/code/nifs.dm index 35177c8c0cf..8f8a0fcb99f 100644 --- a/modular_nova/modules/modular_implants/code/nifs.dm +++ b/modular_nova/modules/modular_implants/code/nifs.dm @@ -20,6 +20,7 @@ w_class = WEIGHT_CLASS_NORMAL slot = ORGAN_SLOT_BRAIN_NIF actions_types = list(/datum/action/item_action/nif/open_menu) + cannot_confiscate = TRUE //User Variables ///What user is currently linked with the NIF? diff --git a/modular_nova/modules/modular_vending/code/clothesmate.dm b/modular_nova/modules/modular_vending/code/clothesmate.dm index 2d9f1dfad31..94a1981a733 100644 --- a/modular_nova/modules/modular_vending/code/clothesmate.dm +++ b/modular_nova/modules/modular_vending/code/clothesmate.dm @@ -121,7 +121,7 @@ /obj/item/clothing/suit/urban = 5, /obj/item/clothing/suit/duster = 5, /obj/item/clothing/suit/fallsparka = 5, - /obj/item/clothing/suit/croptop = 5, + /obj/item/clothing/suit/jacket/croptop = 5, /obj/item/clothing/suit/modernwintercoatthing = 5, /obj/item/clothing/suit/hooded/wintercoat/colourable = 5, /obj/item/clothing/suit/apron/chef/colorable_apron = 5, diff --git a/modular_nova/modules/modular_vending/code/wardrobes.dm b/modular_nova/modules/modular_vending/code/wardrobes.dm index f9bda75749a..29275ff6044 100644 --- a/modular_nova/modules/modular_vending/code/wardrobes.dm +++ b/modular_nova/modules/modular_vending/code/wardrobes.dm @@ -74,6 +74,10 @@ /obj/item/storage/backpack/messenger/science/robo = 2, ) + contraband_nova = list( + /obj/item/organ/internal/tongue/lizard/robot = 2, + ) + /obj/machinery/vending/wardrobe/science_wardrobe products_nova = list( /obj/item/clothing/under/rank/rnd/scientist/nova/hlscience = 3, diff --git a/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/szot_dynamica/ammo/rifle.dm b/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/szot_dynamica/ammo/rifle.dm index e53c55c62e9..a96faa34fcd 100644 --- a/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/szot_dynamica/ammo/rifle.dm +++ b/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/szot_dynamica/ammo/rifle.dm @@ -61,8 +61,13 @@ demolition_mod = 1.8 /// How much damage we add to things that are weak to this bullet var/anti_materiel_damage_addition = 30 - -/obj/projectile/bullet/p60strela/Initialize(mapload) - . = ..() - // We do 80 total damage to anything robotic, namely borgs, and robotic simplemobs - AddElement(/datum/element/bane, target_type = /mob/living, mob_biotypes = MOB_ROBOTIC, damage_multiplier = 0, added_damage = anti_materiel_damage_addition) + /// What biotype we look for + var/biotype_we_look_for = MOB_ROBOTIC + +/obj/projectile/bullet/p60strela/on_hit(atom/target, blocked, pierce_hit) + if(!isliving(target) || (damage > initial(damage))) + return ..() + var/mob/living/target_mob = target + if(target_mob.mob_biotypes & biotype_we_look_for) + damage += anti_materiel_damage_addition + return ..() diff --git a/modular_nova/modules/organs/code/tongue.dm b/modular_nova/modules/organs/code/tongue.dm index c803bfc90c9..593211a652c 100644 --- a/modular_nova/modules/organs/code/tongue.dm +++ b/modular_nova/modules/organs/code/tongue.dm @@ -54,6 +54,39 @@ /obj/item/organ/internal/tongue/human say_mod = "says" +/obj/item/organ/internal/tongue/lizard/robot + name = "robotic lizard voicebox" + desc = "A lizard-like voice synthesizer that can interface with organic lifeforms." + organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES + icon_state = "tonguerobot" + say_mod = "hizzes" + attack_verb_continuous = list("beeps", "boops") + attack_verb_simple = list("beep", "boop") + modifies_speech = TRUE + taste_sensitivity = 25 // not as good as an organic tongue + liked_foodtypes = NONE + disliked_foodtypes = NONE + voice_filter = "alimiter=0.9,acompressor=threshold=0.2:ratio=20:attack=10:release=50:makeup=2,highpass=f=1000" + +/obj/item/organ/internal/tongue/lizard/robot/can_speak_language(language) + return TRUE // THE MAGIC OF ELECTRONICS + +/obj/item/organ/internal/tongue/lizard/robot/modify_speech(datum/source, list/speech_args) + . = ..() + speech_args[SPEECH_SPANS] |= SPAN_ROBOT + +/obj/item/organ/internal/tongue/lizard/cybernetic + name = "forked cybernetic tongue" + icon = 'modular_nova/modules/organs/icons/cyber_tongue.dmi' + icon_state = "cybertongue-lizard" + desc = "A fully-functional forked synthetic tongue, encased in soft silicone. Features include high-resolution vocals and taste receptors." + organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES + // Not as good as organic tongues, not as bad as the robotic voicebox. + taste_sensitivity = 20 + liked_foodtypes = NONE + disliked_foodtypes = NONE + modifies_speech = TRUE + /obj/item/organ/internal/tongue/cybernetic name = "cybernetic tongue" icon = 'modular_nova/modules/organs/icons/cyber_tongue.dmi' @@ -63,6 +96,8 @@ say_mod = "says" // Not as good as organic tongues, not as bad as the robotic voicebox. taste_sensitivity = 20 + liked_foodtypes = NONE + disliked_foodtypes = NONE /obj/item/organ/internal/tongue/vox name = "vox tongue" diff --git a/modular_nova/modules/organs/icons/cyber_tongue.dmi b/modular_nova/modules/organs/icons/cyber_tongue.dmi index 961aeb14f26..f2442fda533 100644 Binary files a/modular_nova/modules/organs/icons/cyber_tongue.dmi and b/modular_nova/modules/organs/icons/cyber_tongue.dmi differ diff --git a/modular_nova/modules/organs/icons/snail_eyes.dmi b/modular_nova/modules/organs/icons/snail_eyes.dmi index f916f09daea..aae11d7d5c9 100644 Binary files a/modular_nova/modules/organs/icons/snail_eyes.dmi and b/modular_nova/modules/organs/icons/snail_eyes.dmi differ diff --git a/modular_nova/modules/sec_haul/code/misc/vending.dm b/modular_nova/modules/sec_haul/code/misc/vending.dm index c095290a116..9e73d3225ed 100644 --- a/modular_nova/modules/sec_haul/code/misc/vending.dm +++ b/modular_nova/modules/sec_haul/code/misc/vending.dm @@ -44,6 +44,8 @@ products = list(/obj/item/clothing/suit/hooded/wintercoat/security = 5, /obj/item/clothing/suit/toggle/jacket/sec = 5, /obj/item/clothing/suit/armor/vest/peacekeeper/brit = 5, + /obj/item/clothing/suit/armor/vest/peacekeeper/jacket = 5, + /obj/item/clothing/suit/armor/vest/peacekeeper/jacket/badge = 5, /obj/item/clothing/neck/security_cape = 5, /obj/item/clothing/neck/security_cape/armplate = 5, /obj/item/storage/backpack/security = 5, diff --git a/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm b/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm index 9a153d53f87..0bec7722bad 100644 --- a/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm +++ b/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm @@ -125,6 +125,26 @@ worn_icon_state = "peacekeeper_spacecoat" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON +/obj/item/clothing/suit/armor/vest/peacekeeper/jacket + name = "peacekeeper jacket" + desc = "A slightly vintage canvas and aramid jacket; hi-vis checkers included. Armored and stylish? Implausible." + icon = 'modular_nova/master_files/icons/obj/clothing/suits/armor.dmi' + worn_icon = 'modular_nova/master_files/icons/mob/clothing/suits/armor.dmi' + icon_state = "peacekeeper_jacket" + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + body_parts_covered = CHEST|GROIN|ARMS + cold_protection = CHEST|GROIN|ARMS + heat_protection = CHEST|GROIN|ARMS + +/obj/item/clothing/suit/armor/vest/peacekeeper/jacket/Initialize(mapload) + . = ..() + AddComponent(/datum/component/toggle_icon, "zipper") + +/obj/item/clothing/suit/armor/vest/peacekeeper/jacket/badge + name = "badged peacekeeper jacket" + desc = "A slightly vintage canvas and aramid jacket; hi-vis checkers and chevron badge included. Armored and stylish? Implausible." + icon_state = "peacekeeper_jacket_badge" + //PEACEKEEPER GLOVES /obj/item/clothing/gloves/combat/peacekeeper name = "peacekeeper gloves" diff --git a/modular_nova/modules/shotgunrebalance/code/shotgun.dm b/modular_nova/modules/shotgunrebalance/code/shotgun.dm index 1c96b0ebeb2..c66154f6ae5 100644 --- a/modular_nova/modules/shotgunrebalance/code/shotgun.dm +++ b/modular_nova/modules/shotgunrebalance/code/shotgun.dm @@ -247,6 +247,25 @@ /obj/projectile/bullet/shotgun_slug/hunter name = "12g hunter slug" damage = 20 + range = 12 + /// How much the damage is multiplied by when we hit a mob with the correct biotype + var/biotype_damage_multiplier = 5 + /// What biotype we look for + var/biotype_we_look_for = MOB_BEAST + +/obj/projectile/bullet/shotgun_slug/hunter/on_hit(atom/target, blocked, pierce_hit) + if(ismineralturf(target)) + var/turf/closed/mineral/mineral_turf = target + mineral_turf.gets_drilled(firer, FALSE) + if(range > 0) + return BULLET_ACT_FORCE_PIERCE + return ..() + if(!isliving(target) || (damage > initial(damage))) + return ..() + var/mob/living/target_mob = target + if(target_mob.mob_biotypes & biotype_we_look_for || istype(target_mob, /mob/living/simple_animal/hostile/megafauna)) + damage *= biotype_damage_multiplier + return ..() /obj/projectile/bullet/shotgun_slug/hunter/Initialize(mapload) . = ..() diff --git a/modular_nova/modules/synths/code/bodyparts/power_cord.dm b/modular_nova/modules/synths/code/bodyparts/power_cord.dm index c8ff5bb58f6..cbe59f6b231 100644 --- a/modular_nova/modules/synths/code/bodyparts/power_cord.dm +++ b/modular_nova/modules/synths/code/bodyparts/power_cord.dm @@ -10,6 +10,7 @@ desc = "An internal power cord. Useful if you run on elecricity. Not so much otherwise." contents = newlist(/obj/item/apc_powercord) zone = "l_arm" + cannot_confiscate = TRUE /obj/item/apc_powercord name = "power cord" diff --git a/strings/antagonist_flavor/traitor_flavor.json b/strings/antagonist_flavor/traitor_flavor.json index 93da8d01374..773d2f55370 100644 --- a/strings/antagonist_flavor/traitor_flavor.json +++ b/strings/antagonist_flavor/traitor_flavor.json @@ -111,5 +111,13 @@ "roundend_report": "was a terrorist from Waffle Corporation.", "ui_theme": "syndicate", "uplink": "You have been provided with a standard uplink to accomplish your task." + }, + "Contractor Support Unit": { + "allies": "You are being sent to help your designated agent. Their allegiences are above all others.", + "goal": "Help your designated agent to the furtest extent you can, their life is above your own.", + "introduction": "You are the Contractor Support Agent.", + "roundend_report": "was a contractor support agent.", + "ui_theme": "syndicate", + "uplink": "You do not come with your own uplink, defer to your agent." } } diff --git a/strings/names/cargorilla.txt b/strings/names/cargorilla.txt new file mode 100644 index 00000000000..ec135f5ca4d --- /dev/null +++ b/strings/names/cargorilla.txt @@ -0,0 +1,7 @@ +Cala +Cerchak +Citrus +Coco +Grodd +Paperwork +Winston diff --git a/tgstation.dme b/tgstation.dme index 8d3c963e83a..b1f4f87d928 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1843,6 +1843,7 @@ #include "code\datums\skills\mining.dm" #include "code\datums\station_traits\_station_trait.dm" #include "code\datums\station_traits\admin_panel.dm" +#include "code\datums\station_traits\job_traits.dm" #include "code\datums\station_traits\negative_traits.dm" #include "code\datums\station_traits\neutral_traits.dm" #include "code\datums\station_traits\positive_traits.dm" @@ -4243,6 +4244,7 @@ #include "code\modules\jobs\job_types\bartender.dm" #include "code\modules\jobs\job_types\botanist.dm" #include "code\modules\jobs\job_types\captain.dm" +#include "code\modules\jobs\job_types\cargo_gorilla.dm" #include "code\modules\jobs\job_types\cargo_technician.dm" #include "code\modules\jobs\job_types\chemist.dm" #include "code\modules\jobs\job_types\chief_engineer.dm" @@ -4330,6 +4332,8 @@ #include "code\modules\jobs\job_types\spawner\syndicate_cybersun_captain.dm" #include "code\modules\jobs\job_types\spawner\venus_human_trap.dm" #include "code\modules\jobs\job_types\spawner\zombie.dm" +#include "code\modules\jobs\job_types\station_trait\bridge_assistant.dm" +#include "code\modules\jobs\job_types\station_trait\cargo_gorilla.dm" #include "code\modules\keybindings\bindings_atom.dm" #include "code\modules\keybindings\bindings_client.dm" #include "code\modules\keybindings\focus.dm" @@ -4559,7 +4563,6 @@ #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" #include "code\modules\mob\camera\camera.dm" -#include "code\modules\mob\dead\crew_manifest.dm" #include "code\modules\mob\dead\dead.dm" #include "code\modules\mob\dead\new_player\latejoin_menu.dm" #include "code\modules\mob\dead\new_player\login.dm" @@ -6216,6 +6219,7 @@ #include "modular_nova\master_files\code\datums\quirks\negative_quirks\nerve_staple.dm" #include "modular_nova\master_files\code\datums\quirks\neutral_quirks\equipping.dm" #include "modular_nova\master_files\code\datums\quirks\neutral_quirks\lungs.dm" +#include "modular_nova\master_files\code\datums\quirks\positive_quirks\spacer.dm" #include "modular_nova\master_files\code\datums\records\record.dm" #include "modular_nova\master_files\code\datums\station_traits\negative_traits.dm" #include "modular_nova\master_files\code\datums\storage\storage.dm" @@ -6287,6 +6291,7 @@ #include "modular_nova\master_files\code\modules\antagonists\changeling\powers\tiny_prick.dm" #include "modular_nova\master_files\code\modules\antagonists\cult\cult_items.dm" #include "modular_nova\master_files\code\modules\antagonists\ert\ert.dm" +#include "modular_nova\master_files\code\modules\antagonists\pirate\pirate_gang.dm" #include "modular_nova\master_files\code\modules\antagonists\pirate\pirate_outfits.dm" #include "modular_nova\master_files\code\modules\antagonists\pirate\pirate_shuttle_equipment.dm" #include "modular_nova\master_files\code\modules\antagonists\traitor\objectives\kill_pet.dm" @@ -6393,6 +6398,7 @@ #include "modular_nova\master_files\code\modules\experisci\experiment.dm" #include "modular_nova\master_files\code\modules\food_and_drinks\recipes\food_mixtures.dm" #include "modular_nova\master_files\code\modules\jobs\off_duty_check.dm" +#include "modular_nova\master_files\code\modules\jobs\prisoner.dm" #include "modular_nova\master_files\code\modules\jobs\departments\departments.dm" #include "modular_nova\master_files\code\modules\jobs\job_types\_job.dm" #include "modular_nova\master_files\code\modules\jobs\job_types\_job_attire.dm" @@ -6493,6 +6499,7 @@ #include "modular_nova\master_files\code\modules\projectiles\guns\ballistic\bows\bow_quivers.dm" #include "modular_nova\master_files\code\modules\projectiles\guns\ballistic\bows\bow_types.dm" #include "modular_nova\master_files\code\modules\projectiles\guns\energy\kinetic_accelerator.dm" +#include "modular_nova\master_files\code\modules\projectiles\guns\energy\recharge.dm" #include "modular_nova\master_files\code\modules\reagents\bottle.dm" #include "modular_nova\master_files\code\modules\reagents\reagent_containers.dm" #include "modular_nova\master_files\code\modules\reagents\reagent_dispenser.dm" @@ -6519,6 +6526,7 @@ #include "modular_nova\master_files\code\modules\surgery\organs\external\wings\functional_wings.dm" #include "modular_nova\master_files\code\modules\surgery\organs\external\wings\wings.dm" #include "modular_nova\master_files\code\modules\surgery\organs\internal\appendix\_appendix.dm" +#include "modular_nova\master_files\code\modules\surgery\organs\internal\cyberimp\augments_internal.dm" #include "modular_nova\master_files\code\modules\vehicles\sealed.dm" #include "modular_nova\master_files\code\modules\vehicles\snowmobile.dm" #include "modular_nova\modules\access_helpers\accesshelpers.dm" @@ -6850,6 +6858,7 @@ #include "modular_nova\modules\clock_cult\code\structures\traps\senders\pressure_sensor.dm" #include "modular_nova\modules\clothing_improvements\code\chaplain.dm" #include "modular_nova\modules\clothing_improvements\code\holsters.dm" +#include "modular_nova\modules\colony_fabricator\code\cargo_packs.dm" #include "modular_nova\modules\colony_fabricator\code\colony_fabricator.dm" #include "modular_nova\modules\colony_fabricator\code\looping_sounds.dm" #include "modular_nova\modules\colony_fabricator\code\repacking_element.dm" @@ -6857,8 +6866,12 @@ #include "modular_nova\modules\colony_fabricator\code\appliances\co2_cracker.dm" #include "modular_nova\modules\colony_fabricator\code\appliances\foodricator.dm" #include "modular_nova\modules\colony_fabricator\code\appliances\recycler.dm" +#include "modular_nova\modules\colony_fabricator\code\appliances\space_heater.dm" #include "modular_nova\modules\colony_fabricator\code\appliances\wall_cell_charger.dm" #include "modular_nova\modules\colony_fabricator\code\appliances\wind_turbine.dm" +#include "modular_nova\modules\colony_fabricator\code\appliances\kitchen_appliances\griddle.dm" +#include "modular_nova\modules\colony_fabricator\code\appliances\kitchen_appliances\macrowave.dm" +#include "modular_nova\modules\colony_fabricator\code\appliances\kitchen_appliances\range.dm" #include "modular_nova\modules\colony_fabricator\code\construction\doors.dm" #include "modular_nova\modules\colony_fabricator\code\construction\manual_door.dm" #include "modular_nova\modules\colony_fabricator\code\construction\turfs.dm" @@ -6885,6 +6898,7 @@ #include "modular_nova\modules\colony_fabricator\code\machines\rtg.dm" #include "modular_nova\modules\colony_fabricator\code\machines\solar_panels.dm" #include "modular_nova\modules\colony_fabricator\code\machines\solid_fuel_generator.dm" +#include "modular_nova\modules\colony_fabricator\code\machines\stirling_generator.dm" #include "modular_nova\modules\colony_fabricator\code\machines\thermomachine.dm" #include "modular_nova\modules\colony_fabricator\code\tools\tools.dm" #include "modular_nova\modules\command_vendor\code\vending.dm" @@ -6926,7 +6940,6 @@ #include "modular_nova\modules\contractor\code\datums\contractor_items.dm" #include "modular_nova\modules\contractor\code\datums\contractor_support.dm" #include "modular_nova\modules\contractor\code\datums\contractor_tablet.dm" -#include "modular_nova\modules\contractor\code\datums\mind_datum.dm" #include "modular_nova\modules\contractor\code\datums\objective.dm" #include "modular_nova\modules\contractor\code\datums\midround\antag_datum.dm" #include "modular_nova\modules\contractor\code\datums\midround\event.dm" diff --git a/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx b/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx index a425a519253..2a625d907cd 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoTraitor.tsx @@ -37,6 +37,7 @@ type Info = { has_uplink: BooleanLike; uplink_intro: string; uplink_unlock_info: string; + given_uplink: BooleanLike; objectives: Objective[]; }; @@ -233,7 +234,7 @@ const CodewordsSection = (props) => { // NOVA EDIT: change height from 580 to 650 export const AntagInfoTraitor = (props) => { const { data } = useBackend(); - const { theme } = data; + const { theme, given_uplink } = data; return ( @@ -248,9 +249,11 @@ export const AntagInfoTraitor = (props) => { - - - + {!!given_uplink && ( + + + + )} diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index 9954fd2e925..0220607e65a 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -1,6 +1,12 @@ import { sortBy, sortStrings } from 'common/collections'; import { BooleanLike, classes } from 'common/react'; -import { ComponentType, createElement, ReactNode, useState } from 'react'; +import { + ComponentType, + createElement, + ReactNode, + useEffect, + useState, +} from 'react'; import { sendAct, useBackend } from '../../../../backend'; import { @@ -349,6 +355,10 @@ export const FeatureValueInput = (props: { createSetPreference(props.act, props.featureId)(newValue); }; + useEffect(() => { + setPredictedValue(props.value); + }, [data.active_slot]); + return ( { diff --git a/tgui/packages/tgui/interfaces/common/JobToIcon.ts b/tgui/packages/tgui/interfaces/common/JobToIcon.ts index ec22869c9e5..aeff8b9bae5 100644 --- a/tgui/packages/tgui/interfaces/common/JobToIcon.ts +++ b/tgui/packages/tgui/interfaces/common/JobToIcon.ts @@ -11,7 +11,9 @@ const BASEICONS = { 'Bit Avatar': 'code', Bitrunner: 'gamepad', Botanist: 'seedling', + 'Bridge Assistant': 'building-shield', Captain: 'crown', + 'Cargo Gorilla': 'paw', 'Cargo Technician': 'box', 'CentCom Commander': 'star', 'CentCom Head Intern': 'pen-fancy', diff --git a/tools/UpdatePaths/Scripts_Nova/573_croptop_repath.txt b/tools/UpdatePaths/Scripts_Nova/573_croptop_repath.txt new file mode 100644 index 00000000000..e9325038a62 --- /dev/null +++ b/tools/UpdatePaths/Scripts_Nova/573_croptop_repath.txt @@ -0,0 +1 @@ +/obj/item/clothing/suit/croptop : /obj/item/clothing/suit/jacket/croptop{@OLD}