diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 3c0e190427..114f9b7c11 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -6,6 +6,7 @@ #define OXY "oxy" #define CLONE "clone" #define HALLOSS "halloss" +#define ELECTROCUTE "electrocute" #define CUT "cut" #define BRUISE "bruise" diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm index bd16322e20..efa5c454f2 100644 --- a/code/datums/supplypacks/engineering.dm +++ b/code/datums/supplypacks/engineering.dm @@ -21,6 +21,48 @@ containertype = /obj/structure/closet/crate/engineering containername = "Superconducting Magnetic Coil crate" +/datum/supply_packs/eng/shield_capacitor + name = "Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor) + cost = 20 + containertype = /obj/structure/closet/crate/engineering + containername = "shield capacitor crate" + +/datum/supply_packs/eng/shield_capacitor/advanced + name = "Advanced Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor/advanced) + cost = 30 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced shield capacitor crate" + +/datum/supply_packs/eng/bubble_shield + name = "Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen) + cost = 40 + containertype = /obj/structure/closet/crate/engineering + containername = "shield bubble generator crate" + +/datum/supply_packs/eng/bubble_shield/advanced + name = "Advanced Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen/advanced) + cost = 60 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced bubble shield generator crate" + +/datum/supply_packs/eng/hull_shield + name = "Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external) + cost = 80 + containertype = /obj/structure/closet/crate/engineering + containername = "shield hull generator crate" + +/datum/supply_packs/eng/hull_shield/advanced + name = "Advanced Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external/advanced) + cost = 120 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced hull shield generator crate" + /datum/supply_packs/eng/electrical name = "Electrical maintenance crate" contains = list( diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm index 54f5f83663..2ea752e3b7 100644 --- a/code/game/antagonist/station/thug.dm +++ b/code/game/antagonist/station/thug.dm @@ -13,5 +13,5 @@ var/datum/antagonist/thug/thugs Try to make sure other players have fun! If you are confused or at a loss, always adminhelp, \ and before taking extreme actions, please try to also contact the administration! \ Think through your actions and make the roleplay immersive! Please remember all \ - rules aside from those without explicit exceptions apply to antagonists." - flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE \ No newline at end of file + rules aside from those with explicit exceptions apply to antagonists." + flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index e54eb3c1cd..7c6a9cc7af 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -219,7 +219,11 @@ turf/proc/AdjacentTurfsRangedSting() victims += C var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims - if(!T) return + if(!T) + return + if(T.isSynthetic()) + src << "We are unable to pierce the outer shell of [T]." + return if(!(T in view(changeling.sting_range))) return if(!sting_can_reach(T, changeling.sting_range)) return if(!changeling_power(required_chems)) return diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm index 139950e900..5ab724789b 100644 --- a/code/game/gamemodes/changeling/powers/armblade.dm +++ b/code/game/gamemodes/changeling/powers/armblade.dm @@ -134,4 +134,5 @@ /obj/item/weapon/melee/changeling/claw/greater name = "hand greatclaw" force = 20 - armor_penetration = 20 \ No newline at end of file + armor_penetration = 20 + pry = 1 \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index ca1d5639e9..8db7a49255 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -123,7 +123,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) return tearreality() if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(src.loc,3) + return emp(src.loc,5) if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) return drain() if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 64f07bd1d5..5669981f77 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -56,31 +56,31 @@ if(shocked) shock(user, 50) - - var/dat = "

Autolathe Control Panel


" + var/list/dat = list() + dat += "

Autolathe Control Panel


" if(!disabled) dat += "" - var/material_top = "" - var/material_bottom = "" + var/list/material_top = list("") + var/list/material_bottom = list("") for(var/material in stored_material) material_top += "" material_bottom += "" - dat += "[material_top][material_bottom]
[material][stored_material[material]]/[storage_capacity[material]]

" + dat += "[material_top.Join()][material_bottom.Join()]
" dat += "

Printable Designs

Showing: [current_category].

