diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index c1606e77f67..bc4a655d3b5 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -43,6 +43,7 @@ #define BE_MORPH 0x40000 #define BE_CORGI 0x80000 #define BE_CURSEDSWORD 0x100000 +#define BE_SURVIVOR 0x200000 //VOREStation Add End var/list/be_special_flags = list( @@ -68,6 +69,7 @@ var/list/be_special_flags = list( "Morph" = BE_MORPH, "Corgi" = BE_CORGI, "Cursed Sword" = BE_CURSEDSWORD, + "Ship Survivor" = BE_SURVIVOR //VOREStation Add End ) @@ -111,6 +113,7 @@ var/list/be_special_flags = list( #define MODE_INFILTRATOR "infiltrator" #define MODE_THUG "thug" #define MODE_STOWAWAY "stowaway" +#define MODE_SURVIVOR "Shipwreck Survivor" #define DEFAULT_TELECRYSTAL_AMOUNT 120 @@ -176,4 +179,4 @@ var/list/be_special_flags = list( #define ASPECT_EMP "emp" //Unused now. #define ASPECT_UNSTABLE "unstable" //Heavily RNG-based, causes instability to the victim. #define ASPECT_CHROMATIC "chromatic" //Used to combine with other spells. -#define ASPECT_UNHOLY "unholy" //Involves the dead, blood, and most things against divine beings. \ No newline at end of file +#define ASPECT_UNHOLY "unholy" //Involves the dead, blood, and most things against divine beings. diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index df7a90632cc..b8457de50bd 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -136,8 +136,9 @@ #define CLASS_MIDDLE "Average" #define CLASS_LOWMID "Underpaid" #define CLASS_LOWER "Poor" +#define CLASS_BROKE "Broke" //VOREStation Add -#define ECONOMIC_CLASS list(CLASS_UPPER,CLASS_UPMID,CLASS_MIDDLE,CLASS_LOWMID,CLASS_LOWER) +#define ECONOMIC_CLASS list(CLASS_UPPER,CLASS_UPMID,CLASS_MIDDLE,CLASS_LOWMID,CLASS_LOWER,CLASS_BROKE) // Defines mob sizes, used by lockers and to determine what is considered a small sized mob, etc. @@ -249,7 +250,7 @@ #define BP_HEAD "head" #define BP_TORSO "torso" #define BP_GROIN "groin" -#define BP_ALL list(BP_GROIN, BP_TORSO, BP_HEAD, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG) +#define BP_ALL list(BP_TORSO, BP_HEAD, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT) //keep so that parent comes before child #define SYNTH_BLOOD_COLOUR "#030303" #define SYNTH_FLESH_COLOUR "#575757" diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 716a1c1540c..81d35aebfa1 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -93,6 +93,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G // Subsystem fire priority, from lowest to highest priority // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) +#define FIRE_PRIORITY_PLAYERTIPS 5 #define FIRE_PRIORITY_SHUTTLES 5 #define FIRE_PRIORITY_SUPPLY 5 #define FIRE_PRIORITY_NIGHTSHIFT 5 diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index a2e4664055f..ec831d8c5f8 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -233,7 +233,7 @@ curblend = BLEND_OVERLAY add = icon(I.icon, I.icon_state, base_icon_dir) else // 'I' is an appearance object. - add = getFlatIcon(image(I), I.dir||curdir, curicon, curstate, curblend, FALSE, no_anim) + add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim) if(!add) continue // Find the new dimensions of the flat icon to fit the added overlay diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index d0a7bff2e0e..cb19ec6c511 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -826,10 +826,22 @@ Turf and target are seperate in case you want to teleport some distance from a t else O=new original.type(locate(0,0,0)) + var/static/list/blacklisted_var_names = list( + "ATOM_TOPIC_EXAMINE", + "type", + "loc", + "locs", + "vars", + "parent", + "parent_type", + "verbs", + "ckey", + "key" + ) if(perfectcopy) if((O) && (original)) for(var/V in original.vars) - if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key"))) + if(!(V in blacklisted_var_names)) O.vars[V] = original.vars[V] return O diff --git a/code/controllers/master.dm b/code/controllers/master.dm index ab2d2a12dea..fe88f6c10e3 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -257,7 +257,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new SS.state = SS_IDLE if (SS.flags & SS_TICKER) tickersubsystems += SS - timer += world.tick_lag * rand(1, 5) + timer += world.tick_lag * rand(0,1) SS.next_fire = timer continue @@ -332,13 +332,16 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/checking_runlevel = current_runlevel if(cached_runlevel != checking_runlevel) //resechedule subsystems + var/list/old_subsystems = current_runlevel_subsystems cached_runlevel = checking_runlevel current_runlevel_subsystems = runlevel_sorted_subsystems[cached_runlevel] - var/stagger = world.time + + //now we'll go through all the subsystems we want to offset and give them a next_fire for(var/datum/controller/subsystem/SS as anything in current_runlevel_subsystems) - if(SS.next_fire <= world.time) - stagger += world.tick_lag * rand(1, 5) - SS.next_fire = stagger + //we only want to offset it if it's new and also behind + if(SS.next_fire > world.time || (SS in old_subsystems)) + continue + SS.next_fire = world.time + world.tick_lag * rand(0, DS2TICKS(min(SS.wait, 2 SECONDS))) subsystems_to_check = current_runlevel_subsystems else diff --git a/code/controllers/subsystems/player_tips.dm b/code/controllers/subsystems/player_tips.dm new file mode 100644 index 00000000000..7ac58b52bd0 --- /dev/null +++ b/code/controllers/subsystems/player_tips.dm @@ -0,0 +1,16 @@ +/* +Player tips procs and lists are defined under /code/modules/player_tips_vr +*/ +SUBSYSTEM_DEF(player_tips) + name = "Periodic Player Tips" + priority = FIRE_PRIORITY_PLAYERTIPS + runlevels = RUNLEVEL_GAME + + wait = 3000 //We check if it's time to send a tip every 5 minutes (300 seconds) + var/static/datum/player_tips/player_tips = new + + + + +/datum/controller/subsystem/player_tips/fire() + player_tips.send_tips() diff --git a/code/controllers/subsystems/xenoarch.dm b/code/controllers/subsystems/xenoarch.dm index 111653fc681..45a437b9668 100644 --- a/code/controllers/subsystems/xenoarch.dm +++ b/code/controllers/subsystems/xenoarch.dm @@ -31,13 +31,13 @@ SUBSYSTEM_DEF(xenoarch) /datum/controller/subsystem/xenoarch/proc/SetupXenoarch() for(var/turf/simulated/mineral/M in world) - if(!M.density || (M.z in using_map.xenoarch_exempt_levels)) + if(!M.density) continue if(isnull(M.geologic_data)) M.geologic_data = new /datum/geosample(M) - if(!prob(XENOARCH_SPAWN_CHANCE)) + if((M.z in using_map.xenoarch_exempt_levels) || !prob(XENOARCH_SPAWN_CHANCE)) continue var/farEnough = 1 diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 04f489be7c4..8328a4f47c8 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -355,7 +355,7 @@ var/global/list/PDA_Manifest = list() G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" G.fields["sex"] = gender2text(H.gender) - G.fields["species"] = H.get_species() + G.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit G.fields["home_system"] = H.home_system G.fields["citizenship"] = H.citizenship G.fields["faction"] = H.personal_faction @@ -365,6 +365,7 @@ var/global/list/PDA_Manifest = list() //Medical Record var/datum/data/record/M = CreateMedicalRecord(H.real_name, id, hidden) + M.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit M.fields["b_type"] = H.b_type M.fields["b_dna"] = H.dna.unique_enzymes M.fields["id_gender"] = gender2text(H.identifying_gender) @@ -377,6 +378,7 @@ var/global/list/PDA_Manifest = list() //Security Record var/datum/data/record/S = CreateSecurityRecord(H.real_name, id, hidden) + S.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit if(H.get_FBP_type()) S.fields["brain_type"] = H.get_FBP_type() else @@ -401,7 +403,7 @@ var/global/list/PDA_Manifest = list() L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.SE // Used in respawning L.fields["identity"] = H.dna.UI // " - L.fields["species"] = H.get_species() + L.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit L.fields["home_system"] = H.home_system L.fields["citizenship"] = H.citizenship L.fields["faction"] = H.personal_faction @@ -468,6 +470,7 @@ var/global/list/PDA_Manifest = list() var/datum/data/record/R = new /datum/data/record() R.name = "Security Record #[id]" R.fields["name"] = name + R.fields["species"] = SPECIES_HUMAN R.fields["id"] = id R.fields["brain_type"] = "Unknown" R.fields["criminal"] = "None" @@ -490,6 +493,7 @@ var/global/list/PDA_Manifest = list() M.name = "Medical Record #[id]" M.fields["id"] = id M.fields["name"] = name + M.fields["species"] = SPECIES_HUMAN M.fields["b_type"] = "AB+" M.fields["b_dna"] = md5(name) M.fields["id_gender"] = "Unknown" diff --git a/code/datums/ghost_query.dm b/code/datums/ghost_query.dm index 6a342f58203..47519813e8e 100644 --- a/code/datums/ghost_query.dm +++ b/code/datums/ghost_query.dm @@ -198,3 +198,12 @@ Would you like to play as the soul imprisoned within?" be_special_flag = BE_CURSEDSWORD cutoff_number = 1 + +/datum/ghost_query/shipwreck_survivor + role_name = "Shipwreck survivor" + question = "A person suspended in cryosleep has been discovered by a crewmember \ + aboard a wrecked spaceship \ + and they are attempting to open the cryopod.\n \ + Would you like to play as the occupant? \n \ + You MUST NOT use your station character!!!" + cutoff_number = 1 diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm index 40caa4c405b..ca19cc342af 100644 --- a/code/datums/supplypacks/recreation.dm +++ b/code/datums/supplypacks/recreation.dm @@ -72,15 +72,16 @@ /obj/item/device/camera_film = 2, /obj/item/weapon/storage/photo_album, /obj/item/weapon/packageWrap, - /obj/item/weapon/reagent_containers/glass/paint/red, - /obj/item/weapon/reagent_containers/glass/paint/green, - /obj/item/weapon/reagent_containers/glass/paint/blue, - /obj/item/weapon/reagent_containers/glass/paint/yellow, - /obj/item/weapon/reagent_containers/glass/paint/purple, - /obj/item/weapon/reagent_containers/glass/paint/black, - /obj/item/weapon/reagent_containers/glass/paint/white, /obj/item/poster/custom, - /obj/item/weapon/wrapping_paper = 3 + /obj/item/weapon/wrapping_paper = 3, + /obj/structure/easel, + /obj/item/paint_brush, + /obj/item/paint_palette, + /obj/item/canvas = 3, + /obj/item/canvas/nineteen_nineteen = 2, + /obj/item/canvas/twentythree_nineteen = 2, + /obj/item/canvas/twentythree_twentythree = 2, + /obj/item/canvas/twentyfour_twentyfour = 2 ) cost = 10 containertype = /obj/structure/closet/crate/allico @@ -94,7 +95,17 @@ contains = list( /obj/item/device/pipe_painter = 2, /obj/item/device/floor_painter = 2, - ///obj/item/device/closet_painter = 2 + /obj/item/weapon/reagent_containers/glass/paint/red, + /obj/item/weapon/reagent_containers/glass/paint/green, + /obj/item/weapon/reagent_containers/glass/paint/blue, + /obj/item/weapon/reagent_containers/glass/paint/yellow, + /obj/item/weapon/reagent_containers/glass/paint/violet, + /obj/item/weapon/reagent_containers/glass/paint/cyan, + /obj/item/weapon/reagent_containers/glass/paint/orange, + /obj/item/weapon/reagent_containers/glass/paint/purple, + /obj/item/weapon/reagent_containers/glass/paint/grey, + /obj/item/weapon/reagent_containers/glass/paint/black, + /obj/item/weapon/reagent_containers/glass/paint/white = 3 ) /datum/supply_pack/recreation/cheapbait diff --git a/code/datums/underwear/bottom.dm b/code/datums/underwear/bottom.dm index 3458c6bab2c..7f16ba66b73 100644 --- a/code/datums/underwear/bottom.dm +++ b/code/datums/underwear/bottom.dm @@ -72,4 +72,19 @@ /datum/category_item/underwear/bottom/thinpanties name = "Panties, Thin" icon_state = "thinpanties" + has_color = TRUE + +/datum/category_item/underwear/bottom/neko + name = "Panties, Neko" + icon_state = "panties_neko" + has_color = TRUE + +/datum/category_item/underwear/bottom/swimbottom + name = "Swimming Bottoms" + icon_state = "swimbottom" + has_color = TRUE + +/datum/category_item/underwear/bottom/onepiece + name = "Swimming One Piece" + icon_state = "onepiece" has_color = TRUE \ No newline at end of file diff --git a/code/datums/underwear/socks.dm b/code/datums/underwear/socks.dm index 72803644dfb..ac29b579d19 100644 --- a/code/datums/underwear/socks.dm +++ b/code/datums/underwear/socks.dm @@ -188,4 +188,24 @@ /datum/category_item/underwear/socks/rippedpantyhose name = "Pantyhose, Ripped" - icon_state = "rippedpantyhose" \ No newline at end of file + icon_state = "rippedpantyhose" + +/datum/category_item/underwear/socks/stirrup + name = "Normal, stirrup" + icon_state = "socks_norm-stir" + has_color = TRUE + +/datum/category_item/underwear/socks/stirrup_knee + name = "Knee, stirrup" + icon_state = "socks_knee-stir" + has_color = TRUE + +/datum/category_item/underwear/socks/stirrup_thigh + name = "Thigh, stirrup" + icon_state = "socks_thigh-stir" + has_color = TRUE + +/datum/category_item/underwear/socks/stirrup_thigh_black + name = "Black Stirrup Stockings" + icon_state = "leggings-stir-black" + has_color = TRUE \ No newline at end of file diff --git a/code/datums/underwear/top.dm b/code/datums/underwear/top.dm index 3811bf4fbd7..5af7870f04e 100644 --- a/code/datums/underwear/top.dm +++ b/code/datums/underwear/top.dm @@ -77,3 +77,22 @@ icon_state = "onesleeve" has_color = TRUE +/datum/category_item/underwear/top/neko + name = "Neko bra" + icon_state = "bra_neko" + has_color = TRUE + +/datum/category_item/underwear/top/tape + name = "Tape" + icon_state = "pasties_alt" + has_color = TRUE + +/datum/category_item/underwear/top/sarashi + name = "Sarashi" + icon_state = "bandages" + has_color = TRUE + +/datum/category_item/underwear/top/swimtop + name = "Swimming Top" + icon_state = "swimtop" + has_color = TRUE \ No newline at end of file diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm index 11c4f1f6b32..2c32ad8e767 100644 --- a/code/datums/underwear/undershirts.dm +++ b/code/datums/underwear/undershirts.dm @@ -206,4 +206,24 @@ /datum/category_item/underwear/undershirt/dress_shirt name = "Dress shirt, masculine" icon_state = "undershirt_dress" + has_color = TRUE + +/datum/category_item/underwear/undershirt/midriff + name = "Tanktop, midriff" + icon_state = "tank_midriff" + has_color = TRUE + +/datum/category_item/underwear/undershirt/midriffshort + name = "Tanktop, midriff, short" + icon_state = "tank_midriff_short" + has_color = TRUE + +/datum/category_item/underwear/undershirt/shibari + name = "Shibari Binding" + icon_state = "shibari" + has_color = TRUE + +/datum/category_item/underwear/undershirt/leotard + name = "Leotard" + icon_state = "leotard" has_color = TRUE \ No newline at end of file diff --git a/code/game/antagonist/outsider/shipwreck_survivor.dm b/code/game/antagonist/outsider/shipwreck_survivor.dm new file mode 100644 index 00000000000..6fdcc47b971 --- /dev/null +++ b/code/game/antagonist/outsider/shipwreck_survivor.dm @@ -0,0 +1,45 @@ +var/datum/antagonist/shipwreck_survivor/survivors + +//Shipwreck survivors can only spawn from ghost_pods at time of this commit. +//These are NOT meant to be real antagonists +//They are, at best, comparable to ERT. +/datum/antagonist/SURVIVOR + id = MODE_SURVIVOR + role_type = BE_SURVIVOR + role_text = "Shipwreck Survivor" + role_text_plural = "Shipwreck Survivors" + bantype = "Shipwreck Survivor" //also blocked by GhostRoles ban, in current implementation at least + welcome_text = "Something disastrous happened to the ship you were on! You awaken to your supposed rescuers in pain..." + antag_text = "You are a NOT an antagonist! All rules apply to you as well. Your job is to help make the world seem more alive. \n \ + You are not an existing station character, but some average person who has suffered a terrible accident. \ + Feel free to make up what happened to the ship you awakened on as you please, \ + but listening to your rescuers for context might help improve your mutual immersion! \n \ + Please play along. It is OK to not be co-operative, but 'yes, and' and \ + 'no, but' are better ways to approach things than to shut them down outright.\n\n \ + Please ahelp if you are uncertain about anything pertaining to this role. \ + It is always better to be safe than sorry! \n\n \ + You will receive the option to set your ambitions. Please remember the server rules \ + abuse can mean being banned from ghost roles \n \ + You should use your ambitions to flesh out why your ship got wrecked \ + and how you wish to proceed now that you were rescued. \n \ + You DON'T need to set your ambitions. Feel free to ignore them." + + antag_sound = 'sound/voice/hiss1.ogg' + + can_speak_aooc = FALSE + can_hear_aooc = FALSE + +/datum/antagonist/SURVIVOR/greet(var/datum/mind/player) + to_chat(player.current, SPAN_WARNING("You are a NOT an antagonist! All rules apply to you as well. Your job is to help make the world seem more alive. \n \ + You are not an existing station character, but some average person who has suffered a terrible accident. \ + Feel free to make up what happened to the ship you awakened on as you please, \ + but listening to your rescuers for context might help improve your mutual immersion! \n \ + Please play along. It is OK to not be co-operative, but 'yes, and' and \ + 'no, but' are better ways to approach things than to shut them down outright.\n\n \ + Please ahelp if you are uncertain about anything pertaining to this role. \ + It is always better to be safe than sorry! \n\n \ + You will receive the option to set your ambitions. Please remember the server rules \ + abuse can mean being banned from ghost roles \n \ + You should use your ambitions to flesh out why your ship got wrecked \ + and how you wish to proceed now that you were rescued. \n \ + You DON'T need to set your ambitions. Feel free to ignore them.")) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index d3207d02935..e2993681208 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -211,6 +211,9 @@ found += A.search_contents_for(path,filter_path) return found +/atom/proc/get_examine_desc() + return desc + //All atoms /atom/proc/examine(mob/user, var/infix = "", var/suffix = "") //This reformat names to get a/an properly working on item descriptions when they are bloody @@ -225,14 +228,13 @@ else f_name += "oil-stained [name][infix]." - var/list/output = list("\icon[src.examine_icon()][bicon(src)] That's [f_name] [suffix]", desc) + var/list/output = list("\icon[src.examine_icon()][bicon(src)] That's [f_name] [suffix]", get_examine_desc()) if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE) output += description_info if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL) user.client.statpanel = "Examine" // Switch to stat panel - SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, output) return output diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index df62ad8ecf4..791524d221b 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -118,6 +118,8 @@ var/global/list/datum/dna/gene/dna_genes[0] var/custom_ask var/custom_whisper var/custom_exclaim + var/list/custom_heat = list() + var/list/custom_cold = list() // VOREStation // New stuff @@ -144,6 +146,8 @@ var/global/list/datum/dna/gene/dna_genes[0] new_dna.custom_ask=custom_ask //VOREStaton Edit new_dna.custom_whisper=custom_whisper //VOREStaton Edit new_dna.custom_exclaim=custom_exclaim //VOREStaton Edit + new_dna.custom_heat=custom_heat //VOREStation Edit + new_dna.custom_cold=custom_cold //VOREStation Edit var/list/body_markings_genetic = (body_markings - body_marking_nopersist_list) new_dna.body_markings=body_markings_genetic.Copy() for(var/b=1;b<=DNA_SE_LENGTH;b++) @@ -216,6 +220,8 @@ var/global/list/datum/dna/gene/dna_genes[0] src.custom_ask = character.custom_ask src.custom_whisper = character.custom_whisper src.custom_exclaim = character.custom_exclaim + src.custom_heat = character.custom_heat + src.custom_cold = character.custom_cold // +1 to account for the none-of-the-above possibility SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index d5cdc700c73..9b57cd87e12 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -244,6 +244,8 @@ H.custom_whisper = dna.custom_whisper H.custom_exclaim = dna.custom_exclaim H.species.blood_color = dna.blood_color + H.custom_heat = dna.custom_heat + H.custom_cold = dna.custom_cold var/datum/species/S = H.species S.produceCopy(dna.species_traits, H, dna.base_species) // VOREStation Edit End diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index cf09d52861b..443b188b60f 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -70,6 +70,7 @@ if(CLASS_MIDDLE) income = 1 if(CLASS_LOWMID) income = 0.75 if(CLASS_LOWER) income = 0.50 + if(CLASS_BROKE) income = 0 //VOREStation Add - Rent's not cheap //give them an account in the station database var/money_amount = (rand(15,40) + rand(15,40)) * income * economic_modifier * ECO_MODIFIER //VOREStation Edit - Smoothed peaks, ECO_MODIFIER rather than per-species ones. @@ -182,4 +183,4 @@ return TRUE if(brain_type in banned_job_species) return TRUE - */ \ No newline at end of file + */ diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 63b067d5425..5f588f4d9b7 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -33,6 +33,7 @@ field_edit_questions = list( // General "sex" = "Please select new sex:", + "species" = "Please input new species:", "age" = "Please input new age:", "fingerprint" = "Please input new fingerprint hash:", "p_stat" = "Please select new physical status:", @@ -137,6 +138,7 @@ fields[++fields.len] = FIELD("Name", active1.fields["name"], null) fields[++fields.len] = FIELD("ID", active1.fields["id"], null) fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex") + fields[++fields.len] = FIELD("Species", active1.fields["species"], "species") fields[++fields.len] = FIELD("Age", "[active1.fields["age"]]", "age") fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint") fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], "p_stat") diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 4222e1264cd..9c8771eeb30 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -31,6 +31,7 @@ "name" = "Please enter new name:", "id" = "Please enter new id:", "sex" = "Please select new sex:", + "species" = "Please input new species:", "age" = "Please input new age:", "rank" = "Please enter new rank:", "fingerprint" = "Please input new fingerprint hash:", @@ -148,6 +149,7 @@ fields[++fields.len] = FIELD("ID", active1.fields["id"], "id") fields[++fields.len] = FIELD("Entity Classification", active1.fields["brain_type"], "brain_type") fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex") + fields[++fields.len] = FIELD("Species", active1.fields["species"], "species") fields[++fields.len] = FIELD("Age", "[active1.fields["age"]]", "age") fields[++fields.len] = FIELD("Rank", active1.fields["rank"], "rank") fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint") diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 7fe2e803648..b30aa5e6a35 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -36,6 +36,7 @@ "name" = "Please input new name:", "id" = "Please input new ID:", "sex" = "Please select new sex:", + "species" = "Please input new species:", "age" = "Please input new age:", "fingerprint" = "Please input new fingerprint hash:", ) @@ -109,6 +110,7 @@ fields[++fields.len] = FIELD("Name", active1.fields["name"], "name") fields[++fields.len] = FIELD("ID", active1.fields["id"], "id") fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex") + fields[++fields.len] = FIELD("Species", active1.fields["species"], "species") fields[++fields.len] = FIELD("Age", active1.fields["age"], "age") fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint") fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], null) diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index 6c71e63207d..c3fa1701fd4 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -202,6 +202,12 @@ frame_class = FRAME_CLASS_MACHINE frame_size = 3 +/datum/frame/frame_types/injector_maker + name = "Ready-to-Use Medicine 3000" + frame_class = FRAME_CLASS_MACHINE + circuit = /obj/machinery/atmospheric_field_generator + frame_size = 3 + ////////////////////////////// // Frame Object (Structure) ////////////////////////////// diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index 7661bb32557..88dace7ff97 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -7,7 +7,6 @@ maint_access = 0 //add_req_access = 0 //operation_req_access = list(access_hos) - damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8) var/am = "d3c2fbcadca903a41161ccc9df9cf948" max_hull_equip = 2 diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 19bd2b9c53e..4ea027f154d 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -8,7 +8,6 @@ health = 300 maxhealth = 300 //Don't forget to update the /old variant if you change this number. deflect_chance = 20 - damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) max_temperature = 30000 infra_luminosity = 8 force = 40 @@ -85,4 +84,4 @@ ..() health = 25 maxhealth = 250 //Just slightly worse. - cell.charge = rand(0, (cell.charge/2)) \ No newline at end of file + cell.charge = rand(0, (cell.charge/2)) diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm index cb9b00ecf26..e306455de45 100644 --- a/code/game/mecha/combat/gorilla.dm +++ b/code/game/mecha/combat/gorilla.dm @@ -11,7 +11,6 @@ maxhealth = 5000 opacity = 0 // Because there's big tall legs to look through. Also it looks fucky if this is set to 1. deflect_chance = 50 - damage_absorption = list("brute"=0.1,"fire"=0.8,"bullet"=0.1,"laser"=0.6,"energy"=0.7,"bomb"=0.7) //values show how much damage will pass through, not how much will be absorbed. max_temperature = 35000 //Just a bit better than the Durand. infra_luminosity = 3 wreckage = /obj/effect/decal/mecha_wreckage/gorilla diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index b2b5fe613f7..1fa6933add7 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -8,7 +8,6 @@ health = 250 maxhealth = 250 //Don't forget to update the /old variant if you change this number. deflect_chance = 15 - damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) max_temperature = 25000 infra_luminosity = 6 wreckage = /obj/effect/decal/mecha_wreckage/gygax @@ -55,7 +54,6 @@ health = 400 maxhealth = 400 deflect_chance = 25 - damage_absorption = list("brute"=0.6,"fire"=0.8,"bullet"=0.6,"laser"=0.5,"energy"=0.65,"bomb"=0.8) max_temperature = 45000 overload_coeff = 1 wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark @@ -92,7 +90,6 @@ maxhealth = 150 deflect_chance = 20 step_in = 2 - damage_absorption = list("brute"=0.9,"fire"=1,"bullet"=0.9,"laser"=0.8,"energy"=0.9,"bomb"=1) max_temperature = 20000 overload_coeff = 1 wreckage = /obj/effect/decal/mecha_wreckage/gygax/serenity @@ -148,4 +145,4 @@ ..() health = 25 maxhealth = 250 //Just slightly worse. - cell.charge = rand(0, (cell.charge/2)) \ No newline at end of file + cell.charge = rand(0, (cell.charge/2)) diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index c2184938478..8fc089c4955 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -8,7 +8,6 @@ health = 350 maxhealth = 350 //Don't forget to update the /old variant if you change this number. deflect_chance = 25 - damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7) max_temperature = 60000 infra_luminosity = 3 operation_req_access = list(access_cent_specops) diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm index 8ec100ad1ea..04e3869cc1c 100644 --- a/code/game/mecha/combat/phazon.dm +++ b/code/game/mecha/combat/phazon.dm @@ -9,7 +9,6 @@ health = 200 //God this is low maxhealth = 200 //Don't forget to update the /old variant if you change this number. deflect_chance = 30 - damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7) max_temperature = 25000 infra_luminosity = 3 wreckage = /obj/effect/decal/mecha_wreckage/phazon @@ -38,6 +37,7 @@ cloak_possible = TRUE phasing_possible = TRUE switch_dmg_type_possible = TRUE + var/list/inherent_damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7) /obj/mecha/combat/phazon/equipped/Initialize() . = ..() @@ -92,7 +92,7 @@ health = 350 maxhealth = 350 deflect_chance = 30 - damage_absorption = list("brute"=0.6,"fire"=0.7,"bullet"=0.7,"laser"=0.9,"energy"=0.7,"bomb"=0.5) + inherent_damage_absorption = list("brute"=0.6,"fire"=0.7,"bullet"=0.7,"laser"=0.9,"energy"=0.7,"bomb"=0.5) max_temperature = 10000 infra_luminosity = 3 wreckage = /obj/effect/decal/mecha_wreckage/janus @@ -125,7 +125,7 @@ src.visible_message("The [src.name] absorbs the incoming projectile's force, negating it!") src.log_append_to_last("Armor negated.") return - else if((Proj.damage && !Proj.nodamage) && istype(Proj, /obj/item/projectile/beam) && prob(max(1, (50 - round((Proj.damage / 2) * damage_absorption["laser"])) * (1 - (Proj.armor_penetration / 100))))) // Base 50% chance to deflect a beam,lowered by half the beam's damage scaled to laser absorption, then multiplied by the remaining percent of non-penetrated armor, with a minimum chance of 1%. + else if((Proj.damage && !Proj.nodamage) && istype(Proj, /obj/item/projectile/beam) && prob(max(1, (50 - round((Proj.damage / 2) * inherent_damage_absorption["laser"])) * (1 - (Proj.armor_penetration / 100))))) // Base 50% chance to deflect a beam,lowered by half the beam's damage scaled to laser absorption, then multiplied by the remaining percent of non-penetrated armor, with a minimum chance of 1%. src.occupant_message("The armor reflects the incoming beam, negating it!") src.visible_message("The [src.name] reflects the incoming beam, negating it!") src.log_append_to_last("Armor reflected.") @@ -134,7 +134,7 @@ ..() /obj/mecha/combat/phazon/janus/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - if(prob(max(1, (50 - round((W.force / 2) * damage_absorption["brute"])) * (1 - (W.armor_penetration / 100))))) + if(prob(max(1, (50 - round((W.force / 2) * inherent_damage_absorption["brute"])) * (1 - (W.armor_penetration / 100))))) src.occupant_message("The armor absorbs the incoming attack's force, negating it!") src.visible_message("The [src.name] absorbs the incoming attack's force, negating it!") src.log_append_to_last("Armor absorbed.") @@ -162,4 +162,4 @@ ..() health = 25 maxhealth = 150 //Just slightly worse. - cell.charge = rand(0, (cell.charge/2)) \ No newline at end of file + cell.charge = rand(0, (cell.charge/2)) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 63d23047496..f5821b18d19 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -44,17 +44,6 @@ var/health = 300 //Health is health var/maxhealth = 300 //Maxhealth is maxhealth. var/deflect_chance = 10 //Chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act. - //the values in this list show how much damage will pass through, not how much will be absorbed. - var/list/damage_absorption = list( - "brute"=0.8, - "fire"=1.2, - "bullet"=0.9, - "laser"=1, - "energy"=1, - "bomb"=1, - "bio"=1, - "rad"=1 - ) var/damage_minimum = 10 //Incoming damage lower than this won't actually deal damage. Scrapes shouldn't be a real thing. var/minimum_penetration = 15 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this. @@ -1043,15 +1032,8 @@ /obj/mecha/proc/get_damage_absorption() var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR] - - if(!istype(AC)) - return - - else - if(AC.get_efficiency() > 0.25) - return AC.damage_absorption - - return + if(istype(AC) && AC.get_efficiency() > 0.25) + return AC.damage_absorption /obj/mecha/proc/absorbDamage(damage,damage_type) return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type) diff --git a/code/game/mecha/micro/micro.dm b/code/game/mecha/micro/micro.dm index 97d6728f54e..d1e5aedf592 100644 --- a/code/game/mecha/micro/micro.dm +++ b/code/game/mecha/micro/micro.dm @@ -26,7 +26,6 @@ max_micro_weapon_equip = 1 //add_req_access = 0 //operation_req_access = list(access_hos) - damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) var/am = "d3c2fbcadca903a41161ccc9df9cf948" damage_minimum = 0 //Incoming damage lower than this won't actually deal damage. Scrapes shouldn't be a real thing. minimum_penetration = 0 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this. diff --git a/code/game/mecha/micro/security.dm b/code/game/mecha/micro/security.dm index d6d054a4f5a..777ae8912bb 100644 --- a/code/game/mecha/micro/security.dm +++ b/code/game/mecha/micro/security.dm @@ -22,7 +22,6 @@ health = 150 step_energy_drain = 4 // less efficient than base micromech, but still a micromech. deflect_chance = 10 - damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) max_temperature = 15000 infra_luminosity = 6 wreckage = /obj/effect/decal/mecha_wreckage/micro/sec/polecat @@ -45,7 +44,6 @@ dir_in = 2 //Facing south. health = 100 deflect_chance = 5 - damage_absorption = list("brute"=1,"fire"=1,"bullet"=0.9,"laser"=0.8,"energy"=0.85,"bomb"=1) max_temperature = 5000 wreckage = /obj/effect/decal/mecha_wreckage/micro/sec/weasel internal_damage_threshold = 20 diff --git a/code/game/mecha/micro/utility.dm b/code/game/mecha/micro/utility.dm index 9ceaa2bae9d..4587a89a217 100644 --- a/code/game/mecha/micro/utility.dm +++ b/code/game/mecha/micro/utility.dm @@ -9,7 +9,6 @@ dir_in = 2 //Facing south. health = 100 deflect_chance = 10 - damage_absorption = list("brute"=0.9,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) max_temperature = 15000 infra_luminosity = 6 wreckage = /obj/effect/decal/mecha_wreckage/micro/utility/gopher diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 61b4d90183d..8d4ee98fbf9 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -59,7 +59,6 @@ max_temperature = 65000 health = 250 lights_power = 8 - damage_absorption = list("fire"=0.5,"bullet"=0.8,"bomb"=0.5) wreckage = /obj/effect/decal/mecha_wreckage/ripley/firefighter max_hull_equip = 2 max_weapon_equip = 0 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 47d3843b7c9..204a8669d58 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -503,17 +503,22 @@ var/list/global/slot_flags_enumeration = list( return if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) return - if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain + if(isanimal(usr)) //VOREStation Edit Start - Allows simple mobs with hands to use the pickup verb + var/mob/living/simple_mob/s = usr + if(!s.has_hands) + to_chat(usr, "You can't pick things up!") + return + else if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain to_chat(usr, "You can't pick things up!") return - var/mob/living/carbon/C = usr + var/mob/living/L = usr if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained to_chat(usr, "You can't pick things up!") return if(src.anchored) //Object isn't anchored to_chat(usr, "You can't pick that up!") return - if(C.get_active_hand()) //Hand is not full + if(L.get_active_hand()) //Hand is not full //VOREStation Edit End to_chat(usr, "Your hand is full.") return if(!istype(src.loc, /turf)) //Object is on a turf diff --git a/code/game/objects/items/devices/advnifrepair.dm b/code/game/objects/items/devices/advnifrepair.dm index 913aad68ad6..ca3e455acc7 100644 --- a/code/game/objects/items/devices/advnifrepair.dm +++ b/code/game/objects/items/devices/advnifrepair.dm @@ -24,7 +24,7 @@ /obj/item/device/nifrepairer/attackby(obj/W, mob/user) if(istype(W,/obj/item/stack/nanopaste)) var/obj/item/stack/nanopaste/np = W - if(np.use(1) && supply.get_free_space() >= efficiency) + if((supply.get_free_space() >= efficiency) && np.use(1)) to_chat(user, "You convert some nanopaste into programmed nanites inside \the [src].") supply.add_reagent(id = "nifrepairnanites", amount = efficiency) update_icon() diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index cc902d3b6da..339b57f0558 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -4,6 +4,7 @@ name = "power sink" desc = "A nulling power sink which drains energy from electrical systems." icon_state = "powersink0" + icon = 'icons/obj/device.dmi' w_class = ITEMSIZE_LARGE throwforce = 5 throw_speed = 1 diff --git a/code/game/objects/items/weapons/capture_crystal.dm b/code/game/objects/items/weapons/capture_crystal.dm index 4cc748af13d..36447ce9cc3 100644 --- a/code/game/objects/items/weapons/capture_crystal.dm +++ b/code/game/objects/items/weapons/capture_crystal.dm @@ -451,7 +451,9 @@ //Let's let our mob out! /obj/item/capture_crystal/proc/unleash(mob/living/user, atom/target) if(!user && !target) //We got thrown but we're not sure who did it, let's go to where the crystal is - bound_mob.forceMove(src.drop_location()) + var/drop_loc = get_turf(src) + if (drop_loc) + bound_mob.forceMove(drop_loc) return if(!target) //We know who wants to let us out, but they didn't say where, so let's drop us on them bound_mob.forceMove(user.drop_location()) diff --git a/code/game/objects/items/weapons/circuitboards/circuitboards_vr.dm b/code/game/objects/items/weapons/circuitboards/circuitboards_vr.dm index 174e1cde971..62281667512 100644 --- a/code/game/objects/items/weapons/circuitboards/circuitboards_vr.dm +++ b/code/game/objects/items/weapons/circuitboards/circuitboards_vr.dm @@ -2,6 +2,17 @@ #error T_BOARD macro is not defined but we need it! #endif +/obj/item/weapon/circuitboard/get_examine_desc() + . = ..() + if(LAZYLEN(req_components)) + var/list/nice_list = list() + for(var/B in req_components) + var/atom/A = B + if(!ispath(A)) + continue + nice_list += list("[req_components[A]] [initial(A.name)]") + . += "Required components: [english_list(nice_list)]." + // VOREStation specific circuit boards! // Board for the parts lathe in partslathe.dm diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index 7ef7c4bfefc..000cd011f6f 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -264,4 +264,17 @@ /obj/item/weapon/stock_parts/micro_laser/high = 2, //field emitters /obj/item/weapon/stock_parts/scanning_module = 1, //atmosphere sensor /obj/item/weapon/stock_parts/capacitor/adv = 1, //for the JUICE - /obj/item/stack/cable_coil = 10) \ No newline at end of file + /obj/item/stack/cable_coil = 10) + + +/obj/item/weapon/circuitboard/injector_maker + name = T_BOARD("Ready-to-Use Medicine 3000") + build_path = /obj/machinery/injector_maker + board_type = new /datum/frame/frame_types/injector_maker + origin_tech = list(TECH_BIO = 3, TECH_ENGINEERING = 2, TECH_MATERIAL = 2) + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/console_screen = 1 + ) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index c3a94fb1003..d7208d5db37 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -54,7 +54,7 @@ wet() else to_chat(user, "You clean \the [target.name].") - target.clean_blood() + target.clean_blood(TRUE) return //attack_as_weapon diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index 9154f348438..9d1d52109a6 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -13,6 +13,7 @@ slot_flags = SLOT_ID | SLOT_EARS var/age = "\[UNSET\]" + var/species = "\[UNSET\]" var/blood_type = "\[UNSET\]" var/dna_hash = "\[UNSET\]" var/fingerprint_hash = "\[UNSET\]" @@ -61,6 +62,7 @@ id_card.age = 0 id_card.registered_name = real_name id_card.sex = capitalize(gender) + id_card.species = SPECIES_HUMAN id_card.set_id_photo(src) if(dna) @@ -72,6 +74,7 @@ /mob/living/carbon/human/set_id_info(var/obj/item/weapon/card/id/id_card) ..() id_card.age = age + id_card.species = "[custom_species ? "[custom_species] ([species.name])" : species.name]" id_card.sex = capitalize(name_gender()) /obj/item/weapon/card/id/tgui_data(mob/user) @@ -79,6 +82,7 @@ data["registered_name"] = registered_name data["sex"] = sex + data["species"] = species data["age"] = age data["assignment"] = assignment data["fingerprint_hash"] = fingerprint_hash diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm index 80ec8d7f7c5..a86c3d4bd4f 100644 --- a/code/game/objects/items/weapons/paint.dm +++ b/code/game/objects/items/weapons/paint.dm @@ -27,44 +27,52 @@ var/global/list/cached_icons = list() return ..() /obj/item/weapon/reagent_containers/glass/paint/New() - if(paint_type && length(paint_type) > 0) - name = paint_type + " " + name ..() - reagents.add_reagent("water", volume*3/5) - reagents.add_reagent("plasticide", volume/5) - if(paint_type == "white") //why don't white crayons exist - reagents.add_reagent("aluminum", volume/5) - else if (paint_type == "black") - reagents.add_reagent("carbon", volume/5) - else - reagents.add_reagent("marker_ink_[paint_type]", volume/5) - reagents.handle_reactions() + if(paint_type) + reagents.add_reagent("paint", volume, paint_type) /obj/item/weapon/reagent_containers/glass/paint/red icon_state = "paint_red" - paint_type = "red" + paint_type = "#FF0000" /obj/item/weapon/reagent_containers/glass/paint/yellow icon_state = "paint_yellow" - paint_type = "yellow" + paint_type = "#FFFF00" /obj/item/weapon/reagent_containers/glass/paint/green icon_state = "paint_green" - paint_type = "green" + paint_type = "#00FF00" /obj/item/weapon/reagent_containers/glass/paint/blue icon_state = "paint_blue" - paint_type = "blue" + paint_type = "#0000FF" -/obj/item/weapon/reagent_containers/glass/paint/purple +/obj/item/weapon/reagent_containers/glass/paint/violet icon_state = "paint_violet" - paint_type = "purple" + paint_type = "#FF00FF" /obj/item/weapon/reagent_containers/glass/paint/black icon_state = "paint_black" - paint_type = "black" + paint_type = "#000000" + +/obj/item/weapon/reagent_containers/glass/paint/grey + icon_state = "paint_neutral" + paint_type = "#808080" + +/obj/item/weapon/reagent_containers/glass/paint/orange + icon_state = "paint_orange" + paint_type = "#FFA500" + +/obj/item/weapon/reagent_containers/glass/paint/purple + icon_state = "paint_purple" + paint_type = "#A500FF" + +/obj/item/weapon/reagent_containers/glass/paint/cyan + icon_state = "paint_cyan" + paint_type = "#00FFFF" /obj/item/weapon/reagent_containers/glass/paint/white + name = "paint remover bucket" icon_state = "paint_white" - paint_type = "white" + paint_type = "#FFFFFF" diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 9bcd59b39f0..e3faa052f0f 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -248,7 +248,7 @@ framed_offset_y = 6 /obj/item/canvas/twentyfour_twentyfour - name = "ai universal standard canvas" + //name = "ai universal standard canvas" // Uncomment this when AI can actually //desc = "Besides being very large, the AI can accept these as a display from their internal database after you've hung it up." // Not yet icon_state = "24x24" width = 24 diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm index 454a070cfe4..cf196ddf0a0 100644 --- a/code/game/objects/structures/crates_lockers/__closets.dm +++ b/code/game/objects/structures/crates_lockers/__closets.dm @@ -397,6 +397,13 @@ if(ishuman(usr) || isrobot(usr)) add_fingerprint(usr) toggle(usr) + else if(isanimal(usr)) //VOREStation Addition Start + var/mob/living/simple_mob/s = usr + if(s.has_hands) + add_fingerprint(usr) + toggle(usr) + else + to_chat(usr, "This mob type can't use this verb.") //VOREStation Addition End else to_chat(usr, "This mob type can't use this verb.") diff --git a/code/game/objects/structures/flora/flora.dm b/code/game/objects/structures/flora/flora.dm index 2b03156385e..a6850cd7690 100644 --- a/code/game/objects/structures/flora/flora.dm +++ b/code/game/objects/structures/flora/flora.dm @@ -607,7 +607,7 @@ to forming buds, the petals of which secrete the luminescent sap containing the pollen at the time of blooming. Certain \ horticulturists have found ways of halting this process prior to the secretion of the sap, leaving the flower's petals \ bright, at the cost of making that bud sterile." - value = CATALOGUER_REWARD_HARD + value = CATALOGUER_REWARD_MEDIUM /obj/structure/flora/sif/frostbelle name = "frostbelle shrub" diff --git a/code/game/objects/structures/ghost_pods/survivor.dm b/code/game/objects/structures/ghost_pods/survivor.dm new file mode 100644 index 00000000000..62dbc2441da --- /dev/null +++ b/code/game/objects/structures/ghost_pods/survivor.dm @@ -0,0 +1,138 @@ +//Based on /manual/human but not created as a child for better control over how we create a mob. +/obj/structure/ghost_pod/manual/survivor + name = "Emergency Cryopod" + desc = "A damaged cryopod smeared with blood. An injured body seems frozen in time within." + description_info = "This contains a body, which may wake at any time. The external controls\ + seem to be functioning, though the warning lights that flash give no solace.." + ghost_query_type = /datum/ghost_query/shipwreck_survivor + var/occupant_type = "shipwreck survivor" + + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "sleeper_1" + icon_state_opened = "sleeper_0" + density = TRUE + + var/allow_appearance_change = TRUE + var/special_role = MODE_SURVIVOR //Set this to NULL as GM if you don't want the "survivor" stuff to fire. + var/list/clothing_possibilities + + var/start_injured = FALSE //failsafe to prevent accidentally making a pod that deals damage when not intended + + var/suffer_brute = FALSE + var/brute_severity = 20 //We inflict UP TO this much damage. Range is 1 to this value + var/brute_instances = 3 //We inflict damage this many times. Helps spread it around multiple limbs! + + + var/suffer_burn = FALSE + var/burn_severity = 20 + var/burn_instances = 3 + + var/suffer_toxloss = FALSE + var/tox_severity = 20 + + var/suffer_oxloss = FALSE + var/oxy_severity = 20 + + var/suffer_cloneloss = FALSE + var/clone_severity = 5 + +/obj/structure/ghost_pod/manual/survivor/Initialize() + . = ..() + + handle_clothing_setup() + +/obj/structure/ghost_pod/manual/survivor/proc/handle_clothing_setup() + clothing_possibilities = list() + + clothing_possibilities |= subtypesof(/obj/item/clothing/under/utility) + clothing_possibilities |= subtypesof(/obj/item/clothing/head/beret) + clothing_possibilities |= /obj/item/clothing/shoes/black + clothing_possibilities |= /obj/item/device/radio/headset + +/obj/structure/ghost_pod/manual/survivor/create_occupant(var/mob/M) + ..() + var/turf/T = get_turf(src) + var/mob/living/carbon/human/H = new(src) + if(M.mind) + M.mind.transfer_to(H) + to_chat(M, "You are a [occupant_type]!") + H.ckey = M.ckey + visible_message("As \the [src] opens, the pipes on \the [src] surge, before it grows dark.") + log_and_message_admins("successfully opened \a [src] and got a [occupant_type].") + + var/list/uniform_options + var/list/shoe_options + var/list/head_options + var/list/headset_options + + if(clothing_possibilities && clothing_possibilities.len) + for(var/path in clothing_possibilities) + if(ispath(path, /obj/item/clothing/under)) + if(!uniform_options) + uniform_options = list() + uniform_options |= path + if(ispath(path, /obj/item/clothing/shoes)) + if(!shoe_options) + shoe_options = list() + shoe_options |= path + if(ispath(path, /obj/item/clothing/head)) + if(!head_options) + head_options = list() + head_options |= path + if(ispath(path, /obj/item/device/radio/headset)) + if(!headset_options) + headset_options = list() + headset_options |= path + + if(uniform_options && uniform_options.len) + var/newpath = pick(uniform_options) + var/obj/item/clothing/C = new newpath(H) + H.equip_to_appropriate_slot(C) + + if(shoe_options && shoe_options.len) + var/newpath = pick(shoe_options) + var/obj/item/clothing/C = new newpath(H) + H.equip_to_appropriate_slot(C) + + if(head_options && head_options.len) + var/newpath = pick(head_options) + var/obj/item/clothing/C = new newpath(H) + H.equip_to_appropriate_slot(C) + + if(headset_options && headset_options.len) + var/newpath = pick(headset_options) + var/obj/item/C = new newpath(H) + H.equip_to_appropriate_slot(C) + + var/newname = sanitize(tgui_input_text(H, "Your mind feels foggy, and you recall your name might be [H.real_name]. Would you like to change your name?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN) + if (newname) + H.real_name = newname + + icon_state = icon_state_opened + + H.forceMove(T) + + if(special_role) + var/datum/antagonist/role = all_antag_types[special_role] //Explicitly NOT an antagonist. + if(role) + if(role.add_antagonist(H.mind, 1, 1, 0, 1, 1)) + log_admin("\The [src] made [key_name(src)] into a [role.role_text].") + + if(start_injured) //Doublechecking if we actually want them to be injured + if(suffer_brute) + for(var/br = 1, br < brute_instances, br++) + H.adjustBruteLoss(rand(1,brute_severity)) + if(suffer_burn) + for(var/bu = 1, bu < burn_instances, bu++) + H.adjustFireLoss(rand(1,burn_severity)) + if(suffer_oxloss) + H.adjustOxyLoss(rand(1,oxy_severity)) + if(suffer_toxloss) + H.adjustToxLoss(rand(1,tox_severity)) + if(suffer_cloneloss) + H.adjustCloneLoss(rand(1,clone_severity)) + + if(allow_appearance_change) + H.change_appearance(APPEARANCE_ALL, H, check_species_whitelist = 1) + + visible_message("\The [src] [pick("gurgles", "seizes", "clangs")] before releasing \the [H]!") diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 1aeb9cdf4cd..84cb98b9635 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -38,7 +38,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) to_chat(user, "There's no room in [src] for [I].") return FALSE - if(!user.unEquip(I, 0, src)) + if(!user.canUnEquip(I)) to_chat(user, "[I] is stuck to your hand.") return FALSE @@ -83,6 +83,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) to_chat(user, "There's no room in [src] for [I].") return FALSE + user.drop_from_inventory(I, src) update_icon() to_chat(user, "You put [I] into [src].") return TRUE diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 4e67afbc462..befc35be268 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -12,7 +12,7 @@ /obj/structure/morgue name = "morgue" - desc = "Used to keep bodies in untill someone fetches them." + desc = "A refrigerated unit used to store bodies, or for surreptitious naps." icon = 'icons/obj/stationobjs.dmi' icon_state = "morgue1" dir = EAST diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm index ea70fa44a64..4c49624d925 100644 --- a/code/game/objects/structures/simple_doors.dm +++ b/code/game/objects/structures/simple_doors.dm @@ -14,7 +14,7 @@ var/oreAmount = 7 var/knock_sound = 'sound/machines/door/knock_glass.ogg' var/knock_hammer_sound = 'sound/weapons/sonic_jackhammer.ogg' - + /obj/structure/simple_door/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) TemperatureAct(exposed_temperature) @@ -171,7 +171,7 @@ return /obj/structure/simple_door/bullet_act(var/obj/item/projectile/Proj) - hardness -= Proj.force/10 + take_damage(Proj.damage/10) CheckHardness() /obj/structure/simple_door/take_damage(var/damage) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index b6c5885ac4e..aff55b72256 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -194,7 +194,7 @@ wash(M) process_heat(M) for (var/atom/movable/G in src.loc) - G.clean_blood() + G.clean_blood(TRUE) else soundloop.stop() diff --git a/code/game/turfs/flooring/seasonal.dm b/code/game/turfs/flooring/seasonal.dm index 19eca39da11..9095abc85c5 100644 --- a/code/game/turfs/flooring/seasonal.dm +++ b/code/game/turfs/flooring/seasonal.dm @@ -41,8 +41,7 @@ var/world_time_season /obj/structure/flora/tree/jungle ) animal_types = list( - /mob/living/simple_mob/vore/redpanda = 40, - /mob/living/simple_mob/vore/redpanda/fae = 2, + /mob/living/simple_mob/vore/redpanda = 5, /mob/living/simple_mob/vore/sheep = 20, /mob/living/simple_mob/vore/rabbit/black = 20, /mob/living/simple_mob/vore/rabbit/white = 20, @@ -50,7 +49,12 @@ var/world_time_season /mob/living/simple_mob/vore/leopardmander = 2, /mob/living/simple_mob/vore/horse/big = 10, /mob/living/simple_mob/vore/bigdragon/friendly = 1, - /mob/living/simple_mob/vore/alienanimals/dustjumper = 20 + /mob/living/simple_mob/vore/alienanimals/dustjumper = 20, + /mob/living/simple_mob/vore/bee = 20, + /mob/living/simple_mob/vore/horse/big = 5, + /mob/living/simple_mob/animal/wolf = 5, + /mob/living/simple_mob/animal/wolf/direwolf = 1, + /mob/living/simple_mob/animal/wolf/direwolf/dog = 1 ) grass_types = list( /obj/structure/flora/ausbushes/sparsegrass, @@ -73,8 +77,7 @@ var/world_time_season /obj/structure/flora/tree/jungle ) animal_types = list( - /mob/living/simple_mob/vore/redpanda = 40, - /mob/living/simple_mob/vore/redpanda/fae = 2, + /mob/living/simple_mob/vore/redpanda = 1, /mob/living/simple_mob/vore/sheep = 20, /mob/living/simple_mob/vore/rabbit/black = 20, /mob/living/simple_mob/vore/rabbit/white = 20, @@ -82,7 +85,13 @@ var/world_time_season /mob/living/simple_mob/vore/leopardmander = 2, /mob/living/simple_mob/vore/horse/big = 10, /mob/living/simple_mob/vore/bigdragon/friendly = 1, - /mob/living/simple_mob/vore/alienanimals/dustjumper = 20 + /mob/living/simple_mob/vore/alienanimals/dustjumper = 20, + /mob/living/simple_mob/vore/bee = 5, + /mob/living/simple_mob/vore/horse/big = 5, + /mob/living/simple_mob/vore/pakkun = 2, + /mob/living/simple_mob/vore/fennix = 1, + /mob/living/simple_mob/animal/wolf/direwolf/dog = 1, + /mob/living/simple_mob/animal/passive/bird/parrot = 1 ) grass_types = list( /obj/structure/flora/ausbushes/sparsegrass, @@ -102,7 +111,11 @@ var/world_time_season /mob/living/simple_mob/vore/rabbit/white = 20, /mob/living/simple_mob/vore/rabbit/brown = 20, /mob/living/simple_mob/vore/horse/big = 10, - /mob/living/simple_mob/vore/alienanimals/dustjumper = 20 + /mob/living/simple_mob/vore/alienanimals/dustjumper = 20, + /mob/living/simple_mob/vore/horse/big = 1, + /mob/living/simple_mob/animal/wolf = 1, + /mob/living/simple_mob/animal/wolf/direwolf = 1, + /mob/living/simple_mob/animal/wolf/direwolf/dog = 1 ) grass_types = list( /obj/structure/flora/ausbushes/sparsegrass, @@ -121,7 +134,14 @@ var/world_time_season animal_types = list( /mob/living/simple_mob/vore/rabbit/white = 40, - /mob/living/simple_mob/vore/redpanda = 10 + /mob/living/simple_mob/vore/redpanda = 10, + /mob/living/simple_mob/animal/wolf = 10, + /mob/living/simple_mob/animal/wolf/direwolf = 1, + /mob/living/simple_mob/animal/wolf/direwolf/dog = 1, + /mob/living/simple_mob/otie/friendly = 2, + /mob/living/simple_mob/otie/friendly/chubby = 1, + /mob/living/simple_mob/otie/red/friendly = 1, + /mob/living/simple_mob/otie/red/chubby = 1 ) if(prob(snow_chance)) chill() diff --git a/code/game/turfs/simulated/outdoors/survival_action_vr.dm b/code/game/turfs/simulated/outdoors/survival_action_vr.dm index c7f90171c76..9f889594938 100644 --- a/code/game/turfs/simulated/outdoors/survival_action_vr.dm +++ b/code/game/turfs/simulated/outdoors/survival_action_vr.dm @@ -1,9 +1,12 @@ +var/static/list/has_rocks = list("dirt5", "dirt6", "dirt7", "dirt8", "dirt9") + /turf/simulated/floor/outdoors/newdirt/attack_hand(mob/user) if(user.pulling) return ..() - var/static/list/has_rocks = list("dirt5", "dirt6", "dirt7", "dirt8", "dirt9") if(!Adjacent(user)) return ..() + if(user.a_intent != I_HELP) + return ..() if(icon_state in has_rocks) user.visible_message("[user] loosens rocks from \the [src]...", "You loosen rocks from \the [src]...") if(do_after(user, 5 SECONDS, exclusive = TASK_USER_EXCLUSIVE)) @@ -76,4 +79,4 @@ S.pixel_y = rand(-6,6) sticks = FALSE else - to_chat(user, "You don't see any loose sticks...") \ No newline at end of file + to_chat(user, "You don't see any loose sticks...") diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index af8799004ba..dfd236c0d92 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -279,7 +279,8 @@ output += "