" for(var/datum/category_item/autolathe/R in current_category.items) if(R.hidden && !hacked) continue var/can_make = 1 - var/material_string = "" - var/multiplier_string = "" + var/list/material_string = list() + var/list/multiplier_string = list() var/max_sheets var/comma if(!R.resources || !R.resources.len) - material_string = "No resources required." + material_string += "No resources required." else //Make sure it's buildable and list requires resources. for(var/material in R.resources) @@ -99,12 +99,12 @@ if(R.is_stack) if(max_sheets && max_sheets > 0) max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type. - multiplier_string += "
" + multiplier_string += "
" for(var/i = 5;i*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string]" + dat += "" dat += "
[material_string]
[R.hidden ? "*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string.Join()][material_string.Join()]

" //Hacking. @@ -114,7 +114,7 @@ dat += "
" - user << browse(dat, "window=autolathe") + user << browse(dat.Join(), "window=autolathe") onclose(user, "autolathe") /obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 96ab5eab20..87077b68db 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -289,3 +289,27 @@ if(!usr.incapacitated()) return go_in(usr) + +/obj/machinery/recharge_station/ghost_pod_recharger + name = "drone pod" + desc = "This is a pod which used to contain a drone... Or maybe it still does?" + icon = 'icons/obj/structures.dmi' + +/obj/machinery/recharge_station/ghost_pod_recharger/update_icon() + ..() + if(stat & BROKEN) + icon_state = "borg_pod_closed" + desc = "It appears broken..." + return + + if(occupant) + if((stat & NOPOWER) && !has_cell_power()) + icon_state = "borg_pod_closed" + desc = "It appears to be unpowered..." + else + icon_state = "borg_pod_closed" + else + icon_state = "borg_pod_opened" + + if(icon_update_tick == 0) + build_overlays() \ No newline at end of file diff --git a/code/game/machinery/vr_console.dm b/code/game/machinery/vr_console.dm new file mode 100644 index 0000000000..ff156fa287 --- /dev/null +++ b/code/game/machinery/vr_console.dm @@ -0,0 +1,222 @@ +/obj/machinery/vr_sleeper + name = "VR sleeper" + desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "syndipod_0" + density = 1 + anchored = 1 + circuit = /obj/item/weapon/circuitboard/vr_sleeper + var/mob/living/carbon/human/occupant = null + var/mob/living/carbon/human/avatar = null + var/datum/mind/vr_mind = null + + use_power = 1 + idle_power_usage = 15 + active_power_usage = 200 + light_color = "#FF0000" + +/obj/machinery/vr_sleeper/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) + component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) + + RefreshParts() + +/obj/machinery/vr_sleeper/initialize() + update_icon() + +/obj/machinery/vr_sleeper/process() + if(stat & (NOPOWER|BROKEN)) + return + +/obj/machinery/vr_sleeper/update_icon() + icon_state = "syndipod_[occupant ? "1" : "0"]" + +/obj/machinery/vr_sleeper/Topic(href, href_list) + if(..()) + return 1 + + if(usr == occupant) + to_chat(usr, "You can't reach the controls from the inside.") + return + + add_fingerprint(usr) + + if(href_list["eject"]) + go_out() + + return 1 + +/obj/machinery/vr_sleeper/attackby(var/obj/item/I, var/mob/user) + add_fingerprint(user) + if(default_deconstruction_screwdriver(user, I)) + return + else if(default_deconstruction_crowbar(user, I)) + return + + +/obj/machinery/vr_sleeper/MouseDrop_T(var/mob/target, var/mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !isliving(target)) + return + go_in(target, user) + + + +/obj/machinery/sleeper/relaymove(var/mob/user) + ..() + if(usr.incapacitated()) + return + go_out() + + + +/obj/machinery/vr_sleeper/emp_act(var/severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(occupant) + // This will eject the user from VR + // ### Fry the brain? + go_out() + + ..(severity) + +/obj/machinery/vr_sleeper/verb/eject() + set src in oview(1) + set category = "Object" + set name = "Eject VR Capsule" + + if(usr.incapacitated()) + return + + if(usr != occupant && avatar && alert(avatar, "Someone wants to remove you from virtual reality. Do you want to leave?", "Leave VR?", "Yes", "No") == "No") + return + + // The player in VR is fine with leaving, kick them out and reset avatar + avatar.exit_vr() + avatar = null + go_out() + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/verb/climb_in() + set src in oview(1) + set category = "Object" + set name = "Enter VR Capsule" + + if(usr.incapacitated()) + return + go_in(usr, usr) + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/relaymove(mob/user as mob) + if(user.incapacitated()) + return 0 //maybe they should be able to get out with cuffs, but whatever + go_out() + +/obj/machinery/vr_sleeper/proc/go_in(var/mob/M, var/mob/user) + if(!M) + return + if(stat & (BROKEN|NOPOWER)) + return + if(!ishuman(M)) + user << "\The [src] rejects [M] with a sharp beep." + if(occupant) + user << "\The [src] is already occupied." + return + + if(M == user) + visible_message("\The [user] starts climbing into \the [src].") + else + visible_message("\The [user] starts putting [M] into \the [src].") + + if(do_after(user, 20)) + if(occupant) + to_chat(user, "\The [src] is already occupied.") + return + M.stop_pulling() + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + update_use_power(2) + occupant = M + + update_icon() + + enter_vr() + return + +/obj/machinery/vr_sleeper/proc/go_out() + if(!occupant) + return + + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + occupant.loc = src.loc + occupant = null + for(var/atom/movable/A in src) // In case an object was dropped inside or something + if(A == circuit) + continue + if(A in component_parts) + continue + A.loc = src.loc + update_use_power(1) + update_icon() + +/obj/machinery/vr_sleeper/proc/enter_vr() + + // No mob to transfer a mind from + if(!occupant) + return + + // No mind to transfer + if(!occupant.mind) + return + + // Mob doesn't have an active consciousness to send/receive from + if(occupant.stat != CONSCIOUS) + return + + avatar = occupant.vr_link + // If they've already enterred VR, and are reconnecting, prompt if they want a new body + if(avatar && alert(occupant, "You already have a Virtual Reality avatar. Would you like to use it?", "New avatar", "Yes", "No") == "No") + // Delink the mob + occupant.vr_link = null + avatar = null + + if(!avatar) + // Get the desired spawn location to put the body + var/S = null + var/list/vr_landmarks = list() + for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list) + vr_landmarks += sloc.name + + S = input(occupant, "Please select a location to spawn your avatar at:", "Spawn location") as null|anything in vr_landmarks + if(!S) + return 0 + + for(var/obj/effect/landmark/virtual_reality/i in landmarks_list) + if(i.name == S) + S = i + break + + avatar = new(S, "Virtual Reality Avatar") + // If the user has a non-default (Human) bodyshape, make it match theirs. + if(occupant.species.name != "Promethean" && occupant.species.name != "Human") + avatar.shapeshifter_change_shape(occupant.species.name) + avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it + avatar.Sleeping(1) + + occupant.enter_vr(avatar) + + // Prompt for username after they've enterred the body. + var/newname = sanitize(input(avatar, "You are enterring virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change") as null|text, MAX_NAME_LEN) + if (newname) + avatar.real_name = newname + + else + occupant.enter_vr(avatar) + diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 547406aa1d..b8cb8006d2 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -107,6 +107,18 @@ return 1 +/obj/effect/landmark/virtual_reality + name = "virtual_reality" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + anchored = 1.0 + +/obj/effect/landmark/virtual_reality/New() + ..() + tag = "virtual_reality*[name]" + invisibility = 101 + return 1 + //Costume spawner landmarks /obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6b4a09c6a5..8b00612641 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -80,6 +80,7 @@ var/list/sprite_sheets_obj = list() var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast. + var/addblends // Icon overlay for ADD highlights when applicable. /obj/item/New() ..() diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 53d647a4f0..ca4b8d8066 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -8,7 +8,7 @@ var/spamcheck = 0 var/emagged = 0 var/insults = 0 - var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TATER!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!") + var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!") /obj/item/device/megaphone/attack_self(mob/living/user as mob) if (user.client) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6065d6a514..a79faa60d2 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -699,54 +699,6 @@ desc = "A \"Space Life\" brand Emergency Response Team Commander action figure." icon_state = "ert" -/obj/item/toy/therapy_red - name = "red therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is red." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyred" - item_state = "egg4" // It's the red egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_purple - name = "purple therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is purple." - icon = 'icons/obj/toy.dmi' - icon_state = "therapypurple" - item_state = "egg1" // It's the magenta egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_blue - name = "blue therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is blue." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyblue" - item_state = "egg2" // It's the blue egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_yellow - name = "yellow therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is yellow." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyyellow" - item_state = "egg5" // It's the yellow egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_orange - name = "orange therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is orange." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyorange" - item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_green - name = "green therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is green." - icon = 'icons/obj/toy.dmi' - icon_state = "therapygreen" - item_state = "egg3" // It's the green egg in items_left/righthand - w_class = ITEMSIZE_TINY - /* * Plushies */ @@ -800,9 +752,10 @@ //Small plushies. /obj/item/toy/plushie name = "generic small plush" - desc = "A very generic small plushie. It seems to not want to exist." + desc = "A small toy plushie. It's very cute." icon = 'icons/obj/toy.dmi' icon_state = "nymphplushie" + w_class = ITEMSIZE_TINY var/last_message = 0 /obj/item/toy/plushie/attack_self(mob/user as mob) @@ -815,9 +768,24 @@ else if (user.a_intent == I_GRAB) user.visible_message("\The [user] attempts to strangle [src]!","You attempt to strangle [src]!") else - user.visible_message("\The [user] pokes the [src].","You poke the [src].") + user.visible_message("\The [user] pokes [src].","You poke [src].") last_message = world.time +obj/item/toy/plushie/verb/rename_plushie() + set name = "Name Plushie" + set category = "Object" + set desc = "Give your plushie a cute name!" + w_class = ITEMSIZE_TINY + var/mob/M = usr + if(!M.mind) return 0 + + var/input = sanitizeSafe(input("What do you want to name the plushie?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + name = input + to_chat(M, "You name the plushie [input], giving it a hug for good luck.") + return 1 + /obj/item/toy/plushie/nymph name = "diona nymph plush" desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not." @@ -830,7 +798,7 @@ /obj/item/toy/plushie/kitten name = "kitten plush" - desc = "A plushie of a cute kitten! Watch as it purrs it's way right into your heart." + desc = "A plushie of a cute kitten! Watch as it purrs its way right into your heart." icon_state = "kittenplushie" /obj/item/toy/plushie/lizard @@ -848,6 +816,49 @@ desc = "A farwa plush doll. It's soft and comforting!" icon_state = "farwaplushie" +/obj/item/toy/plushie/therapy/red + name = "red therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is red." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyred" + item_state = "egg4" // It's the red egg in items_left/righthand + +/obj/item/toy/plushie/therapy/purple + name = "purple therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is purple." + icon = 'icons/obj/toy.dmi' + icon_state = "therapypurple" + item_state = "egg1" // It's the magenta egg in items_left/righthand + +/obj/item/toy/plushie/therapy/blue + name = "blue therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is blue." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyblue" + item_state = "egg2" // It's the blue egg in items_left/righthand + +/obj/item/toy/plushie/therapy/yellow + name = "yellow therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is yellow." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyyellow" + item_state = "egg5" // It's the yellow egg in items_left/righthand + +/obj/item/toy/plushie/therapy/orange + name = "orange therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is orange." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyorange" + item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless + +/obj/item/toy/plushie/therapy/green + name = "green therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is green." + icon = 'icons/obj/toy.dmi' + icon_state = "therapygreen" + item_state = "egg3" // It's the green egg in items_left/righthand + + //Toy cult sword /obj/item/toy/cultsword name = "foam sword" diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index fa48be65bb..3cbc54e855 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -202,6 +202,15 @@ /obj/item/weapon/reagent_containers/syringe = 3, /obj/item/stack/material/glass/reinforced = 2) +/obj/item/weapon/circuitboard/vr_sleeper + name = T_BOARD("VR sleeper") + build_path = /obj/machinery/vr_sleeper + board_type = new /datum/frame/frame_types/medical_pod + origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) + req_components = list( + /obj/item/weapon/stock_parts/scanning_module = 1, + /obj/item/stack/material/glass/reinforced = 2) + /obj/item/weapon/circuitboard/dna_analyzer name = T_BOARD("dna analyzer") build_path = /obj/machinery/dnaforensics 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 f075ea49f9..e0975361eb 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -373,8 +373,8 @@ job_access_type = /datum/job/bartender /obj/item/weapon/card/id/civilian/botanist - assignment = "Gardener" - rank = "Gardener" + assignment = "Botanist" + rank = "Botanist" job_access_type = /datum/job/hydro /obj/item/weapon/card/id/civilian/chaplain diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index fb65fdf195..2330ed3d88 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -657,6 +657,61 @@ nextrefueltick = world.time + 10 reagents.add_reagent("fuel", 1) +/* + * Backpack Welder. + */ + +/obj/item/weapon/weldingtool/tubefed + name = "tube-fed welding tool" + desc = "A bulky, cooler-burning welding tool that draws from a worn welding tank." + icon_state = "tubewelder" + max_fuel = 10 + w_class = ITEMSIZE_NO_CONTAINER + matter = null + toolspeed = 1.25 + change_icons = 0 + flame_intensity = 1 + eye_safety_modifier = 1 + always_process = TRUE + var/obj/item/weapon/weldpack/mounted_pack = null + +/obj/item/weapon/weldingtool/tubefed/New(location) + ..() + if(istype(location, /obj/item/weapon/weldpack)) + var/obj/item/weapon/weldpack/holder = location + mounted_pack = holder + else + qdel(src) + +/obj/item/weapon/weldingtool/tubefed/Destroy() + mounted_pack.nozzle = null + mounted_pack = null + return ..() + +/obj/item/weapon/weldingtool/tubefed/process() + if(mounted_pack) + if(!istype(mounted_pack.loc,/mob/living/carbon/human)) + mounted_pack.return_nozzle() + else + var/mob/living/carbon/human/H = mounted_pack.loc + if(H.back != mounted_pack) + mounted_pack.return_nozzle() + + if(mounted_pack.loc != src.loc && src.loc != mounted_pack) + mounted_pack.return_nozzle() + visible_message("\The [src] retracts to its fueltank.") + + if(get_fuel() <= get_max_fuel()) + mounted_pack.reagents.trans_to_obj(src, 1) + + ..() + +/obj/item/weapon/weldingtool/tubefed/dropped(mob/user) + ..() + if(src.loc != user) + mounted_pack.return_nozzle() + to_chat(user, "\The [src] retracts to its fueltank.") + /* * Electric/Arc Welder */ diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm index 6a6d77521e..0312ca55f8 100644 --- a/code/game/objects/items/weapons/weldbackpack.dm +++ b/code/game/objects/items/weapons/weldbackpack.dm @@ -6,46 +6,140 @@ icon_state = "welderpack" w_class = ITEMSIZE_LARGE var/max_fuel = 350 + var/obj/item/weapon/nozzle = null //Attached welder, or other spray device. + var/nozzle_attached = 0 /obj/item/weapon/weldpack/New() var/datum/reagents/R = new/datum/reagents(max_fuel) //Lotsa refills reagents = R R.my_atom = src R.add_reagent("fuel", max_fuel) + nozzle = new/obj/item/weapon/weldingtool/tubefed(src) + nozzle_attached = 1 + +/obj/item/weapon/weldpack/Destroy() + qdel(nozzle) + nozzle = null + return ..() + +/obj/item/weapon/weldpack/dropped(mob/user) + ..() + if(nozzle) + user.remove_from_mob(nozzle) + return_nozzle() + to_chat(user, "\The [nozzle] retracts to its fueltank.") + +/obj/item/weapon/weldpack/proc/get_nozzle(var/mob/living/user) + if(!ishuman(user)) + return 0 + + var/mob/living/carbon/human/H = user + + if(H.hands_are_full()) //Make sure our hands aren't full. + to_chat(H, "Your hands are full. Drop something first.") + return 0 + + var/obj/item/weapon/F = nozzle + H.put_in_hands(F) + nozzle_attached = 0 + + return 1 + +/obj/item/weapon/weldpack/proc/return_nozzle(var/mob/living/user) + nozzle.forceMove(src) + nozzle_attached = 1 /obj/item/weapon/weldpack/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) + if(istype(W, /obj/item/weapon/weldingtool) && !(W == nozzle)) var/obj/item/weapon/weldingtool/T = W if(T.welding & prob(50)) message_admins("[key_name_admin(user)] triggered a fueltank explosion.") log_game("[key_name(user)] triggered a fueltank explosion.") - user << "That was stupid of you." + to_chat(user,"That was stupid of you.") explosion(get_turf(src),-1,0,2) if(src) qdel(src) return - else + else if(T.status) if(T.welding) - user << "That was close!" + to_chat(user,"That was close!") src.reagents.trans_to_obj(W, T.max_fuel) - user << "Welder refilled!" + to_chat(user, "Welder refilled!") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return - user << "The tank scoffs at your insolence. It only provides services to welders." + else if(nozzle) + if(nozzle == W) + if(!user.unEquip(W)) + to_chat(user,"\The [W] seems to be stuck to your hand.") + return + if(!nozzle_attached) + return_nozzle() + to_chat(user,"You attach \the [W] to the [src].") + return + else + to_chat(user,"The [src] already has a nozzle!") + else + to_chat(user,"The tank scoffs at your insolence. It only provides services to welders.") return +/obj/item/weapon/weldpack/attack_hand(mob/user as mob) + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/wearer = user + if(wearer.back == src) + if(nozzle && nozzle_attached) + if(!wearer.incapacitated()) + get_nozzle(user) + else + to_chat(user,"\The [src] does not have a nozzle attached!") + else + ..() + else + ..() + /obj/item/weapon/weldpack/afterattack(obj/O as obj, mob/user as mob, proximity) if(!proximity) // this replaces and improves the get_dist(src,O) <= 1 checks used previously return if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume < max_fuel) O.reagents.trans_to_obj(src, max_fuel) - user << "You crack the cap off the top of the pack and fill it back up again from the tank." + to_chat(user,"You crack the cap off the top of the pack and fill it back up again from the tank.") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume == max_fuel) - user << "The pack is already full!" + to_chat(user,"The pack is already full!") return +/obj/item/weapon/weldpack/MouseDrop(obj/over_object as obj) //This is terrifying. + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/weapon/weldpack/examine(mob/user) ..(user) user << text("\icon[] [] units of fuel left!", src, src.reagents.total_volume) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index 82545b5293..a244a02a08 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -518,12 +518,12 @@ /obj/random/toy/item_to_spawn() return pick(/obj/item/toy/bosunwhistle, - /obj/item/toy/therapy_red, - /obj/item/toy/therapy_purple, - /obj/item/toy/therapy_blue, - /obj/item/toy/therapy_yellow, - /obj/item/toy/therapy_orange, - /obj/item/toy/therapy_green, + /obj/item/toy/plushie/therapy/red, + /obj/item/toy/plushie/therapy/purple, + /obj/item/toy/plushie/therapy/blue, + /obj/item/toy/plushie/therapy/yellow, + /obj/item/toy/plushie/therapy/orange, + /obj/item/toy/plushie/therapy/green, /obj/item/toy/cultsword, /obj/item/toy/katana, /obj/item/toy/snappop, diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 43f93f1faa..98ecb2bec7 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -258,8 +258,8 @@ new /obj/item/device/tape/random(src) new /obj/item/device/tape/random(src) new /obj/item/device/camera(src) - new /obj/item/toy/therapy_blue(src) new /obj/item/weapon/storage/fancy/vials(src) //VOREStation Edit - adding vials for new hypo + new /obj/item/toy/plushie/therapy/blue(src) return /obj/structure/closet/secure_closet/psych diff --git a/code/game/objects/structures/ghost_pods/ghost_pods.dm b/code/game/objects/structures/ghost_pods/ghost_pods.dm index 7beba29caa..9eeefeee61 100644 --- a/code/game/objects/structures/ghost_pods/ghost_pods.dm +++ b/code/game/objects/structures/ghost_pods/ghost_pods.dm @@ -22,6 +22,8 @@ if(winner.len) var/mob/observer/dead/D = winner[1] create_occupant(D) + new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc) + del(src) return TRUE else return FALSE @@ -29,7 +31,6 @@ // Override this to create whatever mob you need. Be sure to call ..() if you don't want it to make infinite mobs. /obj/structure/ghost_pod/proc/create_occupant(var/mob/M) used = TRUE - icon_state = icon_state_opened return TRUE diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 03128cccf0..d1a7e42908 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -20,7 +20,7 @@ var/material/material var/material/padding_material var/base_icon = "bed" - var/applies_material_colour = 1 //VOREStation Add - For special color beds/chairs + var/applies_material_colour = 1 /obj/structure/bed/New(var/newloc, var/new_material, var/new_padding_material) ..(newloc) @@ -47,6 +47,7 @@ var/cache_key = "[base_icon]-[material.name]" if(isnull(stool_cache[cache_key])) var/image/I = image(icon, base_icon) //VOREStation Edit + //var/image/I = image('icons/obj/furniture.dmi', base_icon) //From Polaris Sync. Not sure if this is a better way of doing it or not. Uncomment if so. if(applies_material_colour) //VOREStation Add - Goes with added var I.color = material.icon_colour stool_cache[cache_key] = I diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 04e647f944..b990e8c514 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -83,7 +83,6 @@ src.set_dir(turn(src.dir, 90)) return -//VOREStation Add - Shuttle Chair /obj/structure/bed/chair/shuttle name = "chair" desc = "You sit in this. Either by will or force." @@ -91,7 +90,7 @@ color = null base_icon = "shuttle_chair" applies_material_colour = 0 -//VOREStation Add End + // Leaving this in for the sake of compilation. /obj/structure/bed/chair/comfy desc = "It's a chair. It looks comfy." diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 843c2f0dab..13a24987b7 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -91,16 +91,13 @@ playsound(src, "shatter", 70, 1) if(display_message) visible_message("[src] shatters!") - if(dir == SOUTHWEST) - var/index = null - index = 0 - while(index < 2) - new shardtype(loc) //todo pooling? - if(reinf) new /obj/item/stack/rods(loc) - index++ - else + new shardtype(loc) + if(reinf) + new /obj/item/stack/rods(loc) + if(is_fulltile()) new shardtype(loc) //todo pooling? - if(reinf) new /obj/item/stack/rods(loc) + if(reinf) + new /obj/item/stack/rods(loc) qdel(src) return @@ -290,11 +287,9 @@ else playsound(src, W.usesound, 75, 1) visible_message("[user] dismantles \the [src].") - if(dir == SOUTHWEST) - var/obj/item/stack/material/mats = new glasstype(loc) - mats.amount = is_fulltile() ? 4 : 2 - else - new glasstype(loc) + var/obj/item/stack/material/mats = new glasstype(loc) + if(is_fulltile()) + mats.amount = 4 qdel(src) else if(istype(W,/obj/item/frame) && anchored) var/obj/item/frame/F = W @@ -329,6 +324,9 @@ if(usr.incapacitated()) return 0 + if(is_fulltile()) + return 0 + if(anchored) usr << "It is fastened to the floor therefore you can't rotate it!" return 0 @@ -348,6 +346,9 @@ if(usr.incapacitated()) return 0 + if(is_fulltile()) + return 0 + if(anchored) usr << "It is fastened to the floor therefore you can't rotate it!" return 0 @@ -361,13 +362,16 @@ /obj/structure/window/New(Loc, start_dir=null, constructed=0) ..() + if (start_dir) + set_dir(start_dir) + //player-constructed windows if (constructed) anchored = 0 + state = 0 update_verbs() - - if (start_dir) - set_dir(start_dir) + if(is_fulltile()) + maxhealth *= 2 health = maxhealth @@ -406,10 +410,10 @@ //Updates the availabiliy of the rotation verbs /obj/structure/window/proc/update_verbs() - if(anchored) + if(anchored || is_fulltile()) verbs -= /obj/structure/window/proc/rotate verbs -= /obj/structure/window/proc/revrotate - else + else if(!is_fulltile()) verbs += /obj/structure/window/proc/rotate verbs += /obj/structure/window/proc/revrotate @@ -507,14 +511,6 @@ glasstype = /obj/item/stack/material/glass/reinforced force_threshold = 6 - -/obj/structure/window/New(Loc, constructed=0) - ..() - - //player-constructed windows - if (constructed) - state = 0 - /obj/structure/window/reinforced/full dir = SOUTHWEST icon_state = "fwindow" diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index 26e3a9c733..b721188bc5 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -104,7 +104,7 @@ // Note that the current station being used will be pruned from this list upon being instantiated destination_names = list( "NSS Exodus in Nyx", - "NCS Northern Star in Vir", + //"NCS Northern Star in Vir", "NLS Southern Cross in Vir", "NAS Vir Central Command", "a dockyard orbiting Sif", diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index ab70fb464a..52b41025e4 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -3,6 +3,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O /datum/preferences var/equip_preview_mob = EQUIP_PREVIEW_ALL + var/icon/bgstate = "000" + var/list/bgstate_options = list("000", "fff", "steel", "white") + /datum/category_item/player_setup_item/general/body name = "Body" sort_order = 3 @@ -34,6 +37,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_green"] >> pref.g_synth S["synth_blue"] >> pref.b_synth pref.preview_icon = null + S["bgstate"] >> pref.bgstate /datum/category_item/player_setup_item/general/body/save_character(var/savefile/S) S["species"] << pref.species @@ -61,6 +65,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_red"] << pref.r_synth S["synth_green"] << pref.g_synth S["synth_blue"] << pref.b_synth + S["bgstate"] << pref.bgstate /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) if(!pref.species || !(pref.species in playable_species)) @@ -87,6 +92,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(!pref.rlimb_data) pref.rlimb_data = list() if(!pref.body_markings) pref.body_markings = list() else pref.body_markings &= body_marking_styles_list + if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options)) + pref.bgstate = "000" // Moved from /datum/preferences/proc/copy_to() /datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character) @@ -268,6 +275,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "Preview
" . += "
" + . += "
Cycle background" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_LOADOUT ? "Hide loadout" : "Show loadout"]" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]" . += "" @@ -701,6 +709,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_synth = hex2num(copytext(new_color, 6, 8)) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["cycle_bg"]) + pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) + return TOPIC_REFRESH_UPDATE_PREVIEW + return ..() /datum/category_item/player_setup_item/general/body/proc/reset_limbs() diff --git a/code/modules/client/preference_setup/loadout/loadout_general.dm b/code/modules/client/preference_setup/loadout/loadout_general.dm index 6f3115fd2f..860869883f 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general.dm @@ -34,6 +34,18 @@ display_name = "Spaceball booster pack" path = /obj/item/weapon/pack/spaceball +/datum/gear/plushie + display_name = "plushie selection" + path = /obj/item/toy/plushie/ + +/datum/gear/plushie/New() + ..() + var/list/plushies = list() + for(var/plushie in subtypesof(/obj/item/toy/plushie/) - /obj/item/toy/plushie/therapy) + var/obj/item/toy/plushie/plushie_type = plushie + plushies[initial(plushie_type.name)] = plushie_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(plushies)) + /datum/gear/flask display_name = "flask" path = /obj/item/weapon/reagent_containers/food/drinks/flask/barflask diff --git a/code/modules/client/preference_setup/loadout/loadout_head.dm b/code/modules/client/preference_setup/loadout/loadout_head.dm index da6c3949f3..38f945648c 100644 --- a/code/modules/client/preference_setup/loadout/loadout_head.dm +++ b/code/modules/client/preference_setup/loadout/loadout_head.dm @@ -154,34 +154,10 @@ path = /obj/item/clothing/head/fedora/grey /datum/gear/head/hairflower - display_name = "hair flower pin, red" - path = /obj/item/clothing/head/hairflower - -/datum/gear/head/hairflower/yellow - display_name = "hair flower pin, yellow" - path = /obj/item/clothing/head/hairflower/yellow - -/datum/gear/head/hairflower/pink - display_name = "hair flower pin, pink" - path = /obj/item/clothing/head/hairflower/pink - -/datum/gear/head/hairflower/blue - display_name = "hair flower pin, blue" - path = /obj/item/clothing/head/hairflower/blue - -/datum/gear/head/hairflower/violet - display_name = "hair flower pin, violet" - path = /obj/item/clothing/head/hairflower/violet - -/datum/gear/head/hairflower/orange - display_name = "hair flower pin, orange" - path = /obj/item/clothing/head/hairflower/orange - -/datum/gear/head/hairflower/white display_name = "hair flower pin" path = /obj/item/clothing/head/hairflower/white -/datum/gear/head/hairflower/white/New() +/datum/gear/head/hairflower/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) @@ -372,4 +348,4 @@ /datum/gear/head/surgical/purple display_name = "surgical cap, purple" - path = /obj/item/clothing/head/surgery/purple \ No newline at end of file + path = /obj/item/clothing/head/surgery/purple diff --git a/code/modules/client/preference_setup/loadout/loadout_shoes.dm b/code/modules/client/preference_setup/loadout/loadout_shoes.dm index ba2d995b27..6b15fba5ea 100644 --- a/code/modules/client/preference_setup/loadout/loadout_shoes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_shoes.dm @@ -73,10 +73,6 @@ display_name = "shoes, yellow" path = /obj/item/clothing/shoes/yellow -/datum/gear/shoes/flats - display_name = "flats, black" - path = /obj/item/clothing/shoes/flats - /datum/gear/shoes/hitops/ display_name = "high-top, white" path = /obj/item/clothing/shoes/hitops/ @@ -109,30 +105,6 @@ display_name = "high-top, yellow" path = /obj/item/clothing/shoes/hitops/yellow -/datum/gear/shoes/flats/blue - display_name = "flats, blue" - path = /obj/item/clothing/shoes/flats/blue - -/datum/gear/shoes/flats/brown - display_name = "flats, brown" - path = /obj/item/clothing/shoes/flats/brown - -/datum/gear/shoes/flats/orange - display_name = "flats, orange" - path = /obj/item/clothing/shoes/flats/orange - -/datum/gear/shoes/flats/purple - display_name = "flats, purple" - path = /obj/item/clothing/shoes/flats/purple - -/datum/gear/shoes/flats/red - display_name = "flats, red" - path = /obj/item/clothing/shoes/flats/red - -/datum/gear/shoes/flats/white - display_name = "flats, white" - path = /obj/item/clothing/shoes/flats/white - /datum/gear/shoes/flipflops display_name = "flip flops" path = /obj/item/clothing/shoes/flipflop @@ -157,11 +129,11 @@ ..() gear_tweaks = list(gear_tweak_free_color_choice) -/datum/gear/shoes/flats/color +/datum/gear/shoes/flats display_name = "flats" path = /obj/item/clothing/shoes/flats/white/color -/datum/gear/shoes/flats/color/New() +/datum/gear/shoes/flats/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) @@ -246,4 +218,4 @@ /datum/gear/shoes/boots/winter/hydro display_name = "hydroponics winter boots" path = /obj/item/clothing/shoes/boots/winter/hydro - allowed_roles = list("Botanist", "Xenobiologist") \ No newline at end of file + allowed_roles = list("Botanist", "Xenobiologist") diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 94ed2c9f87..d7e0362272 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -77,6 +77,7 @@ desc = "A pair of gloves that reach past the elbow. Fancy!" name = "evening gloves" icon_state = "evening_gloves" + addblends = "evening_gloves_a" cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index cc3f276566..85f51e2cdd 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -34,9 +34,11 @@ /obj/item/clothing/head/hairflower/white icon_state = "hairflower_white" + addblends = "hairflower_white_a" /obj/item/clothing/head/hairflower/bow icon_state = "bow" + addblends = "bow_a" name = "hair bow" desc = "A ribbon tied into a bow with a clip on the back to attach to hair." item_state_slots = list(slot_r_hand_str = "pill", slot_l_hand_str = "pill") @@ -155,6 +157,7 @@ /obj/item/clothing/head/flatcap/grey icon_state = "flat_capw" + addblends = "flat_capw_a" item_state_slots = list(slot_r_hand_str = "greysoft", slot_l_hand_str = "greysoft") /obj/item/clothing/head/pirate @@ -300,6 +303,7 @@ name = "hijab" desc = "A veil that is wrapped to cover the head and chest" icon_state = "hijab" + addblends = "hijab_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHAIR @@ -308,12 +312,14 @@ name = "kippa" desc = "A small, brimless cap." icon_state = "kippa" + addblends = "kippa_a" body_parts_covered = 0 /obj/item/clothing/head/turban name = "turban" desc = "A cloth used to wind around the head" icon_state = "turban" + addblends = "turban_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHEADHAIR @@ -322,24 +328,28 @@ name = "taqiyah" desc = "A short, rounded skullcap usually worn for religious purposes." icon_state = "taqiyah" + addblends = "taqiyah_a" item_state_slots = list(slot_r_hand_str = "taq", slot_l_hand_str = "taq") /obj/item/clothing/head/beanie name = "beanie" desc = "A head-hugging brimless winter cap. This one is tight." icon_state = "beanie" + addblends = "beanie_a" body_parts_covered = 0 /obj/item/clothing/head/beanie_loose name = "loose beanie" desc = "A head-hugging brimless winter cap. This one is loose." icon_state = "beanie_hang" + addblends = "beanie_hang_a" body_parts_covered = 0 /obj/item/clothing/head/beretg name = "beret" desc = "A beret, an artists favorite headwear." icon_state = "beret_g" + addblends = "beret_g_a" body_parts_covered = 0 /obj/item/clothing/head/sombrero diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 6b4b270f97..85ffb970b8 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -54,6 +54,7 @@ name = "white flats" desc = "Shiny white flats." icon_state = "flatswhite" + addblends = "flatswhite_a" item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white") /obj/item/clothing/shoes/flats/white/color diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index c1c833a308..8ee0ae2d32 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -124,23 +124,27 @@ name = "flip flops" desc = "A pair of foam flip flops. For those not afraid to show a little ankle." icon_state = "thongsandal" + addblends = "thongsandal_a" /obj/item/clothing/shoes/athletic name = "athletic shoes" desc = "A pair of sleek atheletic shoes. Made by and for the sporty types." icon_state = "sportshoe" + addblends = "sportshoe_a" item_state_slots = list(slot_r_hand_str = "sportheld", slot_l_hand_str = "sportheld") /obj/item/clothing/shoes/skater name = "skater shoes" desc = "A pair of wide shoes with thick soles. Designed for skating." icon_state = "skatershoe" + addblends = "skatershoe_a" item_state_slots = list(slot_r_hand_str = "skaterheld", slot_l_hand_str = "skaterheld") /obj/item/clothing/shoes/heels name = "high heels" desc = "A pair of high-heeled shoes. Fancy!" icon_state = "heels" + addblends = "heels_a" /obj/item/clothing/shoes/footwraps name = "cloth footwraps" diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm index 934d7407d9..dfc416aa69 100644 --- a/code/modules/clothing/spacesuits/void/void.dm +++ b/code/modules/clothing/spacesuits/void/void.dm @@ -54,7 +54,7 @@ //Breach thresholds, should ideally be inherited by most (if not all) voidsuits. //With 0.2 resiliance, will reach 10 breach damage after 3 laser carbine blasts or 8 smg hits. - breach_threshold = 18 + breach_threshold = 12 can_breach = 1 //Inbuilt devices. diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 602b854287..006de8e99c 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -277,6 +277,7 @@ obj/item/clothing/suit/kimono name = "kimono" desc = "A traditional Japanese kimono." icon_state = "kimono" + addblends = "kimono_a" /* * coats @@ -344,6 +345,7 @@ obj/item/clothing/suit/storage/toggle/peacoat name = "peacoat" desc = "A well-tailored, stylish peacoat." icon_state = "peacoat" + addblends = "peacoat_a" item_state_slots = list(slot_r_hand_str = "peacoat", slot_l_hand_str = "peacoat") flags_inv = HIDEHOLSTER /* diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 4392a26492..2acaff6852 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -45,6 +45,16 @@ mob_overlay = image("icon" = sprite_sheets[wearer.species.get_bodytype(wearer)], "icon_state" = "[tmp_icon_state]") else mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]") + if(addblends) + var/icon/base = new/icon("icon" = mob_overlay.icon, "icon_state" = mob_overlay.icon_state) + var/addblend_icon = new/icon("icon" = mob_overlay.icon, "icon_state" = src.addblends) + if(color) + base.Blend(src.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + mob_overlay = image(base) + else + mob_overlay.color = src.color + return mob_overlay //when user attached an accessory to S diff --git a/code/modules/clothing/under/accessories/armband.dm b/code/modules/clothing/under/accessories/armband.dm index 3f53c44392..bf40074a2a 100644 --- a/code/modules/clothing/under/accessories/armband.dm +++ b/code/modules/clothing/under/accessories/armband.dm @@ -37,6 +37,7 @@ /obj/item/clothing/accessory/armband/med/color name = "armband" desc = "A fancy armband." + addblends = "med_a" /obj/item/clothing/accessory/armband/medblue name = "EMT armband" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index f9a0a9ab37..77046dd89e 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -627,17 +627,20 @@ name = "long dress" desc = "A long dress." icon_state = "whitedress2" + addblends = "whitedress2_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/white3 name = "short dress" desc = "A short, plain dress." icon_state = "whitedress3" + addblends = "whitedress3_a" /obj/item/clothing/under/dress/white4 name = "long flared dress" desc = "A long white dress that flares out at the bottom." icon_state = "whitedress4" + addblends = "whitedress4_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/darkred diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 322115cc0b..c306d842d0 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -121,6 +121,7 @@ name = "yoga pants" desc = "A pair of tight-fitting yoga pants for those lazy days." icon_state = "yogapants" + addblends = "yogapants_a" /* * Baggy Pants diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index d752f0d5cd..00e5bf2ea4 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -619,3 +619,235 @@ activate_pin(2) +/obj/item/integrated_circuit/input/atmo_scanner + name = "integrated atmospheric analyser" + desc = "The same atmospheric analysis module that is integrated into every PDA. \ + This allows the machine to know the composition, temperature and pressure of the surrounding atmosphere." + icon_state = "medscan_adv" + complexity = 9 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER, + "temperature" = IC_PINTYPE_NUMBER, + "oxygen" = IC_PINTYPE_NUMBER, + "nitrogen" = IC_PINTYPE_NUMBER, + "carbon dioxide" = IC_PINTYPE_NUMBER, + "phoron" = IC_PINTYPE_NUMBER, + "other" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 60 + +/obj/item/integrated_circuit/input/atmo_scanner/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) + set_pin_data(IC_OUTPUT, 1, pressure) + set_pin_data(IC_OUTPUT, 2, round(environment.temperature-T0C,0.1)) + set_pin_data(IC_OUTPUT, 3, round(o2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 4, round(n2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 5, round(co2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 6, round(phoron_level*100,0.01)) + set_pin_data(IC_OUTPUT, 7, round(unknown_level, 0.01)) + else + set_pin_data(IC_OUTPUT, 1, 0) + set_pin_data(IC_OUTPUT, 2, -273.15) + set_pin_data(IC_OUTPUT, 3, 0) + set_pin_data(IC_OUTPUT, 4, 0) + set_pin_data(IC_OUTPUT, 5, 0) + set_pin_data(IC_OUTPUT, 6, 0) + set_pin_data(IC_OUTPUT, 7, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/pressure_sensor + name = "integrated pressure sensor" + desc = "A tiny pressure sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/pressure_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, pressure) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/temperature_sensor + name = "integrated temperature sensor" + desc = "A tiny temperature sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "temperature" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/temperature_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, round(environment.temperature-T0C,0.1)) + else + set_pin_data(IC_OUTPUT, 1, -273.15) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/oxygen_sensor + name = "integrated oxygen sensor" + desc = "A tiny oxygen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "oxygen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/oxygen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(o2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/co2_sensor + name = "integrated co2 sensor" + desc = "A tiny carbon dioxide sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "co2" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/co2_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(co2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/nitrogen_sensor + name = "integrated nitrogen sensor" + desc = "A tiny nitrogen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "nitrogen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/nitrogen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/n2_level = environment.gas["nitrogen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(n2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/phoron_sensor + name = "integrated phoron sensor" + desc = "A tiny phoron gas sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "phoron" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/phoron_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/phoron_level = environment.gas["phoron"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(phoron_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 4fe77323f2..7ca7f74737 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -201,6 +201,11 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(var/can_reenter_corpse = 1) if(key) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.vr_holder && !can_reenter_corpse) + H.exit_vr() + return 0 var/mob/observer/dead/ghost = new(src) //Transfer safety to observer spawning proc. ghost.can_reenter_corpse = can_reenter_corpse ghost.timeofdeath = src.timeofdeath //BS12 EDIT @@ -243,9 +248,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/turf/location = get_turf(src) message_admins("[key_name_admin(usr)] has ghosted. (JMP)") log_game("[key_name_admin(usr)] has ghosted.") - var/mob/observer/dead/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. - announce_ghost_joinleave(ghost) + var/mob/observer/dead/ghost = ghostize(0) // 0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + if(ghost) + ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. + announce_ghost_joinleave(ghost) /mob/observer/dead/can_use_hands() return 0 /mob/observer/dead/is_active() return 0 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 28f907d55c..84db5c29d2 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -109,20 +109,28 @@ playsound(loc, "sparks", 50, 1, -1) if (shock_damage > 15) src.visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack." \ + "[src] was electrocuted[source ? " by the [source]" : ""]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack." \ ) - if(stun) - Stun(10)//This should work for now, more is really silly and makes you lay there forever - Weaken(10) else src.visible_message( - "[src] was mildly shocked by \the [source].", \ - "You feel a mild shock course through your body.", \ - "You hear a light zapping." \ + "[src] was shocked[source ? " by the [source]" : ""].", \ + "You feel a shock course through your body.", \ + "You hear a zapping sound." \ ) + if(stun) + switch(shock_damage) + if(16 to 20) + Stun(2) + if(21 to 25) + Weaken(2) + if(26 to 30) + Weaken(5) + if(31 to INFINITY) + Weaken(10) //This should work for now, more is really silly and makes you lay there forever + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, loc) s.start() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 66ba7ecd51..08d0c9384e 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -25,7 +25,7 @@ weapon_edge = 0 hit_embed_chance = I.force/(I.w_class*3) - apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) + apply_damage(effective_force, I.damtype, hit_zone, blocked, soaked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) //Melee weapon embedded object code. if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I) && I.embed_chance > 0) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 592ee6a761..5fe75e9eae 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -1,5 +1,15 @@ /mob/living/carbon/human/gib() + if(vr_holder) + exit_vr() + // Delete the link, because this mob won't be around much longer + vr_holder.vr_link = null + + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + for(var/obj/item/organ/I in internal_organs) I.removed() if(istype(loc,/turf)) @@ -81,6 +91,20 @@ if(wearing_rig) wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.") + // If the body is in VR, move the mind back to the real world + if(vr_holder) + src.exit_vr() + src.vr_holder.vr_link = null + for(var/obj/item/W in src) + src.drop_from_inventory(W) + + // If our mind is in VR, bring it back to the real world so it can die with its body + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + to_chat(src, "Everything abruptly stops.") + return ..(gibbed,species.get_death_message(src)) /mob/living/carbon/human/proc/ChangeToHusk() @@ -114,4 +138,4 @@ mutations.Add(SKELETON) status_flags |= DISFIGURED update_body(1) - return + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 61a4d8fb28..06632781a1 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1568,4 +1568,55 @@ var/turf/T = get_turf(src) var/obj/item/clothing/accessory/permit/drone/permit = new(T) permit.set_name(real_name) - equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. \ No newline at end of file + equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. + +// enter_vr is called on the original mob, and puts the mind into the supplied vr mob +/mob/living/carbon/human/proc/enter_vr(var/mob/living/carbon/human/avatar) // Avatar is currently a human, because we have preexisting setup code for appearance manipulation, etc. + if(!istype(avatar)) + return + + // Link the two mobs for client transfer + avatar.vr_holder = src + src.teleop = avatar + src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR + + // Move the mind + avatar.Sleeping(1) + src.mind.transfer_to(avatar) + to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") + to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? + +// exit_vr is called on the vr mob, and puts the mind back into the original mob +/mob/living/carbon/human/verb/exit_vr() + set name = "Exit Virtual Reality" + set category = "Abilities" + + if(!vr_holder) + return + if(!mind) + return + + var/total_damage + // Tally human damage + if(ishuman(src)) + var/mob/living/carbon/human/H = src + total_damage = H.getBruteLoss() + H.getFireLoss() + H.getOxyLoss() + H.getToxLoss() + + // Move the mind back to the original mob +// vr_holder.Sleeping(1) + src.mind.transfer_to(vr_holder) + to_chat(vr_holder, "You black out for a moment, and wake to find yourself back in your own body.") + // Two-thirds damage is transferred as agony for /humans + // Getting hurt in VR doesn't damage the physical body, but you still got hurt. + if(ishuman(vr_holder) && total_damage) + var/mob/living/carbon/human/V = vr_holder + V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m. + to_chat(vr_holder, "Pain from your time in VR lingers.") // 250 damage leaves the user unconscious for several seconds in addition to paincrit + + // Maintain a link with the mob, but don't use teleop + vr_holder.vr_link = src + vr_holder.teleop = null + + if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) + var/obj/machinery/vr_sleeper/V = vr_holder.loc + V.go_out() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 39860aaefa..950fca565e 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -429,9 +429,9 @@ This function restores all organs. zone = BP_HEAD return organs_by_name[zone] -/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) +/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) if(Debug2) - world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]." + world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, an armor value of [blocked], and a soak value of [soaked]." var/obj/item/organ/external/organ = null if(isorgan(def_zone)) @@ -446,7 +446,7 @@ This function restores all organs. if((damage > 25 && prob(20)) || (damage > 50 && prob(60))) if(organ && organ.organ_can_feel_pain()) emote("scream") - ..(damage, damagetype, def_zone, blocked) + ..(damage, damagetype, def_zone, blocked, soaked) return 1 //Handle BRUTE and BURN damage @@ -455,12 +455,18 @@ This function restores all organs. if(blocked >= 100) return 0 + if(soaked >= damage) + return 0 if(!organ) return 0 if(blocked) blocked = (100-blocked)/100 damage = (damage * blocked) + + if(soaked) + damage -= soaked + if(Debug2) world.log << "## DEBUG: [src] was hit for [damage]." diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 103019380a..c1717ee201 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -103,3 +103,8 @@ var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds can_be_antagged = TRUE + +// Used by mobs in virtual reality to point back to the "real" mob the client belongs to. + var/mob/living/carbon/human/vr_holder = null + // Used by "real" mobs after they leave a VR session + var/mob/living/carbon/human/vr_link = null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index a2b38e4c22..f85686e6cd 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -11,6 +11,7 @@ // Icon/appearance vars. var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. + var/icobase_add // Icon set for highlight blends when applicable. var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons. @@ -28,6 +29,7 @@ var/tail // Name of tail state in species effects icon file. var/tail_animation // If set, the icon to obtain tail animation states from. + var/tail_animation_add // Highlight overlay for tail. var/tail_hair var/race_key = 0 // Used for mob icon cache string. @@ -274,11 +276,14 @@ var/t_him = "them" if(ishuman(target)) var/mob/living/carbon/human/T = target - switch(T.identifying_gender) - if(MALE) - t_him = "him" - if(FEMALE) - t_him = "her" + if(!T.species.ambiguous_genders || (T.species.ambiguous_genders && H.species == T.species)) + switch(T.identifying_gender) + if(MALE) + t_him = "him" + if(FEMALE) + t_him = "her" + else + t_him = "them" else switch(target.gender) if(MALE) diff --git a/code/modules/mob/living/carbon/human/species/species_getters.dm b/code/modules/mob/living/carbon/human/species/species_getters.dm index efb053eddf..e0be03af1d 100644 --- a/code/modules/mob/living/carbon/human/species/species_getters.dm +++ b/code/modules/mob/living/carbon/human/species/species_getters.dm @@ -10,6 +10,9 @@ /datum/species/proc/get_tail_animation(var/mob/living/carbon/human/H) return tail_animation +/datum/species/proc/get_tail_animation_a(var/mob/living/carbon/human/H) + return tail_animation_add + /datum/species/proc/get_tail_hair(var/mob/living/carbon/human/H) return tail_hair @@ -28,6 +31,9 @@ /datum/species/proc/get_icobase(var/mob/living/carbon/human/H, var/get_deform) return (get_deform ? deform : icobase) +/datum/species/proc/get_icobase_a(var/mob/living/carbon/human/H) + return icobase_add + /datum/species/proc/get_station_variant() return name diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm index 1fb7b6c300..11a50c1316 100644 --- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -148,9 +148,16 @@ var/list/wrapped_species_by_ref = list() last_special = world.time + 50 - var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + var/new_species = null + new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + if(!new_species || !all_species[new_species] || wrapped_species_by_ref["\ref[src]"] == new_species) return + shapeshifter_change_shape(new_species) + +/mob/living/carbon/human/proc/shapeshifter_change_shape(var/new_species = null) + if(!new_species) + return wrapped_species_by_ref["\ref[src]"] = new_species visible_message("\The [src] shifts and contorts, taking the form of \a [new_species]!") diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 0a6e1df9a4..308c62c4bd 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -26,8 +26,9 @@ tail_hair = "feathers" reagent_tag = IS_TESHARI - icobase = 'icons/mob/human_races/r_seromi.dmi' - deform = 'icons/mob/human_races/r_seromi.dmi' + icobase = 'icons/mob/human_races/r_seromi_m.dmi' + icobase_add = 'icons/mob/human_races/r_seromi_a.dmi' + deform = 'icons/mob/human_races/r_seromi_m.dmi' damage_overlays = 'icons/mob/human_races/masks/dam_seromi.dmi' damage_mask = 'icons/mob/human_races/masks/dam_mask_seromi.dmi' blood_mask = 'icons/mob/human_races/masks/blood_seromi.dmi' diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 1f01aaa3b4..fbe32bef95 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -25,10 +25,12 @@ /datum/species/unathi name = "Unathi" name_plural = "Unathi" - icobase = 'icons/mob/human_races/r_lizard.dmi' + icobase = 'icons/mob/human_races/r_lizard_m.dmi' + icobase_add = 'icons/mob/human_races/r_lizard_a.dmi' deform = 'icons/mob/human_races/r_def_lizard.dmi' tail = "sogtail" - tail_animation = 'icons/mob/species/unathi/tail.dmi' + tail_animation = 'icons/mob/species/unathi/tail_m.dmi' + tail_animation_add = 'icons/mob/species/unathi/tail_a.dmi' unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp) primitive_form = "Stok" darksight = 3 @@ -127,10 +129,12 @@ /datum/species/tajaran name = "Tajara" name_plural = "Tajaran" - icobase = 'icons/mob/human_races/r_tajaran.dmi' + icobase = 'icons/mob/human_races/r_tajaran_m.dmi' + icobase_add = 'icons/mob/human_races/r_tajaran_a.dmi' deform = 'icons/mob/human_races/r_def_tajaran.dmi' tail = "tajtail" - tail_animation = 'icons/mob/species/tajaran/tail.dmi' + tail_animation = 'icons/mob/species/tajaran/tail_m.dmi' + tail_animation_add = 'icons/mob/species/tajaran/tail_a.dmi' unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp) darksight = 8 slowdown = -0.5 @@ -212,7 +216,8 @@ /datum/species/skrell name = "Skrell" name_plural = "Skrell" - icobase = 'icons/mob/human_races/r_skrell.dmi' + icobase = 'icons/mob/human_races/r_skrell_m.dmi' + icobase_add = 'icons/mob/human_races/r_skrell_a.dmi' deform = 'icons/mob/human_races/r_def_skrell.dmi' primitive_form = "Neaera" unarmed_types = list(/datum/unarmed_attack/punch) diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm new file mode 100644 index 0000000000..cd55725b40 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -0,0 +1,32 @@ +// ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. +// ### Any and all of this is open to change for balance or whatever. +// ### +// ### +// Species definition follows. +/datum/species/shapeshifter/promethean/avatar + + name = "Virtual Reality Avatar" + name_plural = "Virtual Reality Avatars" + blurb = "A 3-dimensional representation of some sort of animate object used to display the presence and actions of some-one or -thing using a virtual reality program." + show_ssd = "eerily still" + death_message = "flickers briefly, their gear falling in a heap on the floor around their motionless body." + knockout_message = "has been knocked unconscious!" + + spawn_flags = SPECIES_IS_RESTRICTED + + speech_bubble_appearance = "cyber" + + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') + female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') + male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' + female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' + + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, O_EYES = /obj/item/organ/internal/eyes) // Slime core. + heal_rate = 0 // Avatars don't naturally heal like prometheans, at least not for now + +/datum/species/shapeshifter/promethean/avatar/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/shapeshifter/promethean/avatar/handle_environment_special(var/mob/living/carbon/human/H) + return \ No newline at end of file diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 22289c6b43..07997851ef 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -34,6 +34,8 @@ adjustCloneLoss(damage * blocked) if(HALLOSS) adjustHalLoss(damage * blocked) + if(ELECTROCUTE) + electrocute_act(damage, used_weapon, 1.0, def_zone) flash_weak_pain() updatehealth() return 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 4e18aa64e9..e6929e59ae 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -9,7 +9,7 @@ health = 200 mob_bump_flag = ROBOT - mob_swap_flags = ROBOT|MONKEY|SLIME|SIMPLE_ANIMAL + mob_swap_flags = ~HEAVY mob_push_flags = ~HEAVY //trundle trundle var/lights_on = 0 // Is our integrated light on? diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 92aefe6923..25b7f94dae 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -107,7 +107,9 @@ var/friendly = "nuzzles" // What mobs do to people when they aren't really hostile var/attack_sound = null // Sound to play when I attack var/environment_smash = 0 // How much environment damage do I do when I hit stuff? - var/melee_miss_chance = 25 // percent chance to miss a melee attack. + var/melee_miss_chance = 15 // percent chance to miss a melee attack. + var/melee_attack_minDelay = 5 // How long between attacks at least + var/melee_attack_maxDelay = 10 // How long between attacks at most //Special attacks var/spattack_prob = 0 // Chance of the mob doing a special attack (0 for never) @@ -1175,7 +1177,7 @@ if(!Adjacent(target_mob)) return if(!client) - sleep(rand(8) + 8) + sleep(rand(melee_attack_minDelay, melee_attack_maxDelay)) if(isliving(target_mob)) var/mob/living/L = target_mob @@ -1455,6 +1457,19 @@ agonyDam += agony_amount * 0.5 adjustFireLoss(agonyDam) +/mob/living/simple_animal/emp_act(severity) + if(!isSynthetic()) + return + switch(severity) + if(1) + adjustFireLoss(rand(15, 25)) + if(2) + adjustFireLoss(rand(10, 18)) + if(3) + adjustFireLoss(rand(5, 12)) + if(4) + adjustFireLoss(rand(1, 6)) + // Force it to target something /mob/living/simple_animal/proc/taunt(var/mob/living/new_target, var/forced = FALSE) if(intelligence_level == SA_HUMANOID && !forced) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 8b32ab96ca..202b72c0fc 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -259,7 +259,7 @@ mannequin.delete_inventory(TRUE) dress_preview_mob(mannequin) - preview_icon = icon('icons/effects/effects.dmi', "nothing") + preview_icon = icon('icons/effects/128x48.dmi', bgstate) preview_icon.Scale(48+32, 16+32) mannequin.dir = NORTH diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index f301a36848..0b91e3e39b 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -45,7 +45,8 @@ /datum/sprite_accessory/hair - icon = 'icons/mob/Human_face.dmi' // default icon for all hairs + icon = 'icons/mob/Human_face_m.dmi' // default icon for all hairs + var/icon_add = 'icons/mob/human_face.dmi' bald name = "Bald" diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index d0deb9f55a..30d7040478 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -89,13 +89,13 @@ var/global/list/limb_icon_cache = list() overlays |= facial_s if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair/hair_style = hair_styles_list[owner.h_style] // VOREStation edit + var/datum/sprite_accessory/hair/hair_style = hair_styles_list[owner.h_style] if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") // VOREStation edit + var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) - hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY) // VOREStation edit - hair_s.Blend(hair_s_add, ICON_ADD) // VOREStation edit + hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY) + hair_s.Blend(hair_s_add, ICON_ADD) overlays |= hair_s return mob_icon @@ -145,7 +145,13 @@ var/global/list/limb_icon_cache = list() var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" if(!limb_icon_cache[cache_key]) var/icon/I = icon(species.get_icobase(owner), "[icon_name]_[body_hair]") +<<<<<<< HEAD I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) //VOREStation edit +======= + var/icon/IA = icon(species.get_icobase_a(owner), "[icon_name]_[body_hair]") + I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_MULTIPLY) + I.Blend(IA, ICON_ADD) +>>>>>>> PolarisSS13/master limb_icon_cache[cache_key] = I mob_icon.Blend(limb_icon_cache[cache_key], ICON_OVERLAY) @@ -178,10 +184,14 @@ var/global/list/limb_icon_cache = list() if(nonsolid) applying.MapColors("#4D4D4D","#969696","#1C1C1C", "#000000") +<<<<<<< HEAD if(species && species.get_bodytype(owner) != "Human") applying.SetIntensity(1) // Unathi, Taj and Skrell have -very- dark base icons. VOREStation edit fixes this and brings the number back to 1 else applying.SetIntensity(1) //VOREStation edit to make Prometheans not look like shit with mob coloring. +======= + applying.SetIntensity(0.7) +>>>>>>> PolarisSS13/master else if(status & ORGAN_DEAD) icon_cache_key += "_dead" @@ -195,12 +205,23 @@ var/global/list/limb_icon_cache = list() applying.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) icon_cache_key += "_tone_[s_tone]" else if(s_col && s_col.len >= 3) +<<<<<<< HEAD //VOREStation Edit - Support for species.color_mult if(species && species.color_mult) applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_MULTIPLY) else applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) //VOREStation Edit End +======= + applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_MULTIPLY) + var/gender = "f" + if(owner && owner.gender == MALE) + gender = "m" + var/icon_a = new /icon(species.get_icobase_a(owner), "[icon_name][gendered_icon ? "_[gender]" : ""]") + applying.Blend(icon_a, ICON_ADD) + icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]" + +>>>>>>> PolarisSS13/master // Translucency. if(nonsolid) applying += rgb(,,,180) // SO INTUITIVE TY BYOND diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm new file mode 100644 index 0000000000..bb37a380b6 --- /dev/null +++ b/code/modules/paperwork/paperplane.dm @@ -0,0 +1,102 @@ +// Ported from TG. Known issue: Throw hit can possibly double-proc. Seems to be throw code. +/obj/item/weapon/paperplane + name = "paper plane" + desc = "Paper folded into the shape of a plane." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "paperplane" + throw_range = 7 + throw_speed = 1 + throwforce = 0 + w_class = ITEMSIZE_TINY + + var/obj/item/weapon/paper/internalPaper + +/obj/item/weapon/paperplane/New(loc, obj/item/weapon/paper/newPaper) + . = ..() + pixel_y = rand(-8, 8) + pixel_x = rand(-9, 9) + if(newPaper) + internalPaper = newPaper + flags = newPaper.flags + color = newPaper.color + newPaper.forceMove(src) + else + internalPaper = new /obj/item/weapon/paper(src) + update_icon() + +/obj/item/weapon/paperplane/Destroy() + if(internalPaper) + qdel(internalPaper) + internalPaper = null + return ..() + +/obj/item/weapon/paperplane/update_icon() + overlays.Cut() + var/list/stamped = internalPaper.stamped + if(!stamped) + stamped = new + else if(stamped) + for(var/S in stamped) + var/obj/item/weapon/stamp/ = S + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi', "paperplane_[initial(stamp.icon_state)]") + overlays += stampoverlay + +/obj/item/weapon/paperplane/attack_self(mob/user) + to_chat(user, "You unfold [src].") + var/atom/movable/internal_paper_tmp = internalPaper + internal_paper_tmp.forceMove(loc) + internalPaper = null + qdel(src) + user.put_in_hands(internal_paper_tmp) + +/obj/item/weapon/paperplane/attackby(obj/item/P, mob/living/carbon/human/user, params) + ..() + if(istype(P, /obj/item/weapon/pen)) + to_chat(user, "You should unfold [src] before changing it.") + return + + else if(istype(P, /obj/item/weapon/stamp)) //we don't randomize stamps on a paperplane + internalPaper.attackby(P, user) //spoofed attack to update internal paper. + update_icon() + + else if(is_hot(P)) + if(user.disabilities & CLUMSY && prob(10)) + user.visible_message("[user] accidentally ignites themselves!", \ + "You miss the [src] and accidentally light yourself on fire!") + user.unEquip(P) + user.adjust_fire_stacks(1) + user.IgniteMob() + return + + if(!(in_range(user, src))) //to prevent issues as a result of telepathically lighting a paper + return + user.unEquip(src) + user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!") + fire_act() + + add_fingerprint(user) + +/obj/item/weapon/paperplane/throw_impact(atom/hit_atom) + if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman + return + var/mob/living/carbon/human/H = hit_atom + if(prob(2)) + if((H.head && H.head.body_parts_covered & EYES) || (H.wear_mask && H.wear_mask.body_parts_covered & EYES) || (H.glasses && H.glasses.body_parts_covered & EYES)) + return + visible_message("\The [src] hits [H] in the eye!") + H.eye_blurry += 10 + var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES] + if(E) + E.damage += 2.5 + H.emote("scream") + +/obj/item/weapon/paper/AltClick(mob/living/carbon/user, obj/item/I) + if ( istype(user) ) + if( (!in_range(src, user)) || user.stat || user.restrained() ) + return + to_chat(user, "You fold [src] into the shape of a plane!") + user.unEquip(src) + I = new /obj/item/weapon/paperplane(user, src) + user.put_in_hands(I) + else + to_chat(user, " You lack the dexterity to fold \the [src]. ") diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index bed1bdccba..73ea40f12d 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -681,13 +681,10 @@ else flick("apc-spark", src) if (do_after(user,6)) - if(prob(50)) - emagged = 1 - locked = 0 - to_chat(user,"You emag the APC interface.") - update_icon() - else - to_chat(user,"The APC interface refused to unlock.") + emagged = 1 + locked = 0 + to_chat(user,"You emag the APC interface.") + update_icon() return 1 /obj/machinery/power/apc/attack_hand(mob/user) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 5c5d0cc3a6..604eaa6a3a 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -60,7 +60,57 @@ used = !used return +//A vial-loaded hypospray. Cartridge-based! +/obj/item/weapon/reagent_containers/hypospray/vial + name = "hypospray mkII" + desc = "A new development from DeForest Medical, this new hypospray takes 30-unit vials as the drug supply for easy swapping." + var/obj/item/weapon/reagent_containers/glass/beaker/vial/loaded_vial //Wow, what a name. + volume = 0 +/obj/item/weapon/reagent_containers/hypospray/vial/New() + ..() + loaded_vial = new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) //Comes with an empty vial + volume = loaded_vial.volume + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + +/obj/item/weapon/reagent_containers/hypospray/vial/attack_hand(mob/user as mob) + if(user.get_inactive_hand() == src) + if(loaded_vial) + reagents.trans_to_holder(loaded_vial.reagents,volume) + reagents.maximum_volume = 0 + loaded_vial.update_icon() + user.put_in_hands(loaded_vial) + loaded_vial = null + user << "You remove the vial from the [src]." + update_icon() + playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) + return + ..() + else + return ..() + +/obj/item/weapon/reagent_containers/hypospray/vial/attackby(obj/item/weapon/W, mob/user as mob) + if(istype(W, /obj/item/weapon/reagent_containers/glass/beaker/vial)) + if(!loaded_vial) + user.visible_message("[user] begins loading [W] into \the [src].","You start loading [W] into \the [src].") + if(!do_after(user,30) || loaded_vial || !(W in user)) + return 0 + if(W.is_open_container()) + W.flags ^= OPENCONTAINER + W.update_icon() + user.drop_item() + W.loc = src + loaded_vial = W + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + loaded_vial.reagents.trans_to_holder(reagents,volume) + user.visible_message("[user] has loaded [W] into \the [src].","You have loaded [W] into \the [src].") + update_icon() + playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) + else + user << "\The [src] already has a vial." + else + ..() + /obj/item/weapon/reagent_containers/hypospray/autoinjector name = "autoinjector" desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel." diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 8e531ad687..db06449d18 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -405,7 +405,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, return /obj/machinery/computer/rdconsole/proc/GetResearchLevelsInfo() - var/dat + var/list/dat = list() dat += "" - return dat + return dat.Join() /obj/machinery/computer/rdconsole/proc/GetResearchListInfo() - var/dat + var/list/dat = list() dat += "" - return dat + return dat.Join() /obj/machinery/computer/rdconsole/attack_hand(mob/user as mob) if(stat & (BROKEN|NOPOWER)) return user.set_machine(src) - var/dat = "" + var/list/dat = list() files.RefreshResearch() switch(screen) //A quick check to make sure you get the right screen when a device is disconnected. if(2 to 2.9) @@ -774,7 +774,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "List of Researched Technologies and Designs:" dat += GetResearchListInfo() - user << browse("Research and Development Console
[dat]", "window=rdconsole;size=850x600") + user << browse("Research and Development Console
[dat.Join()]", "window=rdconsole;size=850x600") onclose(user, "rdconsole") /obj/machinery/computer/rdconsole/robotics diff --git a/code/modules/shieldgen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm index 2bddb5af32..f1988ee8c6 100644 --- a/code/modules/shieldgen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -4,7 +4,7 @@ /obj/machinery/shield_capacitor name = "shield capacitor" - desc = "Machine that charges a shield generator." + desc = "A machine that charges a shield generator." icon = 'icons/obj/machines/shielding.dmi' icon_state = "capacitor" var/active = 0 @@ -19,6 +19,12 @@ var/charge_rate = 100000 //100 kW var/obj/machinery/shield_gen/owned_gen +/obj/machinery/shield_capacitor/advanced + name = "advanced shield capacitor" + desc = "A machine that charges a shield generator. This version can store, input, and output more electricity." + max_charge = 12e6 + max_charge_rate = 600000 + /obj/machinery/shield_capacitor/emag_act(var/remaining_charges, var/mob/user) if(prob(75)) src.locked = !src.locked diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index 32d34365b4..fd8e3bf0ca 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -1,6 +1,6 @@ /obj/machinery/shield_gen name = "bubble shield generator" - desc = "Machine that generates an impenetrable field of energy when activated." + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated." icon = 'icons/obj/machines/shielding.dmi' icon_state = "generator0" var/active = 0 @@ -20,10 +20,15 @@ var/target_field_strength = 10 var/max_field_strength = 10 var/time_since_fail = 100 - var/energy_conversion_rate = 0.0002 //how many renwicks per watt? + var/energy_conversion_rate = 0.0002 //how many renwicks per watt? Higher numbers equals more effiency. var/z_range = 0 // How far 'up and or down' to extend the shield to, in z-levels. Only works on MultiZ supported z-levels. use_power = 0 //doesn't use APC power +/obj/machinery/shield_gen/advanced + name = "advanced bubble shield generator" + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." + energy_conversion_rate = 0.0004 + /obj/machinery/shield_gen/New() spawn(1 SECOND) if(anchored) @@ -259,11 +264,14 @@ /obj/machinery/shield_gen/update_icon() if(stat & BROKEN) icon_state = "broke" + set_light(0) else if (src.active) icon_state = "generator1" + set_light(4, 2, "#00CCFF") else icon_state = "generator0" + set_light(0) //grab the border tiles in a circle around this machine /obj/machinery/shield_gen/proc/get_shielded_turfs() diff --git a/code/modules/shieldgen/shield_gen_external.dm b/code/modules/shieldgen/shield_gen_external.dm index 27b1def271..fa4702feee 100644 --- a/code/modules/shieldgen/shield_gen_external.dm +++ b/code/modules/shieldgen/shield_gen_external.dm @@ -7,8 +7,11 @@ /turf/space, /turf/simulated/floor/outdoors, ) -/obj/machinery/shield_gen/external/New() - ..() + +/obj/machinery/shield_gen/external/advanced + name = "advanced hull shield generator" + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." + energy_conversion_rate = 0.0004 //Search for space turfs within range that are adjacent to a simulated turf. /obj/machinery/shield_gen/external/get_shielded_turfs_on_z_level(var/turf/gen_turf) diff --git a/icons/effects/128x48.dmi b/icons/effects/128x48.dmi new file mode 100644 index 0000000000..71038ffdbf Binary files /dev/null and b/icons/effects/128x48.dmi differ diff --git a/icons/effects/species_a.dmi b/icons/effects/species_a.dmi new file mode 100644 index 0000000000..927ec7c82e Binary files /dev/null and b/icons/effects/species_a.dmi differ diff --git a/icons/mob/ears.dmi b/icons/mob/ears.dmi index 14823c7801..88caed94c8 100644 Binary files a/icons/mob/ears.dmi and b/icons/mob/ears.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 48ff6e0103..79b56e487c 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index 0197a18e01..f50c46167d 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index f723644373..9947dec006 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/human_face_m.dmi b/icons/mob/human_face_m.dmi new file mode 100644 index 0000000000..fda6c68b48 Binary files /dev/null and b/icons/mob/human_face_m.dmi differ diff --git a/icons/mob/human_races/r_def_lizard.dmi b/icons/mob/human_races/r_def_lizard.dmi index 6c1f4d94fc..3ebace3090 100644 Binary files a/icons/mob/human_races/r_def_lizard.dmi and b/icons/mob/human_races/r_def_lizard.dmi differ diff --git a/icons/mob/human_races/r_def_skrell.dmi b/icons/mob/human_races/r_def_skrell.dmi index 7b24ba3b4d..3e6a40f3ae 100644 Binary files a/icons/mob/human_races/r_def_skrell.dmi and b/icons/mob/human_races/r_def_skrell.dmi differ diff --git a/icons/mob/human_races/r_def_tajaran.dmi b/icons/mob/human_races/r_def_tajaran.dmi index 44cda2ea86..64b1a2d30d 100644 Binary files a/icons/mob/human_races/r_def_tajaran.dmi and b/icons/mob/human_races/r_def_tajaran.dmi differ diff --git a/icons/mob/human_races/r_lizard_a.dmi b/icons/mob/human_races/r_lizard_a.dmi new file mode 100644 index 0000000000..94dfe1ed32 Binary files /dev/null and b/icons/mob/human_races/r_lizard_a.dmi differ diff --git a/icons/mob/human_races/r_lizard_m.dmi b/icons/mob/human_races/r_lizard_m.dmi new file mode 100644 index 0000000000..ee4fd41995 Binary files /dev/null and b/icons/mob/human_races/r_lizard_m.dmi differ diff --git a/icons/mob/human_races/r_seromi_a.dmi b/icons/mob/human_races/r_seromi_a.dmi new file mode 100644 index 0000000000..24d49ef1eb Binary files /dev/null and b/icons/mob/human_races/r_seromi_a.dmi differ diff --git a/icons/mob/human_races/r_seromi_m.dmi b/icons/mob/human_races/r_seromi_m.dmi new file mode 100644 index 0000000000..9864106bd4 Binary files /dev/null and b/icons/mob/human_races/r_seromi_m.dmi differ diff --git a/icons/mob/human_races/r_skrell_a.dmi b/icons/mob/human_races/r_skrell_a.dmi new file mode 100644 index 0000000000..7da571bf1e Binary files /dev/null and b/icons/mob/human_races/r_skrell_a.dmi differ diff --git a/icons/mob/human_races/r_skrell_m.dmi b/icons/mob/human_races/r_skrell_m.dmi new file mode 100644 index 0000000000..224fb25eae Binary files /dev/null and b/icons/mob/human_races/r_skrell_m.dmi differ diff --git a/icons/mob/human_races/r_tajaran_a.dmi b/icons/mob/human_races/r_tajaran_a.dmi new file mode 100644 index 0000000000..d70bb0b715 Binary files /dev/null and b/icons/mob/human_races/r_tajaran_a.dmi differ diff --git a/icons/mob/human_races/r_tajaran_m.dmi b/icons/mob/human_races/r_tajaran_m.dmi new file mode 100644 index 0000000000..29f6b04e39 Binary files /dev/null and b/icons/mob/human_races/r_tajaran_m.dmi differ diff --git a/icons/mob/items/lefthand_gloves.dmi b/icons/mob/items/lefthand_gloves.dmi index 0c12bda3d5..c00dd71eb0 100644 Binary files a/icons/mob/items/lefthand_gloves.dmi and b/icons/mob/items/lefthand_gloves.dmi differ diff --git a/icons/mob/items/righthand_gloves.dmi b/icons/mob/items/righthand_gloves.dmi index 25b41e25ec..8ad72028b5 100644 Binary files a/icons/mob/items/righthand_gloves.dmi and b/icons/mob/items/righthand_gloves.dmi differ diff --git a/icons/mob/species/tajaran/tail_a.dmi b/icons/mob/species/tajaran/tail_a.dmi new file mode 100644 index 0000000000..1a4245611b Binary files /dev/null and b/icons/mob/species/tajaran/tail_a.dmi differ diff --git a/icons/mob/species/tajaran/tail_m.dmi b/icons/mob/species/tajaran/tail_m.dmi new file mode 100644 index 0000000000..159ca49b32 Binary files /dev/null and b/icons/mob/species/tajaran/tail_m.dmi differ diff --git a/icons/mob/species/unathi/tail_a.dmi b/icons/mob/species/unathi/tail_a.dmi new file mode 100644 index 0000000000..cf3e861a5d Binary files /dev/null and b/icons/mob/species/unathi/tail_a.dmi differ diff --git a/icons/mob/species/unathi/tail_m.dmi b/icons/mob/species/unathi/tail_m.dmi new file mode 100644 index 0000000000..b944c3e37b Binary files /dev/null and b/icons/mob/species/unathi/tail_m.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 9db8ef1fc5..0f88d8fd04 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index 2c17ab4a32..9fd6cba6df 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index f121d14ca4..4dd885d30b 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 42fac1ec7a..b621d05474 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 3618369771..bc4e1880c6 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/furniture.dmi b/icons/obj/furniture.dmi index 0e6659ae4f..42697f358d 100644 Binary files a/icons/obj/furniture.dmi and b/icons/obj/furniture.dmi differ diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi index 5e1ad9e8e0..9cbb46748a 100644 Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 18b10fa3da..bf53bd2a5a 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -666,6 +666,7 @@ #include "code\game\machinery\turret_control.dm" #include "code\game\machinery\vending.dm" #include "code\game\machinery\vending_vr.dm" +#include "code\game\machinery\vr_console.dm" #include "code\game\machinery\wall_frames.dm" #include "code\game\machinery\washing_machine.dm" #include "code\game\machinery\wishgranter.dm" @@ -1913,6 +1914,7 @@ #include "code\modules\mob\living\carbon\human\species\station\traits_vr\neutral.dm" #include "code\modules\mob\living\carbon\human\species\station\traits_vr\positive.dm" #include "code\modules\mob\living\carbon\human\species\station\traits_vr\trait.dm" +#include "code\modules\mob\living\carbon\human\species\virtual_reality\avatar.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_powers.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm" @@ -2172,6 +2174,7 @@ #include "code\modules\paperwork\paper.dm" #include "code\modules\paperwork\paper_bundle.dm" #include "code\modules\paperwork\paperbin.dm" +#include "code\modules\paperwork\paperplane.dm" #include "code\modules\paperwork\papershredder.dm" #include "code\modules\paperwork\pen.dm" #include "code\modules\paperwork\photocopier.dm"