From 342a8d04c7f103aba8fe5602170e70ee6076d5f6 Mon Sep 17 00:00:00 2001 From: JoanRisu Date: Sat, 17 Sep 2016 20:38:45 -0700 Subject: [PATCH 01/31] Adjusting some fluff items and adding in the security train for testing and further coding. (#560) --- code/modules/vehicles/Securitrain_vr.dm | 423 ++++++++++++++++++ .../vore/fluffstuff/custom_boxes_vr.dm | 4 + .../vore/fluffstuff/custom_clothes_vr.dm | 12 +- icons/obj/vehicles_vr.dmi | Bin 7994 -> 8866 bytes 4 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 code/modules/vehicles/Securitrain_vr.dm diff --git a/code/modules/vehicles/Securitrain_vr.dm b/code/modules/vehicles/Securitrain_vr.dm new file mode 100644 index 0000000000..b3698560d6 --- /dev/null +++ b/code/modules/vehicles/Securitrain_vr.dm @@ -0,0 +1,423 @@ +//This is the initial set up for the new carts. Feel free to improve and/or rewrite everything here. +//I don't know what the hell I'm doing right now. Please help. Especially with the update_icons stuff. -Joan Risu + +/obj/vehicle/train/securiengine + name = "Security Cart" + desc = "A ridable electric car designed for pulling trolleys as well as personal transport." + icon = 'icons/obj/vehicles_vr.dmi' + icon_state = "paddywagon" + on = 0 + powered = 1 + locked = 0 + move_delay = 0.5 + + //Health stuff + health = 100 + maxhealth = 100 + fire_dam_coeff = 0.6 + brute_dam_coeff = 0.5 + + load_item_visible = 1 + load_offset_x = 0 + mob_offset_y = 7 + + var/car_limit = 0 //how many cars an engine can pull before performance degrades. This should be 0 to prevent trailers from unhitching. + active_engines = 1 + var/obj/item/weapon/key/securitrain/key + var/siren = 0 //This is for eventually getting the siren sprite to work. + +/obj/item/weapon/key/securitrain + name = "The Security Cart key" + desc = "The Security Cart Key used to start it." + icon = 'icons/obj/vehicles_vr.dmi' + icon_state = "securikey" + w_class = 1 + +/obj/vehicle/train/securitrolley + name = "Train trolley" + desc = "A trolly designed to transport security personnel or prisoners." + icon = 'icons/obj/vehicles_vr.dmi' + icon_state = "paddy_trailer" + anchored = 0 + passenger_allowed = 1 + locked = 0 + + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 4 + mob_offset_y = 8 + +/obj/vehicle/train/securitrolley/cargo + name = "Train trolley" + desc = "A trolley designed to transport security equipment to a scene." + icon = 'icons/obj/vehicles_vr.dmi' + icon_state = "secitemcarrierbot" + passenger_allowed = 0 //Stick a man inside the box. :v + load_item_visible = 0 //The load is supposed to be invisible. + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/train/securiengine/New() + ..() + cell = new /obj/item/weapon/cell/high(src) + key = new(src) + var/image/I = new(icon = 'icons/obj/vehicles_vr.dmi', icon_state = null, layer = src.layer + 0.2) //over mobs + overlays += I + turn_off() //so engine verbs are correctly set + +/obj/vehicle/train/securiengine/Move(var/turf/destination) + if(on && cell.charge < charge_use) + turn_off() + update_stats() + if(load && is_train_head()) + load << "The drive motor briefly whines, then drones to a stop." + + if(is_train_head() && !on) + return 0 + + //space check ~no flying space trains sorry + if(on && istype(destination, /turf/space)) + return 0 + + return ..() + +/obj/vehicle/train/securitrolley/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(open && istype(W, /obj/item/weapon/wirecutters)) + passenger_allowed = !passenger_allowed + user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.") + else + ..() + +/obj/vehicle/train/securiengine/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/key/securitrain)) + if(!key) + user.drop_item() + W.forceMove(src) + key = W + verbs += /obj/vehicle/train/securiengine/verb/remove_key + return + ..() + +//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead +/obj/vehicle/train/securitrolley/bullet_act(var/obj/item/projectile/Proj) + if(buckled_mob && prob(70)) + buckled_mob.bullet_act(Proj) + return + ..() + +/obj/vehicle/train/securitrolley/update_icon() + if(open) + icon_state = initial(icon_state) + "_open" + else + icon_state = initial(icon_state) + +/obj/vehicle/train/securitrolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + return + +/obj/vehicle/train/securiengine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/securiengine/remove_cell(var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/securiengine/Bump(atom/Obstacle) + var/obj/machinery/door/D = Obstacle + var/mob/living/carbon/human/H = load + if(istype(D) && istype(H)) + D.Bumped(H) //a little hacky, but hey, it works, and respects access rights + + ..() + +/obj/vehicle/train/securitrolley/Bump(atom/Obstacle) + if(!lead) + return //so people can't knock others over by pushing a trolley around + ..() + +//------------------------------------------- +// Train procs +//------------------------------------------- +/obj/vehicle/train/securiengine/turn_on() + if(!key) + return + else + ..() + update_stats() + + verbs -= /obj/vehicle/train/securiengine/verb/stop_engine + verbs -= /obj/vehicle/train/securiengine/verb/start_engine + + if(on) + verbs += /obj/vehicle/train/securiengine/verb/stop_engine + else + verbs += /obj/vehicle/train/securiengine/verb/start_engine + +/obj/vehicle/train/securiengine/turn_off() + ..() + + verbs -= /obj/vehicle/train/securiengine/verb/stop_engine + verbs -= /obj/vehicle/train/securiengine/verb/start_engine + + if(!on) + verbs += /obj/vehicle/train/securiengine/verb/start_engine + else + verbs += /obj/vehicle/train/securiengine/verb/stop_engine + +/obj/vehicle/train/securitrolley/RunOver(var/mob/living/carbon/human/H) + var/list/parts = list(BP_HEAD, BP_TORSO, BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM) + + H.apply_effects(5, 5) + for(var/i = 0, i < rand(1,3), i++) + H.apply_damage(rand(1,5), BRUTE, pick(parts)) + +/obj/vehicle/train/securitrolley/RunOver(var/mob/living/carbon/human/H) + ..() + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + +/obj/vehicle/train/securiengine/RunOver(var/mob/living/carbon/human/H) + ..() + + if(is_train_head() && istype(load, /mob/living/carbon/human)) + var/mob/living/carbon/human/D = load + D << "\red \b You ran over [H]!" + visible_message("\red \The [src] ran over [H]!") + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])") + msg_admin_attack("[D.name] ([D.ckey]) ran over [H.name] ([H.ckey]). (JMP)") + else + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + + +//------------------------------------------- +// Interaction procs +//------------------------------------------- +/obj/vehicle/train/securiengine/relaymove(mob/user, direction) + if(user != load) + return 0 + + if(is_train_head()) + if(direction == reverse_direction(dir) && tow) + return 0 + if(Move(get_step(src, direction))) + return 1 + return 0 + else + return ..() + + +/obj/vehicle/train/securiengine/examine(mob/user) + if(!..(user, 1)) + return + + if(!istype(usr, /mob/living/carbon/human)) + return + + user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." + user << "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%" + +/obj/vehicle/train/securiengine/verb/start_engine() + set name = "Start engine" + set category = "Vehicle" + set src in view(0) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(on) + usr << "The engine is already running." + return + + turn_on() + if (on) + usr << "You start [src]'s engine." + else + if(cell.charge < charge_use) + usr << "[src] is out of power." + else + usr << "[src]'s engine won't start." + +/obj/vehicle/train/securiengine/verb/stop_engine() + set name = "Stop engine" + set category = "Vehicle" + set src in view(0) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(!on) + usr << "The engine is already stopped." + return + + turn_off() + if (!on) + usr << "You stop [src]'s engine." + +/obj/vehicle/train/securiengine/verb/remove_key() + set name = "Remove key" + set category = "Vehicle" + set src in view(0) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(!key || (load && load != usr)) + return + + if(on) + turn_off() + + key.loc = usr.loc + if(!usr.get_active_hand()) + usr.put_in_hands(key) + key = null + + verbs -= /obj/vehicle/train/securiengine/verb/remove_key + +//------------------------------------------- +// Loading/unloading procs +//------------------------------------------- +/obj/vehicle/train/securitrolley/load(var/atom/movable/C) + if(ismob(C) && !passenger_allowed) + return 0 + if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !istype(C, /mob/living/carbon/human)) + return 0 + + //if there are any items you don't want to be able to interact with, add them to this check + // ~no more shielded, emitter armed death trains + if(istype(C, /obj/machinery)) + load_object(C) + else + ..() + + if(load) + return 1 + +/obj/vehicle/train/securiengine/load(var/atom/movable/C) + if(!istype(C, /mob/living/carbon/human)) + return 0 + + return ..() + +//Load the object "inside" the trolley and add an overlay of it. +//This prevents the object from being interacted with until it has +// been unloaded. A dummy object is loaded instead so the loading +// code knows to handle it correctly. +/obj/vehicle/train/securitrolley/proc/load_object(var/atom/movable/C) + if(!isturf(C.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly. + return 0 + if(load || C.anchored) + return 0 + + var/datum/vehicle_dummy_load/dummy_load = new() + load = dummy_load + + if(!load) + return + dummy_load.actual_load = C + C.forceMove(src) + + if(load_item_visible) + C.pixel_x += load_offset_x + C.pixel_y += load_offset_y + C.layer = layer + + overlays += C + + //we can set these back now since we have already cloned the icon into the overlay + C.pixel_x = initial(C.pixel_x) + C.pixel_y = initial(C.pixel_y) + C.layer = initial(C.layer) + +/obj/vehicle/train/securitrolley/unload(var/mob/user, var/direction) + if(istype(load, /datum/vehicle_dummy_load)) + var/datum/vehicle_dummy_load/dummy_load = load + load = dummy_load.actual_load + dummy_load.actual_load = null + qdel(dummy_load) + overlays.Cut() + ..() + +//------------------------------------------- +// Latching/unlatching procs +//------------------------------------------- + +/obj/vehicle/train/securiengine/latch(obj/vehicle/train/T, mob/user) + if(!istype(T) || !Adjacent(T)) + return 0 + + //if we are attaching a trolley to an engine we don't care what direction + // it is in and it should probably be attached with the engine in the lead + if(istype(T, /obj/vehicle/train/securitrolley)) + T.attach_to(src, user) + if (istype(T, /obj/vehicle/train/securitrolley/cargo)) + T.attach_to(src, user) + else + var/T_dir = get_dir(src, T) //figure out where T is wrt src + + if(dir == T_dir) //if car is ahead + src.attach_to(T, user) + else if(reverse_direction(dir) == T_dir) //else if car is behind + T.attach_to(src, user) + +//------------------------------------------------------- +// Stat update procs +// +// Update the trains stats for speed calculations. +// The longer the train, the slower it will go. car_limit +// sets the max number of cars one engine can pull at +// full speed. Adding more cars beyond this will slow the +// train proportionate to the length of the train. Adding +// more engines increases this limit by car_limit per +// engine. +//------------------------------------------------------- +/obj/vehicle/train/securiengine/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines + + //Update move delay + if(!is_train_head() || !on) + move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind + else + move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains + move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) + move_delay += config.run_speed //base reference speed + move_delay *= 1.5 //makes cargo trains 10% slower than running when not overweight + +/obj/vehicle/train/securitrolley/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines + + if(!lead && !tow) + anchored = 0 + else + anchored = 1 + +//----------------------------------------------------- +//Update layer stuff +// +//This is supposed to update the layers and put the mob in the correct spot. +//Pls help squirrel get this to work. ;m; +//----------------------------------------------------- +/obj/vehicle/train/securiengine/proc/update_layer() + if(dir == SOUTH) + layer = FLY_LAYER + else + layer = OBJ_LAYER + +/obj/vehicle/train/securiengine/proc/update_mob() + if(buckled_mob) + buckled_mob.set_dir(dir) + switch(dir) + if(SOUTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 7 + if(WEST) + buckled_mob.pixel_x = 13 + buckled_mob.pixel_y = 7 + if(NORTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 4 + if(EAST) + buckled_mob.pixel_x = -13 + buckled_mob.pixel_y = 7 diff --git a/code/modules/vore/fluffstuff/custom_boxes_vr.dm b/code/modules/vore/fluffstuff/custom_boxes_vr.dm index d66de51a4e..8f47d57d96 100644 --- a/code/modules/vore/fluffstuff/custom_boxes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_boxes_vr.dm @@ -81,6 +81,10 @@ new /obj/item/weapon/sword/fluff/joanaria(src) new /obj/item/weapon/flame/lighter/zippo/fluff/joan(src) new /obj/item/clothing/under/rank/internalaffairs/fluff/joan(src) + new /obj/item/clothing/head/helmet/space/fluff/joan(src) + new /obj/item/clothing/suit/space/fluff/joan(src) + + //joanrisu:Katarina Eine /obj/item/weapon/storage/backpack/dufflebag/sec/fluff/Katarina diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm index dc13fcea65..8cb7d3cac2 100644 --- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm @@ -668,9 +668,15 @@ /obj/item/clothing/suit/space/fluff/joan name = "Joan's Combat Spacesuit" desc = "A customized combat spacesuit made for a certain squirrely Commissioned Officer, tail slot included. \ - On the right shoulder, the United Federation's Emblem sits proudly. On the left, there are faded indications \ - that there were different ranks painted on and off. On the collar where the suit is softer is a rectangular \ - name-tag with the name 'Joan' on it. There are indications that the suit has seen combat." + On the right shoulder, the United Federation's Emblem sits proudly with a Rose weaving through it. \ + On the left, there are faded indications that there were different ranks painted on and off. On the collar \ + where the suit is softer is a rectangular name-tag with the name 'Joan' on it. There are indications that the \ + suit has seen combat." + + armor = list(melee = 80, bullet = 50, laser = 35, energy = 15, bomb = 70, bio = 100, rad = 50) //These values were taken from the combat rigs and adjusted to be weaker than said rigs. + slowdown = 0 + allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/melee/baton) + w_class = 3 icon = 'icons/vore/custom_clothes_vr.dmi' icon_state = "joansuit" diff --git a/icons/obj/vehicles_vr.dmi b/icons/obj/vehicles_vr.dmi index 6fa5ae5e08f8ff51f9910379f0b66b9df28a1bd6..a685e7c69731bb0b1e68d6a79af9ea2f34ba8c01 100644 GIT binary patch literal 8866 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 z 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 From 62243ecd3d1616419cede8d200934be775833e9c Mon Sep 17 00:00:00 2001 From: Poojawa Date: Sun, 18 Sep 2016 11:13:44 -0500 Subject: [PATCH 02/31] Vulpkanin chest sprite tweaks (#562) --- icons/mob/human_races/r_vulpkanin.dmi | Bin 5088 -> 5202 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/human_races/r_vulpkanin.dmi b/icons/mob/human_races/r_vulpkanin.dmi index c3325160426ab41f9ac8cba7b24dc0c586073ea2..700fc452584766b8d23ba30eee4c368633e35e30 100644 GIT binary patch literal 5202 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 Igt^E42PToissI20 From 99367b38eb8b1fc6ff1b26ff55a44c5a96a65e46 Mon Sep 17 00:00:00 2001 From: Eearslya Sleiarion Date: Sun, 18 Sep 2016 19:56:05 -0700 Subject: [PATCH 03/31] Cyborgs can no longer use OOC resize (#566) --- code/modules/vore/resizing/resize_vr.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/vore/resizing/resize_vr.dm b/code/modules/vore/resizing/resize_vr.dm index 06daf449ca..7110d2d202 100644 --- a/code/modules/vore/resizing/resize_vr.dm +++ b/code/modules/vore/resizing/resize_vr.dm @@ -70,6 +70,9 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2 Do not abuse their existence outside of ERP scenes where they apply, \ or reverting OOCly unwanted changes like someone lolshooting the crew with a shrink ray. -Ace" + if (!istype(src,/mob/living/carbon/human)) + src << "Only organic creatures can use this command!" + return var/size_name = input(nagmessage, "Pick a Size") in player_sizes_list if (size_name && player_sizes_list[size_name]) src.resize(player_sizes_list[size_name]) From e8b112fdc10cbd0ee47b4ff5acf723775ddf6799 Mon Sep 17 00:00:00 2001 From: Spades Date: Sun, 18 Sep 2016 23:17:55 -0400 Subject: [PATCH 04/31] Contraband Update (#564) --- code/datums/supplypacks/contraband_vr.dm | 7 + code/game/objects/items/contraband_vr.dm | 87 ++++++++++++ code/game/objects/items/devices/PDA/PDA.dm | 4 +- code/game/objects/random/random_vr.dm | 126 ++++++++++++++++++ code/modules/clothing/suits/armor_vr.dm | 12 ++ code/modules/paperwork/pen_vr.dm | 8 ++ .../guns/projectile/automatic_vr.dm | 2 + .../projectiles/guns/projectile/sniper_vr.dm | 37 +++++ .../reagents/reagent_containers/glass_vr.dm | 5 + .../modules/vore/fluffstuff/custom_guns_vr.dm | 9 +- vorestation.dme | 8 ++ 11 files changed, 298 insertions(+), 7 deletions(-) create mode 100644 code/datums/supplypacks/contraband_vr.dm create mode 100644 code/game/objects/items/contraband_vr.dm create mode 100644 code/game/objects/random/random_vr.dm create mode 100644 code/modules/clothing/suits/armor_vr.dm create mode 100644 code/modules/paperwork/pen_vr.dm create mode 100644 code/modules/projectiles/guns/projectile/automatic_vr.dm create mode 100644 code/modules/projectiles/guns/projectile/sniper_vr.dm create mode 100644 code/modules/reagents/reagent_containers/glass_vr.dm diff --git a/code/datums/supplypacks/contraband_vr.dm b/code/datums/supplypacks/contraband_vr.dm new file mode 100644 index 0000000000..7254c45719 --- /dev/null +++ b/code/datums/supplypacks/contraband_vr.dm @@ -0,0 +1,7 @@ +/datum/supply_packs/stolen + name = "Stolen supplies" + contains = list(/obj/item/stolenpackage) + cost = 150 + containertype = /obj/structure/closet/crate + containername = "Stolen crate" + contraband = 1 \ No newline at end of file diff --git a/code/game/objects/items/contraband_vr.dm b/code/game/objects/items/contraband_vr.dm new file mode 100644 index 0000000000..a4ab63151d --- /dev/null +++ b/code/game/objects/items/contraband_vr.dm @@ -0,0 +1,87 @@ +/obj/item/stolenpackage + name = "stolen package" + desc = "What's in the box?" + icon = 'icons/obj/storage.dmi' + icon_state = "deliverycrate4" + item_state = "table_parts" + w_class = 5 + + attack_self(mob/user as mob) + // Another way of doing this. Commented out because the other method is better for this application. + /*var/spawn_chance = rand(1,100) + switch(spawn_chance) + if(0 to 49) + new /obj/random/gun/guarenteed(usr.loc) + usr << "You got a thing!" + if(50 to 99) + new /obj/item/weapon/bikehorn/rubberducky(usr.loc) + new /obj/item/weapon/bikehorn(usr.loc) + usr << "You got two things!" + if(100) + usr << "The box contained nothing!" + return + */ + var/loot = pick(/obj/random/contraband, + /obj/random/contraband, + /obj/item/weapon/book/manual/engineering_hacking, + /obj/item/device/chameleon, + /obj/item/weapon/contraband/poster, + /obj/item/seeds/ambrosiadeusseed, + /obj/item/seeds/ambrosiavulgarisseed, + /obj/item/seeds/libertymycelium, + /obj/item/xenos_claw, + /obj/item/weapon/reagent_containers/food/snacks/xenomeat, + /obj/item/weapon/reagent_containers/food/snacks/clownstears, + /obj/item/weapon/reagent_containers/food/snacks/carpmeat, + /obj/item/clothing/glasses/thermal, + /obj/item/clothing/gloves/combat, + /obj/item/clothing/head/bearpelt, + /obj/item/clothing/mask/balaclava, + /obj/item/weapon/storage/fancy/cigar/havana, + /obj/item/clothing/mask/horsehead, + /obj/item/clothing/mask/muzzle, + /obj/item/weapon/storage/toolbox/syndicate, + /obj/item/weapon/stamp/centcomm, + /obj/item/weapon/stamp/solgov, + /obj/item/weapon/storage/bible/booze, + /obj/item/weapon/pen/reagent/paralysis, + /obj/item/weapon/grenade/flashbang/clusterbang, + /obj/item/weapon/reagent_containers/food/drinks/bottle/pwine, + /obj/item/weapon/reagent_containers/glass/beaker/neurotoxin, + /obj/item/weapon/grenade/flashbang/clusterbang, + /obj/item/weapon/grenade/spawnergrenade/spesscarp, + /obj/item/weapon/card/emag, + /obj/item/weapon/card/emag_broken, + /obj/item/device/pda/syndicate, + /obj/item/weapon/shield/energy, + /obj/item/weapon/melee/energy/sword, + /obj/item/weapon/melee/telebaton, + /obj/item/weapon/melee/classic_baton, + /obj/item/clothing/suit/armor/heavy, + /obj/item/clothing/suit/armor/vest, + /obj/item/clothing/suit/armor/laserproof, + /obj/random/weapon/guarenteed, + /obj/item/weapon/material/knuckledusters, + /obj/effect/landmark/costume, + /obj/item/mecha_parts/chassis/phazon, + /obj/item/mecha_parts/part/phazon_torso, + /obj/item/mecha_parts/part/phazon_head, + /obj/item/mecha_parts/part/phazon_left_arm, + /obj/item/mecha_parts/part/phazon_right_arm, + /obj/item/mecha_parts/part/phazon_left_leg, + /obj/item/mecha_parts/part/phazon_right_leg) + new loot(usr.loc) + usr << "You unwrap the package." + del(src) + +/obj/item/weapon/storage/fancy/cigar/havana // Putting this here 'cuz fuck it. -Spades + name = "\improper Havana cigar case" + desc = "Save these for the fancy-pantses at the next CentCom black tie reception. You can't blow the smoke from such majestic stogies in just anyone's face." + icon_state = "cigarcase" + icon = 'icons/obj/cigarettes.dmi' + w_class = 1 + throwforce = 2 + slot_flags = SLOT_BELT + storage_slots = 7 + can_hold = list(/obj/item/clothing/mask/smokable/cigarette/cigar/havana) + icon_type = "cigar" \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 43c47d135c..a8d1abdd55 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -168,8 +168,8 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/syndicate default_cartridge = /obj/item/weapon/cartridge/syndicate icon_state = "pda-syn" - name = "Military PDA" - owner = "John Doe" +// name = "Military PDA" // Vorestation Edit +// owner = "John Doe" hidden = 1 /obj/item/device/pda/chaplain diff --git a/code/game/objects/random/random_vr.dm b/code/game/objects/random/random_vr.dm new file mode 100644 index 0000000000..3bea0bea48 --- /dev/null +++ b/code/game/objects/random/random_vr.dm @@ -0,0 +1,126 @@ +/obj/random/weapon // For Gateway maps and Syndicate. Can possibly spawn almost any gun in the game. + name = "Random Illegal Weapon" + desc = "This is a random illegal weapon." + icon = 'icons/obj/gun.dmi' + icon_state = "p08" + spawn_nothing_percentage = 50 + item_to_spawn() + return pick(prob(11);/obj/random/ammo_all,\ + prob(11);/obj/item/weapon/gun/energy/laser,\ + prob(11);/obj/item/weapon/gun/projectile/pirate,\ + prob(10);/obj/item/weapon/material/twohanded/spear,\ + prob(10);/obj/item/weapon/gun/energy/stunrevolver,\ + prob(10);/obj/item/weapon/gun/energy/taser,\ + prob(10);/obj/item/weapon/gun/launcher/crossbow,\ + prob(10);/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,\ + prob(10);/obj/item/weapon/material/knife,\ + prob(10);/obj/item/weapon/material/hatchet/tacknife/combatknife,\ + prob(10);/obj/item/weapon/material/butterfly/switchblade,\ + prob(10);/obj/item/weapon/gun/projectile/luger,\ + prob(10);/obj/item/weapon/gun/projectile/luger/brown,\ + /* prob(10);/obj/item/weapon/gun/projectile/pipegun,\ */ + prob(10);/obj/item/weapon/gun/projectile/revolver,\ + prob(10);/obj/item/weapon/gun/projectile/revolver/detective,\ + prob(10);/obj/item/weapon/gun/projectile/revolver/mateba,\ + prob(10);/obj/item/weapon/gun/projectile/revolver/judge,\ + prob(10);/obj/item/weapon/gun/projectile/colt,\ + prob(10);/obj/item/weapon/gun/projectile/shotgun/pump,\ + prob(10);/obj/item/weapon/gun/projectile/shotgun/pump/rifle,\ + prob(10);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,\ + prob(10);/obj/item/weapon/melee/baton,\ + prob(10);/obj/item/weapon/melee/telebaton,\ + prob(10);/obj/item/weapon/melee/classic_baton,\ + prob(10);/obj/item/weapon/melee/energy/sword,\ + prob(9);/obj/item/weapon/gun/projectile/automatic/wt550/lethal,\ + prob(9);/obj/item/weapon/gun/projectile/automatic/pdw,\ + prob(9);/obj/item/weapon/gun/projectile/derringer,\ + prob(9);/obj/item/weapon/gun/energy/crossbow/largecrossbow,\ + prob(9);/obj/item/weapon/gun/projectile/automatic/mini_uzi,\ + prob(9);/obj/item/weapon/gun/projectile/pistol,\ + prob(9);/obj/item/weapon/gun/projectile/shotgun/pump/combat,\ + prob(9);/obj/item/weapon/twohanded/fireaxe,\ + prob(9);/obj/item/weapon/cane/concealed,\ + prob(9);/obj/item/weapon/gun/energy/gun,\ + prob(8);/obj/item/weapon/gun/energy/ionrifle,\ + prob(8);/obj/item/weapon/gun/energy/retro,\ + prob(8);/obj/item/weapon/gun/energy/gun/eluger,\ + prob(8);/obj/item/weapon/gun/energy/xray,\ + prob(8);/obj/item/weapon/gun/projectile/automatic/c20r,\ + prob(8);/obj/item/weapon/gun/projectile/automatic/stg,\ + prob(8);/obj/item/weapon/melee/energy/sword,\ + /* prob(8);/obj/item/weapon/gun/projectile/automatic/m41a,\ */ + prob(7);/obj/item/weapon/gun/energy/captain,\ + prob(7);/obj/item/weapon/gun/energy/sniperrifle,\ + prob(7);/obj/item/weapon/gun/projectile/automatic/p90,\ + prob(7);/obj/item/weapon/gun/projectile/automatic/as24,\ + prob(7);/obj/item/weapon/gun/projectile/automatic/sts35,\ + prob(7);/obj/item/weapon/gun/projectile/automatic/z8,\ + prob(7);/obj/item/weapon/gun/energy/gun/burst,\ + prob(7);/obj/item/weapon/gun/projectile/shotgun/pump/unsc,\ + prob(7);/obj/item/weapon/gun/projectile/deagle,\ + prob(7);/obj/item/weapon/gun/launcher/grenade,\ + prob(6);/obj/item/weapon/gun/projectile/SVD,\ + prob(6);/obj/item/weapon/gun/projectile/automatic/l6_saw,\ + prob(6);/obj/item/weapon/gun/energy/lasercannon,\ + prob(5);/obj/item/weapon/gun/projectile/automatic/carbine,\ + prob(5);/obj/item/weapon/gun/energy/pulse_rifle,\ + prob(4);/obj/item/weapon/gun/projectile/automatic/battlerifle,\ + prob(3);/obj/item/weapon/gun/projectile/deagle/camo,\ + prob(3);/obj/item/weapon/gun/energy/gun/nuclear,\ + prob(2);/obj/item/weapon/gun/projectile/deagle/gold,\ + prob(1);/obj/item/weapon/gun/launcher/rocket,\ + prob(1);/obj/item/weapon/gun/projectile/gyropistol,\ + prob(1);/obj/item/weapon/gun/projectile/heavysniper,\ + prob(1);/obj/item/weapon/plastique,\ + prob(1);/obj/item/weapon/material/sword,\ + prob(1);/obj/item/weapon/material/sword/katana) + +/obj/random/weapon/guarenteed + spawn_nothing_percentage = 0 + +/obj/random/ammo_all + name = "Random Ammunition (All)" + desc = "This is random ammunition. Spawns all ammo types." + icon = 'icons/obj/ammo.dmi' + icon_state = "666" + item_to_spawn() + return pick(/*prob(5);/obj/item/weapon/storage/fancy/shotgun_ammo/beanbag,\ + prob(5);/obj/item/weapon/storage/fancy/shotgun_ammo/pellet,\ + prob(5);/obj/item/weapon/storage/fancy/shotgun_ammo/flash,\ + prob(5);/obj/item/weapon/storage/fancy/shotgun_ammo/slug,\*/ + prob(5);/obj/item/ammo_magazine/a357,\ + prob(5);/obj/item/ammo_magazine/clip/a762,\ + prob(5);/obj/item/ammo_magazine/c45m,\ + prob(5);/obj/item/ammo_magazine/c45m/rubber,\ + prob(5);/obj/item/ammo_magazine/c38,\ + prob(5);/obj/item/ammo_magazine/c38/rubber,\ + prob(5);/obj/item/weapon/storage/box/flashbangs,\ + prob(5);/obj/item/ammo_magazine/s762,\ + prob(4);/obj/item/ammo_magazine/clip/a556,\ + prob(4);/obj/item/ammo_magazine/clip/c45,\ + prob(4);/obj/item/ammo_magazine/clip/c9mm,\ + prob(4);/obj/item/ammo_magazine/c45uzi,\ + prob(4);/obj/item/ammo_magazine/c762,\ + prob(4);/obj/item/ammo_magazine/mc9mm,\ + prob(4);/obj/item/ammo_magazine/mc9mml,\ + prob(4);/obj/item/ammo_magazine/mc9mmt,\ + prob(4);/obj/item/ammo_magazine/mc9mmt/rubber,\ + prob(4);/obj/item/ammo_magazine/a10mm,\ + prob(4);/obj/item/ammo_magazine/p90,\ + /* prob(4);/obj/item/ammo_magazine/m14,\ + prob(4);/obj/item/ammo_magazine/m14/large,\ */ + prob(4);/obj/item/ammo_magazine/c762,\ + prob(4);/obj/item/ammo_magazine/a556,\ + prob(4);/obj/item/ammo_magazine/a556m,\ + prob(3);/obj/item/ammo_magazine/clip/a10mm,\ + prob(3);/obj/item/ammo_magazine/clip/a50,\ + prob(3);/obj/item/ammo_magazine/s762,\ + prob(2);/obj/item/ammo_magazine/a50,\ + prob(2);/obj/item/ammo_magazine/a762,\ + prob(1);/obj/item/ammo_magazine/battlerifle,\ + prob(1);/obj/item/ammo_casing/rocket,\ + prob(1);/obj/item/weapon/storage/box/sniperammo,\ + prob(1);/obj/item/ammo_magazine/stg,\ + prob(1);/obj/item/ammo_magazine/tommydrum,\ + prob(1);/obj/item/ammo_magazine/tommymag + ) \ No newline at end of file diff --git a/code/modules/clothing/suits/armor_vr.dm b/code/modules/clothing/suits/armor_vr.dm new file mode 100644 index 0000000000..5b5000dc34 --- /dev/null +++ b/code/modules/clothing/suits/armor_vr.dm @@ -0,0 +1,12 @@ +/obj/item/clothing/suit/armor/heavy + name = "heavy armor" + desc = "An old military-grade suit of armor. Incredibly robust against brute force damage! However, it offers little protection from energy-based weapons, which, combined with its bulk, makes it woefully obsolete." + icon_state = "heavy" + item_state_slots = list(slot_r_hand_str = "swat", slot_l_hand_str = "swat") + armor = list(melee = 90, bullet = 80, laser = 10, energy = 10, bomb = 80, bio = 0, rad = 0) + w_class = 5 // massively bulky item + gas_transfer_coefficient = 0.90 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + slowdown = 5 // If you're a tank you're gonna move like a tank. + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 0 \ No newline at end of file diff --git a/code/modules/paperwork/pen_vr.dm b/code/modules/paperwork/pen_vr.dm new file mode 100644 index 0000000000..3629169202 --- /dev/null +++ b/code/modules/paperwork/pen_vr.dm @@ -0,0 +1,8 @@ +/obj/item/weapon/pen/reagent/paralysis + origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5) + +/obj/item/weapon/pen/reagent/paralysis/New() + ..() +// reagents.add_reagent("zombiepowder", 10) +// reagents.add_reagent("cryptobiolin", 15) + reagents.add_reagent("neurotoxin", 30) // A lot less griefy. \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/automatic_vr.dm b/code/modules/projectiles/guns/projectile/automatic_vr.dm new file mode 100644 index 0000000000..9b7fc0c726 --- /dev/null +++ b/code/modules/projectiles/guns/projectile/automatic_vr.dm @@ -0,0 +1,2 @@ +/obj/item/weapon/gun/projectile/automatic/wt550/lethal + magazine_type = /obj/item/ammo_magazine/mc9mmt \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/sniper_vr.dm b/code/modules/projectiles/guns/projectile/sniper_vr.dm new file mode 100644 index 0000000000..f2796a61ae --- /dev/null +++ b/code/modules/projectiles/guns/projectile/sniper_vr.dm @@ -0,0 +1,37 @@ +////////////// Dragunov Sniper Rifle ////////////// + +/obj/item/weapon/gun/projectile/SVD + name = "\improper Dragunov" + desc = "The SVD, also known as the Dragunov, was mass produced with an Optical Sniper Sight so simple that even Ivan can figure out how it works. Too bad for you that it's written in Russian. Uses 7.62mm rounds." + icon_state = "SVD" + item_state = "SVD" + w_class = 5 // So it can't fit in a backpack. + force = 10 + slot_flags = SLOT_BACK // Needs a sprite. + origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) + recoil = 2 //extra kickback + caliber = "a762" + load_method = MAGAZINE + accuracy = -3 //shooting at the hip + scoped_accuracy = 0 +// requires_two_hands = 1 + one_handed_penalty = 4 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. + fire_sound = 'sound/weapons/SVD_shot.ogg' + magazine_type = /obj/item/ammo_magazine/s762 + allowed_magazines = list(/obj/item/ammo_magazine/s762, /obj/item/ammo_magazine/c762) + +/obj/item/weapon/gun/projectile/SVD/update_icon() + ..() +// if(istype(ammo_magazine,/obj/item/ammo_magazine/c762) +// icon_state = "SVD-bigmag" //No icon for this exists yet. + if(ammo_magazine) + icon_state = "SVD" + else + icon_state = "SVD-empty" + +/obj/item/weapon/gun/projectile/SVD/verb/scope() + set category = "Object" + set name = "Use Scope" + set popup_menu = 1 + + toggle_scope(2.0) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/glass_vr.dm b/code/modules/reagents/reagent_containers/glass_vr.dm new file mode 100644 index 0000000000..c30839d3f0 --- /dev/null +++ b/code/modules/reagents/reagent_containers/glass_vr.dm @@ -0,0 +1,5 @@ +/obj/item/weapon/reagent_containers/glass/beaker/neurotoxin + New() + ..() + reagents.add_reagent("neurotoxin",50) + update_icon() \ No newline at end of file diff --git a/code/modules/vore/fluffstuff/custom_guns_vr.dm b/code/modules/vore/fluffstuff/custom_guns_vr.dm index 314d1ecac2..6df096a2c4 100644 --- a/code/modules/vore/fluffstuff/custom_guns_vr.dm +++ b/code/modules/vore/fluffstuff/custom_guns_vr.dm @@ -133,15 +133,12 @@ desc = "You notice the serial number on the revolver is 667. The word 'Redemption' is engraved on dark rosewood grip. Uses .357 rounds." // sasoperative : Joseph Skinner -/obj/item/weapon/gun/projectile/revolver/shotgun/fluff/sasoperative +/obj/item/weapon/gun/projectile/revolver/judge/fluff/sasoperative name = "\"The Jury\"" desc = "A customized variant of the \"The Judge\" revolver sold by Cybersun Industries, built specifically for Joseph Skinner. Uses 12g shells." - icon = 'icons/vore/custom_guns_vr.dmi' icon_state = "jury" - item_state = "gun" - accuracy = 0 // Because I know you're not an idiot who needs to be nerfed. -Ace ammo_type = /obj/item/ammo_casing/shotgun/beanbag @@ -166,10 +163,12 @@ item_state = (ammo_magazine)? "arifle" : "arifle-empty" if(!ignore_inhands) update_held_icon() +/* // For general use /obj/item/weapon/gun/projectile/automatic/m14/fluff/gallian name = "\improper Gallian 4 Rifle" desc = "The ever reliable Gallian 4 Rifle. Produced by the National Armory on the Planet of Gaia located in Gallia, the Gallian 4 Rifle offers high accuracy and is widely used in the United Federation's Military. Uses 7.62mm rounds." +*/ // For general use /obj/item/weapon/gun/projectile/shotgun/pump/rifle/zmkar @@ -203,7 +202,7 @@ // For general use /obj/item/weapon/gun/projectile/automatic/pdw // Vorestation SMG because the WT550 is ugly and bad. name = "personal defense weapon" - desc = "The X-9MM is a select-fire personal defense weapon designed in-house by Xing Private Security. It was made to compete with the WT550 Saber, but hasn't yet caught on in popularity outside of the Virgo-Erigone system. Uses 9mm rounds." + desc = "The X-9MM is a select-fire personal defense weapon designed in-house by Xing Private Security. It was made to compete with the WT550 Saber, but hasn't yet caught on with NanoTrasen. Uses 9mm rounds." icon = 'icons/obj/gun_vr.dmi' icon_state = "pdw" item_state = "c20r" // Placeholder diff --git a/vorestation.dme b/vorestation.dme index 9720c7bf50..d40f551034 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -215,6 +215,7 @@ #include "code\datums\repositories\repository.dm" #include "code\datums\supplypacks\atmospherics.dm" #include "code\datums\supplypacks\contraband.dm" +#include "code\datums\supplypacks\contraband_vr.dm" #include "code\datums\supplypacks\costumes.dm" #include "code\datums\supplypacks\engineering.dm" #include "code\datums\supplypacks\hospitality.dm" @@ -760,6 +761,7 @@ #include "code\game\objects\items\blueprints.dm" #include "code\game\objects\items\bodybag.dm" #include "code\game\objects\items\contraband.dm" +#include "code\game\objects\items\contraband_vr.dm" #include "code\game\objects\items\crayons.dm" #include "code\game\objects\items\glassjar.dm" #include "code\game\objects\items\latexballoon.dm" @@ -936,6 +938,7 @@ #include "code\game\objects\items\weapons\tanks\tank_types.dm" #include "code\game\objects\items\weapons\tanks\tanks.dm" #include "code\game\objects\random\random.dm" +#include "code\game\objects\random\random_vr.dm" #include "code\game\objects\structures\barsign.dm" #include "code\game\objects\structures\bedsheet_bin.dm" #include "code\game\objects\structures\coathanger.dm" @@ -1269,6 +1272,7 @@ #include "code\modules\clothing\spacesuits\void\wizard.dm" #include "code\modules\clothing\suits\alien.dm" #include "code\modules\clothing\suits\armor.dm" +#include "code\modules\clothing\suits\armor_vr.dm" #include "code\modules\clothing\suits\bio.dm" #include "code\modules\clothing\suits\jobs.dm" #include "code\modules\clothing\suits\labcoat.dm" @@ -1802,6 +1806,7 @@ #include "code\modules\paperwork\paperbin.dm" #include "code\modules\paperwork\papershredder.dm" #include "code\modules\paperwork\pen.dm" +#include "code\modules\paperwork\pen_vr.dm" #include "code\modules\paperwork\photocopier.dm" #include "code\modules\paperwork\photography.dm" #include "code\modules\paperwork\silicon_photography.dm" @@ -1868,12 +1873,14 @@ #include "code\modules\projectiles\guns\launcher\rocket.dm" #include "code\modules\projectiles\guns\launcher\syringe_gun.dm" #include "code\modules\projectiles\guns\projectile\automatic.dm" +#include "code\modules\projectiles\guns\projectile\automatic_vr.dm" #include "code\modules\projectiles\guns\projectile\boltaction.dm" #include "code\modules\projectiles\guns\projectile\dartgun.dm" #include "code\modules\projectiles\guns\projectile\pistol.dm" #include "code\modules\projectiles\guns\projectile\revolver.dm" #include "code\modules\projectiles\guns\projectile\shotgun.dm" #include "code\modules\projectiles\guns\projectile\sniper.dm" +#include "code\modules\projectiles\guns\projectile\sniper_vr.dm" #include "code\modules\projectiles\projectile\animate.dm" #include "code\modules\projectiles\projectile\beams.dm" #include "code\modules\projectiles\projectile\bullets.dm" @@ -1934,6 +1941,7 @@ #include "code\modules\reagents\reagent_containers\dropper.dm" #include "code\modules\reagents\reagent_containers\food.dm" #include "code\modules\reagents\reagent_containers\glass.dm" +#include "code\modules\reagents\reagent_containers\glass_vr.dm" #include "code\modules\reagents\reagent_containers\hypospray.dm" #include "code\modules\reagents\reagent_containers\pill.dm" #include "code\modules\reagents\reagent_containers\spray.dm" From b29deb61d065b7bed62e3da233596bae8c4df980 Mon Sep 17 00:00:00 2001 From: Cameron653 Date: Sun, 18 Sep 2016 23:18:39 -0400 Subject: [PATCH 05/31] Adds bird mobs (#563) * Adds birbs Sprites from Goonstation * micros should be ate * Forgot to remove editing lines * Adds a bird crate to cargo. Since crates can only have one animal in them at any given time, I had to make a hack to make it spawn multiple birds at once. * Update hydroponics_vr.dm --- code/datums/supplypacks/hydroponics_vr.dm | 6 + .../crates_lockers/largecrate_vr.dm | 38 ++ .../living/simple_animal/friendly/birds_vr.dm | 326 ++++++++++++++++++ icons/mob/birds.dmi | Bin 0 -> 139465 bytes vorestation.dme | 3 + 5 files changed, 373 insertions(+) create mode 100644 code/datums/supplypacks/hydroponics_vr.dm create mode 100644 code/game/objects/structures/crates_lockers/largecrate_vr.dm create mode 100644 code/modules/mob/living/simple_animal/friendly/birds_vr.dm create mode 100644 icons/mob/birds.dmi diff --git a/code/datums/supplypacks/hydroponics_vr.dm b/code/datums/supplypacks/hydroponics_vr.dm new file mode 100644 index 0000000000..6d8db96375 --- /dev/null +++ b/code/datums/supplypacks/hydroponics_vr.dm @@ -0,0 +1,6 @@ +/datum/supply_packs/hydro/goat + name = "Birds Crate" + cost = 200 //You're getting 22 birds. Of course it's going to be a lot! + containertype = /obj/structure/largecrate/birds + containername = "Bird crate" + access = access_hydroponics diff --git a/code/game/objects/structures/crates_lockers/largecrate_vr.dm b/code/game/objects/structures/crates_lockers/largecrate_vr.dm new file mode 100644 index 0000000000..f45636db0c --- /dev/null +++ b/code/game/objects/structures/crates_lockers/largecrate_vr.dm @@ -0,0 +1,38 @@ +/obj/structure/largecrate/birds //This is an awful hack, but it's the only way to get multiple mobs spawned in one crate. + name = "Bird crate" + desc = "You hear chirping and cawing inside the crate. It sounds like there are a lot of birds in there..." + +/obj/structure/largecrate/birds/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + new /obj/item/stack/material/wood(src) + new /mob/living/simple_animal/cat/bird(src) + new /mob/living/simple_animal/cat/bird/fluff/kea(src) + new /mob/living/simple_animal/cat/bird/fluff/eclectus(src) + new /mob/living/simple_animal/cat/bird/fluff/greybird(src) + new /mob/living/simple_animal/cat/bird/fluff/eclectusf(src) + new /mob/living/simple_animal/cat/bird/fluff/blue_caique(src) + new /mob/living/simple_animal/cat/bird/fluff/white_caique(src) + new /mob/living/simple_animal/cat/bird/fluff/green_budgerigar(src) + new /mob/living/simple_animal/cat/bird/fluff/blue_Budgerigar(src) + new /mob/living/simple_animal/cat/bird/fluff/bluegreen_Budgerigar(src) + new /mob/living/simple_animal/cat/bird/fluff/commonblackbird(src) + new /mob/living/simple_animal/cat/bird/fluff/azuretit(src) + new /mob/living/simple_animal/cat/bird/fluff/europeanrobin(src) + new /mob/living/simple_animal/cat/bird/fluff/goldcrest(src) + new /mob/living/simple_animal/cat/bird/fluff/ringneckdove(src) + new /mob/living/simple_animal/cat/bird/fluff/cockatiel(src) + new /mob/living/simple_animal/cat/bird/fluff/white_cockatiel(src) + new /mob/living/simple_animal/cat/bird/fluff/yellowish_cockatiel(src) + new /mob/living/simple_animal/cat/bird/fluff/grey_cockatiel(src) + new /mob/living/simple_animal/cat/bird/fluff/too(src) + new /mob/living/simple_animal/cat/bird/fluff/hooded_too(src) + new /mob/living/simple_animal/cat/bird/fluff/pink_too(src) + var/turf/T = get_turf(src) + for(var/atom/movable/AM in contents) + if(AM.simulated) AM.forceMove(T) + user.visible_message("[user] pries \the [src] open.", \ + "You pry open \the [src].", \ + "You hear splitting wood.") + qdel(src) + else + return attack_hand(user) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/birds_vr.dm b/code/modules/mob/living/simple_animal/friendly/birds_vr.dm new file mode 100644 index 0000000000..4117cf0f4e --- /dev/null +++ b/code/modules/mob/living/simple_animal/friendly/birds_vr.dm @@ -0,0 +1,326 @@ +//Cat +/mob/living/simple_animal/cat/bird + name = "parrot" + desc = "A domesticated bird. Has a tendency to 'adopt' crewmembers." + isPredator = 1 + icon = 'icons/mob/birds.dmi' + icon_state = "parrot-flap" + item_state = null + icon_living = "parrot-flap" + icon_dead = "parrot-dead" + speak = list("Chirp!","Caw!","Screech!","Squawk!") + speak_emote = list("chirps", "caws") + emote_hear = list("chirps","caws") + emote_see = list("shakes their head", "ruffles their feathers") + holder_type = /obj/item/weapon/holder/bird + +/mob/living/simple_animal/cat/bird/New() + if(!vore_organs.len) + var/datum/belly/B = new /datum/belly(src) + B.immutable = 1 + B.name = "Stomach" + B.inside_flavor = "Slick birdguts. Cute on the outside, slimy on the inside!" + B.human_prey_swallow_time = swallowTime + B.nonhuman_prey_swallow_time = swallowTime + vore_organs[B.name] = B + vore_selected = B.name + + B.emote_lists[DM_HOLD] = list( + "The birdguts knead and churn around you harmlessly.", + "With a loud glorp, some air shifts inside the belly.", + "A thick drop of warm bellyslime drips onto you from above.", + "The bird goes into the air suddenly, causing you to be tossed about.", + "During a moment of relative silence, you can hear the bird breathing.", + "The slimey stomach walls squeeze you lightly, then relax.") + + B.emote_lists[DM_DIGEST] = list( + "The guts knead at you, trying to work you into thick soup.", + "You're ground on by the slimey walls, treated like a mouse.", + "The acrid air is hard to breathe, and stings at your lungs.", + "You can feel the acids coating you, ground in by the slick walls.", + "The bird's stomach churns hungrily over your form, trying to take you.", + "With a loud glorp, the stomach spills more acids onto you.") + ..() + + + +/mob/living/simple_animal/cat/bird/Life() + //MICE! + if((src.loc) && isturf(src.loc)) + if(!stat && !resting && !buckled) + for(var/mob/living/simple_animal/mouse/M in loc) + if(!M.stat) + M.splat() + visible_emote(pick("bites \the [M]!","toys with \the [M].","chomps on \the [M]!")) + movement_target = null + stop_automated_movement = 0 + break + + ..() + + for(var/mob/living/simple_animal/mouse/snack in oview(src,5)) + if(snack.stat < DEAD && prob(15)) + audible_emote(pick("chirps and caws!","squawks fiercely!","eyes [snack] hungrily.")) + break + + if(!stat && !resting && !buckled) + turns_since_scan++ + if (turns_since_scan > 5) + walk_to(src,0) + turns_since_scan = 0 + + if (flee_target) //fleeing takes precendence + handle_flee_target_b() + else + handle_movement_target() + + if(!stat && !resting && !buckled) //SEE A MICRO AND ARE A PREDATOR, EAT IT! + for(var/mob/living/carbon/human/food in oview(src, 5)) + + if(food.size_multiplier <= RESIZE_A_SMALLTINY) + if(prob(10)) + custom_emote(1, pick("eyes [food] hungrily!","licks their lips and turns towards [food] a little!","pants as they imagine [food] being in their belly.")) + break + else + if(prob(5)) + movement_target = food + break + + for(var/mob/living/carbon/human/bellyfiller in oview(1, src)) + if(bellyfiller in src.prey_excludes) + continue + + if(bellyfiller.size_multiplier <= RESIZE_A_SMALLTINY && isPredator) + movement_target = null + custom_emote(1, pick("pecks at [bellyfiller] with their beak.","looms over [bellyfiller] with their beak agape.","sniffs at [bellyfiller], their belly grumbling hungrily.")) + sleep(10) + custom_emote(1, "starts to scoop [bellyfiller] into their beak!") + if(bellyfiller in oview(1, src)) + animal_nom(bellyfiller) + else + bellyfiller << "You just manage to slip away from [src]'s jaws before you can be sent to a fleshy prison!" + break + +/mob/living/simple_animal/cat/bird/proc/handle_flee_target_b() + //see if we should stop fleeing + if (flee_target && !(flee_target.loc in view(src))) + flee_target = null + stop_automated_movement = 0 + + if (flee_target) + if(prob(25)) say("Squawk!") + stop_automated_movement = 1 + walk_away(src, flee_target, 7, 2) + + +//Basic friend AI +/mob/living/simple_animal/cat/bird/fluff + var/mob/living/carbon/human/friend + var/befriend_job = null + +/mob/living/simple_animal/cat/bird/fluff/handle_movement_target() + if (friend) + var/follow_dist = 4 + if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit) //danger + follow_dist = 1 + else if (friend.stat || friend.health <= 50) //danger or just sleeping + follow_dist = 2 + var/near_dist = max(follow_dist - 2, 1) + var/current_dist = get_dist(src, friend) + + if (movement_target != friend) + if (current_dist > follow_dist && !istype(movement_target, /mob/living/simple_animal/mouse) && (friend in oview(src))) + //stop existing movement + walk_to(src,0) + turns_since_scan = 0 + + //walk to friend + stop_automated_movement = 1 + movement_target = friend + walk_to(src, movement_target, near_dist, 4) + + //already following and close enough, stop + else if (current_dist <= near_dist) + walk_to(src,0) + movement_target = null + stop_automated_movement = 0 + if (prob(10)) + say("Caw!") + + if (!friend || movement_target != friend) + ..() + +/mob/living/simple_animal/cat/bird/fluff/Life() + ..() + if (stat || !friend) + return + if (get_dist(src, friend) <= 1) + if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit) + if (prob((friend.stat < DEAD)? 50 : 15)) + var/verb = pick("Chirps", "Caws", "Squawks") + audible_emote(pick("[verb] in distress.", "[verb] anxiously.")) + else + if (prob(5)) + visible_emote(pick("nuzzles [friend].", + "brushes against [friend].", + "rubs against [friend].", + "chirps.")) + else if (friend.health <= 50) + if (prob(10)) + var/verb = pick("meows", "mews", "mrowls") + audible_emote("[verb] anxiously.") + +/mob/living/simple_animal/cat/bird/fluff/verb/become_friends_b() + set name = "Become Friends" + set category = "IC" + set src in view(1) + + if(!friend) + var/mob/living/carbon/human/H = usr + if(istype(H) && (!befriend_job || H.job == befriend_job)) + friend = usr + . = 1 + else if(usr == friend) + . = 1 //already friends, but show success anyways + + if(.) + set_dir(get_dir(src, friend)) + visible_emote(pick("nuzzles [friend].", + "brushes against [friend].", + "rubs against [friend].", + "chirps.")) + else + usr << "[src] ignores you." + return + +/mob/living/simple_animal/cat/bird/fluff/kea + name = "Kea" + icon_state = "kea-flap" + icon_living = "kea-flap" + icon_dead = "kea-dead" + +/mob/living/simple_animal/cat/bird/fluff/eclectus + name = "Eclectus" + icon_state = "eclectus-flap" + icon_living = "eclectus-flap" + icon_dead = "eclectus-dead" + +/mob/living/simple_animal/cat/bird/fluff/eclectusf + name = "Eclectus" + icon_state = "eclectusf-flap" + icon_living = "eclectusf-flap" + icon_dead = "eclectusf-dead" + +/mob/living/simple_animal/cat/bird/fluff/greybird + name = "Grey Bird" + icon_state = "agrey-flap" + icon_living = "agrey-flap" + icon_dead = "agrey-dead" + +/mob/living/simple_animal/cat/bird/fluff/blue_caique + name = "Blue Caique " + icon_state = "bcaique-flap" + icon_living = "bcaique-flap" + icon_dead = "bcaique-dead" + +/mob/living/simple_animal/cat/bird/fluff/white_caique + name = "White caique" + icon_state = "wcaique-flap" + icon_living = "wcaique-flap" + icon_dead = "wcaique-dead" + +/mob/living/simple_animal/cat/bird/fluff/green_budgerigar + name = "Green Budgerigar" + icon_state = "gbudge-flap" + icon_living = "gbudge-flap" + icon_dead = "gbudge-dead" + +/mob/living/simple_animal/cat/bird/fluff/blue_Budgerigar + name = "Blue Budgerigar" + icon_state = "bbudge-flap" + icon_living = "bbudge-flap" + icon_dead = "bbudge-dead" + +/mob/living/simple_animal/cat/bird/fluff/bluegreen_Budgerigar + name = "Bluegreen Budgerigar" + icon_state = "bgbudge-flap" + icon_living = "bgbudge-flap" + icon_dead = "bgbudge-dead" + +/mob/living/simple_animal/cat/bird/fluff/commonblackbird + name = "Black Bird" + icon_state = "commonblackbird" + icon_living = "commonblackbird" + icon_dead = "commonblackbird-dead" + +/mob/living/simple_animal/cat/bird/fluff/azuretit + name = "Azure Tit" + icon_state = "azuretit" + icon_living = "azuretit" + icon_dead = "azuretit-dead" + +/mob/living/simple_animal/cat/bird/fluff/europeanrobin + name = "European Robin" + icon_state = "europeanrobin" + icon_living = "europeanrobin" + icon_dead = "europeanrobin-dead" + +/mob/living/simple_animal/cat/bird/fluff/goldcrest + name = "Goldcrest" + icon_state = "goldcrest" + icon_living = "goldcrest" + icon_dead = "goldcrest-dead" + +/mob/living/simple_animal/cat/bird/fluff/ringneckdove + name = "Ringneck Dove" + icon_state = "ringneckdove" + icon_living = "ringneckdove" + icon_dead = "ringneckdove-dead" + +/mob/living/simple_animal/cat/bird/fluff/cockatiel + name = "Cockatiel" + icon_state = "tiel-flap" + icon_living = "tiel-flap" + icon_dead = "tiel-dead" + +/mob/living/simple_animal/cat/bird/fluff/white_cockatiel + name = "White Cockatiel" + icon_state = "wtiel-flap" + icon_living = "wtiel-flap" + icon_dead = "wtiel-dead" + +/mob/living/simple_animal/cat/bird/fluff/yellowish_cockatiel + name = "Yellowish Cockatiel" + icon_state = "luttiel-flap" + icon_living = "luttiel-flap" + icon_dead = "luttiel-dead" + +/mob/living/simple_animal/cat/bird/fluff/grey_cockatiel + name = "Grey Cockatiel" + icon_state = "blutiel-flap" + icon_living = "blutiel-flap" + icon_dead = "blutiel-dead" + +/mob/living/simple_animal/cat/bird/fluff/too + name = "Too" + icon_state = "too-flap" + icon_living = "too-flap" + icon_dead = "too-dead" + +/mob/living/simple_animal/cat/bird/fluff/hooded_too + name = "Utoo" + icon_state = "utoo-flap" + icon_living = "utoo-flap" + icon_dead = "utoo-dead" + +/mob/living/simple_animal/cat/bird/fluff/pink_too + name = "Mtoo" + icon_state = "mtoo-flap" + icon_living = "mtoo-flap" + icon_dead = "mtoo-dead" + +/obj/item/weapon/holder/bird + name = "Bird" + desc = "It's a bird!" + icon_state = null + item_icons = null \ No newline at end of file diff --git a/icons/mob/birds.dmi b/icons/mob/birds.dmi new file mode 100644 index 0000000000000000000000000000000000000000..582fcc60a84f1ae8508208fdc7f3e29946936613 GIT binary patch literal 139465 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�j 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%0A)V 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 J+F5hI{|}IihBE*F literal 0 HcmV?d00001 diff --git a/vorestation.dme b/vorestation.dme index d40f551034..2aaf065957 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -220,6 +220,7 @@ #include "code\datums\supplypacks\engineering.dm" #include "code\datums\supplypacks\hospitality.dm" #include "code\datums\supplypacks\hydroponics.dm" +#include "code\datums\supplypacks\hydroponics_vr.dm" #include "code\datums\supplypacks\materials.dm" #include "code\datums\supplypacks\medical.dm" #include "code\datums\supplypacks\misc.dm" @@ -975,6 +976,7 @@ #include "code\game\objects\structures\crates_lockers\crates.dm" #include "code\game\objects\structures\crates_lockers\crates_vr.dm" #include "code\game\objects\structures\crates_lockers\largecrate.dm" +#include "code\game\objects\structures\crates_lockers\largecrate_vr.dm" #include "code\game\objects\structures\crates_lockers\closets\coffin.dm" #include "code\game\objects\structures\crates_lockers\closets\crittercrate.dm" #include "code\game\objects\structures\crates_lockers\closets\egg_vr.dm" @@ -1685,6 +1687,7 @@ #include "code\modules\mob\living\simple_animal\borer\say.dm" #include "code\modules\mob\living\simple_animal\constructs\constructs.dm" #include "code\modules\mob\living\simple_animal\constructs\soulstone.dm" +#include "code\modules\mob\living\simple_animal\friendly\birds_vr.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi_vr.dm" From 6c311460178ead3e4b0678daa99f68397648319e Mon Sep 17 00:00:00 2001 From: Spades Date: Sun, 18 Sep 2016 23:47:08 -0400 Subject: [PATCH 06/31] Map hotfix (#568) --- maps/RandomZLevels/carpfarm.dmm | 59 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/maps/RandomZLevels/carpfarm.dmm b/maps/RandomZLevels/carpfarm.dmm index 9b1e7df997..d630cef95f 100644 --- a/maps/RandomZLevels/carpfarm.dmm +++ b/maps/RandomZLevels/carpfarm.dmm @@ -56,14 +56,14 @@ "bd" = (/obj/machinery/light{dir = 1},/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) "be" = (/obj/structure/closet/gimmick/russian,/obj/machinery/light{dir = 8},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bf" = (/obj/structure/closet/gimmick/russian,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) -"bg" = (/obj/structure/closet/crate/freezer/rations,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) +"bg" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/structure/closet/crate/freezer,/obj/item/trash/syndi_cakes,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bh" = (/obj/structure/closet/wardrobe/black,/obj/item/clothing/under/syndicate/tacticool,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) -"bi" = (/obj/structure/closet/secure_closet/personal,/obj/random/single,/obj/random/single,/obj/random/single,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) +"bi" = (/obj/structure/closet/secure_closet/personal,/obj/effect/floor_decal/industrial/outline/yellow,/obj/effect/landmark/costume,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bj" = (/obj/machinery/door/airlock/maintenance_hatch,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bk" = (/obj/machinery/light{dir = 8},/obj/structure/closet/crate/internals,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/clothing/mask/breath,/obj/item/clothing/mask/breath,/obj/item/clothing/mask/breath,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bl" = (/obj/structure/closet/crate/internals,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/clothing/mask/breath,/obj/item/clothing/mask/breath,/obj/item/clothing/mask/breath,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bm" = (/obj/structure/closet/crate/plastic,/obj/random/contraband,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) -"bn" = (/obj/structure/closet/crate,/obj/random/single,/obj/random/single,/obj/random/single,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) +"bn" = (/obj/structure/closet/crate,/obj/effect/floor_decal/industrial/outline/yellow,/obj/random/weapon,/turf/simulated/floor/tiled/dark,/area/awaymission/carpfarm/base) "bo" = (/obj/machinery/door/airlock/mining,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) "bp" = (/obj/machinery/door/airlock/glass,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) "bq" = (/obj/structure/table/steel,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) @@ -102,21 +102,22 @@ "bX" = (/obj/structure/closet/emcloset,/obj/item/weapon/storage/toolbox/emergency,/obj/machinery/airlock_sensor{frequency = 1375; id_tag = "carp_sensor"; pixel_x = 28},/turf/simulated/floor/plating,/area/awaymission/carpfarm/base) "bY" = (/obj/structure/closet/secure_closet/freezer/fridge,/obj/effect/floor_decal/corner/white/diagonal,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) "bZ" = (/obj/structure/bed/chair{dir = 1},/obj/effect/floor_decal/corner/white/diagonal,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) -"ca" = (/obj/machinery/door/airlock/external{frequency = 1375; icon_state = "door_locked"; id_tag = "carp_outer"; locked = 1; name = "External Access"; req_access = newlist()},/turf/simulated/floor/plating,/area/awaymission/carpfarm/base) -"cb" = (/obj/machinery/light{dir = 1},/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) -"cc" = (/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) -"cd" = (/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1375; master_tag = "carp_airlock"; name = "exterior access button"; pixel_x = 26; pixel_y = 26; req_access = newlist()},/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) -"ce" = (/obj/structure/lattice,/obj/structure/grille,/turf/space,/area/space) -"cf" = (/obj/effect/floor_decal/industrial/warning{dir = 9},/turf/simulated/floor/airless,/area/space) -"cg" = (/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/airless,/area/space) -"ch" = (/obj/effect/floor_decal/industrial/warning{dir = 5},/turf/simulated/floor/airless,/area/space) -"ci" = (/obj/effect/floor_decal/industrial/warning{dir = 8},/turf/simulated/floor/airless,/area/space) -"cj" = (/turf/simulated/floor/airless,/area/space) -"ck" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor/airless,/area/space) -"cl" = (/obj/effect/gibspawner/human,/turf/simulated/floor/airless,/area/space) -"cm" = (/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor/airless,/area/space) -"cn" = (/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor/airless,/area/space) -"co" = (/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor/airless,/area/space) +"ca" = (/obj/effect/floor_decal/corner/white/diagonal,/obj/structure/closet/crate/bin,/obj/item/trash/candy/proteinbar,/turf/simulated/floor/tiled,/area/awaymission/carpfarm/base) +"cb" = (/obj/machinery/door/airlock/external{frequency = 1375; icon_state = "door_locked"; id_tag = "carp_outer"; locked = 1; name = "External Access"; req_access = newlist()},/turf/simulated/floor/plating,/area/awaymission/carpfarm/base) +"cc" = (/obj/machinery/light{dir = 1},/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) +"cd" = (/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) +"ce" = (/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1375; master_tag = "carp_airlock"; name = "exterior access button"; pixel_x = 26; pixel_y = 26; req_access = newlist()},/turf/simulated/floor/airless,/area/awaymission/carpfarm/base) +"cf" = (/obj/structure/lattice,/obj/structure/grille,/turf/space,/area/space) +"cg" = (/obj/effect/floor_decal/industrial/warning{dir = 9},/turf/simulated/floor/airless,/area/space) +"ch" = (/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/airless,/area/space) +"ci" = (/obj/effect/floor_decal/industrial/warning{dir = 5},/turf/simulated/floor/airless,/area/space) +"cj" = (/obj/effect/floor_decal/industrial/warning{dir = 8},/turf/simulated/floor/airless,/area/space) +"ck" = (/turf/simulated/floor/airless,/area/space) +"cl" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor/airless,/area/space) +"cm" = (/obj/effect/gibspawner/human,/turf/simulated/floor/airless,/area/space) +"cn" = (/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor/airless,/area/space) +"co" = (/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor/airless,/area/space) +"cp" = (/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor/airless,/area/space) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -251,17 +252,17 @@ aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalambcbcbcbcbcbcbFambxbxbxbxbxbxbxbxamamamamamamamamamakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalambcbcbGbHbIbJbKambxbxbxbLbLbxbxbxamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalambMbNbObPbQbQamambxbxbRbSbTbUbxbxamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalamamamamambVbWbXambYbxbxbZbZbxbxbxamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalalalalamcacaamamamamamamamamamamamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalaaaaaacbcccdccakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaaaaacfcgcgchaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahahaiahahacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacealalalcicjcjckalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahajahahaiahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacealalalcicjcjckalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahaiahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaalaacicjcjckaaalaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahahahahahacacacacacacacacacaaaaaaaaaaaaaaaaaeaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacealalalcicjcjckalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacealalalciclcjckalalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacahahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaaaaacmcncncoaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacahahahahahahahacacahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa -aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceaaaaaaaaaaaaaaaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacahahahahahahahahahahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalamamamamambVbWbXambYbxbxbZbZbxbxcaamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalalalalamcbcbamamamamamamamamamamamakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalaaaaaacccdcecdakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfaaaaaacgchchciaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahahaiahahacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfalalalcjckckclalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahajahahaiahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfalalalcjckckclalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacahahaiahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfaaalaacjckckclaaalaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacahahahahahacacacacacacacacacaaaaaaaaaaaaaaaaaeaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfalalalcjckckclalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfalalalcjcmckclalalalalakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacahahahacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfaaaaaacncococpaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacahahahahahahahacacahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa +aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacfaaaaaaaaaaaaaaaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacahahahahahahahahahahahahahacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacahahaiahahahajahahahaiahahacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacahahahahahahahahahahahacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa aaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakakakakakakakakakakakakakakakakakakakakakakakakakakakakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacacacacacacahahahaiahahahacacacacacacacacacacacacacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa From 31b6252f40ca0067a2829b7755875613bcf4a4a5 Mon Sep 17 00:00:00 2001 From: Poojawa Date: Tue, 20 Sep 2016 02:01:53 -0500 Subject: [PATCH 07/31] stray vulp pixel fix (#570) * Tweaks * stray pixel in torso_m --- icons/mob/human_races/r_vulpkanin.dmi | Bin 5202 -> 5193 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/human_races/r_vulpkanin.dmi b/icons/mob/human_races/r_vulpkanin.dmi index 700fc452584766b8d23ba30eee4c368633e35e30..85e2efae98c6b19fd7781134a975f4bca66cc5ae 100644 GIT binary patch delta 2923 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 Date: Tue, 20 Sep 2016 18:45:42 -0400 Subject: [PATCH 08/31] Hotfix to give the RD EVA access again (#574) Merge forced due to Travis being dumb. --- code/game/jobs/job/science.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 891ecc2715..2b2373a719 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -15,11 +15,11 @@ access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva) //VORESTATION EDIT minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva)) //VORESTATION EDIT alt_titles = list("Research Supervisor") minimum_character_age = 25 From 92ff62c95c2a52dcdd829f691756ede6ba588f25 Mon Sep 17 00:00:00 2001 From: Spades Date: Tue, 20 Sep 2016 18:46:17 -0400 Subject: [PATCH 09/31] Moved files to a place they make sense (#575) --- code/modules/vore/weight/fitness_machines_vr.dm | 8 ++++---- .../obj/machines/fitness_machines_vr.dmi | Bin 2 files changed, 4 insertions(+), 4 deletions(-) rename code/modules/vore/weight/fit_vr.dmi => icons/obj/machines/fitness_machines_vr.dmi (100%) diff --git a/code/modules/vore/weight/fitness_machines_vr.dm b/code/modules/vore/weight/fitness_machines_vr.dm index 55e4d012d8..878008e5e4 100644 --- a/code/modules/vore/weight/fitness_machines_vr.dm +++ b/code/modules/vore/weight/fitness_machines_vr.dm @@ -1,6 +1,6 @@ /obj/machinery/workout name = "fitness lifter" - icon = 'code/modules/vore/weight/fit_vr.dmi' + icon = 'icons/obj/machines/fitness_machines_vr.dmi' icon_state = "fitnesslifter" //Sprites ripped from goon. desc = "A utility often used to lose weight." anchored = 1 @@ -49,7 +49,7 @@ /obj/machinery/punching_bag name = "punching bag" - icon = 'code/modules/vore/weight/fit_vr.dmi' + icon = 'icons/obj/machines/fitness_machines_vr.dmi' icon_state = "punchingbag" desc = "A bag often used to releive stress and burn fat." anchored = 1 @@ -84,7 +84,7 @@ /obj/machinery/punching_clown name = "clown punching bag" - icon = 'code/modules/vore/weight/fit_vr.dmi' + icon = 'icons/obj/machines/fitness_machines_vr.dmi' icon_state = "bopbag" desc = "A bag often used to releive stress and burn fat. It has a clown on the front of it." anchored = 0 @@ -122,7 +122,7 @@ /obj/machinery/scale name = "scale" - icon = 'code/modules/vore/weight/fit_vr.dmi' + icon = 'icons/obj/machines/fitness_machines_vr.dmi' icon_state = "scale" desc = "A scale used to measure ones weight relative to their size and species." anchored = 1 // Set to 0 when we can construct or dismantle these. diff --git a/code/modules/vore/weight/fit_vr.dmi b/icons/obj/machines/fitness_machines_vr.dmi similarity index 100% rename from code/modules/vore/weight/fit_vr.dmi rename to icons/obj/machines/fitness_machines_vr.dmi From 670f3bde87d1df6fde873b10440bdf77afb8f69e Mon Sep 17 00:00:00 2001 From: Spades Date: Tue, 20 Sep 2016 18:46:34 -0400 Subject: [PATCH 10/31] Removed broken gateway map from list --- maps/RandomZLevels/fileList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maps/RandomZLevels/fileList.txt b/maps/RandomZLevels/fileList.txt index a10ea9b12f..b3f491236f 100644 --- a/maps/RandomZLevels/fileList.txt +++ b/maps/RandomZLevels/fileList.txt @@ -6,7 +6,7 @@ #maps/RandomZLevels/awaymission.dmm #maps/RandomZLevels/labyrinth.dmm #Broken still. -maps/RandomZLevels/snowfield.dmm +#maps/RandomZLevels/snowfield.dmm #Broken. maps/RandomZLevels/carpfarm.dmm maps/RandomZLevels/listeningpost.dmm maps/RandomZLevels/blackmarketpackers.dmm From 5c2f904eb3e3ecf269c8909c2b92c324dc82ed15 Mon Sep 17 00:00:00 2001 From: killer653 Date: Tue, 20 Sep 2016 21:20:05 -0400 Subject: [PATCH 11/31] AHHHHHHHHHHHHHH COMPILE FIX --- code/game/jobs/job/science.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 2b2373a719..3fb3de5c42 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -19,7 +19,7 @@ minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva)) //VORESTATION EDIT + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva) //VORESTATION EDIT alt_titles = list("Research Supervisor") minimum_character_age = 25 From 5c7f6f98635fa0814e0e566cc12d419907a8455d Mon Sep 17 00:00:00 2001 From: Spades Date: Fri, 23 Sep 2016 00:56:52 -0400 Subject: [PATCH 12/31] Fixes contraband crate (#580) --- code/datums/supplypacks/contraband_vr.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/datums/supplypacks/contraband_vr.dm b/code/datums/supplypacks/contraband_vr.dm index 7254c45719..b419b210fa 100644 --- a/code/datums/supplypacks/contraband_vr.dm +++ b/code/datums/supplypacks/contraband_vr.dm @@ -4,4 +4,5 @@ cost = 150 containertype = /obj/structure/closet/crate containername = "Stolen crate" - contraband = 1 \ No newline at end of file + contraband = 1 + group = "Supplies" \ No newline at end of file From 28175d86c7f8f78a57b8a2a5d46cdb869523d13c Mon Sep 17 00:00:00 2001 From: Cameron653 Date: Sat, 24 Sep 2016 14:12:43 -0400 Subject: [PATCH 13/31] Late September Sync (#579) * Elevators aren't bottomless voids! * Updates changelog * Sombrero Code * Fixes #2365 * Adds changelog * Sleeper is evil. * no message * Changelog * Stops observers from leaving prints on the ground. No more spooking the mortals, ghosts. * Allows autotraitor in secret to start with 0 players * Adds changelog * Makes diona slightly less slow * Adds changelog * Bowling Shirts * Updates changelog * Adds a missing description * Flat Cap Changes and Hair Bow * Fixed Error * Adds an in-hand * Lower Torso cannot be amputated * Smoke works, adds changelog * Updates changelog * Makes Unathi Voidsuits Less Fat * Medical related fixes * Fuzzy Cuffs * Tube Top * Made Icons for Security Suit Less Gaunt * Revert "Medical related fixes" This reverts commit d7c59520e626dc2cebd6ec8dbd89d6ca94ad661f. * Just the fix to random med item now * Adds organ fixing * Fixes Evening Glove Coloring * HAZMAT Suits * Changes Unathi sprite slightly * Tweaks skirt pathing * Corrects changelog * Adds changelog * Construction Voidsuits * makes people bleed real good * adderino changeling * Biohazard Voidsuit * Revert "Revert "Adds hub passwordu"" * Explosive implants should no longer gib on limbs. * Adds space penguins and space geese. * Revert "Revert "Revert "Adds hub passwordu""" * Makes flash rounds respect eye protection * Water > Fire * There's plenty lying around, I think * Naming inconsistencies fixed The short naming of central command has been really inconsistent across the game's files. This has always annoyed the shit out of me. CentComm and Centcomm and Centcom are now all CentCom, specifically with that capitalization. Why one M instead of two M's? Because Comm with two 'M's = Communications. Hence, Telecomms, NOT Telecoms. Telecoms is incorrect. CentCom was also chosen because CentCom with one M and this casing is most found throughout the game's files. Speaking of Telecomms, I corrected one instance in the game where it's Telecom. Like I said, this is not correct. There was only one inconsistency. Likewise, Nanotrasen has been changed to NanoTrasen. Nanotrasen only appears 20 times, where NanoTrasen appears 62. NanoTrasen is clearly the preferred, correct naming. * Almost forgot plural of Telecomm * Finalizes work, adds designs to research. * Press Vest * Removes Mags/Shells, Adds Recorder and Flashlight * Fixes spans. * Raises the number of players needed to start Ninja * Still needs to fix internal bleeding * Allows Wirer To Attach to Toolbelts * Fixes #393 * Tweaks FBP temperature * Corrects Changelog * Fixes some Advanced Egun oversights * Embiggens the laser carbine and the lasercannon. * Messenger Bags * Health analyzers detect appendicitis * Custom Circuit Additions & Fixes Adds Med Scanner and Advanced Med Scanner circuits. Clock circuit is now functional. Five second delay will delay for five seconds and not one second. Renaming circuitry now respects ability to do so (e.g. being alive). Firing circuit can now be obtained by science normally. Examining inside assembly cases now requires adjacency. * More Additions You can now cancel inputting on a text or numberpad. Zero is now displayed properly on the UI and not be shown as null. The small and medium assemblies now have real sprites. Total health percentage for med scanners and advanced med scanners now reports a proper percentage and not 1 or 0. The constant memory chip now can be set by using it in hand, making it usable. The constant memory chip now accepts refs as data to store. To use, select 'ref' when using inhand, then hit it against the thing you want to store. * Allows Chemists to View Medical Records on their PDA * Refactors splinting * Refactors the forceMove() drop. Makes dropping a its proc instead, cleaning up forceMove() handling. * Replaces ORGAN_SPLINTED * Supportive suits now only loop through bad organs * Adds changelog * Lasercannon tweaks * Bloodloss tweak * Adds hawaii shirt Attachable to any uniform, works like suit jackets. * Changelog cause why not At this rate I'll forget how to do those otherwise * Adds randomized alohas Also some color matrix helpers from TG * Appendicitis doesn't cancel itself out. * Removes debug stuff * Radsuit Sprite Changes * Allows us to actually use the messenger bags * Fixes spelling mistake * Ported ventcrawling from vg. * Fixes changelog errors * Updates changelog * Tweaks vent crawling. The ability to ventcrawl is now checked by the /handle_ventcrawl() proc, making it possible to properly check before and after the do_after() call. Moves various checks into the base can_ventcrawl proc. Now lists the first object that prevents a mob from ventcrawling, making it easier to correct the exception list. Removes the issmall() check, instead checks if the crawling mob has the relevant verb. Fixes #14081. * Suit Storage Items * Adds in IB removal * More Circuit Things Adds Locomotion circuit, which makes the machine move in a given direction. Adds Signaler circuit, which can send and receive signals from a signaler. Adds a new tool, the Debugger, which lets one directly set data in a specific pin. It can also pulse activation pins. Adds ability to define custom cooldown times for each component. Smoke generator now has a 30 second cooldown. Cleans up some code somewhat. * Adds design for locomotion circuit. * Cleans up code * Even more sprites by Mechoid. Fixes abs to rel converter. * Black Messenger Bag * Powersink fix * Even More Sodding Circuits Adds new RNG circuit, to make random numbers each time. Adds new Concatenating circuit, so you can make lots of small strings into one big one. Adds new light and advanced light circuit. Basic just has a normal light that can be toggled. Advanced allows it to be any color using RGB, and a brightness between 0 and 6. New sprites for the debugger and wirer, by Mechoid. Hopefully finally fixes smoke generator from being unobtainable. * Adds basic circuit kit and spare circuit tools to Tech Storage. * Part the first * Changelog * Allows robots to be constructed with prosthetic limbs as well as borg limbs. * Map change * Secbelt can hold stun revolvers and eguns * Voidsuit Sprite Changes * Tweaks burst laser * Lasers, energy projectiles, and muzzle flashes now produce light. It's a bit wonky due to lighting only updating once every half-second, but it's very much functional, at least on my desktop. * Adds bridge bunnies * Slightly cleans up the occupation screen, adds uniform to locker * Map Changes * Adds Changelog * Fixes stuff * Allows jobbanning of cargo department jobs * Re-adds balance changes to heavy lasers. They got changed by accident when I did the laser light show. Also, adds changelogs for my last couple changes, because I'm an idiot and forgot them. * Fixed missing sprite * Dress Loadout Additions * I Can't Believe It's Not Circuits (it is) Fixes numberpad and letterpad pulsing. Debugger and Constant chip can now have null written to it. Adds new sound output, with two types so far. One being the 'beeper' type, which can do things like buzz, ping, beep, etc. The second type is a securitron speaker, which allows us to get closer to building a functioning Beepsky. * Adds EPv2 Circuit Adds a circuit that allows it to send and receive EPv2 messages, allowing for a more robust transmission of data that signalers cannot deliver. Bonus: Communicators can send text messages to custom machines using this. * Updates changelog * Fixes not being able to put things in medkits. * Technomancer Tweaks Cost for various spells and equipment adjusted greatly. In general, things are cheaper, and everything should now be in multiples of 25, so no points are wasted. The default jumpsuit for Technomancers is now heavily insulated, protecting them from tasers, batons, and perhaps unfortunate lightning strikes. Instability between 31 and 50 made less harsh. Wards made with a scepter of enhancement will break the cloak of anyone invisible that it can see. Fire aura buffed, increased rate of heating as well as temperature cap for both non-scepter and scepter effects. Reflect spell made more forgiving for the Technomancer, lasting longer before expiring. Projectile spells should be able to hit people more reliably. * Shotgun Reloading Tweak Adds ability to hit a shotgun or similar weapon with a container containing ammo, to load said ammo into the shotgun one at a time automatically, instead of having to play inventory tetris, as requested by some people. * Use sanitizeName for the guest pass terminal name input to prevent excessively long names. * Circuit UI and Assembly Tweaks Adds new drone assembly, which has stats between the medium and large assembly. Sprites by Mechoid. Assemblies now have a light UI when examined while opened, which displays what's inside, as well as how close to the cap for parts or complexity you are getting. Click the names of a component to open the wiring interface for that component. You can also rename each component from the UI. Bonus: Having multiple components of the same name will no longer appear as one component. Adds ability to rename the assembly, using the new UI. * Revert "Ported ventcrawling from vg." * Re-adds a nice, useful macro * Fixes #2431 * Tweaks Riot armor * Fixes a typo in the DNA Modifier * Ripped Jeans (And White Shorts) * Adds shanking * Adds changelog * Removes a stray world << * Ported ventcrawling from vg. * Tweaks vent crawling. The ability to ventcrawl is now checked by the /handle_ventcrawl() proc, making it possible to properly check before and after the do_after() call. Moves various checks into the base can_ventcrawl proc. Now lists the first object that prevents a mob from ventcrawling, making it easier to correct the exception list. Removes the issmall() check, instead checks if the crawling mob has the relevant verb. Fixes #14081. * Long, time-consuming not one-line fix * Makes cigs branded too Description of cig/cigbutt would reveal its brand for dastardly murdersolving revelations. * Adding a article * The door hacker now only pings the user * Removes implants from Deathsquad * Adds the ability to apply pressure to bleeding wounds * Shoes * EVA rigs should use their default sprites on Taj and Unathi * Fixing some errors * Update loadout_xeno.dm * Delete back_vr.dmi * Add files via upload --- code/ATMOSPHERICS/atmospherics.dm | 2 + .../binary_devices/binary_atmos_base.dm | 3 - .../components/binary_devices/pipeturbine.dm | 3 - .../trinary_devices/trinary_base.dm | 2 - code/ATMOSPHERICS/components/tvalve.dm | 2 - code/ATMOSPHERICS/components/valve.dm | 2 - code/ATMOSPHERICS/pipes.dm | 11 - code/__defines/damage_organs.dm | 5 +- code/_helpers/global_lists.dm | 2 +- code/_helpers/matrices.dm | 98 ++++ code/_helpers/mobs.dm | 6 +- code/_macros.dm | 3 + code/controllers/shuttle_controller.dm | 2 +- code/datums/ai_law_sets.dm | 4 +- code/datums/locations/nyx.dm | 8 +- code/datums/locations/vir.dm | 2 +- code/game/antagonist/outsider/deathsquad.dm | 2 +- code/game/antagonist/outsider/mercenary.dm | 1 + code/game/antagonist/outsider/wizard.dm | 1 + code/game/area/Space Station 13 areas.dm | 58 +- code/game/atoms.dm | 25 +- code/game/atoms_movable.dm | 34 +- code/game/dna/dna_modifier.dm | 2 +- code/game/gamemodes/cult/runes.dm | 15 + code/game/gamemodes/newobjective.dm | 2 +- code/game/gamemodes/ninja/ninja.dm | 4 +- code/game/gamemodes/technomancer/clothing.dm | 11 +- .../devices/disposable_teleporter.dm | 2 +- .../technomancer/devices/shield_armor.dm | 2 +- .../technomancer/devices/tesla_armor.dm | 2 +- code/game/gamemodes/technomancer/equipment.dm | 20 +- .../gamemodes/technomancer/instability.dm | 12 +- .../technomancer/spells/abjuration.dm | 2 +- .../technomancer/spells/apportation.dm | 2 +- .../technomancer/spells/audible_deception.dm | 2 +- .../technomancer/spells/aura/biomed_aura.dm | 2 +- .../technomancer/spells/aura/fire_aura.dm | 10 +- .../technomancer/spells/aura/frost_aura.dm | 2 +- .../technomancer/spells/aura/shock_aura.dm | 2 +- .../gamemodes/technomancer/spells/blink.dm | 2 +- .../gamemodes/technomancer/spells/control.dm | 2 +- .../technomancer/spells/energy_siphon.dm | 2 +- .../technomancer/spells/flame_tongue.dm | 2 +- .../gamemodes/technomancer/spells/illusion.dm | 2 +- .../technomancer/spells/insert/corona.dm | 2 +- .../technomancer/spells/insert/mend_organs.dm | 2 +- .../spells/insert/repel_missiles.dm | 2 +- .../technomancer/spells/instability_tap.dm | 2 +- .../technomancer/spells/mark_recall.dm | 4 +- .../technomancer/spells/oxygenate.dm | 2 +- .../technomancer/spells/phase_shift.dm | 2 +- .../technomancer/spells/projectile/beam.dm | 2 +- .../spells/projectile/force_missile.dm | 2 +- .../spells/projectile/overload.dm | 2 +- .../spells/projectile/projectile.dm | 3 +- .../gamemodes/technomancer/spells/radiance.dm | 2 +- .../gamemodes/technomancer/spells/reflect.dm | 8 +- .../gamemodes/technomancer/spells/shield.dm | 2 +- .../technomancer/spells/spawner/darkness.dm | 2 +- .../technomancer/spells/spawner/pulsar.dm | 2 +- .../spells/summon/summon_creature.dm | 2 +- .../technomancer/spells/summon/summon_ward.dm | 9 +- .../technomancer/spells/targeting_matrix.dm | 2 +- .../technomancer/spells/warp_strike.dm | 2 +- .../gamemodes/technomancer/technomancer.dm | 4 +- code/game/jobs/access.dm | 5 + code/game/jobs/job/assistant.dm | 1 + code/game/jobs/job/captain.dm | 38 +- code/game/jobs/job/civilian.dm | 4 + code/game/jobs/job/engineering.dm | 3 + code/game/jobs/job/job.dm | 1 + code/game/jobs/job/medical.dm | 6 + code/game/jobs/job/science.dm | 3 + code/game/jobs/job/security.dm | 4 + code/game/jobs/jobs.dm | 4 +- code/game/machinery/adv_med.dm | 4 +- code/game/machinery/camera/tracking.dm | 2 +- .../game/machinery/computer/communications.dm | 6 +- code/game/machinery/computer/guestpass.dm | 2 +- .../computer3/computers/communications.dm | 10 +- code/game/machinery/computer3/file.dm | 4 +- code/game/machinery/computer3/lapvend.dm | 4 +- code/game/machinery/frame.dm | 101 +++- code/game/machinery/suit_storage_unit.dm | 17 +- code/game/machinery/telecomms/presets.dm | 14 +- .../effects/decals/posters/tgposters.dm | 4 +- code/game/objects/items/devices/PDA/cart.dm | 1 + code/game/objects/items/devices/hacktool.dm | 2 +- code/game/objects/items/devices/powersink.dm | 2 +- code/game/objects/items/devices/scanners.dm | 15 +- code/game/objects/items/stacks/medical.dm | 26 +- .../objects/items/weapons/cigs_lighters.dm | 3 + .../objects/items/weapons/storage/backpack.dm | 59 +++ .../objects/items/weapons/storage/belt.dm | 3 + .../objects/items/weapons/storage/fancy.dm | 12 + .../objects/items/weapons/storage/toolbox.dm | 4 +- .../structures/crates_lockers/closets.dm | 3 + .../crates_lockers/closets/wardrobe.dm | 4 + .../structures/crates_lockers/crates.dm | 2 +- code/global.dm | 2 +- code/modules/admin/topic.dm | 37 +- code/modules/admin/verbs/pray.dm | 4 +- .../preference_setup/general/04_equipment.dm | 2 +- .../loadout/loadout_accessories.dm | 14 +- .../preference_setup/loadout/loadout_shoes.dm | 20 + .../loadout/loadout_uniform.dm | 18 +- .../preference_setup/loadout/loadout_xeno.dm | 2 +- .../preference_setup/occupation/occupation.dm | 2 +- code/modules/clothing/head/misc.dm | 2 +- code/modules/clothing/shoes/jobs.dm | 9 +- code/modules/clothing/shoes/miscellaneous.dm | 12 + .../clothing/spacesuits/rig/suits/station.dm | 15 +- .../modules/clothing/spacesuits/spacesuits.dm | 28 +- .../clothing/spacesuits/void/station.dm | 14 +- code/modules/clothing/suits/armor.dm | 7 +- code/modules/clothing/suits/miscellaneous.dm | 11 + code/modules/clothing/suits/utility.dm | 1 - .../clothing/under/accessories/clothing.dm | 18 +- code/modules/clothing/under/miscellaneous.dm | 7 + code/modules/clothing/under/pants.dm | 25 + code/modules/clothing/under/shorts.dm | 4 + code/modules/economy/TradeDestinations.dm | 2 +- code/modules/examine/descriptions/devices.dm | 2 +- .../modules/examine/descriptions/telecomms.dm | 2 +- code/modules/games/cards.dm | 2 +- .../integrated_electronics/_defines.dm | 387 ++++++++++++++ .../integrated_electronics/arithmetic.dm | 183 +++++++ .../integrated_electronics/assemblies.dm | 168 ++++++ .../integrated_electronics/converters.dm | 133 +++++ .../integrated_electronics/coordinate.dm | 75 +++ .../integrated_electronics/data_transfer.dm | 79 +++ .../integrated_electronics/input_output.dm | 494 ++++++++++++++++++ code/modules/integrated_electronics/logic.dm | 172 ++++++ .../integrated_electronics/manipulation.dm | 158 ++++++ code/modules/integrated_electronics/memory.dm | 101 ++++ code/modules/integrated_electronics/time.dm | 144 +++++ code/modules/integrated_electronics/tools.dm | 227 ++++++++ code/modules/mob/holder.dm | 5 + code/modules/mob/inventory.dm | 21 +- code/modules/mob/living/bot/cleanbot.dm | 10 +- code/modules/mob/living/bot/ed209bot.dm | 2 +- code/modules/mob/living/bot/farmbot.dm | 12 + code/modules/mob/living/bot/floorbot.dm | 2 +- code/modules/mob/living/bot/medbot.dm | 23 + code/modules/mob/living/bot/secbot.dm | 24 +- .../mob/living/carbon/carbon_defense.dm | 77 ++- .../mob/living/carbon/human/examine.dm | 23 +- code/modules/mob/living/carbon/human/human.dm | 2 +- .../living/carbon/human/human_attackhand.dm | 37 +- .../mob/living/carbon/human/human_defense.dm | 29 +- .../mob/living/carbon/human/human_defines.dm | 3 +- .../mob/living/carbon/human/human_movement.dm | 4 +- .../mob/living/carbon/human/human_organs.dm | 4 +- code/modules/mob/living/carbon/human/life.dm | 6 +- .../mob/living/carbon/human/stripping.dm | 12 +- .../mob/living/carbon/human/update_icons.dm | 3 + .../mob/living/carbon/metroid/metroid.dm | 5 - code/modules/mob/living/living.dm | 122 +---- code/modules/mob/living/living_powers.dm | 10 - code/modules/mob/living/silicon/ai/ai.dm | 2 +- code/modules/mob/living/silicon/ai/icons.dm | 2 +- .../modules/mob/living/silicon/robot/robot.dm | 2 + .../living/simple_animal/friendly/penguin.dm | 19 + .../mob/living/simple_animal/hostile/goose.dm | 34 ++ code/modules/mob/mob.dm | 2 +- code/modules/mob/mob_grab.dm | 6 +- code/modules/mob/new_player/new_player.dm | 2 +- .../mob/new_player/preferences_setup.dm | 2 +- code/modules/multiz/pipes.dm | 3 - code/modules/organs/blood.dm | 14 +- code/modules/organs/internal/appendix.dm | 2 +- code/modules/organs/organ.dm | 1 - code/modules/organs/organ_external.dm | 65 ++- code/modules/paperwork/adminpaper.dm | 2 +- code/modules/paperwork/faxmachine.dm | 6 +- code/modules/projectiles/effects.dm | 95 +++- code/modules/projectiles/gun.dm | 70 +++ code/modules/projectiles/guns/energy/laser.dm | 7 +- .../projectiles/guns/energy/nuclear.dm | 17 +- code/modules/projectiles/guns/projectile.dm | 18 + code/modules/projectiles/projectile.dm | 4 + .../modules/projectiles/projectile/animate.dm | 3 + code/modules/projectiles/projectile/beams.dm | 24 +- code/modules/projectiles/projectile/energy.dm | 23 +- .../modules/projectiles/projectile/special.dm | 13 + .../Chemistry-Reagents-Core.dm | 4 +- code/modules/research/designs.dm | 421 +++++++++++++++ .../scripting/Implementations/Telecomms.dm | 2 +- code/modules/shuttles/shuttle_ferry.dm | 8 +- code/modules/surgery/bones.dm | 1 - code/modules/vehicles/vehicle.dm | 2 + code/modules/ventcrawl/ventcrawl.dm | 185 +++++++ .../ventcrawl/ventcrawl_atmospherics.dm | 86 +++ code/modules/ventcrawl/ventcrawl_multiz.dm | 24 + code/modules/ventcrawl/ventcrawl_verb.dm | 7 + code/unit_tests/zas_tests.dm | 6 +- html/changelog.html | 44 ++ html/changelogs/HarpyEagle-Bleeding.yml | 6 + html/changelogs/Yoshax-Shanking.yml | 36 ++ html/changelogs/zuhayr-vent.yml | 5 + icons/mob/animal.dmi | Bin 203944 -> 206319 bytes icons/mob/back.dmi | Bin 81937 -> 85974 bytes icons/mob/back_vr.dmi | Bin 427 -> 424 bytes icons/mob/items/lefthand_shoes.dmi | Bin 1993 -> 2121 bytes icons/mob/items/righthand_shoes.dmi | Bin 2082 -> 2203 bytes icons/obj/electronic_assemblies.dmi | Bin 0 -> 23986 bytes icons/obj/gun.dmi | Bin 58990 -> 58691 bytes icons/obj/storage.dmi | Bin 69984 -> 72096 bytes maps/RandomZLevels/stationCollision.dm | 205 ++++++++ sound/machines/ventcrawl.ogg | Bin 0 -> 40591 bytes vorestation.dme | 18 + 211 files changed, 4812 insertions(+), 518 deletions(-) create mode 100644 code/modules/integrated_electronics/_defines.dm create mode 100644 code/modules/integrated_electronics/arithmetic.dm create mode 100644 code/modules/integrated_electronics/assemblies.dm create mode 100644 code/modules/integrated_electronics/converters.dm create mode 100644 code/modules/integrated_electronics/coordinate.dm create mode 100644 code/modules/integrated_electronics/data_transfer.dm create mode 100644 code/modules/integrated_electronics/input_output.dm create mode 100644 code/modules/integrated_electronics/logic.dm create mode 100644 code/modules/integrated_electronics/manipulation.dm create mode 100644 code/modules/integrated_electronics/memory.dm create mode 100644 code/modules/integrated_electronics/time.dm create mode 100644 code/modules/integrated_electronics/tools.dm create mode 100644 code/modules/mob/living/simple_animal/friendly/penguin.dm create mode 100644 code/modules/mob/living/simple_animal/hostile/goose.dm create mode 100644 code/modules/ventcrawl/ventcrawl.dm create mode 100644 code/modules/ventcrawl/ventcrawl_atmospherics.dm create mode 100644 code/modules/ventcrawl/ventcrawl_multiz.dm create mode 100644 code/modules/ventcrawl/ventcrawl_verb.dm create mode 100644 html/changelogs/HarpyEagle-Bleeding.yml create mode 100644 html/changelogs/Yoshax-Shanking.yml create mode 100644 html/changelogs/zuhayr-vent.yml create mode 100644 icons/obj/electronic_assemblies.dmi create mode 100644 maps/RandomZLevels/stationCollision.dm create mode 100644 sound/machines/ventcrawl.ogg diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 7acf465b3e..b5d4df814e 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -29,6 +29,8 @@ Pipelines + Other Objects -> Pipe network var/pipe_color var/global/datum/pipe_icon_manager/icon_manager + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 /obj/machinery/atmospherics/New() if(!icon_manager) diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm index 37985034b1..2ccfe0f2e8 100644 --- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm +++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm @@ -6,9 +6,6 @@ obj/machinery/atmospherics/binary var/datum/gas_mixture/air1 var/datum/gas_mixture/air2 - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/datum/pipe_network/network1 var/datum/pipe_network/network2 diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm index 0eb342479d..5768def1ec 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm @@ -17,9 +17,6 @@ var/dP = 0 - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/datum/pipe_network/network1 var/datum/pipe_network/network2 diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm index 3f5d66f262..fa066d978f 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm @@ -7,8 +7,6 @@ obj/machinery/atmospherics/trinary var/datum/gas_mixture/air2 var/datum/gas_mixture/air3 - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 var/obj/machinery/atmospherics/node3 var/datum/pipe_network/network1 diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm index 963a4f5009..f93970a93f 100644 --- a/code/ATMOSPHERICS/components/tvalve.dm +++ b/code/ATMOSPHERICS/components/tvalve.dm @@ -12,8 +12,6 @@ var/state = 0 // 0 = go straight, 1 = go to side // like a trinary component, node1 is input, node2 is side output, node3 is straight output - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 var/obj/machinery/atmospherics/node3 var/datum/pipe_network/network_node1 diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm index 6e43afd78e..8969523db4 100644 --- a/code/ATMOSPHERICS/components/valve.dm +++ b/code/ATMOSPHERICS/components/valve.dm @@ -12,8 +12,6 @@ var/open = 0 var/openDuringInit = 0 - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 var/datum/pipe_network/network_node1 var/datum/pipe_network/network_node2 diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index c445988c53..105aaa8c8b 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -153,9 +153,6 @@ dir = SOUTH initialize_directions = SOUTH|NORTH - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/minimum_temperature_difference = 300 var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No @@ -427,8 +424,6 @@ dir = SOUTH initialize_directions = EAST|NORTH|WEST - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 var/obj/machinery/atmospherics/node3 level = 1 @@ -687,8 +682,6 @@ dir = SOUTH initialize_directions = NORTH|SOUTH|EAST|WEST - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 var/obj/machinery/atmospherics/node3 var/obj/machinery/atmospherics/node4 @@ -1074,8 +1067,6 @@ initialize_directions = SOUTH density = 1 - var/obj/machinery/atmospherics/node1 - /obj/machinery/atmospherics/pipe/tank/New() icon_state = "air" initialize_directions = dir @@ -1238,8 +1229,6 @@ var/build_killswitch = 1 - var/obj/machinery/atmospherics/node1 - /obj/machinery/atmospherics/pipe/vent/New() initialize_directions = dir ..() diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 124be53452..3c0e190427 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -35,9 +35,8 @@ #define ORGAN_BLEEDING (1<<1) #define ORGAN_BROKEN (1<<2) #define ORGAN_DESTROYED (1<<3) -#define ORGAN_SPLINTED (1<<4) -#define ORGAN_DEAD (1<<5) -#define ORGAN_MUTATED (1<<6) +#define ORGAN_DEAD (1<<4) +#define ORGAN_MUTATED (1<<5) #define DROPLIMB_EDGE 0 #define DROPLIMB_BLUNT 1 diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 9a90a3676b..044b2264ce 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -55,7 +55,7 @@ var/global/list/skin_styles_female_list = list() //unused var/datum/category_collection/underwear/global_underwear = new() //Backpacks -var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") +var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag") var/global/list/pdachoicelist = list("Default", "Slim", "Old") var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg) diff --git a/code/_helpers/matrices.dm b/code/_helpers/matrices.dm index abb0366382..129e0d41b7 100644 --- a/code/_helpers/matrices.dm +++ b/code/_helpers/matrices.dm @@ -15,3 +15,101 @@ animate(src, transform = m120, time = speed, loops) animate(transform = m240, time = speed) animate(transform = m360, time = speed) + +//The X pixel offset of this matrix +/matrix/proc/get_x_shift() + . = c + +//The Y pixel offset of this matrix +/matrix/proc/get_y_shift() + . = f +// Color matrices: + +//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1. +#define LUMR 0.2126 +#define LUMG 0.7152 +#define LUMB 0.0722 + +//Still need color matrix addition, negation, and multiplication. + +//Returns an identity color matrix which does nothing +/proc/color_identity() + return list(1,0,0, 0,1,0, 0,0,1) + +//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites +//TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone) +/proc/color_rotation(angle) + if(angle == 0) + return color_identity() + angle = Clamp(angle, -180, 180) + var/cos = cos(angle) + var/sin = sin(angle) + + var/constA = 0.143 + var/constB = 0.140 + var/constC = -0.283 + return list( + LUMR + cos * (1-LUMR) + sin * -LUMR, LUMR + cos * -LUMR + sin * constA, LUMR + cos * -LUMR + sin * -(1-LUMR), + LUMG + cos * -LUMG + sin * -LUMG, LUMG + cos * (1-LUMG) + sin * constB, LUMG + cos * -LUMG + sin * LUMG, + LUMB + cos * -LUMB + sin * (1-LUMB), LUMB + cos * -LUMB + sin * constC, LUMB + cos * (1-LUMB) + sin * LUMB + ) + +//Makes everything brighter or darker without regard to existing color or brightness +/proc/color_brightness(power) + power = Clamp(power, -255, 255) + power = power/255 + + return list(1,0,0, 0,1,0, 0,0,1, power,power,power) + +/var/list/delta_index = list( + 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, + 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, + 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, + 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, + 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, + 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, + 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, + 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, + 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, + 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, + 10.0) + +//Exxagerates or removes brightness +/proc/color_contrast(value) + value = Clamp(value, -100, 100) + if(value == 0) + return color_identity() + + var/x = 0 + if (value < 0) + x = 127 + value / 100 * 127; + else + x = value % 1 + if(x == 0) + x = delta_index[value] + else + x = delta_index[value] * (1-x) + delta_index[value+1] * x//use linear interpolation for more granularity. + x = x * 127 + 127 + + var/mult = x / 127 + var/add = 0.5 * (127-x) / 255 + return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add) + +//Exxagerates or removes colors +/proc/color_saturation(value as num) + if(value == 0) + return color_identity() + value = Clamp(value, -100, 100) + if(value > 0) + value *= 3 + var/x = 1 + value / 100 + var/inv = 1 - x + var/R = LUMR * inv + var/G = LUMG * inv + var/B = LUMB * inv + + return list(R + x,R,R, G,G + x,G, B,B,B + x) + +#undef LUMR +#undef LUMG +#undef LUMB \ No newline at end of file diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 8a1df2059b..70456bee77 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -158,7 +158,7 @@ Proc for attack log creation, because really why not else return pick("chest", "groin") -/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1) +/proc/do_mob(mob/user , mob/target, time = 30, target_zone = 0, uninterruptible = 0, progress = 1) if(!user || !target) return 0 var/user_loc = user.loc @@ -194,6 +194,10 @@ Proc for attack log creation, because really why not . = 0 break + if(target_zone && user.zone_sel.selecting != target_zone) + . = 0 + break + if (progbar) qdel(progbar) diff --git a/code/_macros.dm b/code/_macros.dm index 06376205d1..5b94c872cb 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -1,4 +1,5 @@ #define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x)) + #define CLAMP01(x) (Clamp(x, 0, 1)) #define get_turf(A) get_step(A,0) @@ -42,3 +43,5 @@ #define isxeno(A) istype(A, /mob/living/simple_animal/xeno) #define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") + +#define to_chat(target, message) target << message diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 35ef52ff81..7a0deaf799 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -209,7 +209,7 @@ var/global/datum/shuttle_controller/shuttle_controller shuttle.docking_controller_tag = "centcom_shuttle" shuttle.dock_target_station = "centcom_shuttle_dock_airlock" shuttle.dock_target_offsite = "centcom_shuttle_bay" - shuttles["Centcom"] = shuttle + shuttles["CentCom"] = shuttle process_shuttles += shuttle shuttle = new() diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm index 50e05948d5..e2c5161d6d 100644 --- a/code/datums/ai_law_sets.dm +++ b/code/datums/ai_law_sets.dm @@ -10,7 +10,7 @@ add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") ..() -/******************** Nanotrasen/Malf ********************/ +/******************** NanoTrasen/Malf ********************/ /datum/ai_laws/nanotrasen name = "NT Default" selectable = 1 @@ -30,7 +30,7 @@ set_zeroth_law(config.law_zero) ..() -/************* Nanotrasen Aggressive *************/ +/************* NanoTrasen Aggressive *************/ /datum/ai_laws/nanotrasen_aggressive name = "NT Aggressive" selectable = 1 diff --git a/code/datums/locations/nyx.dm b/code/datums/locations/nyx.dm index 35d79243b2..33df619660 100644 --- a/code/datums/locations/nyx.dm +++ b/code/datums/locations/nyx.dm @@ -43,15 +43,15 @@ /datum/locations/exodus name = "NSS Exodus" - desc = "A highly profitable research, mining, and supply dock for Nanotrasen that serves as one of their many facilities in exploiting the \ + desc = "A highly profitable research, mining, and supply dock for NanoTrasen that serves as one of their many facilities in exploiting the \ wonders of phoron. It is currently orbiting around Erebus and maintains close contact with the NAS Crescent. The station itself has been \ - a target for a large number of Mercenaries and other companies wishing to steal Nanotrasen's secrets." + a target for a large number of Mercenaries and other companies wishing to steal NanoTrasen's secrets." /datum/locations/crescent name = "NAS Crescent" - desc = "The main hub for Nanotrasen in the Nyx system and is commonly referred to it by their workers as central command or \"Centcomm\". \ + desc = "The main hub for NanoTrasen in the Nyx system and is commonly referred to it by their workers as central command or \"CentCom\". \ The Crescent refines and stores much of the products that stations (such as the Exodus) bring in. It is also a large refueling and supply \ - station of phoron and tritium in the Nyx system due to Nanotrasen being able to outsell almost any other company." + station of phoron and tritium in the Nyx system due to NanoTrasen being able to outsell almost any other company." /datum/locations/emerald_habitation name = "Emerald Habitation" diff --git a/code/datums/locations/vir.dm b/code/datums/locations/vir.dm index f750fc4c85..377ecc9b03 100644 --- a/code/datums/locations/vir.dm +++ b/code/datums/locations/vir.dm @@ -49,7 +49,7 @@ /datum/locations/northern_star //Inception joke here name = "Northern Star" - desc = "The Northern Star is an asteroid colony owned and operated by Nanotrasen, among many other asteroid installations. \ + desc = "The Northern Star is an asteroid colony owned and operated by NanoTrasen, among many other asteroid installations. \ Originally conceived as 'just another pitstop' for weary asteroid miners, it has grown to become a significant installation in the Kara subsystem." /datum/locations/northern_star/New(var/creator) diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index 1234bdb1f6..c7e1d01094 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -49,7 +49,7 @@ var/datum/antagonist/deathsquad/deathsquad player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand) player.equip_to_slot_or_del(new /obj/item/weapon/rig/ert/assetprotection(player), slot_back) player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store) - player.implant_loyalty() +// player.implant_loyalty() var/obj/item/weapon/card/id/id = create_id("Asset Protection", player) if(id) diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm index c27d510d8b..f4d92e4261 100644 --- a/code/game/antagonist/outsider/mercenary.dm +++ b/code/game/antagonist/outsider/mercenary.dm @@ -41,6 +41,7 @@ var/datum/antagonist/mercenary/mercs if(player.backbag == 2) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(player), slot_back) if(player.backbag == 3) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(player), slot_back) if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(player), slot_back) + if(player.backbag == 5) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(player), slot_back) player.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(player.back), slot_in_backpack) player.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(player), slot_in_backpack) player.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm index 14e5f90063..b88af1b1b9 100644 --- a/code/game/antagonist/outsider/wizard.dm +++ b/code/game/antagonist/outsider/wizard.dm @@ -83,6 +83,7 @@ var/datum/antagonist/wizard/wizards if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(wizard_mob), slot_back) if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back) + if(wizard_mob.backbag == 5) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 7b97481965..0a75438480 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -166,7 +166,7 @@ area/space/atmosalert() icon_state = "shuttle2" /area/shuttle/escape/centcom - name = "\improper Emergency Shuttle Centcom" + name = "\improper Emergency Shuttle CentCom" icon_state = "shuttle" /area/shuttle/escape/transit // the area to pass through for 3 minute transit @@ -282,6 +282,7 @@ area/space/atmosalert() /area/shuttle/cryo/station icon_state = "shuttle2" + base_turf = /turf/simulated/mineral/floor/ignore_mapgen /area/shuttle/cryo/centcom icon_state = "shuttle" @@ -290,9 +291,10 @@ area/space/atmosalert() icon_state = "shuttle" /area/shuttle/mining - name = "\improper Mining Shuttle" + name = "\improper Mining Elevator" music = "music/escape.ogg" lighting_use_dynamic = 0 + base_turf = /turf/simulated/mineral/floor/ignore_mapgen /area/shuttle/mining/station icon_state = "shuttle2" @@ -302,7 +304,7 @@ area/space/atmosalert() /area/shuttle/transport1/centcom icon_state = "shuttle" - name = "\improper Transport Shuttle Centcom" + name = "\improper Transport Shuttle CentCom" /area/shuttle/transport1/station icon_state = "shuttle" @@ -344,7 +346,7 @@ area/space/atmosalert() icon_state = "shuttlered2" /area/shuttle/administration/centcom - name = "\improper Administration Shuttle Centcom" + name = "\improper Administration Shuttle CentCom" icon_state = "shuttlered" /area/shuttle/administration/station @@ -352,7 +354,7 @@ area/space/atmosalert() icon_state = "shuttlered2" /area/shuttle/trade/centcom - name = "\improper Trade Shuttle Centcom" + name = "\improper Trade Shuttle CentCom" icon_state = "shuttlered" /area/shuttle/trade/station @@ -388,9 +390,10 @@ area/space/atmosalert() // === Trying to remove these areas: /area/shuttle/research - name = "\improper Research Shuttle" + name = "\improper Research Elevator" music = "music/escape.ogg" lighting_use_dynamic = 0 + base_turf = /turf/simulated/mineral/floor/ignore_mapgen /area/shuttle/research/station icon_state = "shuttle2" @@ -412,34 +415,34 @@ area/space/atmosalert() // CENTCOM /area/centcom - name = "\improper Centcom" + name = "\improper CentCom" icon_state = "centcom" requires_power = 0 lighting_use_dynamic = 0 /area/centcom/control - name = "\improper Centcom Control" + name = "\improper CentCom Control" /area/centcom/evac - name = "\improper Centcom Emergency Shuttle" + name = "\improper CentCom Emergency Shuttle" /area/centcom/suppy - name = "\improper Centcom Supply Shuttle" + name = "\improper CentCom Supply Shuttle" /area/centcom/ferry - name = "\improper Centcom Transport Shuttle" + name = "\improper CentCom Transport Shuttle" /area/centcom/shuttle - name = "\improper Centcom Administration Shuttle" + name = "\improper CentCom Administration Shuttle" /area/centcom/test - name = "\improper Centcom Testing Facility" + name = "\improper CentCom Testing Facility" /area/centcom/living - name = "\improper Centcom Living Quarters" + name = "\improper CentCom Living Quarters" /area/centcom/specops - name = "\improper Centcom Special Ops" + name = "\improper CentCom Special Ops" /area/centcom/creed name = "Creed's Office" @@ -455,15 +458,15 @@ area/space/atmosalert() name = "\improper Tram Station" /area/centcom/security - name = "\improper Centcom Security" + name = "\improper CentCom Security" icon_state = "centcom_security" /area/centcom/medical - name = "\improper Centcom Medical" + name = "\improper CentCom Medical" icon_state = "centcom_medical" /area/centcom/command - name = "\improper Centcom Command" //Central Command Command totally isn't RAS Syndrome in action. + name = "\improper CentCom Command" //Central Command Command totally isn't RAS Syndrome in action. icon_state = "centcom_command" /area/centcom/main_hall @@ -471,15 +474,15 @@ area/space/atmosalert() icon_state = "centcom_hallway1" /area/centcom/bar - name = "\improper Centcom Bar" + name = "\improper CentCom Bar" icon_state = "centcom_crew" /area/centcom/restaurant - name = "\improper Centcom Restaurant" + name = "\improper CentCom Restaurant" icon_state = "centcom_crew" /area/centcom/bathroom - name = "\improper Centcom Bathroom" + name = "\improper CentCom Bathroom" icon_state = "centcom_crew" //SYNDICATES @@ -2319,6 +2322,7 @@ area/space/atmosalert() name = "\improper Construction Site Shuttle" icon_state = "yellow" lighting_use_dynamic = 0 + base_turf = /turf/simulated/mineral/floor/ignore_mapgen /area/shuttle/constructionsite/station name = "\improper Construction Site Shuttle" @@ -2527,20 +2531,20 @@ area/space/atmosalert() ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') /area/tcommsat/entrance - name = "\improper Telecoms Teleporter" + name = "\improper Telecomms Teleporter" icon_state = "tcomsatentrance" /area/tcommsat/chamber - name = "\improper Telecoms Central Compartment" + name = "\improper Telecomms Central Compartment" icon_state = "tcomsatcham" /area/tcomsat - name = "\improper Telecoms Satellite" + name = "\improper Telecomms Satellite" icon_state = "tcomsatlob" ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') /area/tcomfoyer - name = "\improper Telecoms Foyer" + name = "\improper Telecomms Foyer" icon_state = "tcomsatentrance" ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') @@ -2555,7 +2559,7 @@ area/space/atmosalert() ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') /area/tcommsat/computer - name = "\improper Telecoms Control Room" + name = "\improper Telecomms Control Room" icon_state = "tcomsatcomp" /area/tcommsat/lounge @@ -2632,7 +2636,7 @@ area/space/atmosalert() requires_power = 0 /area/awaymission/spacebattle/cruiser - name = "\improper Nanotrasen Cruiser" + name = "\improper NanoTrasen Cruiser" /area/awaymission/spacebattle/syndicate1 name = "\improper Syndicate Assault Ship 1" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 33f0635015..474b2d3b25 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -463,11 +463,11 @@ its easier to just keep the beam vertical. //spawn(0) //if(I) //It's possible that it could be deleted in the meantime. var/obj/O = I - O.show_message( message, 1, blind_message, 2) + O.show_message(message, 1, blind_message, 2) else if(ismob(I)) var/mob/M = I if(M.see_invisible >= invisibility) // Cannot view the invisible - M.show_message( message, 1, blind_message, 2) + M.show_message(message, 1, blind_message, 2) else if (blind_message) M.show_message(blind_message, 2) @@ -488,7 +488,24 @@ its easier to just keep the beam vertical. spawn(0) if(I) //It's possible that it could be deleted in the meantime. var/obj/O = I - O.show_message( message, 2, deaf_message, 1) + O.show_message(message, 2, deaf_message, 1) else if(ismob(I)) var/mob/M = I - M.show_message( message, 2, deaf_message, 1) + M.show_message(message, 2, deaf_message, 1) + +/atom/movable/proc/dropInto(var/atom/destination) + while(istype(destination)) + var/atom/drop_destination = destination.onDropInto(src) + if(!istype(drop_destination) || drop_destination == destination) + return forceMove(destination) + destination = drop_destination + return forceMove(null) + +/atom/proc/onDropInto(var/atom/movable/AM) + return // If onDropInto returns null, then dropInto will forceMove AM into us. + +/atom/movable/onDropInto(var/atom/movable/AM) + return loc // If onDropInto returns something, then dropInto will attempt to drop AM there. + +/atom/proc/InsertedContents() + return contents diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e45be4bb6a..d164485f38 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -63,13 +63,35 @@ return /atom/movable/proc/forceMove(atom/destination) + if(loc == destination) + return 0 + var/is_origin_turf = isturf(loc) + var/is_destination_turf = isturf(destination) + // It is a new area if: + // Both the origin and destination are turfs with different areas. + // When either origin or destination is a turf and the other is not. + var/is_new_area = (is_origin_turf ^ is_destination_turf) || (is_origin_turf && is_destination_turf && loc.loc != destination.loc) + + var/atom/origin = loc + loc = destination + + if(origin) + origin.Exited(src, destination) + if(is_origin_turf) + for(var/atom/movable/AM in origin) + AM.Uncrossed(src) + if(is_new_area && is_origin_turf) + origin.loc.Exited(src, destination) + if(destination) - if(loc) - loc.Exited(src) - loc = destination - loc.Entered(src) - return 1 - return 0 + destination.Entered(src, origin) + if(is_destination_turf) // If we're entering a turf, cross all movable atoms + for(var/atom/movable/AM in loc) + if(AM != src) + AM.Crossed(src) + if(is_new_area && is_destination_turf) + destination.loc.Entered(src, origin) + return 1 //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, var/speed) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 56719fbce6..87971dd033 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -215,7 +215,7 @@ /obj/machinery/computer/scan_consolenew name = "DNA Modifier Access Console" - desc = "Scand DNA." + desc = "Scan DNA." icon = 'icons/obj/computer.dmi' icon_keyboard = "med_key" icon_screen = "dna" diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 91d802c8bf..8425105020 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -273,6 +273,21 @@ var/list/sacrificed = list() for (,drain>0,drain-=5) sleep(2) user.heal_organ_damage(5, 0) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + for(var/obj/item/organ/I in H.internal_organs) + if(I.damage > 0) + I.damage = max(I.damage - 5, 0) //Heals 5 damage per organ per use + if(I.damage <= 5 && I.organ_tag == O_EYES) + H.sdisabilities &= ~BLIND + for(var/obj/item/organ/E in H.bad_external_organs) + var/obj/item/organ/external/affected = E + if((affected.damage < affected.min_broken_damage * config.organ_health_multiplier) && (affected.status & ORGAN_BROKEN)) + affected.status &= ~ORGAN_BROKEN + for(var/datum/wound/W in affected.wounds) + if(istype(W, /datum/wound/internal_bleeding)) + affected.wounds -= W + affected.update_damages() return diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index e8ea12b84b..1d41289ea2 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -264,7 +264,7 @@ datum target = targeta job = joba weight = get_points(job) - explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the Centcom station alive. We'll handle the rest from there." + explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the CentCom station alive. We'll handle the rest from there." check_completion() if(!emergency_shuttle.returned()) diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index 9109d9297b..f17b693455 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -9,8 +9,8 @@ the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and \ only hope this unknown assassin isn't here for you." config_tag = "ninja" - required_players = 1 - required_players_secret = 3 + required_players = 5 + required_players_secret = 5 required_enemies = 1 end_on_antag_death = 0 antag_tags = list(MODE_NINJA) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/clothing.dm b/code/game/gamemodes/technomancer/clothing.dm index ef243aa484..3c3c79d58e 100644 --- a/code/game/gamemodes/technomancer/clothing.dm +++ b/code/game/gamemodes/technomancer/clothing.dm @@ -9,27 +9,30 @@ /obj/item/clothing/under/technomancer name = "initiate's jumpsuit" - desc = "It's a blue colored jumpsuit. There appears to be light-weight armor padding underneath, providing some protection." + desc = "It's a blue colored jumpsuit. There appears to be light-weight armor padding underneath, providing some protection. \ + There is also a healthy amount of insulation underneath." icon_state = "initiate" armor = list(melee = 10, bullet = 5, laser = 5, energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 + siemens_coefficient = 0.3 /obj/item/clothing/under/technomancer/apprentice name = "apprentice's jumpsuit" desc = "It's a blue colored jumpsuit with some silver markings. There appears to be light-weight armor padding \ - underneath, providing some protection." + underneath, providing some protection. There is also a healthy amount of insulation underneath." icon_state = "apprentice" /obj/item/clothing/under/technomancer/master name = "master's jumpsuit" desc = "It's a blue colored jumpsuit with some gold markings. There appears to be light-weight armor padding \ - underneath, providing some protection." + underneath, providing some protection. There is also a healthy amount of insulation underneath." icon_state = "technomancer" /obj/item/clothing/head/technomancer name = "initiate's hat" desc = "It's a somewhat silly looking blue pointed hat." icon_state = "initiate" + armor = list(melee = 10, bullet = 5, laser = 5, energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.3 /obj/item/clothing/head/technomancer/apprentice name = "apprentice's hat" diff --git a/code/game/gamemodes/technomancer/devices/disposable_teleporter.dm b/code/game/gamemodes/technomancer/devices/disposable_teleporter.dm index 43f0f2737a..4ce5f8a16a 100644 --- a/code/game/gamemodes/technomancer/devices/disposable_teleporter.dm +++ b/code/game/gamemodes/technomancer/devices/disposable_teleporter.dm @@ -2,7 +2,7 @@ name = "Disposable Teleporter" desc = "An ultra-safe teleportation device that can directly teleport you to a number of locations at minimal risk, however \ it has a limited amount of charges." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/disposable_teleporter /obj/item/weapon/disposable_teleporter diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm index 7bcd52babe..3e4ddbce1f 100644 --- a/code/game/gamemodes/technomancer/devices/shield_armor.dm +++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm @@ -6,7 +6,7 @@ of which your Core can provide. When you are struck by something, the shield will block 75% of the damage, deducting energy \ proportional to the amount of force that was inflicted. Armor penetration has no effect on the shield's ability to protect \ you from harm, however the shield will fail if the energy supply cannot meet demand." - cost = 300 + cost = 200 obj_path = /obj/item/clothing/suit/armor/shield /obj/item/clothing/suit/armor/shield diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm index 1446afcba7..6b981aa8eb 100644 --- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm +++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm @@ -4,7 +4,7 @@ the next attack you suffer, and strike the attacker with a strong bolt of lightning. This effect requires twenty seconds to \ recharge. If you are attacked while this is recharging, a weaker lightning bolt is sent out, however you won't be protected from \ the person beating you." - cost = 250 + cost = 150 obj_path = /obj/item/clothing/suit/armor/tesla /obj/item/clothing/suit/armor/tesla diff --git a/code/game/gamemodes/technomancer/equipment.dm b/code/game/gamemodes/technomancer/equipment.dm index 2e0fe3833a..4c94d2e7f0 100644 --- a/code/game/gamemodes/technomancer/equipment.dm +++ b/code/game/gamemodes/technomancer/equipment.dm @@ -11,7 +11,7 @@ desc = "A core optimized for passive regeneration, however at the cost of capacity. Has a capacity of 7,000 units of energy, and \ recharges at a rate of 70 units. Complex gravatics and force manipulation allows the wearer to also run slightly faster, and \ reduces incoming instability from functions by 10%." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/technomancer_core/rapid /datum/technomancer/equipment/bulky_core @@ -20,7 +20,7 @@ purchase one or more energy-generating Functions as well if using this core. Has a capacity of 20,000 units of energy, \ and recharges at a rate of 25 units. The intense weight of the core unfortunately can cause the wear to move slightly slower, \ and the closeness of the capacitors causes a slight increase in incoming instability by 10%." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/technomancer_core/bulky /datum/technomancer/equipment/unstable @@ -29,7 +29,7 @@ better as the user has more instability, which could prove dangerous to the inexperienced or unprepared. Has a capacity of 13,000 \ units of energy, and recharges at a rate of 35 units at no instability, and approximately 110 units when within the \ 'yellow zone' of instability. Incoming instability is also amplified by 30%, due to the nature of this core." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/technomancer_core/unstable /datum/technomancer/equipment/recycling @@ -38,7 +38,7 @@ cores. The focus on efficency also makes instability less of an issue, as incoming instability from functions are reduced by \ 40%. The capacitor is also slightly better, holding 12,000 units of energy, however the reactor is slower to recharge, at a rate \ of 40 units." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/technomancer_core/recycling /datum/technomancer/equipment/summoning @@ -47,13 +47,13 @@ entities from vast distances, and keeping them there. Wearers of this core can maintain up to 30 summons at once, and the energy \ demand for maintaining summons is severely reduced. This comes at the price of capcitors that can only hold 8,000 units of energy, \ a recharging rate of 35 energy, and no shielding from instability." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/technomancer_core/summoner /datum/technomancer/equipment/hypo_belt name = "Hypo Belt" desc = "A medical belt designed to carry autoinjectors and other medical equipment. Comes with one of each hypo." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/storage/belt/medical/technomancer /obj/item/weapon/storage/belt/medical/technomancer @@ -76,7 +76,7 @@ desc = "A belt with a literal pocket which opens to a localized pocket of 'Blue-Space', allowing for more storage. \ The nature of the pocket allows for storage of larger objects than what is typical for other belts, and in larger quanities. \ It will also help keep your pants on." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/storage/belt/holding /obj/item/weapon/storage/belt/holding @@ -103,7 +103,7 @@ /datum/technomancer/equipment/omni_sight name = "Omnisight Scanner" desc = "A very rare scanner worn on the face, which allows the wearer to see nearly anything across walls." - cost = 400 + cost = 300 obj_path = /obj/item/clothing/glasses/omni /obj/item/clothing/glasses/omni @@ -122,7 +122,7 @@ name = "Medical HUD" desc = "A commonly available HUD for medical professionals, which displays how healthy an individual is. \ Recommended for support-based apprentices!" - cost = 30 + cost = 25 obj_path = /obj/item/clothing/glasses/thermal/plain/monocle /datum/technomancer/equipment/scepter @@ -130,7 +130,7 @@ desc = "A gem sometimes found in the depths of asteroids makes up the basis for this device. Energy is channeled into it from \ the Core and the user, causing many functions to be enhanced in various ways, so long as it is held in the off-hand. \ Be careful not to lose this!" - cost = 300 + cost = 200 obj_path = /obj/item/weapon/scepter /obj/item/weapon/scepter diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm index 6be83aef7b..0de94cba7a 100644 --- a/code/game/gamemodes/technomancer/instability.dm +++ b/code/game/gamemodes/technomancer/instability.dm @@ -112,7 +112,7 @@ rng = rand(0,8) switch(rng) if(0) - apply_effect(instability * 0.5, IRRADIATE) + apply_effect(instability * 0.3, IRRADIATE) if(1) return // visible_message("\The [src] suddenly collapses!", @@ -120,21 +120,21 @@ // Weaken(instability * 0.1) if(2) if(can_feel_pain()) - apply_effect(instability * 0.5, AGONY) + apply_effect(instability * 0.3, AGONY) src << "You feel a sharp pain!" if(3) - apply_effect(instability * 0.5, EYE_BLUR) + apply_effect(instability * 0.3, EYE_BLUR) src << "Your eyes start to get cloudy!" if(4) electrocute_act(instability * 0.3, "unstable energies") if(5) - adjustFireLoss(instability * 0.2) //10 burn @ 50 instability + adjustFireLoss(instability * 0.15) //7.5 burn @ 50 instability src << "You feel your skin burn!" if(6) - adjustBruteLoss(instability * 0.2) //10 brute @ 50 instability + adjustBruteLoss(instability * 0.15) //7.5 brute @ 50 instability src << "You feel a sharp pain as an unseen force harms your body!" if(7) - adjustToxLoss(instability * 0.2) //10 tox @ 50 instability + adjustToxLoss(instability * 0.15) //7.5 tox @ 50 instability if(8) safe_blink(src, range = 6) src << "You're teleported against your will!" diff --git a/code/game/gamemodes/technomancer/spells/abjuration.dm b/code/game/gamemodes/technomancer/spells/abjuration.dm index 2422ef00bf..005f1561bf 100644 --- a/code/game/gamemodes/technomancer/spells/abjuration.dm +++ b/code/game/gamemodes/technomancer/spells/abjuration.dm @@ -2,7 +2,7 @@ name = "Abjuration" desc = "This ability attempts to send summoned or teleported entities or anomalies to the place from whence they came, or at least \ far away from the caster. Failing that, it may inhibit those entities in some form." - cost = 40 + cost = 25 obj_path = /obj/item/weapon/spell/abjuration category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/apportation.dm b/code/game/gamemodes/technomancer/spells/apportation.dm index 150559b9cd..9cc95b1e6e 100644 --- a/code/game/gamemodes/technomancer/spells/apportation.dm +++ b/code/game/gamemodes/technomancer/spells/apportation.dm @@ -2,7 +2,7 @@ name = "Apportation" desc = "This allows you to teleport objects into your hand, or to pull people towards you. If they're close enough, the function \ will grab them automatically." - cost = 50 + cost = 25 obj_path = /obj/item/weapon/spell/apportation category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/audible_deception.dm b/code/game/gamemodes/technomancer/spells/audible_deception.dm index 06930828af..970d983894 100644 --- a/code/game/gamemodes/technomancer/spells/audible_deception.dm +++ b/code/game/gamemodes/technomancer/spells/audible_deception.dm @@ -3,7 +3,7 @@ desc = "Allows you to create a specific sound at a location of your choosing." enhancement_desc = "An extremely loud sound that a large amount of energy and instability becomes available, which will \ deafen and stun all who are near the targeted tile, including yourself if unprotected." - cost = 150 + cost = 50 obj_path = /obj/item/weapon/spell/audible_deception ability_icon_state = "tech_audibledeception" category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm b/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm index 52cbdfbfdf..024002814e 100644 --- a/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/biomed_aura name = "Restoration Aura" desc = "Heals you and your allies (or everyone, if you want) of trauma and burns slowly, as long as they remain within four meters." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/aura/biomed ability_icon_state = "tech_biomedaura" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm index 0c28f31577..5e1028192b 100644 --- a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm @@ -4,7 +4,7 @@ This does not affect you or your allies. It also causes a large amount of fire to erupt around you, however the main threat is \ still the heating up." enhancement_desc = "Increased heat generation, more fires, and higher temperature cap." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/aura/fire ability_icon_state = "tech_fireaura" category = OFFENSIVE_SPELLS @@ -21,13 +21,13 @@ qdel(src) var/list/nearby_things = range(4,owner) - var/temp_change = 25 - var/temp_cap = 500 + var/temp_change = 40 + var/temp_cap = 600 var/fire_power = 2 if(check_for_scepter()) - temp_change = 50 - temp_cap = 700 + temp_change = 80 + temp_cap = 1000 fire_power = 4 for(var/mob/living/carbon/human/H in nearby_things) if(is_ally(H)) diff --git a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm index d5dd78b793..610702646d 100644 --- a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm @@ -3,7 +3,7 @@ desc = "Lowers the core body temperature of everyone around you (except for your friends), causing them to freeze to death if \ they stay within four meters of you." enhancement_desc = "The chill becomes lethal." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/aura/frost ability_icon_state = "tech_frostaura" category = DEFENSIVE_SPELLS // Scepter-less frost aura is nonlethal. diff --git a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm index a9e50b2fa3..70ae416ec0 100644 --- a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/shock_aura name = "Electric Aura" desc = "Repeatively electrocutes enemies within four meters of you, as well as nearby electronics." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/aura/shock ability_icon_state = "tech_shockaura" category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/blink.dm b/code/game/gamemodes/technomancer/spells/blink.dm index 9dae12e39e..19f6e84c83 100644 --- a/code/game/gamemodes/technomancer/spells/blink.dm +++ b/code/game/gamemodes/technomancer/spells/blink.dm @@ -3,7 +3,7 @@ desc = "Force the target to teleport a short distance away. This target could be anything from something lying on the ground, to someone trying to \ fight you, or even yourself. Using this on someone next to you makes their potential distance after teleportation greater." enhancement_desc = "Blink distance is increased greatly." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/spell/blink category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/control.dm b/code/game/gamemodes/technomancer/spells/control.dm index b5eaad8f44..17fb821d35 100644 --- a/code/game/gamemodes/technomancer/spells/control.dm +++ b/code/game/gamemodes/technomancer/spells/control.dm @@ -5,7 +5,7 @@ targets. This function will have no effect on entities of higher intelligence, such as humans and similar alien species, as it's \ not true mind control, but merely pheromone synthesis for living animals, and electronic hacking for simple robots. The green web \ around the entity is merely a hologram used to allow the user to know if the creature is safe or not." - cost = 200 + cost = 100 obj_path = /obj/item/weapon/spell/control category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/energy_siphon.dm b/code/game/gamemodes/technomancer/spells/energy_siphon.dm index 0e8e23ffd8..ad379b2d3c 100644 --- a/code/game/gamemodes/technomancer/spells/energy_siphon.dm +++ b/code/game/gamemodes/technomancer/spells/energy_siphon.dm @@ -4,7 +4,7 @@ Every second, electricity is stolen until the link is broken by the target moving too far away, or having no more energy left. \ Can drain from powercells, microbatteries, and other Cores. The beam created by the siphoning is harmful to touch." enhancement_desc = "Rate of siphoning is doubled." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/energy_siphon ability_icon_state = "tech_energysiphon" category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/flame_tongue.dm b/code/game/gamemodes/technomancer/spells/flame_tongue.dm index 5afa25ae90..923cde0b9d 100644 --- a/code/game/gamemodes/technomancer/spells/flame_tongue.dm +++ b/code/game/gamemodes/technomancer/spells/flame_tongue.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/flame_tongue name = "Flame Tongue" desc = "Using a miniturized flamethrower in your gloves, you can emit a flame strong enough to melt both your enemies and walls." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/spell/flame_tongue ability_icon_state = "tech_flametongue" category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/illusion.dm b/code/game/gamemodes/technomancer/spells/illusion.dm index e450e4480f..9667df1db4 100644 --- a/code/game/gamemodes/technomancer/spells/illusion.dm +++ b/code/game/gamemodes/technomancer/spells/illusion.dm @@ -2,7 +2,7 @@ name = "Illusion" desc = "Allows you to create and control a holographic illusion, that can take the form of most object or entities." enhancement_desc = "Illusions will be made of hard light, allowing the interception of attacks, appearing more realistic." - cost = 100 + cost = 25 obj_path = /obj/item/weapon/spell/illusion ability_icon_state = "tech_illusion" category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/insert/corona.dm b/code/game/gamemodes/technomancer/spells/insert/corona.dm index bde3ee9984..a070108a68 100644 --- a/code/game/gamemodes/technomancer/spells/insert/corona.dm +++ b/code/game/gamemodes/technomancer/spells/insert/corona.dm @@ -2,7 +2,7 @@ name = "Corona" desc = "Causes the victim to glow very brightly, which while harmless in itself, makes it easier for them to be hit. The \ bright glow also makes it very difficult to be stealthy. The effect lasts for one minute." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/spell/insert/corona ability_icon_state = "tech_corona" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm b/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm index e9450b9586..a43bb7611d 100644 --- a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm +++ b/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm @@ -2,7 +2,7 @@ name = "Mend Organs" desc = "Heals the target's internal organs, both organic and robotic. Instability is split between the target \ and technomancer, if seperate." - cost = 75 + cost = 50 obj_path = /obj/item/weapon/spell/insert/mend_organs ability_icon_state = "tech_mendwounds" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm index 8fb549039f..a95afa0a1f 100644 --- a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm +++ b/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm @@ -2,7 +2,7 @@ name = "Repel Missiles" desc = "Places a repulsion field around you, which attempts to deflect incoming bullets and lasers, making them 30% less likely \ to hit you. The field lasts for five minutes and can be granted to yourself or an ally." - cost = 60 + cost = 25 obj_path = /obj/item/weapon/spell/insert/repel_missiles ability_icon_state = "tech_repelmissiles" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/instability_tap.dm b/code/game/gamemodes/technomancer/spells/instability_tap.dm index ada2989444..8ad52f3b3f 100644 --- a/code/game/gamemodes/technomancer/spells/instability_tap.dm +++ b/code/game/gamemodes/technomancer/spells/instability_tap.dm @@ -2,7 +2,7 @@ name = "Instability Tap" desc = "Creates a large sum of energy, at the cost of a very large amount of instability afflicting you." enhancement_desc = "50% more energy gained, 20% less instability gained." - cost = 120 + cost = 100 obj_path = /obj/item/weapon/spell/instability_tap ability_icon_state = "tech_instabilitytap" category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/mark_recall.dm b/code/game/gamemodes/technomancer/spells/mark_recall.dm index 63e6d67fad..528b860094 100644 --- a/code/game/gamemodes/technomancer/spells/mark_recall.dm +++ b/code/game/gamemodes/technomancer/spells/mark_recall.dm @@ -3,7 +3,7 @@ desc = "This function places a specific 'mark' beacon under you, which is used by the Recall function as a destination. \ Note that using Mark again will move the destination instead of creating a second destination, and only one destination \ can exist, regardless of who casted Mark." - cost = 50 + cost = 25 obj_path = /obj/item/weapon/spell/mark ability_icon_state = "tech_mark" category = UTILITY_SPELLS @@ -50,7 +50,7 @@ desc = "This function teleports you to where you placed a mark using the Mark function. Without the Mark function, this \ function is useless. Note that teleporting takes three seconds. Being incapacitated while teleporting will cancel it." enhancement_desc = "Recall takes two seconds instead of three." - cost = 50 + cost = 25 obj_path = /obj/item/weapon/spell/recall ability_icon_state = "tech_recall" category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/oxygenate.dm b/code/game/gamemodes/technomancer/spells/oxygenate.dm index 3f9bb6f9e5..f1edc635c1 100644 --- a/code/game/gamemodes/technomancer/spells/oxygenate.dm +++ b/code/game/gamemodes/technomancer/spells/oxygenate.dm @@ -2,7 +2,7 @@ name = "Oxygenate" desc = "This function creates oxygen at a location of your chosing. If used on a humanoid entity, it heals oxygen deprivation. \ If casted on the envirnment, air (oxygen and nitrogen) is moved from a distant location to your target." - cost = 70 + cost = 50 obj_path = /obj/item/weapon/spell/oxygenate ability_icon_state = "oxygenate" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/phase_shift.dm b/code/game/gamemodes/technomancer/spells/phase_shift.dm index 20fb033872..a571d6789d 100644 --- a/code/game/gamemodes/technomancer/spells/phase_shift.dm +++ b/code/game/gamemodes/technomancer/spells/phase_shift.dm @@ -2,7 +2,7 @@ name = "Phase Shift" desc = "Hides you in the safest possible place, where no harm can come to you. Unfortunately you can only stay inside for a few moments before \ draining your powercell." - cost = 80 + cost = 50 obj_path = /obj/item/weapon/spell/phase_shift category = DEFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/projectile/beam.dm b/code/game/gamemodes/technomancer/spells/projectile/beam.dm index 429a83dd9b..13d5fe934a 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/beam.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/beam.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/beam name = "Beam" desc = "Fires a laser at your target. Cheap, reliable, and a bit boring." - cost = 150 + cost = 100 ability_icon_state = "tech_beam" obj_path = /obj/item/weapon/spell/projectile/beam category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm b/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm index dad3c88f45..ab295f58f3 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm @@ -2,7 +2,7 @@ name = "Force Missile" desc = "This fires a missile at your target. It's cheap to use, however the projectile itself moves and impacts in such a way \ that armor designed to protect from blunt force will mitigate this function as well." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/spell/projectile/force_missile category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/projectile/overload.dm b/code/game/gamemodes/technomancer/spells/projectile/overload.dm index e6f0c898e2..90bf50e7d6 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/overload.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/overload.dm @@ -2,7 +2,7 @@ name = "Overload" desc = "Fires a bolt of highly unstable energy, that does damaged equal to 1.5% of the technomancer's current reserve of energy. \ This energy pierces all known armor." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/projectile/overload category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/projectile/projectile.dm b/code/game/gamemodes/technomancer/spells/projectile/projectile.dm index 69e1efc92f..ea2f0db4e3 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/projectile.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/projectile.dm @@ -10,10 +10,9 @@ var/fire_sound = null /obj/item/weapon/spell/projectile/on_ranged_cast(atom/hit_atom, mob/living/user) - var/turf/T = get_turf(hit_atom) if(set_up(hit_atom, user)) var/obj/item/projectile/new_projectile = new spell_projectile(get_turf(user)) - new_projectile.launch(T) + new_projectile.launch(hit_atom) if(fire_sound) playsound(get_turf(src), fire_sound, 75, 1) owner.adjust_instability(instability_per_shot) diff --git a/code/game/gamemodes/technomancer/spells/radiance.dm b/code/game/gamemodes/technomancer/spells/radiance.dm index 9d484ddc5c..7cd7694122 100644 --- a/code/game/gamemodes/technomancer/spells/radiance.dm +++ b/code/game/gamemodes/technomancer/spells/radiance.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/radiance name = "Radiance" desc = "Causes you to be very radiant, glowing brightly in visible light, thermal energy, and deadly ionizing radiation." - cost = 180 + cost = 100 obj_path = /obj/item/weapon/spell/radiance category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/reflect.dm b/code/game/gamemodes/technomancer/spells/reflect.dm index 7a8fa0a4de..d841db2acc 100644 --- a/code/game/gamemodes/technomancer/spells/reflect.dm +++ b/code/game/gamemodes/technomancer/spells/reflect.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/reflect name = "Reflect" desc = "Emits a protective shield fron your hand in front of you, which will reflect one attack back at the attacker." - cost = 120 + cost = 100 obj_path = /obj/item/weapon/spell/reflect ability_icon_state = "tech_reflect" category = DEFENSIVE_SPELLS @@ -22,7 +22,7 @@ spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) spark_system.set_up(5, 0, src) owner << "Your shield will expire in 3 seconds!" - spawn(3 SECONDS) + spawn(5 SECONDS) if(src) owner << "Your shield expires!" qdel(src) @@ -67,7 +67,7 @@ if(!reflecting) reflecting = 1 - spawn(1 SECOND) //To ensure that most or all of a burst fire cycle is reflected. + spawn(2 SECONDS) //To ensure that most or all of a burst fire cycle is reflected. owner << "Your shield fades due being used up!" qdel(src) @@ -87,7 +87,7 @@ if(!reflecting) reflecting = 1 - spawn(1 SECOND) //To ensure that most or all of a burst fire cycle is reflected. + spawn(2 SECONDS) //To ensure that most or all of a burst fire cycle is reflected. owner << "Your shield fades due being used up!" qdel(src) return 1 diff --git a/code/game/gamemodes/technomancer/spells/shield.dm b/code/game/gamemodes/technomancer/spells/shield.dm index 330de0ff26..ac6910c478 100644 --- a/code/game/gamemodes/technomancer/spells/shield.dm +++ b/code/game/gamemodes/technomancer/spells/shield.dm @@ -2,7 +2,7 @@ name = "Shield" desc = "Emits a protective shield fron your hand in front of you, which will protect you from almost anything able to harm \ you, so long as you can power it." - cost = 120 + cost = 100 obj_path = /obj/item/weapon/spell/shield ability_icon_state = "tech_shield" category = DEFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm index ac5e799d72..ecb18b3481 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/darkness name = "Darkness" desc = "Disrupts photons moving in a local area, causing darkness to shroud yourself or a position of your choosing." - cost = 30 + cost = 25 obj_path = /obj/item/weapon/spell/spawner/darkness category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/spawner/pulsar.dm b/code/game/gamemodes/technomancer/spells/spawner/pulsar.dm index a2c22b0f76..c1b016116a 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/pulsar.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/pulsar.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/pulsar name = "Pulsar" desc = "Emits electronic pulses to destroy, disable, or otherwise harm devices and machines. Be sure to not hit yourself with this." - cost = 150 + cost = 100 obj_path = /obj/item/weapon/spell/spawner/pulsar category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm b/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm index 497a8422bd..053f449095 100644 --- a/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm +++ b/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm @@ -6,7 +6,7 @@ The creatures take a few moments to be teleported to the targeted tile. Note that the creatures summoned are \ not inherently loyal to the technomancer, and that the creatures will be hurt slightly from being teleported to you." enhancement_desc = "Summoned entities will never harm their summoner." - cost = 200 + cost = 100 obj_path = /obj/item/weapon/spell/summon/summon_creature category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/summon/summon_ward.dm b/code/game/gamemodes/technomancer/spells/summon/summon_ward.dm index 5323c5beda..e4154eddf2 100644 --- a/code/game/gamemodes/technomancer/spells/summon/summon_ward.dm +++ b/code/game/gamemodes/technomancer/spells/summon/summon_ward.dm @@ -3,7 +3,7 @@ desc = "Teleports a prefabricated 'ward' drone to the target location, which will alert you and your allies when it sees entities \ moving around it, or when it is attacked. They can see for up to five meters. Wards expire in six minutes." enhancement_desc = "Wards can detect invisibile entities, and are more specific in relaying information about what it sees." - cost = 100 + cost = 25 obj_path = /obj/item/weapon/spell/summon/summon_ward category = UTILITY_SPELLS @@ -84,6 +84,9 @@ if(L.alpha <= 127) continue // Too transparent, as a mercy to camo lings. + else + L.break_cloak() + // Warn the Technomancer when it sees a new mob. if(!(L in seen_mobs)) seen_mobs.Add(L) @@ -111,3 +114,7 @@ overlays.Cut() var/image/I = image('icons/mob/critter.dmi',"ward_truesight") overlays.Add(I) + +/mob/living/simple_animal/ward/invisible_detect + true_sight = 1 + see_invisible = SEE_INVISIBLE_LEVEL_TWO diff --git a/code/game/gamemodes/technomancer/spells/targeting_matrix.dm b/code/game/gamemodes/technomancer/spells/targeting_matrix.dm index aff00f0197..b227748aeb 100644 --- a/code/game/gamemodes/technomancer/spells/targeting_matrix.dm +++ b/code/game/gamemodes/technomancer/spells/targeting_matrix.dm @@ -2,7 +2,7 @@ name = "Targeting Matrix" desc = "Automatically targets and fires a ranged weapon or function at a non-friendly target near a targeted tile. \ Each target assisted attack costs some energy and instability." - cost = 150 + cost = 50 ability_icon_state = "tech_targetingmatrix" obj_path = /obj/item/weapon/spell/targeting_matrix category = UTILITY_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/warp_strike.dm b/code/game/gamemodes/technomancer/spells/warp_strike.dm index a308066ae5..11b3ba032e 100644 --- a/code/game/gamemodes/technomancer/spells/warp_strike.dm +++ b/code/game/gamemodes/technomancer/spells/warp_strike.dm @@ -1,7 +1,7 @@ /datum/technomancer/spell/warp_strike name = "Warp Strike" desc = "Teleports you next to your target, and attacks them with whatever is in your off-hand, spell or object." - cost = 200 + cost = 100 obj_path = /obj/item/weapon/spell/warp_strike ability_icon_state = "tech_warpstrike" category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/technomancer.dm b/code/game/gamemodes/technomancer/technomancer.dm index a7131fb54c..cf37046d0f 100644 --- a/code/game/gamemodes/technomancer/technomancer.dm +++ b/code/game/gamemodes/technomancer/technomancer.dm @@ -7,8 +7,8 @@ their powers can be used for good or if their arrival foreshadows the destruction of the entire colony, or worse." config_tag = "technomancer" votable = 0 - required_players = 8 - required_players_secret = 10 + required_players = 5 + required_players_secret = 5 required_enemies = 1 end_on_antag_death = 0 antag_tags = list(MODE_TECHNOMANCER) \ No newline at end of file diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index c5d8f8f445..25acb8caa7 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -239,6 +239,11 @@ proc/get_all_job_icons() //For all existing HUD icons if(I.rank in job_icons) return I.rank + var/centcom = get_all_centcom_jobs() + if(I.assignment in centcom) //Return with the NT logo if it is a CentCom job + return "CentCom" + if(I.rank in centcom) + return "CentCom" else return diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm index 5e2b40d952..cc0faede19 100644 --- a/code/game/jobs/job/assistant.dm +++ b/code/game/jobs/job/assistant.dm @@ -19,6 +19,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) if(has_alt_title(H, alt_title,"Visitor")) //I doubt someone visiting the station would want to wear an ugly grey uniform H.equip_to_slot_or_del(new /obj/item/clothing/under/assistantformal(H), slot_w_uniform) else if(has_alt_title(H, alt_title,"Resident")) diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm index c091a599c3..a98bfe4544 100644 --- a/code/game/jobs/job/captain.dm +++ b/code/game/jobs/job/captain.dm @@ -30,6 +30,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/captain(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/cap(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/com(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/captain(H), slot_w_uniform) if(H.age>49) // Since we can have something other than the default uniform at this @@ -109,4 +110,39 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/ids(H.back), slot_in_backpack) H.implant_loyalty() - return 1 \ No newline at end of file + return 1 + +/datum/job/secretary + title = "Command Secretary" + flag = BRIDGE + department = "Civilian" + head_position = 1 + department_flag = CIVILIAN + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "command staff" + selection_color = "#2F2F7F" + idtype = /obj/item/weapon/card/id/silver + alt_titles = list("Command Liaison", "Bridge Secretary") + minimal_player_age = 5 + economic_modifier = 7 + + access = list(access_heads) + minimal_access = list(access_heads) + +/datum/job/secretary/equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_com(H), slot_l_ear) + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/device/pda/heads/hop(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/female/skirt(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/charcoal(H), slot_w_uniform) + return 1 \ No newline at end of file diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index b617c65da9..a8e4d3f3f6 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -21,6 +21,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_service(H), slot_l_ear) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) @@ -86,6 +87,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/hydroponics(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/hyd(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/hyd(H), slot_back) return 1 @@ -171,6 +173,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/engi(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/device/pda/shaftminer(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) @@ -265,6 +268,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/internalaffairs(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index 53c642b816..227297ca05 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -35,6 +35,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/engi(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/device/pda/heads/ce(H), slot_l_store) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) @@ -73,6 +74,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/engi(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) @@ -111,6 +113,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/engi(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/atmos(H), slot_l_store) diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 6c575bef00..6add65ce55 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -33,6 +33,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) /datum/job/proc/equip_survival(var/mob/living/carbon/human/H) if(!H) return 0 diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 69a94f0ade..0c2053f8d6 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -30,6 +30,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/med(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/heads/cmo(H), slot_belt) @@ -63,6 +64,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/med(H), slot_back) if(has_alt_title(H, alt_title,"Emergency Physician")) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/fr_jacket(H), slot_wear_suit) @@ -78,6 +80,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/virology(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/vir(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/viro(H), slot_back) else if(has_alt_title(H, alt_title,"Medical Doctor")) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat(H), slot_wear_suit) @@ -128,6 +131,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/chemistry(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/chem(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/chem(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/chemist(H), slot_wear_suit) return 1 @@ -185,6 +189,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) if(has_alt_title(H, alt_title,"Psychiatrist")) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/psych(H), slot_w_uniform) else if(has_alt_title(H, alt_title,"Psychologist")) @@ -221,6 +226,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/med(H), slot_back) if(has_alt_title(H, alt_title,"Emergency Medical Technician")) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/paramedic(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/fr_jacket(H), slot_wear_suit) diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 3fb3de5c42..b13d623fd6 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -37,6 +37,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/toxins(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/tox(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat(H), slot_wear_suit) return 1 @@ -70,6 +71,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/toxins(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/tox(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit) return 1 @@ -101,6 +103,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/toxins(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/tox(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit) return 1 diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 071c1cbf1b..f151a5fb83 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -30,6 +30,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/sec(H), slot_back) H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hos(H), slot_l_ear) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) @@ -70,6 +71,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/sec(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/warden(H), slot_belt) @@ -108,6 +110,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/det(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt) @@ -151,6 +154,7 @@ if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(5) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger/sec(H), slot_back) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/security(H), slot_belt) diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 61324580ff..bf3b4ea8ff 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -44,6 +44,7 @@ var/const/CHAPLAIN =(1<<10) var/const/CLOWN =(1<<11) var/const/MIME =(1<<12) var/const/ASSISTANT =(1<<13) +var/const/BRIDGE =(1<<14) var/list/assistant_occupations = list( @@ -56,7 +57,8 @@ var/list/command_positions = list( "Head of Security", "Chief Engineer", "Research Director", - "Chief Medical Officer" + "Chief Medical Officer", + "Command Secretary" ) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 2e7224169f..5efd83bb92 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -329,7 +329,7 @@ organStatus["broken"] = E.broken_description if(E.status & ORGAN_ROBOT) organStatus["robotic"] = 1 - if(E.status & ORGAN_SPLINTED) + if(E.splinted) organStatus["splinted"] = 1 if(E.status & ORGAN_BLEEDING) organStatus["bleeding"] = 1 @@ -483,7 +483,7 @@ break if(istype(e, /obj/item/organ/external/chest) && occupant.is_lung_ruptured()) lung_ruptured = "Lung ruptured:" - if(e.status & ORGAN_SPLINTED) + if(e.splinted) splint = "Splinted:" if(e.status & ORGAN_BLEEDING) bled = "Bleeding:" diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 739583ede8..cb57906e30 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -222,7 +222,7 @@ mob/living/proc/near_camera() /mob/living/proc/tracking_status() // Easy checks first. - // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. + // Don't detect mobs on CentCom. Since the wizard den is on CentCom, we only need this. var/obj/item/weapon/card/id/id = GetIdCard() if(id && id.prevent_tracking()) return TRACKING_TERMINATE diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index a657d881a8..9ff98b84b4 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -173,7 +173,7 @@ src.updateDialog() // OMG CENTCOMM LETTERHEAD - if("MessageCentcomm") + if("MessageCentCom") if(src.authenticated==2) if(centcomm_message_cooldown) usr << "\red Arrays recycling. Please stand by." @@ -181,7 +181,7 @@ var/input = sanitize(input("Please choose a message to transmit to [boss_short] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "")) if(!input || !(usr in view(1,src))) return - Centcomm_announce(input, usr) + CentCom_announce(input, usr) usr << "\blue Message transmitted." log_say("[key_name(usr)] has made an IA [boss_short] announcement: [input]") centcomm_message_cooldown = 1 @@ -295,7 +295,7 @@ if (src.authenticated==2) dat += "
\[
Make An Announcement \]" if(src.emagged == 0) - dat += "
\[ Send an emergency message to [boss_short] \]" + dat += "
\[ Send an emergency message to [boss_short] \]" else dat += "
\[ Send an emergency message to \[UNKNOWN\] \]" dat += "
\[ Restore Backup Routing Data \]" diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm index 3fced68e65..b01b03f9b3 100644 --- a/code/game/machinery/computer/guestpass.dm +++ b/code/game/machinery/computer/guestpass.dm @@ -132,7 +132,7 @@ if (href_list["choice"]) switch(href_list["choice"]) if ("giv_name") - var/nam = sanitize(input("Person pass is issued to", "Name", giv_name) as text|null) + var/nam = sanitizeName(input("Person pass is issued to", "Name", giv_name) as text|null) if (nam) giv_name = nam if ("reason") diff --git a/code/game/machinery/computer3/computers/communications.dm b/code/game/machinery/computer3/computers/communications.dm index 8168a3f8da..cace79d378 100644 --- a/code/game/machinery/computer3/computers/communications.dm +++ b/code/game/machinery/computer3/computers/communications.dm @@ -22,8 +22,8 @@ /datum/file/program/communications - name = "Centcom communications relay" - desc = "Used to connect to Centcom." + name = "CentCom communications relay" + desc = "Used to connect to CentCom." active_state = "comm" req_access = list(access_heads) @@ -185,7 +185,7 @@ computer.updateDialog() // OMG CENTCOMM LETTERHEAD - if("MessageCentcomm" in href_list) + if("MessageCentCom" in href_list) if(!computer.radio.subspace) return if(authenticated==2) @@ -195,7 +195,7 @@ var/input = sanitize(input("Please choose a message to transmit to [boss_short] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")) if(!input || !interactable()) return - Centcomm_announce(input, usr) + CentCom_announce(input, usr) usr << "Message transmitted." log_say("[key_name(usr)] has made a [boss_short] announcement: [input]") centcomm_message_cooldown = 1 @@ -288,7 +288,7 @@ if (authenticated==2) dat += "
\[ Make An Announcement \]" if(computer.emagged == 0) - dat += "
\[ Send an emergency message to [boss_short] \]" + dat += "
\[ Send an emergency message to [boss_short] \]" else dat += "
\[ Send an emergency message to \[UNKNOWN\] \]" dat += "
\[ Restore Backup Routing Data \]" diff --git a/code/game/machinery/computer3/file.dm b/code/game/machinery/computer3/file.dm index be4285b3e1..c425bcc0aa 100644 --- a/code/game/machinery/computer3/file.dm +++ b/code/game/machinery/computer3/file.dm @@ -62,13 +62,13 @@ return 1 /* - Centcom root authorization certificate + CentCom root authorization certificate Non-destructive, officially sanctioned. Has the same effect on computers as an emag. */ /datum/file/centcom_auth - name = "Centcom Root Access Token" + name = "CentCom Root Access Token" extension = "auth" volume = 100 copy() diff --git a/code/game/machinery/computer3/lapvend.dm b/code/game/machinery/computer3/lapvend.dm index 3800fb9440..e31dd57fa2 100644 --- a/code/game/machinery/computer3/lapvend.dm +++ b/code/game/machinery/computer3/lapvend.dm @@ -178,7 +178,7 @@ else usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call [boss_short] Support." else - usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentCom Support." else transfer_and_vend(CH, C) @@ -328,7 +328,7 @@ usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call [boss_short] Support." return 0 else - usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentCom Support." return 0 else transfer_and_reimburse(CH) diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index 3005996f0b..f553bfa9fe 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -447,6 +447,31 @@ state = 3 if(frame_type.frame_class == "machine") user << desc + else if(state == 3) + if(frame_type.frame_class == "machine") + for(var/I in req_components) + if(istype(P, I) && (req_components[I] > 0)) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/CP = P + if(CP.get_amount() > 1) + var/camt = min(CP.amount, req_components[I]) // amount of cable to take, idealy amount required, but limited by amount provided + var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src) + CC.amount = camt + CC.update_icon() + CP.use(camt) + components += CC + req_components[I] -= camt + update_desc() + break + + user.drop_item() + P.forceMove(src) + components += P + req_components[I]-- + update_desc() + break + user << desc else if(istype(P, /obj/item/weapon/wirecutters)) if(state == 3) @@ -506,20 +531,7 @@ for(var/I in req_components) if(istype(P, I) && (req_components[I] > 0)) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CP = P - if(CP.get_amount() > 1) - var/camt = min(CP.amount, req_components[I]) // amount of cable to take, idealy amount required, but limited by amount provided - var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src) - CC.amount = camt - CC.update_icon() - CP.use(camt) - components += CC - req_components[I] -= camt - update_desc() - break - - else if(istype(P, /obj/item/stack/material/glass/reinforced)) + if(istype(P, /obj/item/stack/material/glass/reinforced)) var/obj/item/stack/material/glass/reinforced/CP = P if(CP.get_amount() > 1) var/camt = min(CP.amount, req_components[I]) // amount of glass to take, idealy amount required, but limited by amount provided @@ -539,8 +551,65 @@ update_desc() break user << desc - if(P && P.loc != src && !istype(P, /obj/item/stack/cable_coil) && !istype(P, /obj/item/stack/material)) + if(P && P.loc != src && !istype(P, /obj/item/stack/material)) user << "You cannot add that component to the machine!" return - update_icon() \ No newline at end of file + update_icon() + +/obj/structure/frame/verb/rotate() + set name = "Rotate Frame Counter-Clockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(anchored) + usr << "It is fastened to the floor therefore you can't rotate it!" + return 0 + + set_dir(turn(dir, 90)) + + var/dir_text + if(dir == 1) + dir_text = "north" + else if(dir == 2) + dir_text = "south" + else if(dir == 4) + dir_text = "east" + else if(dir == 8) + dir_text = "west" + + usr << "You rotate the [src] to face [dir_text]!" + + return + + +/obj/structure/frame/verb/revrotate() + set name = "Rotate Frame Clockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(anchored) + usr << "It is fastened to the floor therefore you can't rotate it!" + return 0 + + set_dir(turn(dir, 270)) + + var/dir_text + if(dir == 1) + dir_text = "north" + else if(dir == 2) + dir_text = "south" + else if(dir == 4) + dir_text = "east" + else if(dir == 8) + dir_text = "west" + + usr << "You rotate the [src] to face [dir_text]!" + + return \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 9700dfd69a..3234d03a1f 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -586,7 +586,7 @@ var/electrified = 0 //Departments that the cycler can paint suits to look like. - var/list/departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction") + var/list/departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard") //Species that the suits can be configured to fit. var/list/species = list("Human","Skrell","Unathi","Tajara", "Teshari") @@ -634,7 +634,7 @@ name = "Medical suit cycler" model_text = "Medical" req_access = list(access_medical) - departments = list("Medical") + departments = list("Medical","Biohazard") /obj/machinery/suit_cycler/syndicate name = "Nonstandard suit cycler" @@ -751,8 +751,8 @@ //Clear the access reqs, disable the safeties, and open up all paintjobs. user << "You run the sequencer across the interface, corrupting the operating protocols." - departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","^%###^%$") - species = list("Human","Tajara","Skrell","Unathi", "Teshari") + departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","^%###^%$") + species = list("Human","Skrell","Unathi","Tajara", "Teshari", "Nevrean", "Akula", "Sergal", "Flatland Zorren", "Highlander Zorren", "Vulpkanin", "Promethean", "Xenomorph Hybrid") //VORESTATION EDIT emagged = 1 safeties = 0 @@ -1036,6 +1036,15 @@ suit.name = "Construction voidsuit" suit.icon_state = "rig-engineering_con" suit.item_state = "eng_voidsuit_con" + if("Biohazard") + if(helmet) + helmet.name = "Biohazard voidsuit helmet" + helmet.icon_state = "rig0-medical_bio" + helmet.item_state = "rig0-medical_bio" + if(suit) + suit.name = "Biohazard voidsuit" + suit.icon_state = "rig-medical_bio" + suit.item_state = "medical_voidsuit_bio" if("^%###^%$" || "Mercenary") if(helmet) helmet.name = "blood-red voidsuit helmet" diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index ca35f59236..4a6aded43b 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -25,7 +25,7 @@ autolinkers = list("r_relay") /obj/machinery/telecomms/relay/preset/centcom - id = "Centcom Relay" + id = "CentCom Relay" hide = 1 toggled = 1 //anchored = 1 @@ -44,7 +44,7 @@ "receiverA", "broadcasterA") /obj/machinery/telecomms/hub/preset_cent - id = "CentComm Hub" + id = "CentCom Hub" network = "tcommsat" produces_heat = 0 autolinkers = list("hub_cent", "c_relay", "s_relay", "m_relay", "r_relay", @@ -65,7 +65,7 @@ ..() /obj/machinery/telecomms/receiver/preset_cent - id = "CentComm Receiver" + id = "CentCom Receiver" network = "tcommsat" produces_heat = 0 autolinkers = list("receiverCent") @@ -106,7 +106,7 @@ autolinkers = list("processor4", "engineering", "common") /obj/machinery/telecomms/bus/preset_cent - id = "CentComm Bus" + id = "CentCom Bus" network = "tcommsat" freq_listening = list(ERT_FREQ, DTH_FREQ) produces_heat = 0 @@ -135,7 +135,7 @@ autolinkers = list("processor4") /obj/machinery/telecomms/processor/preset_cent - id = "CentComm Processor" + id = "CentCom Processor" network = "tcommsat" produces_heat = 0 autolinkers = list("processorCent") @@ -200,7 +200,7 @@ autolinkers = list("security") /obj/machinery/telecomms/server/presets/centcomm - id = "CentComm Server" + id = "CentCom Server" freq_listening = list(ERT_FREQ, DTH_FREQ) produces_heat = 0 autolinkers = list("centcomm") @@ -216,7 +216,7 @@ autolinkers = list("broadcasterA") /obj/machinery/telecomms/broadcaster/preset_cent - id = "CentComm Broadcaster" + id = "CentCom Broadcaster" network = "tcommsat" produces_heat = 0 autolinkers = list("broadcasterCent") \ No newline at end of file diff --git a/code/game/objects/effects/decals/posters/tgposters.dm b/code/game/objects/effects/decals/posters/tgposters.dm index 5fb94396d5..50d615efa0 100644 --- a/code/game/objects/effects/decals/posters/tgposters.dm +++ b/code/game/objects/effects/decals/posters/tgposters.dm @@ -41,10 +41,10 @@ /datum/poster/tg_9 name = "Missing Gloves" - desc = "This poster is about the uproar that followed Nanotrasen's financial cuts towards insulated-glove purchases." + desc = "This poster is about the uproar that followed NanoTrasen's financial cuts towards insulated-glove purchases." icon_state="poster9" /datum/poster/tg_10 name = "Hacking Guide" - desc = "This poster details the internal workings of the common Nanotrasen airlock." + desc = "This poster details the internal workings of the common NanoTrasen airlock." icon_state="poster10" \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index a0e37e28b8..94230418e8 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -97,6 +97,7 @@ var/list/civilian_cartridges = list( name = "\improper ChemWhiz cartridge" icon_state = "cart-chem" access_reagent_scanner = 1 + access_medical = 1 /obj/item/weapon/cartridge/security name = "\improper R.O.B.U.S.T. cartridge" diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm index 0cf4af6c74..2f05a6f385 100644 --- a/code/game/objects/items/devices/hacktool.dm +++ b/code/game/objects/items/devices/hacktool.dm @@ -62,7 +62,7 @@ if(hack_result && in_hack_mode) user << "Your hacking attempt was succesful!" - playsound(src.loc, 'sound/piano/A#6.ogg', 75) + user.playsound_local(get_turf(src), 'sound/piano/A#6.ogg', 50) else user << "Your hacking attempt failed!" return 0 diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index a7210721c8..3478abce1d 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -18,7 +18,7 @@ var/apc_drain_rate = 5000 // Max. amount drained from single APC. In Watts. var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts. var/power_drained = 0 // Amount of power drained. - var/max_power = 5e9 // Detonation point. + var/max_power = 1e9 // Detonation point. var/mode = 0 // 0 = off, 1=clamped (off), 2=operating var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs. diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 7b70216330..5388dc4420 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -143,13 +143,25 @@ REAGENT SCANNER user.show_message("Significant brain damage detected. Subject may have had a concussion.") if(ishuman(M)) var/mob/living/carbon/human/H = M + for(var/name_i in H.internal_organs_by_name) + var/obj/item/organ/internal/i = H.internal_organs_by_name[name_i] + if(istype(i, /obj/item/organ/internal/appendix)) + var/obj/item/organ/internal/appendix/a = H.internal_organs_by_name[name_i] + if(a.inflamed > 3) + user.show_message(text("Severe inflammation detected in subject [a.name]."), 1) + else if(a.inflamed > 2) + user.show_message(text("Moderate inflammation detected in subject [a.name]."), 1) + else if(a.inflamed >= 1) + user.show_message(text("Mild inflammation detected in subject [a.name]."), 1) + + for(var/name in H.organs_by_name) var/obj/item/organ/external/e = H.organs_by_name[name] if(!e) continue var/limb = e.name if(e.status & ORGAN_BROKEN) - if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!(e.status & ORGAN_SPLINTED))) + if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!e.splinted)) user << "Unsecured fracture in subject [limb]. Splinting recommended for transport." if(e.has_infected_wound()) user << "Infected wound detected in subject [limb]. Disinfection recommended." @@ -165,6 +177,7 @@ REAGENT SCANNER for(var/datum/wound/W in e.wounds) if(W.internal) user.show_message(text("Internal bleeding detected. Advanced scanner required for location."), 1) break + if(M:vessel) var/blood_volume = H.vessel.get_reagent_amount("blood") var/blood_percent = round((blood_volume / H.species.blood_volume)*100) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 3e9c9a7524..41ae7ac7c3 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -264,7 +264,7 @@ if(!(affecting.organ_tag in splintable_organs)) user << "You can't use \the [src] to apply a splint there!" return - if(affecting.status & ORGAN_SPLINTED) + if(affecting.splinted) user << "[M]'s [limb] is already splinted!" return if (M != user) @@ -275,17 +275,21 @@ user << "You can't apply a splint to the arm you're using!" return user.visible_message("[user] starts to apply \the [src] to their [limb].", "You start to apply \the [src] to your [limb].", "You hear something being wrapped.") - if(do_after(user, 50)) - if (M != user) - user.visible_message("[user] finishes applying \the [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.") - else - if(prob(25)) - user.visible_message("[user] successfully applies \the [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.") - else - user.visible_message("[user] fumbles \the [src].", "You fumble \the [src].", "You hear something being wrapped.") + if(do_after(user, 50, M)) + if(M == user && prob(75)) + user.visible_message("\The [user] fumbles [src].", "You fumble [src].", "You hear something being wrapped.") + return + var/obj/item/stack/medical/splint/S = split(1) + if(S) + if(affecting.apply_splint(S)) + S.forceMove(affecting) + if (M != user) + user.visible_message("\The [user] finishes applying [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.") + else + user.visible_message("\The [user] successfully applies [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.") return - affecting.status |= ORGAN_SPLINTED - use(1) + S.dropInto(src.loc) //didn't get applied, so just drop it + user.visible_message("\The [user] fails to apply [src].", "You fail to apply [src].", "You hear something being wrapped.") return diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index f201fbb3c6..3d3cb46192 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -94,6 +94,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/zippomes = "USER lights NAME with FLAME" var/weldermes = "USER lights NAME with FLAME" var/ignitermes = "USER lights NAME with FLAME" + var/brand /obj/item/clothing/mask/smokable/New() ..() @@ -169,6 +170,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM if (type_butt) var/obj/item/butt = new type_butt(T) transfer_fingerprints_to(butt) + if(brand) + butt.desc += " This one is \a [brand]." if(ismob(loc)) var/mob/living/M = loc if (!nomessage) diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 69207191e7..6189cc9658 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -280,3 +280,62 @@ name = "emergency response team medical backpack" desc = "A spacious backpack with lots of pockets, worn by medical members of an Emergency Response Team." icon_state = "ert_medical" + +/* + * Courier Bags + */ + +/obj/item/weapon/storage/backpack/messenger + name = "messenger bag" + desc = "A sturdy backpack worn over one shoulder." + icon_state = "courierbag" + item_state_slots = list(slot_r_hand_str = "backpack", slot_l_hand_str = "backpack") + +/obj/item/weapon/storage/backpack/messenger/chem + name = "chemistry messenger bag" + desc = "A serile backpack worn over one shoulder. This one is in Chemsitry colors." + icon_state = "courierbagchem" + item_state_slots = list(slot_r_hand_str = "chempack", slot_l_hand_str = "chempack") + +/obj/item/weapon/storage/backpack/messenger/med + name = "medical messenger bag" + desc = "A sterile backpack worn over one shoulder used in medical departments." + icon_state = "courierbagmed" + item_state_slots = list(slot_r_hand_str = "medicalpack", slot_l_hand_str = "medicalpack") + +/obj/item/weapon/storage/backpack/messenger/viro + name = "virology messenger bag" + desc = "A sterile backpack worn over one shoulder. This one is in Virology colors." + icon_state = "courierbagviro" + item_state_slots = list(slot_r_hand_str = "viropack", slot_l_hand_str = "viropack") + +/obj/item/weapon/storage/backpack/messenger/tox + name = "research messenger bag" + desc = "A backpack worn over one shoulder. Useful for holding science materials." + icon_state = "courierbagtox" + item_state_slots = list(slot_r_hand_str = "toxpack", slot_l_hand_str = "toxpack") + +/obj/item/weapon/storage/backpack/messenger/com + name = "command messenger bag" + desc = "A special backpack worn over one shoulder. This one is made specifically for officers." + icon_state = "courierbagcom" + item_state_slots = list(slot_r_hand_str = "captainpack", slot_l_hand_str = "captainpack") + +/obj/item/weapon/storage/backpack/messenger/engi + name = "engineering messenger bag" + icon_state = "courierbagengi" + item_state_slots = list(slot_r_hand_str = "engiepack", slot_l_hand_str = "engiepack") + +/obj/item/weapon/storage/backpack/messenger/hyd + name = "hydroponics messenger bag" + desc = "A backpack worn over one shoulder. This one is designed for plant-related work." + icon_state = "courierbaghyd" + +/obj/item/weapon/storage/backpack/messenger/sec + name = "security messenger bag" + desc = "A tactical backpack worn over one shoulder. This one is in Security colors." + icon_state = "courierbagsec" + item_state_slots = list(slot_r_hand_str = "securitypack", slot_l_hand_str = "securitypack") + +/obj/item/weapon/storage/backpack/messenger/black + icon_state = "courierbagblk" \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index f7de0b46f6..6f0beed5e9 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -56,6 +56,7 @@ /obj/item/weapon/extinguisher/mini, /obj/item/device/flashlight/maglight, /obj/item/weapon/tape_roll, + /obj/item/device/integrated_electronics/wirer, ) /obj/item/weapon/storage/belt/utility/full/New() @@ -128,6 +129,8 @@ /obj/item/weapon/reagent_containers/food/snacks/donut/, /obj/item/weapon/melee/baton, /obj/item/weapon/gun/energy/taser, + /obj/item/weapon/gun/energy/stunrevolver, + /obj/item/weapon/gun/energy/gun, /obj/item/weapon/flame/lighter, /obj/item/device/flashlight, /obj/item/device/pda, diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 2561886efa..009e1fcc90 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -134,6 +134,7 @@ storage_slots = 6 can_hold = list(/obj/item/clothing/mask/smokable/cigarette, /obj/item/weapon/flame/lighter) icon_type = "cigarette" + var/brand = "\improper Trans-Stellar Duty-free" /obj/item/weapon/storage/fancy/cigarettes/New() ..() @@ -142,6 +143,10 @@ new /obj/item/clothing/mask/smokable/cigarette(src) create_reagents(15 * storage_slots)//so people can inject cigarettes without opening a packet, now with being able to inject the whole one flags |= OPENCONTAINER + if(brand) + for(var/obj/item/clothing/mask/smokable/cigarette/C in src) + C.brand = brand + C.desc += " This one is \a [brand]." /obj/item/weapon/storage/fancy/cigarettes/update_icon() icon_state = "[initial(icon_state)][contents.len]" @@ -186,11 +191,13 @@ name = "\improper DromedaryCo packet" desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" icon_state = "Dpacket" + brand = "\improper Dromedary Co. cigarette" /obj/item/weapon/storage/fancy/cigarettes/killthroat name = "\improper AcmeCo packet" desc = "A packet of six AcmeCo cigarettes. For those who somehow want to obtain the record for the most amount of cancerous tumors." icon_state = "Bpacket" + brand = "\improper Acme Co. cigarette" // New() // ..() @@ -202,26 +209,31 @@ name = "\improper pack of Lucky Stars" desc = "A mellow blend made from synthetic, pod-grown tobacco. The commercial jingle is guaranteed to get stuck in your head." icon_state = "LSpacket" + brand = "\improper Lucky Star" /obj/item/weapon/storage/fancy/cigarettes/jerichos name = "\improper pack of Jerichos" desc = "Typically seen dangling from the lips of Martian soldiers and border world hustlers. Tastes like hickory smoke, feels like warm liquid death down your lungs." icon_state = "Jpacket" + brand = "\improper Jericho" /obj/item/weapon/storage/fancy/cigarettes/menthols name = "\improper pack of Temperamento Menthols" desc = "With a sharp and natural organic menthol flavor, these Temperamentos are a favorite of NDV crews. Hardly anyone knows they make 'em in non-menthol!" icon_state = "TMpacket" + brand = "\improper Temperamento Menthol" /obj/item/weapon/storage/fancy/cigarettes/carcinomas name = "\improper pack of Carcinoma Angels" desc = "This unknown brand was slated for the chopping block, until they were publicly endorsed by an old Earthling gonzo journalist. The rest is history. They sell a variety for cats, too." icon_state = "CApacket" + brand = "\improper Carcinoma Angel" /obj/item/weapon/storage/fancy/cigarettes/professionals name = "\improper pack of Professional 120s" desc = "Let's face it - if you're smoking these, you're either trying to look upper-class or you're 80 years old. That's the only excuse. They are, however, very good quality." icon_state = "P100packet" + brand = "\improper Professional 120" /obj/item/weapon/storage/fancy/cigar name = "cigar case" diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 7d0161a2fd..9c779f013a 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -127,10 +127,10 @@ filled = TRUE /obj/item/weapon/storage/toolbox/lunchbox/nt - name = "Nanotrasen brand lunchbox" + name = "NanoTrasen brand lunchbox" icon_state = "lunchbox_nanotrasen" item_state_slots = list(slot_r_hand_str = "toolbox_blue", slot_l_hand_str = "toolbox_blue") - desc = "A little lunchbox. This one is branded with the Nanotrasen logo!" + desc = "A little lunchbox. This one is branded with the NanoTrasen logo!" /obj/item/weapon/storage/toolbox/lunchbox/nt/filled filled = TRUE diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index d88e8c5372..107ea11520 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -394,3 +394,6 @@ var/shake_dir = pick(-1, 1) animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1) animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) + +/obj/structure/closet/onDropInto(var/atom/movable/AM) + return diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index a422768269..0f5d5119bb 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -131,6 +131,7 @@ new /obj/item/clothing/mask/bandana(src) new /obj/item/clothing/mask/bandana(src) new /obj/item/clothing/mask/bandana(src) + new /obj/item/weapon/storage/backpack/messenger/black(src) return @@ -539,6 +540,8 @@ new /obj/item/clothing/under/pants/khaki(src) new /obj/item/clothing/mask/bandana/blue(src) new /obj/item/clothing/mask/bandana/blue(src) + new /obj/item/clothing/accessory/hawaii(src) + new /obj/item/clothing/accessory/hawaii/random(src) return /obj/structure/closet/wardrobe/tactical @@ -603,6 +606,7 @@ new /obj/item/clothing/under/sl_suit(src) new /obj/item/clothing/under/suit_jacket(src) new /obj/item/clothing/under/suit_jacket/female(src) + new /obj/item/clothing/under/suit_jacket/female/skirt(src) new /obj/item/clothing/under/suit_jacket/really_black(src) new /obj/item/clothing/under/suit_jacket/red(src) new /obj/item/clothing/under/scratch(src) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index d6034bbb8a..5cdb49657a 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -265,7 +265,7 @@ /obj/structure/closet/crate/contraband name = "Poster crate" - desc = "A random assortment of posters manufactured by providers NOT listed under Nanotrasen's whitelist." + desc = "A random assortment of posters manufactured by providers NOT listed under NanoTrasen's whitelist." icon_state = "crate" icon_opened = "crateopen" icon_closed = "crate" diff --git a/code/global.dm b/code/global.dm index e2df3f0661..746352df6c 100644 --- a/code/global.dm +++ b/code/global.dm @@ -30,7 +30,7 @@ var/const/station_orig = "Virgo Orbital Research Establishment" //station_name c var/const/station_short = "V.O.R.E." var/const/dock_name = "Virgo-Erigone Central Command" var/const/boss_name = "Central Command" -var/const/boss_short = "Centcom" +var/const/boss_short = "CentCom" var/const/company_name = "NanoTrasen" var/const/company_short = "NT" var/const/star_name = "Virgo-Erigone" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index eaadf431bc..fe427b54d8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -440,6 +440,27 @@ counter = 0 jobs += "" + //Cargo (Yellow) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in cargo_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Cargo Positions
[replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
" + //Medical (White) counter = 0 jobs += "" @@ -617,6 +638,12 @@ var/datum/job/temp = job_master.GetJob(jobPos) if(!temp) continue joblist += temp.title + if("cargodept") + for(var/jobPos in cargo_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title if("medicaldept") for(var/jobPos in medical_positions) if(!jobPos) continue @@ -1323,19 +1350,19 @@ M.Weaken(20) M.stuttering = 20 - else if(href_list["CentcommReply"]) - var/mob/living/L = locate(href_list["CentcommReply"]) + else if(href_list["CentComReply"]) + var/mob/living/L = locate(href_list["CentComReply"]) if(!istype(L)) usr << "This can only be used on instances of type /mob/living/" return if(L.can_centcom_reply()) - var/input = sanitize(input(src.owner, "Please enter a message to reply to [key_name(L)] via their headset.","Outgoing message from Centcomm", "")) + var/input = sanitize(input(src.owner, "Please enter a message to reply to [key_name(L)] via their headset.","Outgoing message from CentCom", "")) if(!input) return src.owner << "You sent [input] to [L] via a secure channel." - log_admin("[src.owner] replied to [key_name(L)]'s Centcomm message with the message [input].") - message_admins("[src.owner] replied to [key_name(L)]'s Centcom message with: \"[input]\"") + log_admin("[src.owner] replied to [key_name(L)]'s CentCom message with the message [input].") + message_admins("[src.owner] replied to [key_name(L)]'s CentCom message with: \"[input]\"") if(!isAI(L)) L << "You hear something crackle in your headset for a moment before a voice speaks." L << "Please stand by for a message from Central Command." diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 844f74b5f6..1307086a87 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -27,8 +27,8 @@ feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //log_admin("HELP: [key_name(src)]: [msg]") -/proc/Centcomm_announce(var/msg, var/mob/Sender, var/iamessage) - msg = "\blue [uppertext(boss_short)]M[iamessage ? " IA" : ""]:[key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, src)]) (CA) (BSA) (RPLY): [msg]" +/proc/CentCom_announce(var/msg, var/mob/Sender, var/iamessage) + msg = "\blue [uppertext(boss_short)]M[iamessage ? " IA" : ""]:[key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, src)]) (CA) (BSA) (RPLY): [msg]" for(var/client/C in admins) if(R_ADMIN & C.holder.rights) C << msg diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm index 537f2632e7..79adec9afc 100644 --- a/code/modules/client/preference_setup/general/04_equipment.dm +++ b/code/modules/client/preference_setup/general/04_equipment.dm @@ -34,7 +34,7 @@ pref.all_underwear -= underwear_category_name // TODO - Looks like this is duplicating the work of sanitize_character() if so, remove - if(pref.backbag > 4 || pref.backbag < 1) + if(pref.backbag > 5 || pref.backbag < 1) pref.backbag = 1 //Same as above character.backbag = pref.backbag diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm index 769e9966c3..c5a67ad920 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm @@ -218,4 +218,16 @@ /datum/gear/accessory/chaps/black display_name = "chaps, black" - path = /obj/item/clothing/accessory/chaps/black \ No newline at end of file + path = /obj/item/clothing/accessory/chaps/black + +/datum/gear/accessory/hawaii + display_name = "hawaii shirt" + path = /obj/item/clothing/accessory/hawaii + +/datum/gear/accessory/hawaii/New() + ..() + var/list/shirts = list() + shirts["blue hawaii shirt"] = /obj/item/clothing/accessory/hawaii + shirts["red hawaii shirt"] = /obj/item/clothing/accessory/hawaii/red + shirts["random colored hawaii shirt"] = /obj/item/clothing/accessory/hawaii/random + gear_tweaks += new/datum/gear_tweak/path(shirts) diff --git a/code/modules/client/preference_setup/loadout/loadout_shoes.dm b/code/modules/client/preference_setup/loadout/loadout_shoes.dm index 29c6317b1f..29d6b5944e 100644 --- a/code/modules/client/preference_setup/loadout/loadout_shoes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_shoes.dm @@ -13,6 +13,10 @@ display_name = "workboots" path = /obj/item/clothing/shoes/workboots +/datum/gear/shoes/workboots/toeless + display_name = "toe-less workboots" + path = /obj/item/clothing/shoes/workboots/toeless + /datum/gear/shoes/sandals display_name = "sandals" path = /obj/item/clothing/shoes/sandal @@ -102,5 +106,21 @@ path = /obj/item/clothing/shoes/flipflop /datum/gear/shoes/flipflops/New() + ..() + gear_tweaks = list(gear_tweak_free_color_choice) + +/datum/gear/shoes/athletic + display_name = "athletic shoes" + path = /obj/item/clothing/shoes/athletic + +/datum/gear/shoes/athletic/New() + ..() + gear_tweaks = list(gear_tweak_free_color_choice) + +/datum/gear/shoes/skater + display_name = "skater shoes" + path = /obj/item/clothing/shoes/skater + +/datum/gear/shoes/skater/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index 041751d5c9..c79d4d31b2 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -364,4 +364,20 @@ /datum/gear/uniform/whitewedding display_name= "white wedding dress" - path = /obj/item/clothing/under/dress/white \ No newline at end of file + path = /obj/item/clothing/under/dress/white + +/datum/gear/uniform/skirts + display_name = "executive skirt" + path = /obj/item/clothing/under/suit_jacket/female/skirt + +/datum/gear/uniform/dresses + display_name = "sailor dress" + path = /obj/item/clothing/under/dress/sailordress + +/datum/gear/uniform/dresses/eveninggown + display_name = "red evening gown" + path = /obj/item/clothing/under/dress/redeveninggown + +/datum/gear/uniform/dresses/janimaid + display_name = "maid uniform" + path = /obj/item/clothing/under/dress/janimaid \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno.dm b/code/modules/client/preference_setup/loadout/loadout_xeno.dm index b8ed50c23f..cfe92370bf 100644 --- a/code/modules/client/preference_setup/loadout/loadout_xeno.dm +++ b/code/modules/client/preference_setup/loadout/loadout_xeno.dm @@ -126,4 +126,4 @@ display_name = "loincloth (Tajaran, Unathi)" path = /obj/item/clothing/under/shorts/loincloth sort_category = "Xenowear" - whitelisted = list("Tajaran", "Unathi") + //whitelisted = list("Tajaran", "Unathi") //VORESTATION EDIT diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index f815a3c5ea..444b87754e 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -54,7 +54,7 @@ if(alt_title && !(alt_title in job.alt_titles)) pref.player_alt_titles -= job.title -/datum/category_item/player_setup_item/occupation/content(mob/user, limit = 16, list/splitJobs = list("Chief Medical Officer")) +/datum/category_item/player_setup_item/occupation/content(mob/user, limit = 17, list/splitJobs = list("Chief Medical Officer")) if(!job_master) return diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index f65b5373bb..a8305dd9ac 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -1,5 +1,5 @@ /obj/item/clothing/head/centhat - name = "\improper CentComm. hat" + name = "\improper CentCom. hat" icon_state = "centcom" desc = "It's good to be emperor." siemens_coefficient = 0.9 diff --git a/code/modules/clothing/shoes/jobs.dm b/code/modules/clothing/shoes/jobs.dm index 63d4dc192a..00dc994cad 100644 --- a/code/modules/clothing/shoes/jobs.dm +++ b/code/modules/clothing/shoes/jobs.dm @@ -29,4 +29,11 @@ icon_state = "workboots" armor = list(melee = 40, bullet = 0, laser = 0, energy = 15, bomb = 20, bio = 0, rad = 20) siemens_coefficient = 0.7 - can_hold_knife = 1 \ No newline at end of file + can_hold_knife = 1 + +/obj/item/clothing/shoes/workboots/toeless + name = "toe-less workboots" + desc = "A pair of toeless work boots designed for use in industrial settings. Modified for species whose toes have claws." + icon_state = "workbootstoeless" + item_state_slots = list(slot_r_hand_str = "workboots", slot_l_hand_str = "workboots") + species_restricted = null \ No newline at end of file diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 723d802186..fd8e5c7c40 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -205,3 +205,15 @@ name = "flip flops" desc = "A pair of foam flip flops. For those not afraid to show a little ankle." icon_state = "thongsandal" + +/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" + 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" + item_state_slots = list(slot_r_hand_str = "skaterheld", slot_l_hand_str = "skaterheld") diff --git a/code/modules/clothing/spacesuits/rig/suits/station.dm b/code/modules/clothing/spacesuits/rig/suits/station.dm index 17d5d53425..914afe8d97 100644 --- a/code/modules/clothing/spacesuits/rig/suits/station.dm +++ b/code/modules/clothing/spacesuits/rig/suits/station.dm @@ -124,15 +124,16 @@ offline_vision_restriction = 0 helm_type = /obj/item/clothing/head/helmet/space/rig/ce + glove_type = /obj/item/clothing/gloves/gauntlets/rig/ce allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) - req_access = list() req_one_access = list() - boot_type = null - glove_type = null +/obj/item/clothing/gloves/gauntlets/rig/ce + name = "insulated gauntlets" + siemens_coefficient = 0 /obj/item/weapon/rig/ce/equipped @@ -146,14 +147,6 @@ /obj/item/rig_module/vision/meson ) - chest_type = /obj/item/clothing/suit/space/rig/ce - boot_type = null - glove_type = null - -/obj/item/clothing/suit/space/rig/ce - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - /obj/item/weapon/rig/hazmat name = "AMI control module" diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index f06e839ae3..942921b0e9 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -63,7 +63,7 @@ var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit. /obj/item/clothing/suit/space/equipped(mob/M) - check_limb_support() + check_limb_support(M) ..() /obj/item/clothing/suit/space/dropped(var/mob/user) @@ -77,14 +77,24 @@ /obj/item/clothing/suit/space/proc/check_limb_support(var/mob/living/carbon/human/user) // If this isn't set, then we don't need to care. - if(!supporting_limbs || !supporting_limbs.len) + if(!istype(user) || isnull(supporting_limbs)) return - if(!istype(user) || user.wear_suit == src) - return + if(user.wear_suit == src) + for(var/obj/item/organ/external/E in user.bad_external_organs) + if(E.is_broken() && E.apply_splint(src)) + user << "You feel [src] constrict about your [E.name], supporting it." + supporting_limbs |= E + else + // Otherwise, remove the splints. + for(var/obj/item/organ/external/E in supporting_limbs) + if(E.splinted == src && E.remove_splint(src)) + user << "\The [src] stops supporting your [E.name]." + supporting_limbs.Cut() - // Otherwise, remove the splints. - for(var/obj/item/organ/external/E in supporting_limbs) - E.status &= ~ ORGAN_SPLINTED - user << "The suit stops supporting your [E.name]." - supporting_limbs = list() +/obj/item/clothing/suit/space/proc/handle_fracture(var/mob/living/carbon/human/user, var/obj/item/organ/external/E) + if(!istype(user) || isnull(supporting_limbs)) + return + if(E.is_broken() && E.apply_splint(src)) + user << "You feel [src] constrict about your [E.name], supporting it." + supporting_limbs |= E diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index f69df89f3f..fd03c3cbe4 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -7,7 +7,7 @@ item_state_slots = list(slot_r_hand_str = "eng_helm", slot_l_hand_str = "eng_helm") armor = list(melee = 40, bullet = 5, laser = 20, energy = 5, bomb = 35, bio = 100, rad = 80) -/obj/item/clothing/head/helmet/space/void/engineering/rad +/obj/item/clothing/head/helmet/space/void/engineering/hazmat name = "HAZMAT voidsuit helmet" icon_state = "rig0-engineering_rad" item_state_slots = list(slot_r_hand_str = "eng_helm_rad", slot_l_hand_str = "eng_helm_rad") @@ -26,7 +26,7 @@ armor = list(melee = 40, bullet = 5, laser = 20, energy = 5, bomb = 35, bio = 100, rad = 80) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) -/obj/item/clothing/suit/space/void/engineering/rad +/obj/item/clothing/suit/space/void/engineering/hazmat name = "HAZMAT voidsuit" icon_state = "rig-engineering_rad" item_state_slots = list(slot_r_hand_str = "eng_voidsuit_rad", slot_l_hand_str = "eng_voidsuit_rad") @@ -60,6 +60,11 @@ item_state_slots = list(slot_r_hand_str = "medical_helm", slot_l_hand_str = "medical_helm") armor = list(melee = 30, bullet = 5, laser = 20, energy = 5, bomb = 25, bio = 100, rad = 50) +/obj/item/clothing/head/helmet/space/void/medical/bio + name = "biohazard voidsuit helmet" + icon_state = "rig0-medical_bio" + item_state_slots = list(slot_r_hand_str = "medical_helm_bio", slot_l_hand_str = "medical_helm_bio") + /obj/item/clothing/suit/space/void/medical name = "medical voidsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." @@ -68,6 +73,11 @@ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) armor = list(melee = 30, bullet = 5, laser = 20, energy = 5, bomb = 25, bio = 100, rad = 50) +/obj/item/clothing/suit/space/void/medical/bio + name = "biohazard voidsuit" + icon_state = "rig-medical_bio" + item_state_slots = list(slot_r_hand_str = "medical_voidsuit_bio", slot_l_hand_str = "medical_voidsuit_bio") + //Security /obj/item/clothing/head/helmet/space/void/security name = "security voidsuit helmet" diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 3476ea183a..648cf07a41 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -44,7 +44,6 @@ desc = "A vest with heavy padding to protect against melee attacks." icon_state = "riot" item_state_slots = list(slot_r_hand_str = "swat", slot_l_hand_str = "swat") - slowdown = 1 armor = list(melee = 80, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) flags_inv = HIDEJUMPSUIT siemens_coefficient = 0.5 @@ -323,6 +322,12 @@ icon_badge = "detectivevest_badge" icon_nobadge = "detectivevest_nobadge" +/obj/item/clothing/suit/storage/vest/press + name = "press vest" + desc = "A simple kevlar plate carrier. This one has the word 'Press' embroidered on patches on the back and front." + item_state_slots = list(slot_r_hand_str = "armor", slot_l_hand_str = "armor") + allowed = list(/obj/item/device/flashlight,/obj/item/device/taperecorder,/obj/item/weapon/pen,/obj/item/device/camera_film,/obj/item/device/camera) + /obj/item/clothing/suit/storage/vest/heavy name = "heavy armor vest" desc = "A heavy kevlar plate carrier with webbing attached." diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index fecc19b5a2..2dc9e22404 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -90,6 +90,7 @@ icon_state = "vest" item_state_slots = list(slot_r_hand_str = "wcoat", slot_l_hand_str = "wcoat") blood_overlay_type = "armor" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) body_parts_covered = UPPER_TORSO|LOWER_TORSO /obj/item/clothing/suit/wcoat/red @@ -203,6 +204,7 @@ name = "leather coat" desc = "A long, thick black leather coat." icon_state = "leathercoat_alt" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket") /obj/item/clothing/suit/leathercoat/sec @@ -215,12 +217,14 @@ name = "brown leather coat" desc = "A long, brown leather coat." icon_state = "browncoat" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket") /obj/item/clothing/suit/neocoat name = "black coat" desc = "A flowing, black coat." icon_state = "neocoat" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket") /obj/item/clothing/suit/customs @@ -292,6 +296,7 @@ item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket") icon_open = "bomber_open" icon_closed = "bomber" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) body_parts_covered = UPPER_TORSO|ARMS cold_protection = UPPER_TORSO|ARMS min_cold_protection_temperature = T0C - 20 @@ -311,6 +316,7 @@ name = "leather jacket" desc = "A black leather coat." icon_state = "leather_jacket" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) body_parts_covered = UPPER_TORSO|ARMS /obj/item/clothing/suit/storage/leather_jacket/alt @@ -330,6 +336,7 @@ item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket") icon_open = "brown_jacket_open" icon_closed = "brown_jacket" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) body_parts_covered = UPPER_TORSO|ARMS /obj/item/clothing/suit/storage/toggle/brown_jacket/nanotrasen @@ -491,6 +498,7 @@ hooded = 1 action_button_name = "Toggle Winter Hood" hoodtype = /obj/item/clothing/head/winterhood + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) /obj/item/clothing/head/winterhood name = "winter hood" @@ -556,6 +564,7 @@ name = "black varsity jacket" desc = "A favorite of jocks everywhere from Sol to Nyx." icon_state = "varsity" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black") /obj/item/clothing/suit/varsity/red @@ -588,6 +597,7 @@ item_state_slots = list(slot_r_hand_str = "black_labcoat", slot_l_hand_str = "black_labcoat") icon_open = "trackjacket_open" icon_closed = "trackjacket" + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) /obj/item/clothing/suit/storage/toggle/track/blue name = "blue track jacket" @@ -624,6 +634,7 @@ desc = "A comfy, grey flannel shirt. Unleash your inner hipster." icon_state = "flannel" item_state_slots = list(slot_r_hand_str = "black_labcoat", slot_l_hand_str = "black_labcoat") + allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask) var/rolled = 0 var/tucked = 0 var/buttoned = 0 diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index e732a1318e..53ea2d85b6 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -78,7 +78,6 @@ name = "Radiation Hood" icon_state = "rad" desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation" - flags_inv = BLOCKHAIR body_parts_covered = HEAD|FACE|EYES armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) diff --git a/code/modules/clothing/under/accessories/clothing.dm b/code/modules/clothing/under/accessories/clothing.dm index 9878420d7c..af5b6c1c7a 100644 --- a/code/modules/clothing/under/accessories/clothing.dm +++ b/code/modules/clothing/under/accessories/clothing.dm @@ -112,4 +112,20 @@ name = "cargo poncho" desc = "A simple, comfortable cloak without sleeves. This one is tan and grey, the colors of Cargo." icon_state = "cargoponcho" - item_state = "cargoponcho" \ No newline at end of file + item_state = "cargoponcho" + +/obj/item/clothing/accessory/hawaii + name = "flower-pattern shirt" + desc = "You probably need some welder googles to look at this." + icon_state = "hawaii" + +/obj/item/clothing/accessory/hawaii/red + icon_state = "hawaii2" + +/obj/item/clothing/accessory/hawaii/random + name = "flower-pattern shirt" + +/obj/item/clothing/accessory/hawaii/random/New() + if(prob(50)) + icon_state = "hawaii2" + color = color_rotation(rand(-11,12)*15) \ No newline at end of file diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index e673de378c..4b22d93877 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -182,6 +182,13 @@ icon_state = "black_suit_fem" item_state_slots = list(slot_r_hand_str = "lawyer_black", slot_l_hand_str = "lawyer_black") +/obj/item/clothing/under/suit_jacket/female/skirt + name = "executive skirt" + desc = "A formal suit skirt for women, intended for the station's finest." + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + icon_state = "black_suit_fem" + item_state = "black_formal_skirt" + /obj/item/clothing/under/suit_jacket/red name = "red suit" desc = "A red suit and blue tie. Somewhat formal." diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 3c210cc0c0..3d35b489d6 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -6,26 +6,51 @@ gender = PLURAL body_parts_covered = LOWER_TORSO|LEGS +/obj/item/clothing/under/pants/ripped + name = "ripped jeans" + desc = "A nondescript pair of tough blue jeans with holes in them." + icon_state = "jeansripped" + /obj/item/clothing/under/pants/classicjeans name = "classic jeans" desc = "You feel cooler already." icon_state = "jeansclassic" +/obj/item/clothing/under/pants/classicjeans/ripped + name = "ripped classic jeans" + desc = "You feel cooler already. These have holes in them." + icon_state = "jeansclassicripped" + /obj/item/clothing/under/pants/mustangjeans name = "must hang jeans" desc = "Made in the finest space jeans factory this side of Alpha Centauri." icon_state = "jeansmustang" +/obj/item/clothing/under/pants/mustangjeans/ripped + name = "ripped must hang jeans" + desc = "Made in the finest space jeans factory this side of Alpha Centauri. These have holes in them." + icon_state = "jeansmustangripped" + /obj/item/clothing/under/pants/blackjeans name = "black jeans" desc = "Only for those who can pull it off." icon_state = "jeansblack" +/obj/item/clothing/under/pants/blackjeans/ripped + name = "ripped black jeans" + desc = "Only for those who can pull it off. These have holes in them." + icon_state = "jeansblackripped" + /obj/item/clothing/under/pants/greyjeans name = "grey jeans" desc = "Only for those who can pull it off." icon_state = "jeansgrey" +/obj/item/clothing/under/pants/greyjeans/ripped + name = "ripped grey jeans" + desc = "Only for those who can pull it off. These have holes in them." + icon_state = "jeansgreyripped" + /obj/item/clothing/under/pants/youngfolksjeans name = "young folks jeans" desc = "For those tired of boring old jeans. Relive the passion of your youth!" diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index e108c7f33e..0db35dd08c 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -25,6 +25,10 @@ name = "grey athletic shorts" icon_state = "greyshorts" +/obj/item/clothing/under/shorts/white + name = "white shorts" + icon_state = "whiteshorts" + /obj/item/clothing/under/shorts/jeans name = "jeans shorts" desc = "Some jeans! Just in short form!" diff --git a/code/modules/economy/TradeDestinations.dm b/code/modules/economy/TradeDestinations.dm index ccedfe35ef..8ae548e2ff 100644 --- a/code/modules/economy/TradeDestinations.dm +++ b/code/modules/economy/TradeDestinations.dm @@ -18,7 +18,7 @@ var/list/weighted_mundaneevent_locations = list() //distance is measured in AU and co-relates to travel time /datum/trade_destination/centcomm - name = "CentComm" + name = "CentCom" description = "NanoTrasen's administrative centre for Tau Ceti." distance = 1.2 willing_to_buy = list() diff --git a/code/modules/examine/descriptions/devices.dm b/code/modules/examine/descriptions/devices.dm index 05182df0a5..33954f6672 100644 --- a/code/modules/examine/descriptions/devices.dm +++ b/code/modules/examine/descriptions/devices.dm @@ -8,7 +8,7 @@ that while in space, across star systems, and that the consumer can afford and use without training, is much more recent, and is thanks to the backbone \ that is the Exonet.
\
\ - The Exonet is the predominant interstellar telecom system, servicing trillions of devices across a large portion of human-controlled space. \ + The Exonet is the predominant interstellar telecomm system, servicing trillions of devices across a large portion of human-controlled space. \ It is distributed by a massive network of telecommunication satellites, some privately owned and others owned by the systems’ local governments, \ that utilize FTL technologies to bounce data between satellites at speeds that would not be possible at sub-light technology. This communicator \ uses a protocol called Exonet Protocol Version 2, generally shortened to EPv2.
\ diff --git a/code/modules/examine/descriptions/telecomms.dm b/code/modules/examine/descriptions/telecomms.dm index 747697f55f..45101ec130 100644 --- a/code/modules/examine/descriptions/telecomms.dm +++ b/code/modules/examine/descriptions/telecomms.dm @@ -30,7 +30,7 @@ Exonets at the root node(s), and is typically arranged in a tree structure. The root node(s) are generally government-owned and are very secure \ and resilient to failure.
\
\ - This node is privately owned and maintained by Nanotrasen, and allows the colonists of the "+station_orig+" to have access to the Exonet." + This node is privately owned and maintained by NanoTrasen, and allows the colonists of the "+station_orig+" to have access to the Exonet." description_antag = "An EMP will disable this device for a short period of time. A longer downage can be achieved by turning it off, or rigging \ the APC it uses to turn off remotely, such as with a signaler in the right wire." \ No newline at end of file diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index 3fcf07713b..42bd4b709b 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -146,7 +146,7 @@ for(var/datum/playingcard/P in cards) H.cards += P H.concealed = src.concealed - user.drop_from_inventory(src,user.loc) + user.drop_from_inventory(src) qdel(src) H.update_icon() return diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm new file mode 100644 index 0000000000..97acfd2c98 --- /dev/null +++ b/code/modules/integrated_electronics/_defines.dm @@ -0,0 +1,387 @@ +#define DATA_CHANNEL "data channel" +#define PULSE_CHANNEL "pulse channel" + +/obj/item/integrated_circuit + name = "integrated circuit" + desc = "It's a tiny chip! This one doesn't seem to do much, however." + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "template" + w_class = 1 + var/extended_desc = null + var/list/inputs = list() + var/list/outputs = list() + var/list/activators = list() + var/number_of_inputs = 0 //This is how many input pins are created + var/number_of_outputs = 0 //Likewise for output + var/number_of_activators = 0 //Guess + var/list/input_names = list() + var/list/output_names = list() + var/list/activator_names = list() + var/last_used = 0 //Uses world.time + var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. + var/cooldown_per_use = 2 SECONDS + +/obj/item/integrated_circuit/examine(mob/user) + ..() + user << "This board has [inputs.len] input [inputs.len != 1 ? "pins" : "pin"] and \ + [outputs.len] output [outputs.len != 1 ? "pins" : "pin"]." + for(var/datum/integrated_io/input/I in inputs) + if(I.linked.len) + user << "\The [I.name] is connected to [I.get_linked_to_desc()]." + for(var/datum/integrated_io/output/O in outputs) + if(O.linked.len) + user << "\The [O.name] is connected to [O.get_linked_to_desc()]." + for(var/datum/integrated_io/activate/A in activators) + if(A.linked.len) + user << "\The [A.name] is connected to [A.get_linked_to_desc()]." + + interact(user) + +/obj/item/integrated_circuit/New() + ..() + var/i = 0 + if(number_of_inputs) + for(i = number_of_inputs, i > 0, i--) + inputs.Add(new /datum/integrated_io/input(src)) + + if(number_of_outputs) + for(i = number_of_outputs, i > 0, i--) + outputs.Add(new /datum/integrated_io/output(src)) + + if(number_of_activators) + for(i = number_of_activators, i > 0, i--) + activators.Add(new /datum/integrated_io/activate(src)) + + apply_names_to_io() + +/obj/item/integrated_circuit/proc/apply_names_to_io() + var/i = 1 + if(input_names.len) + for(var/datum/integrated_io/input/I in inputs) + I.name = "[input_names[i]]" + i++ + i = 1 + if(output_names.len) + for(var/datum/integrated_io/output/O in outputs) + O.name = "[output_names[i]]" + i++ + + i = 1 + if(activator_names.len) + for(var/datum/integrated_io/activate/A in activators) + A.name = "[activator_names[i]]" + i++ + +/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit. + return + +/obj/item/integrated_circuit/Destroy() + for(var/datum/integrated_io/I in inputs) + qdel(I) + for(var/datum/integrated_io/O in outputs) + qdel(O) + for(var/datum/integrated_io/A in activators) + qdel(A) + ..() + +/obj/item/integrated_circuit/emp_act(severity) + for(var/datum/integrated_io/io in inputs + outputs + activators) + io.scramble() + +/obj/item/integrated_circuit/verb/rename_component() + set name = "Rename Circuit" + set category = "Object" + set desc = "Rename your circuit, useful to stay organized." + + var/mob/M = usr + + if(!M.canmove || M.stat || M.restrained()) + return + + var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name), MAX_NAME_LEN) + + if(src && input) + M << "The circuit '[src.name]' is now labeled '[input]'." + name = input + +/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number) + switch(pin_type) + if("input") + if(pin_number > inputs.len) + return null + return inputs[pin_number] + if("output") + if(pin_number > outputs.len) + return null + return outputs[pin_number] + if("activator") + if(pin_number > activators.len) + return null + return activators[pin_number] + return null + +/obj/item/integrated_circuit/interact(mob/user) + if(get_dist(get_turf(src), user) > 1) + user.unset_machine(src) + return + var/HTML = "[src.name]" + HTML += "
" + HTML += "
" + + HTML += "
\[Refresh\] | " + HTML += "\[Rename\]
" + + HTML += "" + HTML += "" + HTML += "" + HTML += "" + HTML += "" + + var/column_width = 3 + var/row_height = max(inputs.len, outputs.len, 1) + var/i + var/j + for(i = 1, i < row_height+1, i++) + HTML += "" + for(j = 1, j < column_width+1, j++) + var/datum/integrated_io/io = null + var/words = null + var/height = 1 + switch(j) + if(1) + io = get_pin_ref("input",i) + if(io) + if(io.linked.len) + words = "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else // "Click here!" + words = "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + if(outputs.len > inputs.len) + // height = Floor(outputs.len / inputs.len) + height = 1 // Because of bugs, if there's more outputs than inputs, it causes the output side to be hidden. + //world << "I wrote [words] at ([i],[j]). Height = [height]." + if(2) + if(i == 1) + words = "[src.name]

[src.desc]" + height = row_height + //world << "I wrote the center piece because i was equal to 1, at ([i],[j]). Height = [height]." + else + continue + if(3) + io = get_pin_ref("output",i) + if(io) + if(io.linked.len) + words = "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else + words = "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + if(inputs.len > outputs.len) + // height = Floor(inputs.len / outputs.len) + height = 1 // See above. + //world << "I wrote [words] at ([i],[j]). Height = [height]." + HTML += "" + //HTML += "" + //world << "Writing to ([i],[j])." + HTML += "" + + if(activators.len) + for(i = 1, i < activators.len+1, i++) + var/datum/integrated_io/io = null + var/words = null + io = get_pin_ref("activator",i) + if(io) + if(io.linked.len) + words = "[io.name]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else // "Click here!" + words = "[io.name]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + HTML += "" + HTML += "" + HTML += "" + + HTML += "
[words][words]
[words]
" + HTML += "" + + HTML += "
Complexity: [complexity]" + HTML += "
[extended_desc]" + + HTML += "" + user << browse(HTML, "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") + + //user << sanitize(HTML, "window=debug;size=400x400;border=1;can_resize=1;can_close=1;can_minimize=1") + //world << sanitize(HTML) + + user.set_machine(src) + onclose(user, "circuit-\ref[src]") + +/obj/item/integrated_circuit/Topic(href, href_list[]) + var/mob/living/user = locate(href_list["user"]) in mob_list + var/pin = locate(href_list["pin"]) in inputs + outputs + activators + + if(!user || !user.Adjacent(get_turf(src)) ) + return 1 + + if(!user.canmove || user.stat || user.restrained()) + return + + if(href_list["wire"]) + if(ishuman(user) && Adjacent(user)) + var/mob/living/carbon/human/H = user + var/obj/held_item = H.get_active_hand() + + if(istype(held_item, /obj/item/device/integrated_electronics/wirer)) + var/obj/item/device/integrated_electronics/wirer/wirer = held_item + if(pin) + wirer.wire(pin, user) + + else if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) + var/obj/item/device/integrated_electronics/debugger/debugger = held_item + if(pin) + debugger.write_data(pin, user) + + // if(istype(H.r_hand, /obj/item/device/integrated_electronics/wirer)) + // wirer = H.r_hand + // else if(istype(H.l_hand, /obj/item/device/integrated_electronics/wirer)) + // wirer = H.l_hand + + // if(wirer && pin) + // wirer.wire(pin, user) + else + user << "You can't do a whole lot without tools." + + if(href_list["examine"]) + examine(user) + + if(href_list["rename"]) + rename_component(user) + + interact(user) // To refresh the UI. + +/datum/integrated_io + var/name = "input/output" + var/obj/item/integrated_circuit/holder = null + var/data = null + var/list/linked = list() + var/io_type = DATA_CHANNEL + +/datum/integrated_io/New(var/newloc) + ..() + holder = newloc + if(!holder) + message_admins("ERROR: An integrated_io ([src.name]) spawned without a holder! This is a bug.") + +/datum/integrated_io/Destroy() + disconnect() + holder = null + ..() + +/datum/integrated_io/proc/display_data() + if(isnull(data)) + return "(null)" // Empty data means nothing to show. + if(istext(data)) + return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'. + if(istype(data, /atom)) + var/atom/A = data + return "([A.name] \[Ref\])" // For refs, we want just the name displayed. + return "([data])" // Nothing special needed for numbers or other stuff. + +/datum/integrated_io/activate/display_data() + return "(\[pulse\])" + +/datum/integrated_io/proc/scramble() + if(isnull(data)) + return + if(isnum(data)) + write_data_to_pin(rand(-10000, 10000)) + if(istext(data)) + write_data_to_pin("ERROR") + push_data() + +/datum/integrated_io/activate/scramble() + push_data() + +/datum/integrated_io/proc/write_data_to_pin(var/new_data) + if(isnull(new_data) || isnum(new_data) || istext(new_data) || istype(new_data, /atom/) ) // Anything else is a type we don't want. + data = new_data + holder.on_data_written() + +/datum/integrated_io/proc/push_data() + if(linked.len) + for(var/datum/integrated_io/io in linked) + io.write_data_to_pin(data) + +/datum/integrated_io/activate/push_data() + if(linked.len) + for(var/datum/integrated_io/io in linked) + io.holder.work() + +/datum/integrated_io/proc/pull_data() + if(linked.len) + for(var/datum/integrated_io/io in linked) + write_data_to_pin(io.data) + +/datum/integrated_io/proc/get_linked_to_desc() + if(linked.len) + var/result = english_list(linked) + return "the [result]" + return "nothing" + +/datum/integrated_io/proc/disconnect() + if(linked.len) + //First we iterate over everything we are linked to. + for(var/datum/integrated_io/their_io in linked) + //While doing that, we iterate them as well, and disconnect ourselves from them. + for(var/datum/integrated_io/their_linked_io in their_io.linked) + if(their_linked_io == src) + their_io.linked.Remove(src) + else + continue + //Now that we're removed from them, we gotta remove them from us. + src.linked.Remove(their_io) + +/datum/integrated_io/input + name = "input pin" + +/datum/integrated_io/output + name = "output pin" + +/datum/integrated_io/activate + name = "activation pin" + io_type = PULSE_CHANNEL + +/obj/item/integrated_circuit/proc/push_data() + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +/obj/item/integrated_circuit/proc/pull_data() + for(var/datum/integrated_io/input/I in inputs) + I.push_data() + +/obj/item/integrated_circuit/proc/work(var/datum/integrated_io/io) + if(last_used + cooldown_per_use > world.time) // All intergrated circuits have an internal cooldown, to protect from spam. + return 0 + last_used = world.time + return 1 + +/obj/item/integrated_circuit/proc/disconnect_all() + for(var/datum/integrated_io/input/I in inputs) + I.disconnect() + for(var/datum/integrated_io/output/O in outputs) + O.disconnect() + for(var/datum/integrated_io/activate/A in activators) + A.disconnect() \ No newline at end of file diff --git a/code/modules/integrated_electronics/arithmetic.dm b/code/modules/integrated_electronics/arithmetic.dm new file mode 100644 index 0000000000..3fc60c64f9 --- /dev/null +++ b/code/modules/integrated_electronics/arithmetic.dm @@ -0,0 +1,183 @@ +//These circuits do simple math. +/obj/item/integrated_circuit/arithmetic + complexity = 1 + number_of_inputs = 8 + number_of_outputs = 1 + number_of_activators = 1 + input_names = list( + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H" + ) + output_names = list( + "result" + ) + activator_names = list( + "compute" + ) + +// +Adding+ // + +/obj/item/integrated_circuit/arithmetic/addition + name = "addition circuit" + desc = "This circuit can add numbers together." + icon_state = "addition" + +/obj/item/integrated_circuit/arithmetic/addition/work() + if(..()) + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data)) + result = result + I.data + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// -Subtracting- // + +/obj/item/integrated_circuit/arithmetic/subtraction + name = "subtraction circuit" + desc = "This circuit can subtract numbers." + icon_state = "subtraction" + +/obj/item/integrated_circuit/arithmetic/subtraction/work() + if(..()) + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data)) + result = result - I.data + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// *Multiply* // + +/obj/item/integrated_circuit/arithmetic/multiplication + name = "multiplication circuit" + desc = "This circuit can multiply numbers." + icon_state = "multiplication" + +/obj/item/integrated_circuit/arithmetic/subtraction/work() + if(..()) + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data)) + result = result * I.data + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// /Division/ // + +/obj/item/integrated_circuit/arithmetic/division + name = "division circuit" + desc = "This circuit can divide numbers, just don't think about trying to divide by zero!" + icon_state = "division" + +/obj/item/integrated_circuit/arithmetic/division/work() + if(..()) + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data) && I.data != 0) //No runtimes here. + result = result / I.data + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// Absolute // + +/obj/item/integrated_circuit/arithmetic/absolute + name = "absolute circuit" + desc = "This outputs a non-negative version of the number you put in. This may also be thought of as its distance from zero." + icon_state = "absolute" + number_of_inputs = 1 + number_of_outputs = 1 + +/obj/item/integrated_circuit/arithmetic/absolute/work() + if(..()) + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data) && I.data != 0) + result = abs(result) + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// Averaging // + +/obj/item/integrated_circuit/arithmetic/average + name = "average circuit" + desc = "This circuit is of average quality, however it will compute the average for numbers you give it." + icon_state = "average" + +/obj/item/integrated_circuit/arithmetic/average/work() + if(..()) + var/result = 0 + var/inputs_used = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data)) + inputs_used++ + result = result + I.data + + if(inputs_used) + result = result / inputs_used + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// Pi, because why the hell not? // +/obj/item/integrated_circuit/arithmetic/pi + name = "pi constant circuit" + desc = "Not recommended for cooking. Outputs '3.14159' when it receives a pulse." + icon_state = "pi" + number_of_inputs = 0 + number_of_outputs = 1 + +/obj/item/integrated_circuit/arithmetic/pi/work() + if(..()) + var/datum/integrated_io/output/O = outputs[1] + O.data = 3.14159 + O.push_data() + +// Random // +/obj/item/integrated_circuit/arithmetic/random + name = "random number generator circuit" + desc = "This gives a random (integer) number between values A and B inclusive." + icon_state = "random" + number_of_inputs = 2 + number_of_outputs = 1 + number_of_activators = 1 + input_names = list( + "L", + "H" + ) + +/obj/item/integrated_circuit/arithmetic/random/work() + if(..()) + var/result = 0 + var/datum/integrated_io/L = inputs[1] + var/datum/integrated_io/H = inputs[2] + + if(isnum(L.data) && isnum(H.data)) + result = rand(L.data, H.data) + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/assemblies.dm b/code/modules/integrated_electronics/assemblies.dm new file mode 100644 index 0000000000..f9037e60e7 --- /dev/null +++ b/code/modules/integrated_electronics/assemblies.dm @@ -0,0 +1,168 @@ +/obj/item/device/electronic_assembly + name = "electronic assembly" + desc = "It's a case, for building electronics with." + w_class = 2 + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "setup_small" + var/max_components = 10 + var/max_complexity = 40 + var/opened = 0 + +/obj/item/device/electronic_assembly/medium + name = "electronic mechanism" + icon_state = "setup_medium" + w_class = 3 + max_components = 20 + max_complexity = 80 + +/obj/item/device/electronic_assembly/large + name = "electronic machine" + icon_state = "setup_large" + w_class = 4 + max_components = 30 + max_complexity = 120 + +/obj/item/device/electronic_assembly/drone + name = "electronic drone" + icon_state = "setup_drone" + w_class = 3 + max_components = 25 + max_complexity = 100 + +/obj/item/device/electronic_assembly/interact(mob/user) + if(get_dist(get_turf(src), user) > 1) + user.unset_machine(src) + return + var/total_parts = 0 + var/total_complexity = 0 + for(var/obj/item/integrated_circuit/part in contents) + total_parts++ + total_complexity = total_complexity + part.complexity + var/HTML = "[src.name]" + + HTML += "
\[Refresh\] | " + HTML += "\[Rename\]
" + HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.
" + HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity." + HTML += "

" + HTML += "Components;
" + for(var/obj/item/integrated_circuit/circuit in contents) + HTML += "[circuit.name] | " + HTML += "\[Rename\]" + HTML += "
" + + HTML += "" + user << browse(HTML, "window=assembly-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") + +/obj/item/device/electronic_assembly/Topic(href, href_list[]) + var/mob/living/user = locate(href_list["user"]) in mob_list + + if(..()) + return 1 + + if(!user.canmove || user.stat || user.restrained()) + return + + if(href_list["rename"]) + rename(user) + + interact(user) // To refresh the UI. + +/obj/item/device/electronic_assembly/verb/rename() + set name = "Rename Circuit" + set category = "Object" + set desc = "Rename your circuit, useful to stay organized." + + var/mob/M = usr + + if(!M.canmove || M.stat || M.restrained()) + return + + var/input = sanitizeSafe(input("What do you want to name this?", "Rename", src.name), MAX_NAME_LEN) + + if(src && input) + M << "The machine now has a label reading '[input]'." + name = input + +/obj/item/device/electronic_assembly/update_icon() + if(opened) + icon_state = initial(icon_state) + "-open" + else + icon_state = initial(icon_state) + +/obj/item/device/electronic_assembly/examine(mob/user) + ..() + if(user.Adjacent(src)) + if(!opened) + for(var/obj/item/integrated_circuit/output/screen/S in contents) + if(S.stuff_to_display) + user << "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'." + else + interact(user) + // var/obj/item/integrated_circuit/IC = input(user, "Which circuit do you want to examine?", "Examination") as null|anything in contents + // if(IC) + // IC.examine(user) + +/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/integrated_circuit)) + if(!opened) + user << "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar." + return 0 + var/obj/item/integrated_circuit/IC = I + var/total_parts = 0 + var/total_complexity = 0 + for(var/obj/item/integrated_circuit/part in contents) + total_parts++ + total_complexity = total_complexity + part.complexity + + if( (total_parts + 1) >= max_components) + user << "You can't seem to add this [IC.name], since there's no more room." + return 0 + if( (total_complexity + IC.complexity) >= max_complexity) + user << "You can't seem to add this [IC.name], since this setup's too complicated for the case." + return 0 + + user << "You slide \the [IC] inside \the [src]." + user.drop_item() + IC.forceMove(src) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + if(istype(I, /obj/item/weapon/screwdriver)) + if(!opened) + user << "\The [src] isn't opened, so you can't remove anything inside. Try using a crowbar." + return 0 + if(!contents.len) + user << "There's nothing inside this to remove!" + return 0 + var/obj/item/integrated_circuit/option = input("What do you want to remove?", "Component Removal") as null|anything in contents + if(option) + option.disconnect_all() + option.forceMove(get_turf(src)) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + user << "You pop \the [option] out of the case, and slide it out." + if(istype(I, /obj/item/weapon/crowbar)) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + opened = !opened + user << "You [opened ? "opened" : "closed"] \the [src]." + update_icon() + if(istype(I, /obj/item/device/integrated_electronics/wirer)) + if(opened) + var/obj/item/integrated_circuit/IC = input(user, "Which circuit do you want to examine?", "Examination") as null|anything in contents + if(IC) + IC.examine(user) + else + user << "\The [src] isn't opened, so you can't fiddle with the internal components. \ + Try using a crowbar." + +/obj/item/device/electronic_assembly/attack_self(mob/user) + var/list/available_inputs = list() + for(var/obj/item/integrated_circuit/input/input in contents) + if(input.can_be_asked_input) + available_inputs.Add(input) + var/obj/item/integrated_circuit/input/choice = input(user, "What do you want to interact with?", "Interaction") as null|anything in available_inputs + if(choice) + choice.ask_for_input(user) + +/obj/item/device/electronic_assembly/emp_act(severity) + ..() + for(var/atom/movable/AM in contents) + AM.emp_act(severity) diff --git a/code/modules/integrated_electronics/converters.dm b/code/modules/integrated_electronics/converters.dm new file mode 100644 index 0000000000..7a837abbfa --- /dev/null +++ b/code/modules/integrated_electronics/converters.dm @@ -0,0 +1,133 @@ +//These circuits convert one variable to another. +/obj/item/integrated_circuit/converter + complexity = 2 + number_of_inputs = 1 + number_of_outputs = 1 + number_of_activators = 1 + input_names = list( + "input", + ) + output_names = list( + "result" + ) + activator_names = list( + "convert" + ) + +/obj/item/integrated_circuit/converter/num2text + name = "number to string" + desc = "This circuit can convert a number variable into a string." + icon_state = "num-string" + +/obj/item/integrated_circuit/converter/num2text/work() + if(..()) + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + if(incoming.data && isnum(incoming.data)) + result = num2text(incoming.data) + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/text2num + name = "string to number" + desc = "This circuit can convert a string variable into a number." + icon_state = "string-num" + +/obj/item/integrated_circuit/converter/text2num/work() + if(..()) + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + if(incoming.data && istext(incoming.data)) + result = text2num(incoming.data) + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/ref2text + name = "reference to string" + desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference." + icon_state = "ref-string" + +/obj/item/integrated_circuit/converter/ref2text/work() + if(..()) + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + if(incoming.data && istype(incoming.data, /atom/)) + var/atom/A = incoming.data + result = A.name + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/lowercase + name = "lowercase string converter" + desc = "this will cause a string to come out in all lowercase." + icon_state = "lowercase" + +/obj/item/integrated_circuit/converter/lowercase/work() + if(..()) + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + if(incoming.data && istext(incoming.data)) + result = lowertext(incoming.data) + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/uppercase + name = "uppercase string converter" + desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE." + icon_state = "uppercase" + +/obj/item/integrated_circuit/converter/uppercase/work() + if(..()) + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + if(incoming.data && istext(incoming.data)) + result = uppertext(incoming.data) + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/concatenatior + name = "concatenatior" + desc = "This joins many strings together to get one big string." + complexity = 4 + number_of_inputs = 8 + number_of_outputs = 1 + number_of_activators = 1 + input_names = list( + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H" + ) + output_names = list( + "result" + ) + activator_names = list( + "concatenate" + ) + + +/obj/item/integrated_circuit/converter/concatenatior/work() + if(..()) + var/result = null + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(istext(I.data)) + result = result + I.data + + var/datum/integrated_io/outgoing = outputs[1] + outgoing.data = result + outgoing.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/coordinate.dm b/code/modules/integrated_electronics/coordinate.dm new file mode 100644 index 0000000000..78b7ebcb4f --- /dev/null +++ b/code/modules/integrated_electronics/coordinate.dm @@ -0,0 +1,75 @@ +//This circuit gives information on where the machine is. +/obj/item/integrated_circuit/gps + name = "global positioning system" + desc = "This allows you to easily know the position of a machine containing this device." + icon_state = "gps" + complexity = 4 + number_of_inputs = 0 + number_of_outputs = 2 + number_of_activators = 1 + input_names = list( + ) + output_names = list( + "X (abs)", + "Y (abs)" + ) + activator_names = list( + "get coordinates" + ) + +/obj/item/integrated_circuit/gps/work() + if(..()) + var/turf/T = get_turf(src) + var/datum/integrated_io/result_x = outputs[1] + var/datum/integrated_io/result_y = outputs[2] + + result_x.data = null + result_y.data = null + if(!T) + return + + result_x.data = T.x + result_y.data = T.y + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +/obj/item/integrated_circuit/abs_to_rel_coords + name = "abs to rel coordinate converter" + desc = "Easily convert absolute coordinates to relative coordinates with this." + complexity = 4 + number_of_inputs = 4 + number_of_outputs = 2 + number_of_activators = 1 + input_names = list( + "X1 (abs)", + "Y1 (abs)", + "X2 (abs)", + "Y2 (abs)" + ) + output_names = list( + "X (rel)", + "Y (rel)" + ) + activator_names = list( + "compute rel coordinates" + ) + +/obj/item/integrated_circuit/abs_to_rel_coords/work() + var/datum/integrated_io/x1 = inputs[1] + var/datum/integrated_io/y1 = inputs[2] + + var/datum/integrated_io/x2 = inputs[3] + var/datum/integrated_io/y2 = inputs[4] + + var/datum/integrated_io/result_x = outputs[1] + var/datum/integrated_io/result_y = outputs[2] + + if(x1.data && y1.data && x2.data && y2.data) + result_x.data = x1.data - x2.data + result_y.data = y1.data - y2.data + + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + ..() diff --git a/code/modules/integrated_electronics/data_transfer.dm b/code/modules/integrated_electronics/data_transfer.dm new file mode 100644 index 0000000000..12380e9cca --- /dev/null +++ b/code/modules/integrated_electronics/data_transfer.dm @@ -0,0 +1,79 @@ +/obj/item/integrated_circuit/transfer/splitter + name = "splitter" + desc = "Splits incoming data into all of the output pins." + icon_state = "splitter" + complexity = 3 + number_of_inputs = 1 + number_of_outputs = 2 + input_names = list( + "data to split" + ) + output_names = list( + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H" + ) + +/obj/item/integrated_circuit/transfer/splitter/medium + name = "four splitter" + icon_state = "splitter4" + complexity = 5 + number_of_inputs = 1 + number_of_outputs = 4 + +/obj/item/integrated_circuit/transfer/splitter/large + name = "eight splitter" + icon_state = "splitter8" + complexity = 9 + number_of_inputs = 1 + number_of_outputs = 8 + +/obj/item/integrated_circuit/transfer/splitter/work() + if(..()) + var/datum/integrated_io/I = inputs[1] + for(var/datum/integrated_io/output/O in outputs) + O.data = I.data + +/obj/item/integrated_circuit/transfer/activator_splitter + name = "activator splitter" + desc = "Splits incoming activation pulses into all of the output pins." + icon_state = "splitter" + complexity = 3 + number_of_activators = 3 + activator_names = list( + "incoming pulse", + "outgoing pulse A", + "outgoing pulse B", + "outgoing pulse C", + "outgoing pulse D", + "outgoing pulse E", + "outgoing pulse F", + "outgoing pulse G", + "outgoing pulse H" + ) + +/obj/item/integrated_circuit/transfer/activator_splitter/work() + if(..()) + for(var/datum/integrated_io/activate/A in outputs) + if(A == activators[1]) + continue + if(A.linked.len) + for(var/datum/integrated_io/activate/target in A.linked) + target.holder.work() + +/obj/item/integrated_circuit/transfer/activator_splitter/medium + name = "four activator splitter" + icon_state = "splitter4" + complexity = 5 + number_of_activators = 5 + +/obj/item/integrated_circuit/transfer/activator_splitter/large + name = "eight activator splitter" + icon_state = "splitter4" + complexity = 9 + number_of_activators = 9 diff --git a/code/modules/integrated_electronics/input_output.dm b/code/modules/integrated_electronics/input_output.dm new file mode 100644 index 0000000000..42da340654 --- /dev/null +++ b/code/modules/integrated_electronics/input_output.dm @@ -0,0 +1,494 @@ +/obj/item/integrated_circuit/input + var/can_be_asked_input = 0 + +/obj/item/integrated_circuit/input/proc/ask_for_input(mob/user) + return + +/obj/item/integrated_circuit/input/button + name = "button" + desc = "This tiny button must do something, right?" + icon_state = "button" + number_of_inputs = 0 + number_of_outputs = 0 + number_of_activators = 1 + complexity = 1 + can_be_asked_input = 1 + activator_names = list( + "on pressed" + ) + +/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use. + var/datum/integrated_io/A = activators[1] + if(A.linked.len) + for(var/datum/integrated_io/activate/target in A.linked) + target.holder.work() + user << "You press the button labeled '[src.name]'." + +/obj/item/integrated_circuit/input/numberpad + name = "number pad" + desc = "This small number pad allows someone to input a number into the system." + icon_state = "numberpad" + number_of_inputs = 0 + number_of_outputs = 1 + number_of_activators = 1 + complexity = 2 + can_be_asked_input = 1 + output_names = list( + "number entered" + ) + activator_names = list( + "on entered" + ) + +/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user) + var/new_input = input(user, "Enter a number, please.","Number pad") as null|num + if(isnum(new_input)) + var/datum/integrated_io/O = outputs[1] + O.data = new_input + O.push_data() + var/datum/integrated_io/A = activators[1] + A.push_data() + +/obj/item/integrated_circuit/input/textpad + name = "text pad" + desc = "This small text pad allows someone to input a string into the system." + icon_state = "textpad" + number_of_inputs = 0 + number_of_outputs = 1 + number_of_activators = 1 + complexity = 2 + can_be_asked_input = 1 + output_names = list( + "string entered" + ) + activator_names = list( + "on entered" + ) + +/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user) + var/new_input = input(user, "Enter some words, please.","Number pad") as null|text + if(new_input && istext(new_input)) + var/datum/integrated_io/O = outputs[1] + O.data = new_input + O.push_data() + var/datum/integrated_io/A = activators[1] + A.push_data() + +/obj/item/integrated_circuit/input/med_scanner + name = "integrated medical analyser" + desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is." + icon_state = "medscan" + number_of_inputs = 1 + number_of_outputs = 2 + number_of_activators = 1 + complexity = 4 + input_names = list( + "target ref" + ) + output_names = list( + "total health %", + "total missing health" + ) + activator_names = list( + "scan" + ) + +/obj/item/integrated_circuit/input/med_scanner/work() + if(..()) + var/datum/integrated_io/I = inputs[1] + if(!I.data || !ishuman(I.data)) //Invalid input + return + var/mob/living/carbon/human/H = I.data + if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. + var/total_health = round(H.health/H.maxHealth, 0.1)*100 + var/missing_health = H.maxHealth - H.health + + var/datum/integrated_io/total = outputs[1] + var/datum/integrated_io/missing = outputs[2] + + total.data = total_health + missing.data = missing_health + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +/obj/item/integrated_circuit/input/adv_med_scanner + name = "integrated advanced medical analyser" + desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is. \ + This type is much more precise, allowing the machine to know much more about the target than a normal analyzer." + icon_state = "medscan_adv" + number_of_inputs = 1 + number_of_outputs = 7 + number_of_activators = 1 + complexity = 12 + input_names = list( + "target ref" + ) + output_names = list( + "total health %", + "total missing health", + "brute damage", + "burn damage", + "tox damage", + "oxy damage", + "clone damage" + ) + activator_names = list( + "scan" + ) + +/obj/item/integrated_circuit/input/adv_med_scanner/work() + if(..()) + var/datum/integrated_io/I = inputs[1] + if(!I.data || !ishuman(I.data)) //Invalid input + return + var/mob/living/carbon/human/H = I.data + if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. + var/total_health = round(H.health/H.maxHealth, 0.1)*100 + var/missing_health = H.maxHealth - H.health + + var/datum/integrated_io/total = outputs[1] + var/datum/integrated_io/missing = outputs[2] + var/datum/integrated_io/brute = outputs[3] + var/datum/integrated_io/burn = outputs[4] + var/datum/integrated_io/tox = outputs[5] + var/datum/integrated_io/oxy = outputs[6] + var/datum/integrated_io/clone = outputs[7] + + total.data = total_health + missing.data = missing_health + brute.data = H.getBruteLoss() + burn.data = H.getFireLoss() + tox.data = H.getToxLoss() + oxy.data = H.getOxyLoss() + clone.data = H.getCloneLoss() + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +/obj/item/integrated_circuit/input/local_locator + name = "local locator" + desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \ + that is holding the machine containing it." + number_of_inputs = 0 + number_of_outputs = 1 + number_of_activators = 1 + complexity = 4 + output_names = list( + "located ref" + ) + activator_names = list( + "locate" + ) + +/obj/item/integrated_circuit/input/local_locator/work() + if(..()) + var/mob/living/L = null + var/datum/integrated_io/O = outputs[1] + O.data = null + if(istype(src.loc, /obj/item/device/electronic_assembly)) // Check to make sure we're actually in a machine. + var/obj/item/device/electronic_assembly/assembly = src.loc + if(istype(assembly.loc, /mob/living)) // Now check if someone's holding us. + L = assembly.loc + + if(L) + O.data = L + + O.push_data() + +/obj/item/integrated_circuit/input/signaler + name = "integrated signaler" + desc = "Signals from a signaler can be received with this, allowing for remote control. Additionally, it can send signals as well." + extended_desc = "When a signal is received from another signaler, the 'on signal received' activator pin will be pulsed. \ + The two input pins are to configure the integrated signaler's settings. Note that the frequency should not have a decimal in it. \ + Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin." + icon_state = "signal" + number_of_inputs = 2 + number_of_outputs = 0 + number_of_activators = 2 + complexity = 4 + input_names = list( + "frequency", + "code" + ) + activator_names = list( + "send signal", + "on signal received" + ) + var/frequency = 1457 + var/code = 30 + var/datum/radio_frequency/radio_connection + +/obj/item/integrated_circuit/input/signaler/New() + ..() + spawn(4 SECONDS) + set_frequency(frequency) + var/datum/integrated_io/new_freq = inputs[1] + var/datum/integrated_io/new_code = inputs[2] + // Set the pins so when someone sees them, they won't show as null + new_freq.data = frequency + new_code.data = code + +/obj/item/integrated_circuit/input/signaler/Destroy() + if(radio_controller) + radio_controller.remove_object(src,frequency) + frequency = 0 + ..() + +/obj/item/integrated_circuit/input/signaler/on_data_written() + var/datum/integrated_io/new_freq = inputs[1] + var/datum/integrated_io/new_code = inputs[2] + if(isnum(new_freq.data)) + set_frequency(new_freq.data) + if(isnum(new_code.data)) + code = new_code.data + + +/obj/item/integrated_circuit/input/signaler/work() // Sends a signal. + if(..()) + if(!radio_connection) + return + + var/datum/signal/signal = new() + signal.source = src + signal.encryption = code + signal.data["message"] = "ACTIVATE" + radio_connection.post_signal(src, signal) + +/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency) + if(!frequency) + return + if(!radio_controller) + sleep(20) + if(!radio_controller) + return + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + +/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal) + var/datum/integrated_io/new_code = inputs[2] + var/code = 0 + + if(isnum(new_code.data)) + code = new_code.data + if(!signal) + return 0 + if(signal.encryption != code) + return 0 + if(signal.source == src) // Don't trigger ourselves. + return 0 + + var/datum/integrated_io/A = activators[2] + A.push_data() + + for(var/mob/O in hearers(1, src.loc)) + O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) + + +/obj/item/integrated_circuit/input/EPv2 + name = "\improper EPv2 circuit" + desc = "Enables the sending and receiving of messages on the Exonet with the EPv2 protocol." + extended_desc = "An EPv2 address is a string with the format of XXXX:XXXX:XXXX:XXXX. Data can be send or received using the \ + second pin on each side, with additonal data reserved for the third pin. When a message is received, the second activaiton pin \ + will pulse whatever's connected to it. Pulsing the first activation pin will send a message." + icon_state = "signal" + number_of_inputs = 3 + number_of_outputs = 3 + number_of_activators = 2 + complexity = 4 + input_names = list( + "target EPv2 address", + "data to send", + "secondary text" + ) + output_names = list( + "address received", + "data received", + "secondary text received" + ) + activator_names = list( + "send data", + "on data received" + ) + var/datum/exonet_protocol/exonet = null + +/obj/item/integrated_circuit/input/EPv2/New() + ..() + exonet = new(src) + exonet.make_address("EPv2_circuit-\ref[src]") + desc += "This circuit's EPv2 address is: [exonet.address]." + +/obj/item/integrated_circuit/input/EPv2/Destroy() + if(exonet) + exonet.remove_address() + qdel(exonet) + ..() + +/obj/item/integrated_circuit/input/EPv2/work() + if(..()) + var/datum/integrated_io/target_address = inputs[1] + var/datum/integrated_io/message = inputs[2] + var/datum/integrated_io/text = inputs[3] + if(istext(target_address.data)) + exonet.send_message(target_address.data, message.data, text.data) + +/obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text) + var/datum/integrated_io/message_received = outputs[1] + var/datum/integrated_io/data_received = outputs[2] + var/datum/integrated_io/text_received = outputs[3] + + var/datum/integrated_io/A = activators[2] + A.push_data() + + message_received.write_data_to_pin(origin_address) + data_received.write_data_to_pin(message) + text_received.write_data_to_pin(text) + +/obj/item/integrated_circuit/output/screen + name = "screen" + desc = "This small screen can display a single piece of data, when the machine is examined closely." + icon_state = "screen" + complexity = 4 + number_of_inputs = 1 + number_of_outputs = 0 + number_of_activators = 1 + input_names = list( + "displayed data" + ) + activator_names = list( + "load data" + ) + var/stuff_to_display = null + +/obj/item/integrated_circuit/output/screen/work() + var/datum/integrated_io/I = inputs[1] + stuff_to_display = I.data + +/obj/item/integrated_circuit/output/light + name = "light" + desc = "This light can turn on and off on command." + icon_state = "light_adv" +// icon_state = "light" + complexity = 4 + number_of_inputs = 0 + number_of_outputs = 0 + number_of_activators = 1 + activator_names = list( + "toggle light" + ) + var/light_toggled = 0 + var/light_brightness = 3 + var/light_rgb = "#FFFFFF" + +/obj/item/integrated_circuit/output/light/work() + if(..()) + light_toggled = !light_toggled + update_lighting() + +/obj/item/integrated_circuit/output/light/proc/update_lighting() + if(light_toggled) + set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb) + else + set_light(0) + +/obj/item/integrated_circuit/output/light/advanced/update_lighting() + var/datum/integrated_io/R = inputs[1] + var/datum/integrated_io/G = inputs[2] + var/datum/integrated_io/B = inputs[3] + var/datum/integrated_io/brightness = inputs[4] + + if(isnum(R.data) && isnum(G.data) && isnum(B.data) && isnum(brightness.data)) + R.data = Clamp(R.data, 0, 255) + G.data = Clamp(G.data, 0, 255) + B.data = Clamp(B.data, 0, 255) + brightness.data = Clamp(brightness.data, 0, 6) + light_rgb = rgb(R.data, G.data, B.data) + light_brightness = brightness.data + + ..() + +/obj/item/integrated_circuit/output/light/advanced + name = "advanced light" + desc = "This light can turn on and off on command, in any color, and in various brightness levels." + icon_state = "light_adv" + complexity = 8 + number_of_inputs = 4 + number_of_outputs = 0 + number_of_activators = 1 + input_names = list( + "R", + "G", + "B", + "Brightness" + ) + +/obj/item/integrated_circuit/output/light/advanced/on_data_written() + update_lighting() + +/obj/item/integrated_circuit/output/sound + name = "speaker circuit" + desc = "A miniature speaker is attached to this component." + icon_state = "speaker" + complexity = 8 + cooldown_per_use = 4 SECONDS + number_of_inputs = 3 + number_of_outputs = 0 + number_of_activators = 1 + input_names = list( + "sound ID", + "volume", + "frequency" + ) + activator_names = list( + "play sound" + ) + var/list/sounds = list() + +/obj/item/integrated_circuit/output/sound/work() + if(..()) + var/datum/integrated_io/ID = inputs[1] + var/datum/integrated_io/vol = inputs[2] + var/datum/integrated_io/frequency = inputs[3] + if(istext(ID.data) && isnum(vol.data) && isnum(frequency.data)) + var/selected_sound = sounds[ID.data] + vol.data = Clamp(vol.data, 0, 1) + frequency.data = Clamp(frequency.data, 0, 100) + playsound(get_turf(src), selected_sound, vol.data, frequency.data, -1) + +/obj/item/integrated_circuit/output/sound/beeper + name = "beeper circuit" + desc = "A miniature speaker is attached to this component. This is often used in the construction of motherboards, which use \ + the speaker to tell the user if something goes very wrong when booting up. It can also do other similar synthetic sounds such \ + as buzzing, pinging, chiming, and more." + extended_desc = "The first input pin determines what sound is used. The choices are; beep, chime, buzz sigh, buzz twice, ping, \ + synth yes, synth no, warning buzz. The second pin determines the volume of sound that is played, and the third determines if \ + the frequency of the sound will vary with each activation." + sounds = list( + "beep" = 'sound/machines/twobeep.ogg', + "chime" = 'sound/machines/chime.ogg', + "buzz sigh" = 'sound/machines/buzz-sigh.ogg', + "buzz twice" = 'sound/machines/buzz-two.ogg', + "ping" = 'sound/machines/ping.ogg', + "synth yes" = 'sound/machines/synth_yes.ogg', + "synth no" = 'sound/machines/synth_no.ogg', + "warning buzz" = 'sound/machines/warning-buzzer.ogg' + ) + +/obj/item/integrated_circuit/output/sound/beepsky + name = "securitron sound circuit" + desc = "A miniature speaker is attached to this component. Considered by some to be the essential component for a securitron." + extended_desc = "The first input pin determines what sound is used. The choices are; creep, criminal, freeze, god, \ + i am the law, insult, radio, secure day. The second pin determines the volume of sound that is played, and the \ + third determines if the frequency of the sound will vary with each activation." + sounds = list( + "creep" = 'sound/voice/bcreep.ogg', + "criminal" = 'sound/voice/bcriminal.ogg', + "freeze" = 'sound/voice/bfreeze.ogg', + "god" = 'sound/voice/bgod.ogg', + "i am the law" = 'sound/voice/biamthelaw.ogg', + "insult" = 'sound/voice/binsult.ogg', + "radio" = 'sound/voice/bradio.ogg', + "secure day" = 'sound/voice/bsecureday.ogg', + ) + diff --git a/code/modules/integrated_electronics/logic.dm b/code/modules/integrated_electronics/logic.dm new file mode 100644 index 0000000000..4d123c61d0 --- /dev/null +++ b/code/modules/integrated_electronics/logic.dm @@ -0,0 +1,172 @@ +/obj/item/integrated_circuit/logic + name = "logic gate" + desc = "This tiny chip will decide for you!" + complexity = 3 + number_of_inputs = 2 + number_of_outputs = 1 + number_of_activators = 2 + input_names = list( + "A", + "B" + ) + output_names = list( + "result" + ) + activator_names = list( + "compare", + "on true result" + ) + +/obj/item/integrated_circuit/logic/equals + name = "equal gate" + desc = "This gate compares two values, and outputs the number one if both are the same." + icon_state = "equal" + +/obj/item/integrated_circuit/logic/equals/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data == B.data) + O.data = 1 + O.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/not + name = "not gate" + desc = "This gate inverts what's fed into it." + icon_state = "not" + number_of_inputs = 1 + number_of_outputs = 1 + number_of_activators = 1 + output_names = list( + "invert" + ) + + +/obj/item/integrated_circuit/logic/not/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/O = outputs[1] + if(A.data) + O.data = !A.data + O.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/and + name = "and gate" + desc = "This gate will output 'one' if both inputs evaluate to true." + icon_state = "and" + +/obj/item/integrated_circuit/logic/and/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data && B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/or + name = "or gate" + desc = "This gate will output 'one' if one of the inputs evaluate to true." + icon_state = "or" + +/obj/item/integrated_circuit/logic/or/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data || B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/less_than + name = "less than gate" + desc = "This will output 'one' if the first input is less than the second input." + icon_state = "less_than" + +/obj/item/integrated_circuit/logic/less_than/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data < B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/less_than_or_equal + name = "less than or equal gate" + desc = "This will output 'one' if the first input is less than, or equal to the second input." + icon_state = "less_than_or_equal" + +/obj/item/integrated_circuit/logic/less_than_or_equal/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data <= B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/greater_than + name = "greater than gate" + desc = "This will output 'one' if the first input is greater than the second input." + icon_state = "greater_than" + +/obj/item/integrated_circuit/logic/greater_than/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data > B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 + +/obj/item/integrated_circuit/logic/greater_than_or_equal + name = "greater_than or equal gate" + desc = "This will output 'one' if the first input is greater than, or equal to the second input." + icon_state = "greater_than_or_equal" + +/obj/item/integrated_circuit/logic/greater_than_or_equal/work() + if(..()) + var/datum/integrated_io/A = inputs[1] + var/datum/integrated_io/B = inputs[2] + var/datum/integrated_io/O = outputs[1] + var/datum/integrated_io/P = activators[2] + if(A.data >= B.data) + O.data = 1 + O.push_data() + A.push_data() + P.push_data() + else + O.data = 0 \ No newline at end of file diff --git a/code/modules/integrated_electronics/manipulation.dm b/code/modules/integrated_electronics/manipulation.dm new file mode 100644 index 0000000000..256d7b6b7a --- /dev/null +++ b/code/modules/integrated_electronics/manipulation.dm @@ -0,0 +1,158 @@ +/obj/item/integrated_circuit/manipulation/weapon_firing + name = "weapon firing mechanism" + desc = "This somewhat complicated system allows one to slot in a gun, direct it towards a position, and remotely fire it." + extended_desc = "The firing mechanism can slot in most ranged weapons, ballistic and energy. \ + The first and second inputs need to be numbers. They are coordinates for the gun to fire at, relative to the machine itself. \ + The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Note that the \ + normal limitations to firearms, such as ammunition requirements and firing delays, still hold true if fired by the mechanism." + complexity = 20 + number_of_inputs = 2 + number_of_outputs = 0 + number_of_activators = 1 + input_names = list( + "target X rel", + "target Y rel" + ) + activator_names = list( + "fire" + ) + var/obj/item/weapon/gun/installed_gun = null + +/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy() + qdel(installed_gun) + ..() + +/obj/item/integrated_circuit/manipulation/weapon_firing/attackby(var/obj/O, var/mob/user) + if(istype(O, /obj/item/weapon/gun)) + var/obj/item/weapon/gun/gun = O + if(installed_gun) + user << "There's already a weapon installed." + return + user.drop_from_inventory(gun) + installed_gun = gun + gun.forceMove(src) + user << "You slide \the [gun] into the firing mechanism." + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + else + ..() + +/obj/item/integrated_circuit/manipulation/weapon_firing/attack_self(var/mob/user) + if(installed_gun) + installed_gun.forceMove(get_turf(src)) + user << "You slide \the [installed_gun] out of the firing mechanism." + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + installed_gun = null + else + user << "There's no weapon to remove from the mechanism." + +/obj/item/integrated_circuit/manipulation/weapon_firing/work() + if(..()) + if(!installed_gun) + return + + var/datum/integrated_io/target_x = inputs[1] + var/datum/integrated_io/target_y = inputs[2] + + if(target_x.data && target_y.data && isnum(target_x.data) && isnum(target_y.data)) + var/turf/T = get_turf(src) + + if(target_x.data == 0 && target_y.data == 0) // Don't shoot ourselves. + return + + // We need to do this in order to enable relative coordinates, as locate() only works for absolute coordinates. + var/i + if(target_x.data > 0) + i = abs(target_x.data) + while(i) + T = get_step(T, EAST) + i-- + else if(target_x.data < 0) + i = abs(target_x.data) + while(i) + T = get_step(T, WEST) + i-- + + if(target_y.data > 0) + i = abs(target_y.data) + while(i) + T = get_step(T, NORTH) + i-- + else if(target_y.data < 0) + i = abs(target_y.data) + while(i) + T = get_step(T, SOUTH) + i-- + + if(!T) + return + installed_gun.Fire_userless(T) + +/obj/item/integrated_circuit/manipulation/smoke + name = "smoke generator" + desc = "Unlike most electronics, creating smoke is completely intentional." + icon_state = "smoke" + extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \ + into the smoke clouds when activated." + flags = OPENCONTAINER + complexity = 20 + number_of_inputs = 0 + number_of_outputs = 0 + number_of_activators = 1 + cooldown_per_use = 30 SECONDS + input_names = list() + activator_names = list( + "create smoke" + ) + +/obj/item/integrated_circuit/manipulation/smoke/New() + ..() + create_reagents(100) + +/obj/item/integrated_circuit/manipulation/smoke/work() + if(..()) + playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new() + smoke_system.set_up(reagents, 10, 0, get_turf(src)) + spawn(0) + for(var/i = 1 to 8) + smoke_system.start() + reagents.clear_reagents() + +/obj/item/integrated_circuit/manipulation/locomotion + name = "locomotion circuit" + desc = "This allows a machine to move in a given direction." + icon_state = "locomotion" + extended_desc = "The circuit accepts a number as a direction to move towards.
\ + North/Fore = 1,
\ + South/Aft = 2,
\ + East/Starboard = 4,
\ + West/Port = 8,
\ + Northeast = 5,
\ + Northwest = 9,
\ + Southeast = 6,
\ + Southwest = 10
\ +
\ + Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \ + being held, or anchored in some way." + complexity = 20 + number_of_inputs = 1 + number_of_outputs = 0 + number_of_activators = 1 + input_names = list( + "dir num" + ) + activator_names = list( + "step towards dir" + ) + +/obj/item/integrated_circuit/manipulation/locomotion/work() + if(..()) + var/turf/T = get_turf(src) + if(istype(loc, /obj/item/device/electronic_assembly)) + var/obj/item/device/electronic_assembly/machine = loc + if(machine.anchored || machine.w_class >= 4) + return + if(machine.loc && machine.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held. + var/datum/integrated_io/wanted_dir = inputs[1] + if(isnum(wanted_dir.data)) + step(machine, wanted_dir.data) \ No newline at end of file diff --git a/code/modules/integrated_electronics/memory.dm b/code/modules/integrated_electronics/memory.dm new file mode 100644 index 0000000000..8599cc2aed --- /dev/null +++ b/code/modules/integrated_electronics/memory.dm @@ -0,0 +1,101 @@ +/obj/item/integrated_circuit/memory + name = "memory chip" + desc = "This tiny chip can store one piece of data." + icon_state = "memory" + complexity = 1 + number_of_inputs = 1 + number_of_outputs = 1 + number_of_activators = 1 + activator_names = list( + "set" + ) + +/obj/item/integrated_circuit/memory/examine(mob/user) + ..() + var/i + for(i = 1, i <= outputs.len, i++) + var/datum/integrated_io/O = outputs[i] + user << "\The [src] has [O.data ? "'O.data'" : "nothing"] saved to address [i]." + +/obj/item/integrated_circuit/memory/work() + if(..()) + var/i + for(i = 1, i <= inputs.len, i++) + var/datum/integrated_io/I = inputs[i] + var/datum/integrated_io/O = outputs[i] + O.data = I.data + +/obj/item/integrated_circuit/memory/medium + name = "memory circuit" + desc = "This circuit can store four pieces of data." + icon_state = "memory4" + complexity = 4 + number_of_inputs = 4 + number_of_outputs = 4 + +/obj/item/integrated_circuit/memory/large + name = "large memory circuit" + desc = "This big circuit can hold eight pieces of data." + icon_state = "memory8" + complexity = 8 + number_of_inputs = 8 + number_of_outputs = 8 + +/obj/item/integrated_circuit/memory/huge + name = "large memory stick" + desc = "This stick of memory can hold up up to sixteen pieces of data." + icon_state = "memory16" + complexity = 16 + number_of_inputs = 16 + number_of_outputs = 16 + +/obj/item/integrated_circuit/memory/constant + name = "constant chip" + desc = "This tiny chip can store one piece of data, which cannot be overwritten without disassembly." + icon_state = "memory" + complexity = 1 + number_of_inputs = 0 + number_of_outputs = 1 + number_of_activators = 1 + activator_names = list( + "push data" + ) + var/accepting_refs = 0 + +/obj/item/integrated_circuit/memory/constant/work() + var/datum/integrated_io/O = outputs[1] + O.push_data() + +/obj/item/integrated_circuit/memory/constant/attack_self(mob/user) + var/datum/integrated_io/O = outputs[1] + var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null") + var/new_data = null + switch(type_to_use) + if("string") + accepting_refs = 0 + new_data = input("Now type in a string.","[src] string writing") as null|text + if(istext(new_data)) + O.data = new_data + user << "You set \the [src]'s memory to [O.display_data()]." + if("number") + accepting_refs = 0 + new_data = input("Now type in a number.","[src] number writing") as null|num + if(isnum(new_data)) + O.data = new_data + user << "You set \the [src]'s memory to [O.display_data()]." + if("ref") + accepting_refs = 1 + user << "You turn \the [src]'s ref scanner on. Slide it across \ + an object for a ref of that object to save it in memory." + if("null") + O.data = null + user << "You set \the [src]'s memory to absolutely nothing." + +/obj/item/integrated_circuit/memory/constant/afterattack(atom/target, mob/living/user, proximity) + if(accepting_refs && proximity) + var/datum/integrated_io/O = outputs[1] + O.data = target + visible_message("[user] slides \a [src]'s over \the [target].") + user << "You set \the [src]'s memory to a reference to [O.display_data()]. The ref scanner is \ + now off." + accepting_refs = 0 \ No newline at end of file diff --git a/code/modules/integrated_electronics/time.dm b/code/modules/integrated_electronics/time.dm new file mode 100644 index 0000000000..95b8e02c46 --- /dev/null +++ b/code/modules/integrated_electronics/time.dm @@ -0,0 +1,144 @@ +/obj/item/integrated_circuit/time + name = "time circuit" + desc = "Now you can build your own clock!" + complexity = 2 + number_of_inputs = 0 + number_of_outputs = 0 + +/obj/item/integrated_circuit/time/delay + name = "two-sec delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit is set to send a pulse after a delay of two seconds." + icon_state = "delay-20" + number_of_activators = 2 + var/delay = 20 + activator_names = list( + "incoming pulse", + "outgoing pulse" + ) + +/obj/item/integrated_circuit/time/delay/work() + if(..()) + var/datum/integrated_io/out_pulse = activators[2] + sleep(delay) + out_pulse.push_data() + +/obj/item/integrated_circuit/time/delay/five_sec + name = "five-sec delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit is set to send a pulse after a delay of five seconds." + icon_state = "delay-50" + delay = 50 + +/obj/item/integrated_circuit/time/delay/one_sec + name = "one-sec delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit is set to send a pulse after a delay of one second." + icon_state = "delay-10" + delay = 10 + +/obj/item/integrated_circuit/time/delay/half_sec + name = "half-sec delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit is set to send a pulse after a delay of half a second." + icon_state = "delay-5" + delay = 5 + +/obj/item/integrated_circuit/time/delay/tenth_sec + name = "tenth-sec delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit is set to send a pulse after a delay of 1/10th of a second." + icon_state = "delay-1" + delay = 1 + +/obj/item/integrated_circuit/time/delay/custom + name = "custom delay circuit" + desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ + This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse." + icon_state = "delay" + number_of_inputs = 1 + input_names = list( + "delay time", + ) + +/obj/item/integrated_circuit/time/delay/custom/work() + var/datum/integrated_io/delay_input = inputs[1] + if(delay_input.data && isnum(delay_input.data) ) + var/new_delay = min(delay_input.data, 1) + new_delay = max(new_delay, 36000) //An hour. + delay = new_delay + + ..() + +/obj/item/integrated_circuit/time/ticker + name = "ticker circuit" + desc = "This circuit sends an automatic pulse every four seconds." + icon_state = "tick-m" + complexity = 8 + number_of_inputs = 1 + number_of_activators = 1 + var/ticks_to_pulse = 2 + var/ticks_completed = 0 + input_names = list( + "toggle ticking" + ) + activator_names = list( + "outgoing pulse" + ) + +/obj/item/integrated_circuit/time/ticker/New() + ..() + processing_objects |= src + +/obj/item/integrated_circuit/time/ticker/Destroy() + processing_objects -= src + +/obj/item/integrated_circuit/time/ticker/process() + ticks_completed++ + if( (ticks_completed % ticks_to_pulse) == 0) + var/datum/integrated_io/pulser = activators[1] + pulser.push_data() + +/obj/item/integrated_circuit/time/ticker/fast + name = "fast ticker" + desc = "This advanced circuit sends an automatic pulse every two seconds." + icon_state = "tick-f" + complexity = 12 + ticks_to_pulse = 1 + +/obj/item/integrated_circuit/time/ticker/slow + name = "slow ticker" + desc = "This simple circuit sends an automatic pulse every six seconds." + icon_state = "tick-s" + complexity = 4 + ticks_to_pulse = 3 + + +/obj/item/integrated_circuit/time/clock + name = "integrated clock" + desc = "Tells you what the local time is, specific to your station or planet." + icon_state = "clock" + number_of_inputs = 0 + number_of_outputs = 4 + number_of_activators = 1 + output_names = list( + "time (string)", + "hours (number)", + "minutes (number)", + "seconds (number)" + ) + +/obj/item/integrated_circuit/time/clock/work() + if(..()) + var/datum/integrated_io/time = outputs[1] + var/datum/integrated_io/hour = outputs[2] + var/datum/integrated_io/min = outputs[3] + var/datum/integrated_io/sec = outputs[4] + + time.data = time2text(station_time_in_ticks, "hh:mm:ss") + hour.data = text2num(time2text(station_time_in_ticks, "hh")) + min.data = text2num(time2text(station_time_in_ticks, "mm")) + sec.data = text2num(time2text(station_time_in_ticks, "ss")) + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/tools.dm b/code/modules/integrated_electronics/tools.dm new file mode 100644 index 0000000000..75609ca59c --- /dev/null +++ b/code/modules/integrated_electronics/tools.dm @@ -0,0 +1,227 @@ +#define WIRE "wire" +#define WIRING "wiring" +#define UNWIRE "unwire" +#define UNWIRING "unwiring" + + +/obj/item/device/integrated_electronics/wirer + name = "circuit wirer" + desc = "It's a small wiring tool, with a wire roll, electric soldering iron, wire cutter, and more in one package. \ + The wires used are generally useful for small electronics, such as circuitboards and breadboards, as opposed to larger wires \ + used for power or data transmission." + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "wirer-wire" + flags = CONDUCT + w_class = 2 + var/datum/integrated_io/selected_io = null + var/mode = WIRE + +/obj/item/device/integrated_electronics/wirer/New() + ..() + +/obj/item/device/integrated_electronics/wirer/update_icon() + icon_state = "wirer-[mode]" + +/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user) + if(mode == WIRE) + selected_io = io + user << "You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel." + mode = WIRING + update_icon() + else if(mode == WIRING) + if(io == selected_io) + user << "Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless." + return + if(io.io_type != selected_io.io_type) + user << "Those two types of channels are incompatable. The first is a [selected_io.io_type], \ + while the second is a [io.io_type]." + return + selected_io.linked |= io + io.linked |= selected_io + + user << "You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name]." + mode = WIRE + update_icon() + //io.updateDialog() + //selected_io.updateDialog() + selected_io.holder.interact(user) // This is to update the UI. + selected_io = null + + else if(mode == UNWIRE) + selected_io = io + if(!io.linked.len) + user << "There is nothing connected to \the [selected_io] data channel." + selected_io = null + return + user << "You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel." + mode = UNWIRING + update_icon() + return + + else if(mode == UNWIRING) + if(io == selected_io) + user << "You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \ + the same pin is rather moot." + return + if(selected_io in io.linked) + io.linked.Remove(selected_io) + selected_io.linked.Remove(io) + user << "You disconnect \the [selected_io.holder]'s [selected_io.name] from \ + \the [io.holder]'s [io.name]." + //io.updateDialog() + //selected_io.updateDialog() + selected_io.holder.interact(user) // This is to update the UI. + selected_io = null + mode = UNWIRE + update_icon() + else + user << "\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \ + [io.name] are not connected." + return + return + +/obj/item/device/integrated_electronics/wirer/attack_self(mob/user) + switch(mode) + if(WIRE) + mode = UNWIRE + if(WIRING) + if(selected_io) + user << "You decide not to wire the data channel." + selected_io = null + mode = UNWIRE + if(UNWIRE) + mode = WIRE + if(UNWIRING) + if(selected_io) + user << "You decide not to disconnect the data channel." + selected_io = null + mode = UNWIRE + update_icon() + user << "You set \the [src] to [mode]." + +#undef WIRE +#undef WIRING +#undef UNWIRE +#undef UNWIRING + +/obj/item/device/integrated_electronics/debugger + name = "circuit debugger" + desc = "This small tool allows one working with custom machinery to directly set data to a specific pin, useful for writing \ + settings to specific circuits, or for debugging purposes. It can also pulse activation pins." + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "debugger" + flags = CONDUCT + w_class = 2 + var/data_to_write = null + var/accepting_refs = 0 + +/obj/item/device/integrated_electronics/debugger/attack_self(mob/user) + var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null") + var/new_data = null + switch(type_to_use) + if("string") + accepting_refs = 0 + new_data = input("Now type in a string.","[src] string writing") as null|text + if(istext(new_data)) + data_to_write = new_data + user << "You set \the [src]'s memory to \"[new_data]\"." + if("number") + accepting_refs = 0 + new_data = input("Now type in a number.","[src] number writing") as null|num + if(isnum(new_data)) + data_to_write = new_data + user << "You set \the [src]'s memory to [new_data]." + if("ref") + accepting_refs = 1 + user << "You turn \the [src]'s ref scanner on. Slide it across \ + an object for a ref of that object to save it in memory." + if("null") + data_to_write = null + user << "You set \the [src]'s memory to absolutely nothing." + +/obj/item/device/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity) + if(accepting_refs && proximity) + data_to_write = target + visible_message("[user] slides \a [src]'s over \the [target].") + user << "You set \the [src]'s memory to a reference to [target.name] \[Ref\]. The ref scanner is \ + now off." + accepting_refs = 0 + +/obj/item/device/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user) + if(io.io_type == DATA_CHANNEL) + io.write_data_to_pin(data_to_write) + user << "You write [data_to_write] to \the [io.holder]'s [io]." + else if(io.io_type == PULSE_CHANNEL) + io.holder.work() + user << "You pulse \the [io.holder]'s [io]." + + io.holder.interact(user) // This is to update the UI. + +/obj/item/weapon/storage/bag/circuits + name = "circuit kit" + desc = "This kit's essential for any circuitry projects." + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "circuit_kit" + w_class = 3 + storage_slots = 200 + max_storage_space = 400 + max_w_class = 3 + display_contents_with_number = 1 + can_hold = list(/obj/item/integrated_circuit, /obj/item/device/integrated_electronics, /obj/item/device/electronic_assembly, + /obj/item/weapon/screwdriver, /obj/item/weapon/crowbar) + +/obj/item/weapon/storage/bag/circuits/basic/New() + ..() + var/list/types_to_spawn = typesof(/obj/item/integrated_circuit/arithmetic, + /obj/item/integrated_circuit/logic, + /obj/item/integrated_circuit/memory, + ) - list(/obj/item/integrated_circuit/arithmetic, + /obj/item/integrated_circuit/memory, + /obj/item/integrated_circuit/logic, + ) + + types_to_spawn.Add(/obj/item/integrated_circuit/input/numberpad, + /obj/item/integrated_circuit/input/textpad, + /obj/item/integrated_circuit/input/button, + /obj/item/integrated_circuit/input/signaler, + /obj/item/integrated_circuit/input/local_locator, + /obj/item/integrated_circuit/output/screen, + /obj/item/integrated_circuit/converter/num2text, + /obj/item/integrated_circuit/converter/text2num, + /obj/item/integrated_circuit/converter/uppercase, + /obj/item/integrated_circuit/converter/lowercase, + /obj/item/integrated_circuit/time/delay/five_sec, + /obj/item/integrated_circuit/time/delay/one_sec, + /obj/item/integrated_circuit/time/delay/half_sec, + /obj/item/integrated_circuit/time/delay/tenth_sec, + /obj/item/integrated_circuit/time/ticker/slow, + /obj/item/integrated_circuit/time/clock + ) + + for(var/thing in types_to_spawn) + var/i = 3 + while(i) + new thing(src) + i-- + + new /obj/item/device/electronic_assembly(src) + new /obj/item/device/integrated_electronics/wirer(src) + new /obj/item/device/integrated_electronics/debugger(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/screwdriver(src) + +/obj/item/weapon/storage/bag/circuits/all/New() + ..() + var/list/types_to_spawn = typesof(/obj/item/integrated_circuit) + + for(var/thing in types_to_spawn) + var/i = 10 + while(i) + new thing(src) + i-- + + new /obj/item/device/electronic_assembly(src) + new /obj/item/device/integrated_electronics/wirer(src) + new /obj/item/device/integrated_electronics/debugger(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/screwdriver(src) \ No newline at end of file diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index b56435a59e..ab88819b53 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -50,6 +50,11 @@ var/list/holder_mob_icon_cache = list() continue M.forceMove(get_turf(src)) +/obj/item/weapon/holder/onDropInto(var/atom/movable/AM) + if(ismob(loc)) // Bypass our holding mob and drop directly to its loc + return loc.loc + return ..() + /obj/item/weapon/holder/GetID() for(var/mob/M in contents) var/obj/item/I = M.GetIdCard() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index ad71cebe1f..1c6e2436d4 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -126,16 +126,12 @@ var/list/slot_equipment_priority = list( \ // Removes an item from inventory and places it in the target atom. // If canremove or other conditions need to be checked then use unEquip instead. -/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null) +/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/target = null) if(W) - if(!Target) - Target = loc - - remove_from_mob(W) - if(!(W && W.loc)) return 1 // self destroying objects (tk, grabs) - - W.forceMove(Target) + remove_from_mob(W, target) + if(!(W && W.loc)) + return 1 // self destroying objects (tk, grabs) update_icons() return 1 return 0 @@ -194,7 +190,9 @@ var/list/slot_equipment_priority = list( \ //Attemps to remove an object on a mob. -/mob/proc/remove_from_mob(var/obj/O) +/mob/proc/remove_from_mob(var/obj/O, var/atom/target) + if(!O) // Nothing to remove, so we succeed. + return 1 src.u_equip(O) if (src.client) src.client.screen -= O @@ -202,7 +200,10 @@ var/list/slot_equipment_priority = list( \ O.screen_loc = null if(istype(O, /obj/item)) var/obj/item/I = O - I.forceMove(src.loc) + if(target) + I.forceMove(target) + else + I.dropInto(loc) I.dropped(src) return 1 diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm index 6cb5908f6f..a6fc34f738 100644 --- a/code/modules/mob/living/bot/cleanbot.dm +++ b/code/modules/mob/living/bot/cleanbot.dm @@ -180,11 +180,11 @@ w_class = 3.0 var/created_name = "Cleanbot" -/obj/item/weapon/bucket_sensor/attackby(var/obj/item/O, var/mob/user) +/obj/item/weapon/bucket_sensor/attackby(var/obj/item/W, var/mob/user) ..() - if(istype(O, /obj/item/robot_parts/l_arm) || istype(O, /obj/item/robot_parts/r_arm)) + if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm) || (istype(W, /obj/item/organ/external/arm) && ((W.name == "robotic left arm") || (W.name == "robotic right arm")))) user.drop_item() - qdel(O) + qdel(W) var/turf/T = get_turf(loc) var/mob/living/bot/cleanbot/A = new /mob/living/bot/cleanbot(T) A.name = created_name @@ -192,10 +192,10 @@ user.drop_from_inventory(src) qdel(src) - else if(istype(O, /obj/item/weapon/pen)) + else if(istype(W, /obj/item/weapon/pen)) var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && src.loc != usr) return - created_name = t + created_name = t \ No newline at end of file diff --git a/code/modules/mob/living/bot/ed209bot.dm b/code/modules/mob/living/bot/ed209bot.dm index ec4278c967..80279a4538 100644 --- a/code/modules/mob/living/bot/ed209bot.dm +++ b/code/modules/mob/living/bot/ed209bot.dm @@ -94,7 +94,7 @@ switch(build_step) if(0, 1) - if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg)) + if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg) || (istype(W, /obj/item/organ/external/leg) && ((W.name == "robotic right leg") || (W.name == "robotic left leg")))) user.drop_item() qdel(W) build_step++ diff --git a/code/modules/mob/living/bot/farmbot.dm b/code/modules/mob/living/bot/farmbot.dm index 42452c49fa..905c53a20a 100644 --- a/code/modules/mob/living/bot/farmbot.dm +++ b/code/modules/mob/living/bot/farmbot.dm @@ -337,6 +337,18 @@ new /obj/item/weapon/farmbot_arm_assembly(loc, src) +/obj/structure/reagent_dispensers/watertank/attackby(var/obj/item/organ/external/S, mob/user as mob) + if ((!istype(S, /obj/item/organ/external/arm)) && (!S.robotic == ORGAN_ROBOT)) + ..() + return + + user << "You add the robot arm to [src]." + + user.drop_from_inventory(S) + qdel(S) + + new /obj/item/weapon/farmbot_arm_assembly(loc, src) + /obj/item/weapon/farmbot_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() if((istype(W, /obj/item/device/analyzer/plant_analyzer)) && (build_step == 0)) diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm index 0072d9a444..ca4f572775 100644 --- a/code/modules/mob/living/bot/floorbot.dm +++ b/code/modules/mob/living/bot/floorbot.dm @@ -339,7 +339,7 @@ /obj/item/weapon/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob) ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm) || (istype(W, /obj/item/organ/external/arm) && ((W.name == "robotic right arm") || (W.name == "robotic left arm")))) qdel(W) var/turf/T = get_turf(user.loc) var/mob/living/bot/floorbot/A = new /mob/living/bot/floorbot(T) diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index 8a0c7564d1..fffe5879fa 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -286,6 +286,29 @@ user.drop_from_inventory(src) qdel(src) +/obj/item/weapon/storage/firstaid/attackby(var/obj/item/organ/external/S, mob/user as mob) + if (!istype(S, /obj/item/organ/external/arm) || !(S.robotic == ORGAN_ROBOT)) + ..() + return + + if(contents.len >= 1) + user << "You need to empty [src] out first." + return + + var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly + if(istype(src, /obj/item/weapon/storage/firstaid/fire)) + A.skin = "ointment" + else if(istype(src, /obj/item/weapon/storage/firstaid/toxin)) + A.skin = "tox" + else if(istype(src, /obj/item/weapon/storage/firstaid/o2)) + A.skin = "o2" + + qdel(S) + user.put_in_hands(A) + user << "You add the robot arm to the first aid kit." + user.drop_from_inventory(src) + qdel(src) + /obj/item/weapon/firstaid_arm_assembly name = "first aid/robot arm assembly" desc = "A first aid kit with a robot arm permanently grafted to it." diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index b07202572e..f7556e0ece 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -258,40 +258,40 @@ var/build_step = 0 var/created_name = "Securitron" -/obj/item/weapon/secbot_assembly/attackby(var/obj/item/O, var/mob/user) +/obj/item/weapon/secbot_assembly/attackby(var/obj/item/W, var/mob/user) ..() - if(istype(O, /obj/item/weapon/weldingtool) && !build_step) - var/obj/item/weapon/weldingtool/WT = O + if(istype(W, /obj/item/weapon/weldingtool) && !build_step) + var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) build_step = 1 overlays += image('icons/obj/aibots.dmi', "hs_hole") user << "You weld a hole in \the [src]." - else if(isprox(O) && (build_step == 1)) + else if(isprox(W) && (build_step == 1)) user.drop_item() build_step = 2 - user << "You add \the [O] to [src]." + user << "You add \the [W] to [src]." overlays += image('icons/obj/aibots.dmi', "hs_eye") name = "helmet/signaler/prox sensor assembly" - qdel(O) + qdel(W) - else if((istype(O, /obj/item/robot_parts/l_arm) || istype(O, /obj/item/robot_parts/r_arm)) && build_step == 2) + else if((istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm) || (istype(W, /obj/item/organ/external/arm) && ((W.name == "robotic right arm") || (W.name == "robotic left arm")))) && build_step == 2) user.drop_item() build_step = 3 - user << "You add \the [O] to [src]." + user << "You add \the [W] to [src]." name = "helmet/signaler/prox sensor/robot arm assembly" overlays += image('icons/obj/aibots.dmi', "hs_arm") - qdel(O) + qdel(W) - else if(istype(O, /obj/item/weapon/melee/baton) && build_step == 3) + else if(istype(W, /obj/item/weapon/melee/baton) && build_step == 3) user.drop_item() user << "You complete the Securitron! Beep boop." var/mob/living/bot/secbot/S = new /mob/living/bot/secbot(get_turf(src)) S.name = created_name - qdel(O) + qdel(W) qdel(src) - else if(istype(O, /obj/item/weapon/pen)) + else if(istype(W, /obj/item/weapon/pen)) var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) if(!t) return diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index dd9e4f28b9..aa4e6ced11 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -1,12 +1,11 @@ - //Called when the mob is hit with an item in combat. /mob/living/carbon/resolve_item_attack(obj/item/I, mob/living/user, var/effective_force, var/hit_zone) - if(check_attack_throat(I, user)) + if(check_neckgrab_attack(I, user, hit_zone)) return null ..() /mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone) - if(!effective_force || blocked >= 100) + if(!effective_force || blocked >= 100) return 0 //Hulk modifier @@ -39,18 +38,23 @@ return 1 // Attacking someone with a weapon while they are neck-grabbed -/mob/living/carbon/proc/check_attack_throat(obj/item/W, mob/user) +/mob/living/carbon/proc/check_neckgrab_attack(obj/item/W, mob/user, var/hit_zone) if(user.a_intent == I_HURT) for(var/obj/item/weapon/grab/G in src.grabbed_by) - if(G.assailant == user && G.state >= GRAB_NECK) - if(attack_throat(W, G, user)) - return 1 + if(G.assailant == user) + if(G.state >= GRAB_AGGRESSIVE) + if(hit_zone == BP_TORSO && shank_attack(W, G, user)) + return 1 + if(G.state >= GRAB_NECK) + if(hit_zone == BP_HEAD && attack_throat(W, G, user, hit_zone)) + return 1 return 0 + // Knifing /mob/living/carbon/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user) - if(!W.edge || !W.force || W.damtype != BRUTE) + if(!W.edge || !W.force || W.damtype != BRUTE) return 0 //unsuitable weapon user.visible_message("\The [user] begins to slit [src]'s throat with \the [W]!") @@ -95,4 +99,59 @@ user.attack_log += "\[[time_stamp()]\] Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" src.attack_log += "\[[time_stamp()]\] Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" ) - return 1 \ No newline at end of file + return 1 + +/mob/living/carbon/proc/shank_attack(obj/item/W, obj/item/weapon/grab/G, mob/user, hit_zone) + + if(!W.sharp || !W.force || W.damtype != BRUTE) + return 0 //unsuitable weapon + + user.visible_message("\The [user] plunges \the [W] into \the [src]!") + + var/damage = shank_armor_helper(W, G, user) + apply_damage(damage, W.damtype, "torso", 0, sharp=W.sharp, edge=W.edge) + + if(W.hitsound) + playsound(loc, W.hitsound, 50, 1, -1) + + user.attack_log += "\[[time_stamp()]\] Shanked [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" + src.attack_log += "\[[time_stamp()]\] Got shanked by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" + msg_admin_attack("[key_name(user)] shanked [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" ) + + return 1 + +/mob/living/carbon/proc/shank_armor_helper(obj/item/W, obj/item/weapon/grab/G, mob/user) + var/damage = W.force + var/damage_mod = 1 + if(W.edge) + damage = damage * 1.25 //small damage bonus for having sharp and edge + + var/obj/item/clothing/suit/worn_suit + var/obj/item/clothing/under/worn_under + var/worn_suit_armor + var/worn_under_armor + + //if(slot_wear_suit) + if(get_equipped_item(slot_wear_suit)) + worn_suit = get_equipped_item(slot_wear_suit) + //worn_suit = get_equipped_item(slot_wear_suit) + worn_suit_armor = worn_suit.armor["melee"] + else + worn_suit_armor = 0 + + //if(slot_w_uniform) + if(get_equipped_item(slot_w_uniform)) + worn_under = get_equipped_item(slot_w_uniform) + //worn_under_armor = slot_w_uniform.armor["melee"] + worn_under_armor = worn_under.armor["melee"] + else + worn_under_armor = 0 + + if(worn_under_armor > worn_suit_armor) + damage_mod = 1 - (worn_under_armor/100) + else + damage_mod = 1 - (worn_suit_armor/100) + + damage = damage * damage_mod + + return damage \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 7ac543f1f2..195816f255 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -67,7 +67,7 @@ BP_L_LEG = skiplegs, BP_R_LEG = skiplegs) - var/msg = "*---------*\nThis is " + var/list/msg = list("*---------*\nThis is ") var/datum/gender/T = gender_datums[get_gender()] if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender @@ -253,8 +253,8 @@ //splints for(var/organ in list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM)) var/obj/item/organ/external/o = get_organ(organ) - if(o && o.status & ORGAN_SPLINTED) - msg += "[T.He] [T.has] a splint on [T.his] [o.name]!\n" + if(o && o.splinted && o.splinted.loc == o) + msg += "[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!\n" if(suiciding) msg += "[T.He] appears to have commited suicide... there is no hope of recovery.\n" @@ -316,6 +316,7 @@ var/list/wound_flavor_text = list() var/list/is_bleeding = list() + var/applying_pressure = "" for(var/organ_tag in species.has_limbs) @@ -349,8 +350,6 @@ wound_flavor_text["[temp.name]"] = "[T.He] has [temp.get_wounds_desc()] on [T.his] [parent.name].
" else wound_flavor_text["[temp.name]"] = "[T.He] has [temp.get_wounds_desc()] on [T.his] [temp.name].
" - if(temp.status & ORGAN_BLEEDING) - is_bleeding["[temp.name]"] = "[T.His] [temp.name] is bleeding!
" else wound_flavor_text["[temp.name]"] = "" if(temp.dislocated == 2) @@ -358,9 +357,14 @@ if(((temp.status & ORGAN_BROKEN) && temp.brute_dam > temp.min_broken_damage) || (temp.status & ORGAN_MUTATED)) wound_flavor_text["[temp.name]"] += "[T.His] [temp.name] is dented and swollen!
" + if(!wound_flavor_text["[temp.name]"] && (temp.status & ORGAN_BLEEDING)) + is_bleeding["[temp.name]"] = "[T.His] [temp.name] is bleeding!
" + + if(temp.applied_pressure == src) + applying_pressure = "[T.He] is applying pressure to [T.his] [temp.name].
" + for(var/limb in wound_flavor_text) msg += wound_flavor_text[limb] - is_bleeding[limb] = null for(var/limb in is_bleeding) msg += is_bleeding[limb] for(var/implant in get_visible_implants(0)) @@ -421,13 +425,14 @@ msg += "OOC Notes: \[View\]\n" // VOREStation End - msg += "*---------*
" + msg += "*---------*

" + msg += applying_pressure if (pose) if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\n[T.He] [pose]" + msg += "[T.He] [pose]" - user << msg + user << jointext(msg, null) //Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. /proc/hasHUD(mob/M as mob, hudtype) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a53363e586..03a7b0db45 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1018,7 +1018,7 @@ /mob/living/carbon/human/proc/handle_embedded_objects() for(var/obj/item/organ/external/organ in src.organs) - if(organ.status & ORGAN_SPLINTED) //Splints prevent movement. + if(organ.splinted) //Splints prevent movement. continue for(var/obj/item/O in organ.implants) if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index d638d779d1..e790d1b5fd 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -92,7 +92,7 @@ src << "You feel a breath of fresh air enter your lungs. It feels good." H << "Repeat at least every 7 seconds." - else + else if(!(M == src && apply_pressure(M, M.zone_sel.selecting))) help_shake_act(M) return 1 @@ -363,3 +363,38 @@ spawn(1) qdel(rgrab) return success + +/* + We want to ensure that a mob may only apply pressure to one organ of one mob at any given time. Currently this is done mostly implicitly through + the behaviour of do_after() and the fact that applying pressure to someone else requires a grab: + If you are applying pressure to yourself and attempt to grab someone else, you'll change what you are holding in your active hand which will stop do_mob() + If you are applying pressure to another and attempt to apply pressure to yourself, you'll have to switch to an empty hand which will also stop do_mob() + Changing targeted zones should also stop do_mob(), preventing you from applying pressure to more than one body part at once. +*/ +/mob/living/carbon/human/proc/apply_pressure(mob/living/user, var/target_zone) + var/obj/item/organ/external/organ = get_organ(target_zone) + if(!organ || !(organ.status & ORGAN_BLEEDING) || (organ.robotic >= ORGAN_ROBOT)) + return 0 + + if(organ.applied_pressure) + user << "Someone is already applying pressure to [user == src? "your [organ.name]" : "[src]'s [organ.name]"]." + return 0 + + if(user == src) + user.visible_message("\The [user] starts applying pressure to \his [organ.name]!", "You start applying pressure to your [organ.name]!") + else + user.visible_message("\The [user] starts applying pressure to [src]'s [organ.name]!", "You start applying pressure to [src]'s [organ.name]!") + spawn(0) + organ.applied_pressure = user + + //apply pressure as long as they stay still and keep grabbing + do_mob(user, src, INFINITY, target_zone, progress = 0) + + organ.applied_pressure = null + + if(user == src) + user.visible_message("\The [user] stops applying pressure to \his [organ.name]!", "You stop applying pressure to your [organ]!") + else + user.visible_message("\The [user] stops applying pressure to [src]'s [organ.name]!", "You stop applying pressure to [src]'s [organ.name]!") + + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1d716b519d..2adb24665b 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -147,7 +147,7 @@ emp_act ..() /mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone) - if(check_attack_throat(I, user)) + if(check_neckgrab_attack(I, user, target_zone)) return null if(user == src) // Attacking yourself can't miss @@ -464,3 +464,30 @@ emp_act return perm +/mob/living/carbon/human/shank_attack(obj/item/W, obj/item/weapon/grab/G, mob/user, hit_zone) + + if(!..()) + return 0 + + var/organ_chance = 50 + var/damage = shank_armor_helper(W, G, user) + var/obj/item/organ/external/chest = get_organ(hit_zone) + + if(W.edge) + organ_chance = 75 + user.next_move = world.time + 20 + user.visible_message("\The [user] begins to twist \the [W] around inside [src]'s [chest]!") + if(!do_after(user, 20)) + return 0 + if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab + return 0 + + user.visible_message("\The [user] twists \the [W] around inside [src]'s [chest]!") + + if(prob(organ_chance)) + var/obj/item/organ/internal/selected_organ = pick(chest.internal_organs) + selected_organ.damage = max(selected_organ.damage, damage * 0.5) + G.last_action = world.time + flick(G.hud.icon_state, G.hud) + + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index ad6d078869..c225e63838 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -87,7 +87,8 @@ var/list/flavor_texts = list() var/gunshot_residue var/pulling_punches // Are you trying not to hurt your opponent? - var/robolimb_count = 0 // Number of robot limbs. + var/robolimb_count = 0 // Total number of external robot parts. + var/robobody_count = 0 // Counts torso, groin, and head, if they're robotic mob_bump_flag = HUMAN mob_push_flags = ~HEAVY diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index ae9dd9a506..de4b36dceb 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -45,7 +45,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) tally += 4 - if(E.status & ORGAN_SPLINTED) + if(E.splinted) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 @@ -57,7 +57,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) tally += 4 - else if(E.status & ORGAN_SPLINTED) + else if(E.splinted) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 494126e312..97153394db 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -142,10 +142,10 @@ return for (var/obj/item/organ/external/E in organs) - if(!E || !E.can_grasp || (E.status & ORGAN_SPLINTED)) + if(!E || !E.can_grasp) continue - if(E.is_broken() || E.is_dislocated()) + if((E.is_broken() || E.is_dislocated()) && !E.splinted) switch(E.body_part) if(HAND_LEFT, ARM_LEFT) if(!l_hand) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 8fc44a0671..ceef119b33 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -693,9 +693,9 @@ if (species.body_temperature == null) return //this species doesn't have metabolic thermoregulation - // Robolimbs cause overheating too. - if(robolimb_count) - bodytemperature += round(robolimb_count/2) + // FBPs will overheat, prosthetic limbs are fine. + if(robobody_count) + bodytemperature += round(robobody_count*1.75) var/body_temperature_difference = species.body_temperature - bodytemperature diff --git a/code/modules/mob/living/carbon/human/stripping.dm b/code/modules/mob/living/carbon/human/stripping.dm index f1c92b6255..d67eaf76a9 100644 --- a/code/modules/mob/living/carbon/human/stripping.dm +++ b/code/modules/mob/living/carbon/human/stripping.dm @@ -125,11 +125,13 @@ if(can_reach_splints) var/removed_splint for(var/obj/item/organ/external/o in organs) - if (o && o.status & ORGAN_SPLINTED) - var/obj/item/W = new /obj/item/stack/medical/splint(get_turf(src), 1) - o.status &= ~ORGAN_SPLINTED - W.add_fingerprint(user) - removed_splint = 1 + if (o && o.splinted) + var/obj/item/S = o.splinted + if(istype(S) && S.loc == o) //can only remove splints that are actually worn on the organ (deals with hardsuit splints) + S.add_fingerprint(user) + if(o.remove_splint()) + user.put_in_active_hand(S) + removed_splint = 1 if(removed_splint) visible_message("\The [user] removes \the [src]'s splints!") else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 6bc000f0f1..5c6868edc0 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -226,6 +226,7 @@ var/global/list/damage_icon_parts = list() var/skeleton = (SKELETON in src.mutations) robolimb_count = 0 + robobody_count = 0 //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. @@ -257,6 +258,8 @@ var/global/list/damage_icon_parts = list() else if(part.robotic >= ORGAN_ROBOT) icon_key += "2[part.model ? "-[part.model]": ""]" robolimb_count++ + if(part.organ_tag == BP_HEAD || part.organ_tag == BP_TORSO || part.organ_tag == BP_GROIN) + robobody_count ++ else if(part.status & ORGAN_DEAD) icon_key += "3" else diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index b7a66b6842..3c0bfbdbad 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -381,8 +381,3 @@ powerlevel = 10 adjustToxLoss(-10) nutrition = max(nutrition, get_max_nutrition()) - -/mob/living/carbon/slime/cannot_use_vents() - if(Victim) - return "You cannot ventcrawl while feeding." - ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 8fc7ef0f8c..bbb9a1acc8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -651,126 +651,10 @@ default behaviour is: resting = !resting src << "You are now [resting ? "resting" : "getting up"]" -/mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item) - return (get_inventory_slot(carried_item) == 0) - -/mob/living/simple_animal/spiderbot/is_allowed_vent_crawl_item(var/obj/item/carried_item) - if(carried_item == held_item) - return 0 - return ..() - -//called when the mob receives a bright flash -/mob/living/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash) - if(override_blindness_check || !(disabilities & BLIND)) - overlay_fullscreen("flash", type) - spawn(25) - if(src) - clear_fullscreen("flash", 25) - return 1 - -/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null, var/ignore_items = 0) // -- TLE -- Merged by Carn - if(stat) - src << "You must be conscious to do this!" - return - if(lying) - src << "You can't vent crawl while you're stunned!" - return - var/special_fail_msg = cannot_use_vents() - if(special_fail_msg) - src << "[special_fail_msg]" - return - - if(vent_found) // one was passed in, probably from vent/AltClick() - if(vent_found.welded) - src << "That vent is welded shut." - return - if(!vent_found.Adjacent(src)) - return // don't even acknowledge that - else - for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) - if(!v.welded) - if(v.Adjacent(src)) - vent_found = v - if(!vent_found) - src << "You'll need a non-welded vent to crawl into!" - return - - if(!vent_found.network || !vent_found.network.normal_members.len) - src << "This vent is not connected to anything." - return - - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.welded) - continue - if(temp_vent in loc) - continue - var/turf/T = get_turf(temp_vent) - - if(!T || T.z != loc.z) - continue - - var/i = 1 - var/index = "[T.loc.name]\[[i]\]" - while(index in vents) - i++ - index = "[T.loc.name]\[[i]\]" - vents[index] = temp_vent - if(!vents.len) - src << "\red There are no available vents to travel to, they could be welded." - return - - var/obj/selection = input("Select a destination.", "Duct System") as null|anything in sortAssoc(vents) - if(!selection) return - - if(!vent_found.Adjacent(src)) - src << "Never mind, you left." - return - - if(!ignore_items) - var/list/badItems = list() - for(var/obj/item/carried_item in contents)//If the monkey got on objects. - if(!is_allowed_vent_crawl_item(carried_item)) - badItems += carried_item.name - if(badItems.len) - src << "Your [english_list(badItems)] prevent[badItems.len == 1 ? "s" : ""] you from ventcrawling." - return - - if(isslime(src)) - var/mob/living/carbon/slime/S = src - if(S.Victim) - src << "\red You'll have to let [S.Victim] go or finish eating \him first." - return - - var/obj/machinery/atmospherics/unary/vent_pump/target_vent = vents[selection] - if(!target_vent) - return - - for(var/mob/O in viewers(src, null)) - O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) - loc = target_vent - - var/travel_time = round(get_dist(loc, target_vent.loc) / 2) - - spawn(travel_time) - - if(!target_vent) return - for(var/mob/O in hearers(target_vent,null)) - O.show_message("You hear something squeezing through the ventilation ducts.",2) - - sleep(travel_time) - - if(!target_vent) return - if(target_vent.welded) //the vent can be welded while alien scrolled through the list or travelled. - target_vent = vent_found //travel back. No additional time required. - src << "\red The vent you were heading to appears to be welded." - loc = target_vent.loc - var/area/new_area = get_area(loc) - if(new_area) - new_area.Entered(src) - /mob/living/proc/cannot_use_vents() - return "You can't fit into that vent." + if(mob_size > MOB_SMALL) + return "You can't fit into that vent." + return null /mob/living/proc/has_brain() return 1 diff --git a/code/modules/mob/living/living_powers.dm b/code/modules/mob/living/living_powers.dm index b4310d77b5..4fb4c1bcbd 100644 --- a/code/modules/mob/living/living_powers.dm +++ b/code/modules/mob/living/living_powers.dm @@ -1,13 +1,3 @@ -/mob/living/proc/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Abilities" - - if(stat == DEAD || paralysis || weakened || stunned || restrained()) - return - - handle_ventcrawl() - /mob/living/proc/hide() set name = "Hide" set desc = "Allows to hide beneath tables or certain items. Toggled on or off." diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 3c6f8585f6..fd38776dd5 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -400,7 +400,7 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c var/input = sanitize(input(usr, "Please choose a message to transmit to [boss_short] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "")) if(!input) return - Centcomm_announce(input, usr) + CentCom_announce(input, usr) usr << "Message transmitted." log_say("[key_name(usr)] has made an IA [boss_short] announcement: [input]") emergency_message_cooldown = 1 diff --git a/code/modules/mob/living/silicon/ai/icons.dm b/code/modules/mob/living/silicon/ai/icons.dm index 83689c9dd4..ebd47cc02d 100644 --- a/code/modules/mob/living/silicon/ai/icons.dm +++ b/code/modules/mob/living/silicon/ai/icons.dm @@ -112,7 +112,7 @@ var/list/datum/ai_icon/ai_icons alive_light = "#585858" /datum/ai_icon/nanotrasen - name = "Nanotrasen" + name = "NanoTrasen" alive_icon = "ai-nanotrasen" alive_light = "#000029" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index f9c26528b6..f038324299 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -465,6 +465,7 @@ return var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0)) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) adjustBruteLoss(-30) updatehealth() add_fingerprint(user) @@ -480,6 +481,7 @@ return var/obj/item/stack/cable_coil/coil = W if (coil.use(1)) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) adjustFireLoss(-30) updatehealth() for(var/mob/O in viewers(user, null)) diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm new file mode 100644 index 0000000000..b843013c39 --- /dev/null +++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm @@ -0,0 +1,19 @@ +/mob/living/simple_animal/penguin + name = "space penguin" + desc = "An ungainly, waddling, cute, and VERY well-dressed bird." + icon_state = "penguin" + icon_living = "penguin" + icon_dead = "penguin_dead" + icon_gib = "generic_gib" + speak_chance = 0 + turns_per_move = 5 + maxHealth = 20 + health = 20 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + response_help = "pets" + response_disarm = "pushes aside" + response_harm = "hits" + harm_intent_damage = 5 + melee_damage_upper = 15 + melee_damage_lower = 10 + attacktext = "pecked" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm new file mode 100644 index 0000000000..0f2c4af611 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -0,0 +1,34 @@ + + +/mob/living/simple_animal/hostile/goose + name = "space goose" + desc = "That's no duck. That's a space goose. You have a bad feeling about this." + icon_state = "goose" + icon_living = "goose" + icon_dead = "goose_dead" + icon_gib = "generic_gib" + speak_chance = 0 + turns_per_move = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speed = 4 + maxHealth = 15 //nothing an unarmed crewmember shouldn't be able to stomp into the dirt, if they're alone. + health = 15 + + harm_intent_damage = 5 + melee_damage_lower = 5 //they're meant to be annoying, not threatening. + melee_damage_upper = 5 //unless there's like a dozen of them, then you're screwed. + attacktext = "pecked" + attack_sound = 'sound/weapons/bite.ogg' + + break_stuff_probability = 5 + + faction = "geese" + + +/mob/living/simple_animal/hostile/goose/FindTarget() + . = ..() + if(.) + custom_emote(1,"flaps and honks at [.]!") \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 75f061e2e1..41cbbbc5e9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -520,7 +520,7 @@ for(var/name in H.organs_by_name) var/obj/item/organ/external/e = H.organs_by_name[name] if(e && H.lying) - if(((e.status & ORGAN_BROKEN && !(e.status & ORGAN_SPLINTED)) || e.status & ORGAN_BLEEDING) && (H.getBruteLoss() + H.getFireLoss() >= 100)) + if(((e.status & ORGAN_BROKEN && !(e.splinted)) || e.status & ORGAN_BLEEDING) && (H.getBruteLoss() + H.getFireLoss() >= 100)) return 1 break return 0 diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index e40b14dffd..a7b982b1b7 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -301,6 +301,7 @@ //clicking on the victim while grabbing them if(M == affecting) if(ishuman(affecting)) + var/mob/living/carbon/human/H = affecting var/hit_zone = assailant.zone_sel.selecting flick(hud.icon_state, hud) switch(assailant.a_intent) @@ -309,7 +310,10 @@ assailant << "You are no longer pinning [affecting] to the ground." force_down = 0 return - inspect_organ(affecting, assailant, hit_zone) + if(state >= GRAB_AGGRESSIVE) + H.apply_pressure(assailant, hit_zone) + else + inspect_organ(affecting, assailant, hit_zone) if(I_GRAB) jointlock(affecting, assailant, hit_zone) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index c2b83551ec..f50b91f291 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -371,7 +371,7 @@ dat += "Welcome, [name].
" dat += "Round Duration: [roundduration2text()]
" - if(emergency_shuttle) //In case Nanotrasen decides reposess CentComm's shuttles. + if(emergency_shuttle) //In case NanoTrasen decides reposess CentCom's shuttles. if(emergency_shuttle.going_to_centcom()) //Shuttle is going to centcomm, not recalled dat += "The station has been evacuated.
" if(emergency_shuttle.online()) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index a10049a644..92f0f512bd 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -29,7 +29,7 @@ all_underwear[WRC.name] = WRI.name - backbag = rand(1,4) + backbag = rand(1,5) pdachoice = rand(1,3) age = rand(current_species.min_age, current_species.max_age) b_type = RANDOM_BLOOD_TYPE diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 85e23b6797..1cb5b9b4da 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -13,9 +13,6 @@ obj/machinery/atmospherics/pipe/zpipe dir = SOUTH initialize_directions = SOUTH - var/obj/machinery/atmospherics/node1 //connection on the same Z - var/obj/machinery/atmospherics/node2 //connection on the other Z - var/minimum_temperature_difference = 300 var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index c167f949fa..7637264bac 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -128,8 +128,18 @@ var/const/BLOOD_VOLUME_SURVIVE = 40 for(var/obj/item/organ/external/temp in organs) if(!(temp.status & ORGAN_BLEEDING) || (temp.robotic >= ORGAN_ROBOT)) continue - for(var/datum/wound/W in temp.wounds) if(W.bleeding()) - blood_max += W.damage / 30 + for(var/datum/wound/W in temp.wounds) + if(W.bleeding()) + if(temp.applied_pressure) + if(ishuman(temp.applied_pressure)) + var/mob/living/carbon/human/H = temp.applied_pressure + H.bloody_hands(src, 0) + //somehow you can apply pressure to every wound on the organ at the same time + //you're basically forced to do nothing at all, so let's make it pretty effective + var/min_eff_damage = max(0, W.damage - 10) / 6 //still want a little bit to drip out, for effect + blood_max += max(min_eff_damage, W.damage - 30) / 30 + else + blood_max += W.damage / 30 if (temp.open) blood_max += 2 //Yer stomach is cut open drip(blood_max) diff --git a/code/modules/organs/internal/appendix.dm b/code/modules/organs/internal/appendix.dm index b3fdc28bc2..f756b71efa 100644 --- a/code/modules/organs/internal/appendix.dm +++ b/code/modules/organs/internal/appendix.dm @@ -46,7 +46,7 @@ var/datum/wound/W = new /datum/wound/internal_bleeding(20) owner.adjustToxLoss(25) groin.wounds += W - inflamed = 0 + inflamed = 1 /obj/item/organ/internal/appendix/removed() if(inflamed) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index fad60cc0d7..c3a349df17 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -254,7 +254,6 @@ var/list/organ_cache = list() robotic = ORGAN_ROBOT src.status &= ~ORGAN_BROKEN src.status &= ~ORGAN_BLEEDING - src.status &= ~ORGAN_SPLINTED src.status &= ~ORGAN_CUT_AWAY /obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 612cda4a98..49917d8a23 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -38,6 +38,7 @@ var/list/s_col // skin colour var/list/h_col // hair colour var/body_hair // Icon blend for body hair if any. + var/mob/living/applied_pressure // Wound and structural data. var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often @@ -50,6 +51,7 @@ var/list/implants = list() // Currently implanted objects. var/organ_rel_size = 25 // Relative size of the organ. var/base_miss_chance = 20 // Chance of missing. + var/atom/movable/splinted // Joint/state stuff. var/can_grasp // It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point @@ -84,6 +86,10 @@ for(var/obj/item/organ/O in internal_organs) qdel(O) + if(splinted && splinted.loc == src) + qdel(splinted) + splinted = null + if(owner) owner.organs -= src owner.organs_by_name[organ_tag] = null @@ -524,11 +530,11 @@ This function completely restores a damaged organ to perfect condition. //external organs handle brokenness a bit differently when it comes to damage. Instead brute_dam is checked inside process() //this also ensures that an external organ cannot be "broken" without broken_description being set. /obj/item/organ/external/is_broken() - return ((status & ORGAN_CUT_AWAY) || ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED))) + return ((status & ORGAN_CUT_AWAY) || ((status & ORGAN_BROKEN) && !(splinted))) //Determines if we even need to process this organ. /obj/item/organ/external/proc/need_process() - if(status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED)) + if(status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED)) return 1 if((brute_dam || burn_dam) && (robotic < ORGAN_ROBOT)) //Robot limbs don't autoheal and thus don't need to process when damaged return 1 @@ -1006,21 +1012,10 @@ Note that amputating the affected organ does in fact remove the infection from t // This is mostly for the ninja suit to stop ninja being so crippled by breaks. // TODO: consider moving this to a suit proc or process() or something during // hardsuit rewrite. - if(owner && !(status & ORGAN_SPLINTED) && istype(owner,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = owner - - if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) - - var/obj/item/clothing/suit/space/suit = H.wear_suit - - if(isnull(suit.supporting_limbs)) - return - - owner << "You feel \the [suit] constrict about your [name], supporting it." - status |= ORGAN_SPLINTED - suit.supporting_limbs |= src - return + if(!(splinted) && owner && istype(owner.wear_suit, /obj/item/clothing/suit/space)) + var/obj/item/clothing/suit/space/suit = owner.wear_suit + suit.handle_fracture(owner, src) /obj/item/organ/external/proc/mend_fracture() if(robotic >= ORGAN_ROBOT) @@ -1031,6 +1026,24 @@ Note that amputating the affected organ does in fact remove the infection from t status &= ~ORGAN_BROKEN return 1 +/obj/item/organ/external/proc/apply_splint(var/atom/movable/splint) + if(!splinted) + splinted = splint + if(!applied_pressure) + applied_pressure = splint + return 1 + return 0 + +/obj/item/organ/external/proc/remove_splint() + if(splinted) + if(splinted.loc == src) + splinted.dropInto(owner? owner.loc : src.loc) + if(applied_pressure == splinted) + applied_pressure = null + splinted = null + return 1 + return 0 + /obj/item/organ/external/robotize(var/company, var/skip_prosthetics = 0, var/keep_organs = 0) if(robotic >= ORGAN_ROBOT) @@ -1054,6 +1067,7 @@ Note that amputating the affected organ does in fact remove the infection from t dislocated = -1 cannot_break = 1 + remove_splint() get_icon() unmutate() @@ -1235,11 +1249,20 @@ Note that amputating the affected organ does in fact remove the infection from t for(var/datum/wound/W in wounds) if(W.internal && !open) continue // can't see internal wounds var/this_wound_desc = W.desc - if(W.damage_type == BURN && W.salved) this_wound_desc = "salved [this_wound_desc]" - if(W.bleeding()) this_wound_desc = "bleeding [this_wound_desc]" - else if(W.bandaged) this_wound_desc = "bandaged [this_wound_desc]" - if(W.germ_level > 600) this_wound_desc = "badly infected [this_wound_desc]" - else if(W.germ_level > 330) this_wound_desc = "lightly infected [this_wound_desc]" + + if(W.damage_type == BURN && W.salved) + this_wound_desc = "salved [this_wound_desc]" + + if(W.bleeding()) + this_wound_desc = "bleeding [this_wound_desc]" + else if(W.bandaged) + this_wound_desc = "bandaged [this_wound_desc]" + + if(W.germ_level > 600) + this_wound_desc = "badly infected [this_wound_desc]" + else if(W.germ_level > 330) + this_wound_desc = "lightly infected [this_wound_desc]" + if(wound_descriptors[this_wound_desc]) wound_descriptors[this_wound_desc] += W.amount else diff --git a/code/modules/paperwork/adminpaper.dm b/code/modules/paperwork/adminpaper.dm index 7843552f8c..230d8984e8 100644 --- a/code/modules/paperwork/adminpaper.dm +++ b/code/modules/paperwork/adminpaper.dm @@ -40,7 +40,7 @@ var/originhash = md5("[origin]") var/timehash = copytext(md5("[world.time]"),1,10) var/text = null - var/logo = alert(usr, "Do you want the header of your fax to have a Nanotrasen or SolGov logo?","Fax Logo","Nanotrasen","SolGov") + var/logo = alert(usr, "Do you want the header of your fax to have a NanoTrasen or SolGov logo?","Fax Logo","NanoTrasen","SolGov") if(logo == "SolGov") logo = "sglogo.png" else diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index cf1da677f0..f2c309ff03 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -181,11 +181,11 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins //message badmins that a fax has arrived if (destination == boss_name) - message_admins(sender, "[uppertext(boss_short)] FAX", rcvdcopy, "CentcommFaxReply", "#006100") + message_admins(sender, "[uppertext(boss_short)] FAX", rcvdcopy, "CentComFaxReply", "#006100") else if ("Sif Governmental Authority") - message_admins(sender, "SIF GOVERNMENT FAX", rcvdcopy, "CentcommFaxReply", "#1F66A0") + message_admins(sender, "SIF GOVERNMENT FAX", rcvdcopy, "CentComFaxReply", "#1F66A0") else if ("Supply") - message_admins(sender, "[uppertext(boss_short)] SUPPLY FAX", rcvdcopy, "CentcommFaxReply", "#5F4519") + message_admins(sender, "[uppertext(boss_short)] SUPPLY FAX", rcvdcopy, "CentComFaxReply", "#5F4519") else message_admins(sender, "[uppertext(destination)] FAX", rcvdcopy, "UNKNOWN") diff --git a/code/modules/projectiles/effects.dm b/code/modules/projectiles/effects.dm index 2235f188e7..94e39f41cc 100644 --- a/code/modules/projectiles/effects.dm +++ b/code/modules/projectiles/effects.dm @@ -11,7 +11,8 @@ if(istype(M)) transform = M -/obj/effect/projectile/proc/activate(var/kill_delay = 3) +/obj/effect/projectile/proc/activate(var/kill_delay = 5) + update_light() spawn(kill_delay) qdel(src) //see effect_system.dm - sets loc to null and lets GC handle removing these effects @@ -22,117 +23,207 @@ //---------------------------- /obj/effect/projectile/laser/tracer icon_state = "beam" + light_range = 2 + light_power = 0.5 + light_color = "#FF0D00" /obj/effect/projectile/laser/muzzle icon_state = "muzzle_laser" + light_range = 2 + light_power = 0.5 + light_color = "#FF0D00" /obj/effect/projectile/laser/impact icon_state = "impact_laser" + light_range = 2 + light_power = 0.5 + light_color = "#FF0D00" //---------------------------- // Blue laser beam //---------------------------- /obj/effect/projectile/laser_blue/tracer icon_state = "beam_blue" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" /obj/effect/projectile/laser_blue/muzzle icon_state = "muzzle_blue" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" /obj/effect/projectile/laser_blue/impact icon_state = "impact_blue" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" //---------------------------- // Omni laser beam //---------------------------- /obj/effect/projectile/laser_omni/tracer icon_state = "beam_omni" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" /obj/effect/projectile/laser_omni/muzzle icon_state = "muzzle_omni" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" /obj/effect/projectile/laser_omni/impact icon_state = "impact_omni" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" //---------------------------- // Xray laser beam //---------------------------- /obj/effect/projectile/xray/tracer icon_state = "xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" /obj/effect/projectile/xray/muzzle icon_state = "muzzle_xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" /obj/effect/projectile/xray/impact icon_state = "impact_xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" //---------------------------- // Heavy laser beam //---------------------------- /obj/effect/projectile/laser_heavy/tracer icon_state = "beam_heavy" + light_range = 3 + light_power = 1 + light_color = "#FF0D00" /obj/effect/projectile/laser_heavy/muzzle icon_state = "muzzle_beam_heavy" + light_range = 3 + light_power = 1 + light_color = "#FF0D00" /obj/effect/projectile/laser_heavy/impact icon_state = "impact_beam_heavy" + light_range = 3 + light_power = 1 + light_color = "#FF0D00" //---------------------------- // Pulse laser beam //---------------------------- /obj/effect/projectile/laser_pulse/tracer icon_state = "u_laser" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" /obj/effect/projectile/laser_pulse/muzzle icon_state = "muzzle_u_laser" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" /obj/effect/projectile/laser_pulse/impact icon_state = "impact_u_laser" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" //---------------------------- // Pulse muzzle effect only //---------------------------- /obj/effect/projectile/pulse/muzzle icon_state = "muzzle_pulse" + light_range = 2 + light_power = 0.5 + light_color = "#0066FF" //---------------------------- // Emitter beam //---------------------------- /obj/effect/projectile/emitter/tracer icon_state = "emitter" + icon_state = "impact_xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" /obj/effect/projectile/emitter/muzzle icon_state = "muzzle_emitter" + icon_state = "impact_xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" /obj/effect/projectile/emitter/impact icon_state = "impact_emitter" + icon_state = "impact_xray" + light_range = 2 + light_power = 0.5 + light_color = "#00CC33" //---------------------------- // Stun beam //---------------------------- /obj/effect/projectile/stun/tracer icon_state = "stun" + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" /obj/effect/projectile/stun/muzzle icon_state = "muzzle_stun" + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" /obj/effect/projectile/stun/impact icon_state = "impact_stun" + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" //---------------------------- // Bullet //---------------------------- /obj/effect/projectile/bullet/muzzle icon_state = "muzzle_bullet" + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" //---------------------------- // Lightning beam //---------------------------- /obj/effect/projectile/lightning/tracer icon_state = "lightning" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" /obj/effect/projectile/lightning/muzzle icon_state = "muzzle_lightning" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" /obj/effect/projectile/lightning/impact - icon_state = "impact_lightning" \ No newline at end of file + icon_state = "impact_lightning" + light_range = 2 + light_power = 0.5 + light_color = "#00C6FF" \ No newline at end of file diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 9271e50503..01dfce8e8c 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -290,6 +290,76 @@ if(muzzle_flash) set_light(0) +// Similar to the above proc, but does not require a user, which is ideal for things like turrets. +/obj/item/weapon/gun/proc/Fire_userless(atom/target) + if(!target) + return + + if(world.time < next_fire_time) + return + + var/shoot_time = (burst - 1)* burst_delay + next_fire_time = world.time + shoot_time + + var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed. + for(var/i in 1 to burst) + var/obj/projectile = consume_next_projectile() + if(!projectile) + handle_click_empty() + break + + if(istype(projectile, /obj/item/projectile)) + var/obj/item/projectile/P = projectile + + var/acc = burst_accuracy[min(i, burst_accuracy.len)] + var/disp = dispersion[min(i, dispersion.len)] + + P.accuracy = accuracy + acc + P.dispersion = disp + + P.shot_from = src.name + P.silenced = silenced + + P.launch(target) + + if(silenced) + playsound(src, fire_sound, 10, 1) + else + playsound(src, fire_sound, 50, 1) + + if(muzzle_flash) + set_light(muzzle_flash) + update_icon() + + //process_accuracy(projectile, user, target, acc, disp) + + // if(pointblank) + // process_point_blank(projectile, user, target) + + // if(process_projectile(projectile, null, target, user.zone_sel.selecting, clickparams)) + // handle_post_fire(null, target, pointblank, reflex) + + // update_icon() + + if(i < burst) + sleep(burst_delay) + + if(!(target && target.loc)) + target = targloc + //pointblank = 0 + + log_and_message_admins("Fired [src].") + + //admin_attack_log(usr, attacker_message="Fired [src]", admin_message="fired a gun ([src]) (MODE: [src.mode_name]) [reflex ? "by reflex" : "manually"].") + + //update timing + next_fire_time = world.time + fire_delay + + if(muzzle_flash) + set_light(0) + + + //obtains the next projectile to fire /obj/item/weapon/gun/proc/consume_next_projectile() return null diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 5d2fe06fa4..cef84810bd 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -6,7 +6,7 @@ item_state = "laser" fire_sound = 'sound/weapons/Laser.ogg' slot_flags = SLOT_BELT|SLOT_BACK - w_class = 3 + w_class = 4 force = 10 origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) matter = list(DEFAULT_WALL_MATERIAL = 2000) @@ -69,8 +69,9 @@ obj/item/weapon/gun/energy/retro origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) slot_flags = SLOT_BELT|SLOT_BACK projectile_type = /obj/item/projectile/beam/heavylaser/cannon - max_shots = 1 - fire_delay = 30 + max_shots = 4 + fire_delay = 20 + w_class = 4 // requires_two_hands = 1 one_handed_penalty = 6 // The thing's heavy and huge. accuracy = 3 diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 2352cdce28..6819c1cd81 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -24,11 +24,14 @@ /obj/item/weapon/gun/energy/gun/burst name = "burst laser" - desc = "The FM-2t is a versatile energy based small arm, capable of switching between stun or kill with a three round burst option for both settings." - icon_state = "fm-2tstun100" + desc = "The FM-2t is a versatile energy based weapon, capable of switching between stun or kill with a three round burst option for both settings." + icon_state = "fm-2tstun100" //May resprite this to be more rifley item_state = null //so the human update icon uses the icon_state instead. fire_sound = 'sound/weapons/Taser.ogg' - max_shots = 21 //7 trigger pulls + max_shots = 18 + force = 8 + w_class = 4 //Probably gonna make it a rifle sooner or later + fire_delay = 6 projectile_type = /obj/item/projectile/beam/stun/weak origin_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 2, TECH_ILLEGAL = 3) @@ -39,9 +42,9 @@ firemodes = list( list(mode_name="stun", burst=1, projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", fire_sound='sound/weapons/Taser.ogg'), - list(mode_name="stun burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0), projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", fire_sound='sound/weapons/Taser.ogg'), - list(mode_name="lethal", burst=1, projectile_type=/obj/item/projectile/beam/weaklaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg'), - list(mode_name="lethal burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0), projectile_type=/obj/item/projectile/beam/weaklaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg'), + list(mode_name="stun burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", fire_sound='sound/weapons/Taser.ogg'), + list(mode_name="lethal", burst=1, projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg'), + list(mode_name="lethal burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg'), ) /obj/item/weapon/gun/energy/gun/nuclear @@ -51,6 +54,8 @@ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3) slot_flags = SLOT_BELT force = 8 //looks heavier than a pistol + w_class = 4 //Looks bigger than a pistol, too. + fire_delay = 6 //This one's not a handgun, it should have the same fire delay as everything else self_recharge = 1 modifystate = null diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index d1fc9ee4a8..93904387cd 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -141,6 +141,24 @@ user.visible_message("[user] inserts \a [C] into [src].", "You insert \a [C] into [src].") playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) + else if(istype(A, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/storage = A + if(!(load_method & SINGLE_CASING)) + return //incompatible + + user << "You start loading \the [src]." + sleep(1 SECOND) + for(var/obj/item/ammo_casing/ammo in storage.contents) + if(caliber != ammo.caliber) + continue + + load_ammo(ammo, user) + + if(loaded.len >= max_shells) + user << "[src] is full." + break + sleep(1 SECOND) + update_icon() //attempts to unload src. If allow_dump is set to 0, the speedloader unloading method will be disabled diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index ee46b5f42e..81149cf2cb 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -293,6 +293,7 @@ trajectory.increment() // increment the current location location = trajectory.return_location(location) // update the locally stored location data + update_light() //energy projectiles will look glowy and fun if(!location) qdel(src) // if it's left the world... kill it @@ -354,6 +355,7 @@ M.set_transform(T) M.pixel_x = location.pixel_x M.pixel_y = location.pixel_y + M.update_light() M.activate() /obj/item/projectile/proc/tracer_effect(var/matrix/M) @@ -364,6 +366,7 @@ P.set_transform(M) P.pixel_x = location.pixel_x P.pixel_y = location.pixel_y + P.update_light() if(!hitscan) P.activate(step_delay) //if not a hitscan projectile, remove after a single delay else @@ -377,6 +380,7 @@ P.set_transform(M) P.pixel_x = location.pixel_x P.pixel_y = location.pixel_y + P.update_light() P.activate() //"Tracing" projectile diff --git a/code/modules/projectiles/projectile/animate.dm b/code/modules/projectiles/projectile/animate.dm index 0f92729ad4..c09b98a32b 100644 --- a/code/modules/projectiles/projectile/animate.dm +++ b/code/modules/projectiles/projectile/animate.dm @@ -5,6 +5,9 @@ damage_type = BURN nodamage = 1 check_armour = "energy" + light_range = 2 + light_power = 0.5 + light_color = "#55AAFF" /obj/item/projectile/animate/Bump(var/atom/change) if((istype(change, /obj/item) || istype(change, /obj/structure)) && !is_type_in_list(change, protected_objects)) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 1049f5f70d..1f0dd03854 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -9,6 +9,9 @@ var/frequency = 1 hitscan = 1 invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine + light_range = 2 + light_power = 0.5 + light_color = "#FF0D00" muzzle_type = /obj/effect/projectile/laser/muzzle tracer_type = /obj/effect/projectile/laser/tracer @@ -28,6 +31,11 @@ icon_state = "laser" damage = 15 +/obj/item/projectile/beam/burstlaser + damage = 30 + armor_penetration = 10 + + /obj/item/projectile/beam/midlaser damage = 40 armor_penetration = 10 @@ -37,20 +45,25 @@ icon_state = "heavylaser" damage = 60 armor_penetration = 30 + light_range = 3 + light_power = 1 + light_color = "#FF0D00" muzzle_type = /obj/effect/projectile/laser_heavy/muzzle tracer_type = /obj/effect/projectile/laser_heavy/tracer impact_type = /obj/effect/projectile/laser_heavy/impact /obj/item/projectile/beam/heavylaser/cannon - damage = 90 - armor_penetration = 100 + damage = 80 + armor_penetration = 50 + light_color = "#FF0D00" /obj/item/projectile/beam/xray name = "xray beam" icon_state = "xray" damage = 25 armor_penetration = 50 + light_color = "#00CC33" muzzle_type = /obj/effect/projectile/xray/muzzle tracer_type = /obj/effect/projectile/xray/tracer @@ -61,6 +74,7 @@ icon_state = "u_laser" damage = 50 armor_penetration = 30 + light_color = "#0066FF" muzzle_type = /obj/effect/projectile/laser_pulse/muzzle tracer_type = /obj/effect/projectile/laser_pulse/tracer @@ -75,6 +89,7 @@ name = "emitter beam" icon_state = "emitter" damage = 0 // The actual damage is computed in /code/modules/power/singularity/emitter.dm + light_color = "#00CC33" muzzle_type = /obj/effect/projectile/emitter/muzzle tracer_type = /obj/effect/projectile/emitter/tracer @@ -88,6 +103,7 @@ no_attack_log = 1 damage_type = BURN check_armour = "laser" + light_color = "#0066FF" muzzle_type = /obj/effect/projectile/laser_blue/muzzle tracer_type = /obj/effect/projectile/laser_blue/tracer @@ -108,6 +124,7 @@ no_attack_log = 1 damage_type = BURN check_armour = "laser" + light_color = "#FF0D00" /obj/item/projectile/beam/lastertag/red/on_hit(var/atom/target, var/blocked = 0) if(istype(target, /mob/living/carbon/human)) @@ -123,6 +140,7 @@ damage = 0 damage_type = BURN check_armour = "laser" + light_color = "#00C6FF" muzzle_type = /obj/effect/projectile/laser_omni/muzzle tracer_type = /obj/effect/projectile/laser_omni/tracer @@ -140,6 +158,7 @@ icon_state = "xray" damage = 50 armor_penetration = 10 + light_color = "#00CC33" muzzle_type = /obj/effect/projectile/xray/muzzle tracer_type = /obj/effect/projectile/xray/tracer @@ -152,6 +171,7 @@ taser_effect = 1 agony = 40 damage_type = HALLOSS + light_color = "#FFFFFF" muzzle_type = /obj/effect/projectile/stun/muzzle tracer_type = /obj/effect/projectile/stun/tracer diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 9a9fa74292..3eb848c733 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -25,14 +25,14 @@ for (var/mob/living/carbon/M in viewers(T, flash_range)) if(M.eyecheck() < 1) M.flash_eyes() - if(ishuman(M)) - var/mob/living/carbon/human/H = M - flash_strength *= H.species.flash_mod + if(ishuman(M)) + var/mob/living/carbon/human/H = M + flash_strength *= H.species.flash_mod - if(flash_strength > 0) - H.confused = max(H.confused, flash_strength + 5) - H.eye_blind = max(H.eye_blind, flash_strength) - H.eye_blurry = max(H.eye_blurry, flash_strength + 5) + if(flash_strength > 0) + H.confused = max(H.confused, flash_strength + 5) + H.eye_blind = max(H.eye_blind, flash_strength) + H.eye_blurry = max(H.eye_blurry, flash_strength + 5) //snap pop @@ -68,6 +68,9 @@ taser_effect = 1 agony = 40 damage_type = HALLOSS + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" //Damage will be handled on the MOB side, to prevent window shattering. /obj/item/projectile/energy/electrode/strong @@ -85,6 +88,9 @@ nodamage = 1 damage_type = CLONE irradiate = 40 + light_range = 2 + light_power = 0.5 + light_color = "#33CC00" /obj/item/projectile/energy/dart @@ -124,3 +130,6 @@ damage = 20 damage_type = TOX irradiate = 20 + light_range = 2 + light_power = 0.5 + light_color = "#33CC00" diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 788886af30..b567512a05 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -5,6 +5,9 @@ damage_type = BURN nodamage = 1 check_armour = "energy" + light_range = 2 + light_power = 0.5 + light_color = "#55AAFF" on_hit(var/atom/target, var/blocked = 0) @@ -32,6 +35,9 @@ nodamage = 1 check_armour = "energy" var/temperature = 300 + light_range = 2 + light_power = 0.5 + light_color = "#55AAFF" on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob @@ -77,6 +83,9 @@ damage_type = TOX nodamage = 1 check_armour = "energy" + light_range = 2 + light_power = 0.5 + light_color = "#33CC00" on_hit(var/atom/target, var/blocked = 0) var/mob/living/M = target @@ -116,6 +125,9 @@ damage_type = TOX nodamage = 1 check_armour = "energy" + light_range = 2 + light_power = 0.5 + light_color = "#FFFFFF" on_hit(var/atom/target, var/blocked = 0) var/mob/M = target @@ -136,6 +148,7 @@ if(ishuman(target)) var/mob/living/carbon/human/M = target M.confused += rand(5,8) + /obj/item/projectile/chameleon name = "bullet" icon_state = "bullet" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index f051e8307f..fcabfa811c 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -125,10 +125,10 @@ /datum/reagent/water/touch_mob(var/mob/living/L, var/amount) if(istype(L)) - var/needed = L.fire_stacks * 10 + var/needed = L.fire_stacks * 5 if(amount > needed) L.ExtinguishMob() - L.adjust_fire_stacks(-(amount / 10)) + L.adjust_fire_stacks(-(amount / 5)) remove_self(needed) /datum/reagent/water/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index c0ecdbfc3d..78715938c3 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1486,6 +1486,427 @@ CIRCUITS BELOW build_path = /obj/item/weapon/cartridge/captain sort_string = "VBAAO" + + +/datum/design/item/wirer + name = "Custom wirer tool" + id = "wirer" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) + build_path = /obj/item/device/integrated_electronics/wirer + sort_string = "VBVAA" + +/datum/design/item/debugger + name = "Custom circuit debugger tool" + id = "debugger" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) + build_path = /obj/item/device/integrated_electronics/debugger + sort_string = "VBVAB" + + + +/datum/design/item/custom_circuit_assembly + name = "Small custom assembly" + desc = "An customizable assembly for simple, small devices." + id = "assembly-small" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 10000) + build_path = /obj/item/device/electronic_assembly + sort_string = "VCAAA" + +/datum/design/item/custom_circuit_assembly/medium + name = "Medium custom assembly" + desc = "An customizable assembly suited for more ambitious mechanisms." + id = "assembly-medium" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 20000) + build_path = /obj/item/device/electronic_assembly/medium + +/datum/design/item/custom_circuit_assembly/large + name = "Large custom assembly" + desc = "An customizable assembly for large machines." + id = "assembly-large" + req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(DEFAULT_WALL_MATERIAL = 40000) + build_path = /obj/item/device/electronic_assembly/large + +/datum/design/circuit/integrated_circuit + req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2) + +/datum/design/circuit/integrated_circuit/AssembleDesignName() + ..() + name = "Custom circuitry ([item_name])" + +/datum/design/circuit/integrated_circuit/AssembleDesignDesc() + if(!desc) + desc = "Allows for the construction of \a [name] custom circuit." + +/datum/design/circuit/integrated_circuit/arithmetic/AssembleDesignName() + ..() + name = "Custom circuitry \[Arithmetic\] ([item_name])" + +/datum/design/circuit/integrated_circuit/arithmetic/addition + id = "cc-addition" + build_path = /obj/item/integrated_circuit/arithmetic/addition + sort_string = "WAAAA" + +/datum/design/circuit/integrated_circuit/arithmetic/subtraction + id = "cc-subtraction" + build_path = /obj/item/integrated_circuit/arithmetic/subtraction + sort_string = "WAAAB" + +/datum/design/circuit/integrated_circuit/arithmetic/multiplication + id = "cc-multiplication" + build_path = /obj/item/integrated_circuit/arithmetic/multiplication + sort_string = "WAAAC" + +/datum/design/circuit/integrated_circuit/arithmetic/division + id = "cc-division" + build_path = /obj/item/integrated_circuit/arithmetic/division + sort_string = "WAAAD" + +/datum/design/circuit/integrated_circuit/arithmetic/absolute + id = "cc-absolute" + build_path = /obj/item/integrated_circuit/arithmetic/absolute + sort_string = "WAAAE" + +/datum/design/circuit/integrated_circuit/arithmetic/average + id = "cc-average" + build_path = /obj/item/integrated_circuit/arithmetic/average + sort_string = "WAAAF" + +/datum/design/circuit/integrated_circuit/arithmetic/pi + id = "cc-pi" + build_path = /obj/item/integrated_circuit/arithmetic/pi + sort_string = "WAAAG" + +/datum/design/circuit/integrated_circuit/arithmetic/random + id = "cc-random" + build_path = /obj/item/integrated_circuit/arithmetic/random + sort_string = "WAAAH" + + + +/datum/design/circuit/integrated_circuit/converter/AssembleDesignName() + ..() + name = "Custom circuitry \[Conversion\] ([item_name])" + +/datum/design/circuit/integrated_circuit/converter/num2text + id = "cc-num2text" + build_path = /obj/item/integrated_circuit/converter/num2text + sort_string = "WAABA" + +/datum/design/circuit/integrated_circuit/converter/text2num + id = "cc-text2num" + build_path = /obj/item/integrated_circuit/converter/text2num + sort_string = "WAABB" + +/datum/design/circuit/integrated_circuit/converter/ref2text + id = "cc-ref2text" + build_path = /obj/item/integrated_circuit/converter/ref2text + sort_string = "WAABC" + +/datum/design/circuit/integrated_circuit/converter/lowercase + id = "cc-lowercase" + build_path = /obj/item/integrated_circuit/converter/lowercase + sort_string = "WAABD" + +/datum/design/circuit/integrated_circuit/converter/uppercase + id = "cc-uppercase" + build_path = /obj/item/integrated_circuit/converter/uppercase + sort_string = "WAABD" + +/datum/design/circuit/integrated_circuit/converter/concatenatior + id = "cc-concatenatior" + build_path = /obj/item/integrated_circuit/converter/concatenatior + sort_string = "WAABC" + + + +/datum/design/circuit/integrated_circuit/coordinate/AssembleDesignName() + ..() + name = "Custom circuitry \[Coordinate\] ([item_name])" + +/datum/design/circuit/integrated_circuit/coordinate/gps + id = "cc-gps" + build_path = /obj/item/integrated_circuit/gps + sort_string = "WAACA" + +/datum/design/circuit/integrated_circuit/coordinate/abs_to_rel_coords + id = "cc-abs_to_rel_coords" + build_path = /obj/item/integrated_circuit/abs_to_rel_coords + sort_string = "WAACB" + + + +/datum/design/circuit/integrated_circuit/transfer/AssembleDesignName() + ..() + name = "Custom circuitry \[Transfer\] ([item_name])" + +/datum/design/circuit/integrated_circuit/transfer/splitter + id = "cc-splitter" + build_path = /obj/item/integrated_circuit/transfer/splitter + sort_string = "WAADA" + +/datum/design/circuit/integrated_circuit/transfer/splitter4 + id = "cc-splitter4" + build_path = /obj/item/integrated_circuit/transfer/splitter/medium + sort_string = "WAADB" + +/datum/design/circuit/integrated_circuit/transfer/splitter8 + id = "cc-splitter8" + build_path = /obj/item/integrated_circuit/transfer/splitter/large + sort_string = "WAADC" + +/datum/design/circuit/integrated_circuit/transfer/activator_splitter + id = "cc-activator_splitter" + build_path = /obj/item/integrated_circuit/transfer/activator_splitter + sort_string = "WAADD" + +/datum/design/circuit/integrated_circuit/transfer/activator_splitter4 + id = "cc-activator_splitter4" + build_path = /obj/item/integrated_circuit/transfer/activator_splitter/medium + sort_string = "WAADE" + +/datum/design/circuit/integrated_circuit/transfer/activator_splitter8 + id = "cc-activator_splitter8" + build_path = /obj/item/integrated_circuit/transfer/activator_splitter/large + sort_string = "WAADF" + + + +/datum/design/circuit/integrated_circuit/input_output/AssembleDesignName() + ..() + name = "Custom circuitry \[Input/Output\] ([item_name])" + +/datum/design/circuit/integrated_circuit/input_output/button + id = "cc-button" + build_path = /obj/item/integrated_circuit/input/button + sort_string = "WAAEA" + +/datum/design/circuit/integrated_circuit/input_output/numberpad + id = "cc-numberpad" + build_path = /obj/item/integrated_circuit/input/numberpad + sort_string = "WAAEB" + +/datum/design/circuit/integrated_circuit/input_output/textpad + id = "cc-textpad" + build_path = /obj/item/integrated_circuit/input/textpad + sort_string = "WAAEC" + +/datum/design/circuit/integrated_circuit/input_output/screen + id = "cc-screen" + build_path = /obj/item/integrated_circuit/output/screen + sort_string = "WAAED" + +/datum/design/circuit/integrated_circuit/input_output/med_scanner + id = "cc-medscanner" + build_path = /obj/item/integrated_circuit/input/med_scanner + req_tech = list(TECH_MATERIAL = 2, TECH_MAGNETS = 2, TECH_BIOMED = 2) + sort_string = "WAAEE" + +/datum/design/circuit/integrated_circuit/input_output/adv_med_scanner + id = "cc-advmedscanner" + build_path = /obj/item/integrated_circuit/input/adv_med_scanner + req_tech = list(TECH_MATERIAL = 2, TECH_MAGNETS = 3, TECH_BIOMED = 4) + sort_string = "WAAEF" + +/datum/design/circuit/integrated_circuit/input_output/local_locator + id = "cc-locallocator" + build_path = /obj/item/integrated_circuit/input/local_locator + sort_string = "WAAEG" + +/datum/design/circuit/integrated_circuit/input_output/signaler + id = "cc-signaler" + build_path = /obj/item/integrated_circuit/input/signaler + sort_string = "WAAEJ" + +/datum/design/circuit/integrated_circuit/input_output/light + id = "cc-light" + build_path = /obj/item/integrated_circuit/output/light + sort_string = "WAAEH" + +/datum/design/circuit/integrated_circuit/input_output/adv_light + id = "cc-adv_light" + build_path = /obj/item/integrated_circuit/output/light/advanced + sort_string = "WAAEI" + +/datum/design/circuit/integrated_circuit/input_output/beeper + id = "cc-sound_beeper" + build_path = /obj/item/integrated_circuit/output/sound/beeper + sort_string = "WAAEJ" + +/datum/design/circuit/integrated_circuit/input_output/beepsky_sound + id = "cc-sound_beepsky" + build_path = /obj/item/integrated_circuit/output/sound/beepsky + sort_string = "WAAEK" + req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1) + +/datum/design/circuit/integrated_circuit/input_output/EPv2 + id = "cc-epv2" + build_path = /obj/item/integrated_circuit/input/EPv2 + sort_string = "WAAEL" + req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNETS = 2, TECH_BLUESPACE = 2) + + +/datum/design/circuit/integrated_circuit/logic/AssembleDesignName() + ..() + name = "Custom circuitry \[Logic\] ([item_name])" + +/datum/design/circuit/integrated_circuit/logic/equals + id = "cc-equals" + build_path = /obj/item/integrated_circuit/logic/equals + sort_string = "WAAFA" + +/datum/design/circuit/integrated_circuit/logic/not + id = "cc-not" + build_path = /obj/item/integrated_circuit/logic/not + sort_string = "WAAFB" + +/datum/design/circuit/integrated_circuit/logic/and + id = "cc-and" + build_path = /obj/item/integrated_circuit/logic/and + sort_string = "WAAFC" + +/datum/design/circuit/integrated_circuit/logic/or + id = "cc-or" + build_path = /obj/item/integrated_circuit/logic/or + sort_string = "WAAFD" + +/datum/design/circuit/integrated_circuit/logic/less_than + id = "cc-less_than" + build_path = /obj/item/integrated_circuit/logic/less_than + sort_string = "WAAFE" + +/datum/design/circuit/integrated_circuit/logic/less_than_or_equal + id = "cc-less_than_or_equal" + build_path = /obj/item/integrated_circuit/logic/less_than_or_equal + sort_string = "WAAFF" + +/datum/design/circuit/integrated_circuit/logic/greater_than + id = "cc-greater_than" + build_path = /obj/item/integrated_circuit/logic/greater_than + sort_string = "WAAFG" + +/datum/design/circuit/integrated_circuit/logic/greater_than_or_equal + id = "cc-greater_than_or_equal" + build_path = /obj/item/integrated_circuit/logic/greater_than_or_equal + sort_string = "WAAFH" + + + +/datum/design/circuit/integrated_circuit/manipulation/AssembleDesignName() + ..() + name = "Custom circuitry \[Manipulation\] ([item_name])" + +/datum/design/circuit/integrated_circuit/manipulation/weapon_firing + name = "weapon firing mechanism" + id = "cc-weapon_firing" + build_path = /obj/item/integrated_circuit/manipulation/weapon_firing + sort_string = "WAAGA" + req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4) + +/datum/design/circuit/integrated_circuit/manipulation/smoke + name = "smoke generator" + id = "cc-smoke" + build_path = /obj/item/integrated_circuit/manipulation/smoke + sort_string = "WAAGB" + req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4) + +/datum/design/circuit/integrated_circuit/manipulation/locomotion + name = "locomotion" + id = "cc-locomotion" + build_path = /obj/item/integrated_circuit/manipulation/locomotion + sort_string = "WAAGB" + req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + + + +/datum/design/circuit/integrated_circuit/memory/AssembleDesignName() + ..() + name = "Custom circuitry \[Memory\] ([item_name])" + +/datum/design/circuit/integrated_circuit/memory + id = "cc-memory" + build_path = /obj/item/integrated_circuit/memory + sort_string = "WAAHA" + +/datum/design/circuit/integrated_circuit/memory/medium + id = "cc-memory4" + build_path = /obj/item/integrated_circuit/memory/medium + sort_string = "WAAHB" + +/datum/design/circuit/integrated_circuit/memory/large + id = "cc-memory8" + build_path = /obj/item/integrated_circuit/memory/large + sort_string = "WAAHC" + +/datum/design/circuit/integrated_circuit/memory/huge + id = "cc-memory16" + build_path = /obj/item/integrated_circuit/memory/huge + sort_string = "WAAHD" + +/datum/design/circuit/integrated_circuit/memory/constant + id = "cc-constant" + build_path = /obj/item/integrated_circuit/memory/constant + sort_string = "WAAHH" + +/datum/design/circuit/integrated_circuit/time/AssembleDesignName() + ..() + name = "Custom circuitry \[Time\] ([item_name])" + +/datum/design/circuit/integrated_circuit/time/delay + id = "cc-delay" + build_path = /obj/item/integrated_circuit/time/delay + sort_string = "WAAIA" + +/datum/design/circuit/integrated_circuit/time/delay/five_sec + id = "cc-five_sec_delay" + build_path = /obj/item/integrated_circuit/time/delay/five_sec + sort_string = "WAAIB" + +/datum/design/circuit/integrated_circuit/time/delay/one_sec + id = "cc-one_sec_delay" + build_path = /obj/item/integrated_circuit/time/delay/one_sec + sort_string = "WAAIC" + +/datum/design/circuit/integrated_circuit/time/delay/half_sec + id = "cc-half_sec_delay" + build_path = /obj/item/integrated_circuit/time/delay/half_sec + sort_string = "WAAID" + +/datum/design/circuit/integrated_circuit/time/delay/tenth_sec + id = "cc-tenth_sec_delay" + build_path = /obj/item/integrated_circuit/time/delay/tenth_sec + sort_string = "WAAIF" + +/datum/design/circuit/integrated_circuit/time/delay/custom + id = "cc-custom_delay" + build_path = /obj/item/integrated_circuit/time/delay/custom + sort_string = "WAAIG" + +/datum/design/circuit/integrated_circuit/time/ticker + id = "cc-ticker" + build_path = /obj/item/integrated_circuit/time/ticker + sort_string = "WAAIH" + +/datum/design/circuit/integrated_circuit/time/ticker/slow + id = "cc-ticker_slow" + build_path = /obj/item/integrated_circuit/time/ticker/slow + sort_string = "WAAII" + +/datum/design/circuit/integrated_circuit/time/ticker/fast + id = "cc-ticker_fast" + build_path = /obj/item/integrated_circuit/time/ticker/fast + sort_string = "WAAIJ" + req_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4) + +/datum/design/circuit/integrated_circuit/time/clock + id = "cc-clock" + build_path = /obj/item/integrated_circuit/time/clock + sort_string = "WAAIK" + /* Uncomment if someone makes these buildable /datum/design/circuit/general_alert name = "general alert console" diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index 87c6fa5ea3..1277d2b594 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -2,7 +2,7 @@ /* --- Traffic Control Scripting Language --- */ - // Nanotrasen TCS Language - Made by Doohl + // NanoTrasen TCS Language - Made by Doohl /n_Interpreter/TCS_Interpreter var/datum/TCS_Compiler/Compiler diff --git a/code/modules/shuttles/shuttle_ferry.dm b/code/modules/shuttles/shuttle_ferry.dm index 5d6663f3b5..0a288a1ba9 100644 --- a/code/modules/shuttles/shuttle_ferry.dm +++ b/code/modules/shuttles/shuttle_ferry.dm @@ -16,7 +16,7 @@ //TODO: change location to a string and use a mapping for area and dock targets. var/dock_target_station var/dock_target_offsite - + var/last_dock_attempt_time = 0 /datum/shuttle/ferry/short_jump(var/area/origin,var/area/destination) @@ -85,15 +85,15 @@ long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction) else short_jump() - + process_state = WAIT_ARRIVE - + if (WAIT_ARRIVE) if (moving_status == SHUTTLE_IDLE) dock() in_use = null //release lock process_state = WAIT_FINISH - + if (WAIT_FINISH) if (skip_docking_checks() || docking_controller.docked() || world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT) process_state = IDLE_STATE diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index cc4428fcb6..818e208ff4 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -140,7 +140,6 @@ user.visible_message("\blue [user] has mended the damaged bones in [target]'s [affected.name] with \the [tool]." , \ "\blue You have mended the damaged bones in [target]'s [affected.name] with \the [tool]." ) affected.status &= ~ORGAN_BROKEN - affected.status &= ~ORGAN_SPLINTED affected.stage = 0 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index ddc56dad3f..80eb2f1a44 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -93,6 +93,7 @@ if(health < maxhealth) if(open) health = min(maxhealth, health+10) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) user.visible_message("\red [user] repairs [src]!","\blue You repair [src]!") else user << "Unable to repair with the maintenance panel closed." @@ -101,6 +102,7 @@ else user << "Unable to repair while [src] is off." else if(hasvar(W,"force") && hasvar(W,"damtype")) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) switch(W.damtype) if("fire") health -= W.force * fire_dam_coeff diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm new file mode 100644 index 0000000000..9b2b83d3e7 --- /dev/null +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -0,0 +1,185 @@ +var/list/ventcrawl_machinery = list( + /obj/machinery/atmospherics/unary/vent_pump, + /obj/machinery/atmospherics/unary/vent_scrubber + ) + +// Vent crawling whitelisted items, whoo +/mob/living/var/list/can_enter_vent_with = list( + /obj/item/weapon/implant, + /obj/item/device/radio/borg, + /obj/item/weapon/holder, + /obj/machinery/camera, + /mob/living/simple_animal/borer, + ) + +/mob/living/var/list/icon/pipes_shown = list() +/mob/living/var/last_played_vent +/mob/living/var/is_ventcrawling = 0 +/mob/var/next_play_vent = 0 + +/mob/living/proc/can_ventcrawl() + if(!client) + return FALSE + if(!(/mob/living/proc/ventcrawl in verbs)) + to_chat(src, "You don't possess the ability to ventcrawl!") + return FALSE + if(incapacitated()) + to_chat(src, "You cannot ventcrawl in your current state!") + return FALSE + return ventcrawl_carry() + +/mob/living/Login() + . = ..() + //login during ventcrawl + if(is_ventcrawling && istype(loc, /obj/machinery/atmospherics)) //attach us back into the pipes + remove_ventcrawl() + add_ventcrawl(loc) + +/mob/living/carbon/slime/can_ventcrawl() + if(Victim) + to_chat(src, "You cannot ventcrawl while feeding.") + return FALSE + . = ..() + +/mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item) + if(carried_item == ability_master) + return 1 + for(var/type in can_enter_vent_with) + if(istype(carried_item, can_enter_vent_with)) + return get_inventory_slot(carried_item) == 0 + return 0 + +/mob/living/carbon/is_allowed_vent_crawl_item(var/obj/item/carried_item) + if(carried_item in internal_organs) + return 1 + return ..() + +/mob/living/carbon/human/is_allowed_vent_crawl_item(var/obj/item/carried_item) + if(carried_item in organs) + return 1 + return ..() + +/mob/living/simple_animal/spiderbot/is_allowed_vent_crawl_item(var/obj/item/carried_item) + if(carried_item == held_item) + return 1 + return ..() + +/mob/living/proc/ventcrawl_carry() + for(var/atom/A in contents) + if(!is_allowed_vent_crawl_item(A)) + to_chat(src, "You can't carry \the [A] while ventcrawling!") + return FALSE + return TRUE + +/mob/living/AltClickOn(var/atom/A) + if(is_type_in_list(A,ventcrawl_machinery)) + handle_ventcrawl(A) + return 1 + return ..() + +/mob/proc/start_ventcrawl() + var/atom/pipe + var/list/pipes = list() + for(var/obj/machinery/atmospherics/unary/U in range(1)) + if(is_type_in_list(U,ventcrawl_machinery) && Adjacent(U)) + pipes |= U + if(!pipes || !pipes.len) + to_chat(src, "There are no pipes that you can ventcrawl into within range!") + return + if(pipes.len == 1) + pipe = pipes[1] + else + pipe = input("Crawl Through Vent", "Pick a pipe") as null|anything in pipes + if(canmove && pipe) + return pipe + +/mob/living/carbon/alien/ventcrawl_carry() + return 1 + +/mob/living/var/ventcrawl_layer = 3 + +/mob/living/proc/handle_ventcrawl(var/atom/clicked_on) + if(!can_ventcrawl()) + return + + var/obj/machinery/atmospherics/unary/vent_found + if(clicked_on && Adjacent(clicked_on)) + vent_found = clicked_on + if(!istype(vent_found) || !vent_found.can_crawl_through()) + vent_found = null + + if(!vent_found) + for(var/obj/machinery/atmospherics/machine in range(1,src)) + if(is_type_in_list(machine, ventcrawl_machinery)) + vent_found = machine + + if(!vent_found || !vent_found.can_crawl_through()) + vent_found = null + + if(vent_found) + break + + if(vent_found) + if(vent_found.network && (vent_found.network.normal_members.len || vent_found.network.line_members.len)) + + to_chat(src, "You begin climbing into the ventilation system...") + if(vent_found.air_contents && !issilicon(src)) + + switch(vent_found.air_contents.temperature) + if(0 to BODYTEMP_COLD_DAMAGE_LIMIT) + to_chat(src, "You feel a painful freeze coming from the vent!") + if(BODYTEMP_COLD_DAMAGE_LIMIT to T0C) + to_chat(src, "You feel an icy chill coming from the vent.") + if(T0C + 40 to BODYTEMP_HEAT_DAMAGE_LIMIT) + to_chat(src, "You feel a hot wash coming from the vent.") + if(BODYTEMP_HEAT_DAMAGE_LIMIT to INFINITY) + to_chat(src, "You feel a searing heat coming from the vent!") + + switch(vent_found.air_contents.return_pressure()) + if(0 to HAZARD_LOW_PRESSURE) + to_chat(src, "You feel a rushing draw pulling you into the vent!") + if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) + to_chat(src, "You feel a strong drag pulling you into the vent.") + if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) + to_chat(src, "You feel a strong current pushing you away from the vent.") + if(HAZARD_HIGH_PRESSURE to INFINITY) + to_chat(src, "You feel a roaring wind pushing you away from the vent!") + + if(!do_after(src, 45, vent_found, 1, 1)) + return + if(!can_ventcrawl()) + return + + visible_message("[src] scrambles into the ventilation ducts!", "You climb into the ventilation system.") + + forceMove(vent_found) + add_ventcrawl(vent_found) + + else + to_chat(src, "This vent is not connected to anything.") + + else + to_chat(src, "You must be standing on or beside an air vent to enter it.") + +/mob/living/proc/add_ventcrawl(obj/machinery/atmospherics/starting_machine) + is_ventcrawling = 1 + //candrop = 0 + var/datum/pipe_network/network = starting_machine.return_network(starting_machine) + if(!network) + return + for(var/datum/pipeline/pipeline in network.line_members) + for(var/obj/machinery/atmospherics/A in (pipeline.members || pipeline.edges)) + if(!A.pipe_image) + A.pipe_image = image(A, A.loc, layer = 20, dir = A.dir) + pipes_shown += A.pipe_image + client.images += A.pipe_image + +/mob/living/proc/remove_ventcrawl() + is_ventcrawling = 0 + //candrop = 1 + if(client) + for(var/image/current_image in pipes_shown) + client.images -= current_image + client.eye = src + + pipes_shown.len = 0 \ No newline at end of file diff --git a/code/modules/ventcrawl/ventcrawl_atmospherics.dm b/code/modules/ventcrawl/ventcrawl_atmospherics.dm new file mode 100644 index 0000000000..bb2d121125 --- /dev/null +++ b/code/modules/ventcrawl/ventcrawl_atmospherics.dm @@ -0,0 +1,86 @@ +/obj/machinery/atmospherics/var/image/pipe_image + +/obj/machinery/atmospherics/Destroy() + for(var/mob/living/M in src) //ventcrawling is serious business + M.remove_ventcrawl() + M.forceMove(get_turf(src)) + if(pipe_image) + for(var/mob/living/M in player_list) + if(M.client) + M.client.images -= pipe_image + M.pipes_shown -= pipe_image + pipe_image = null + . = ..() + +/obj/machinery/atmospherics/ex_act(severity) + for(var/atom/movable/A in src) //ventcrawling is serious business + A.ex_act(severity) + . = ..() + +/obj/machinery/atmospherics/Entered(atom/movable/Obj) + if(istype(Obj, /mob/living)) + var/mob/living/L = Obj + L.ventcrawl_layer = layer + . = ..() + +/obj/machinery/atmospherics/relaymove(mob/living/user, direction) + if(user.loc != src || !(direction & initialize_directions)) //can't go in a way we aren't connecting to + return + ventcrawl_to(user,findConnecting(direction, user.ventcrawl_layer),direction) + +/obj/machinery/atmospherics/proc/ventcrawl_to(var/mob/living/user, var/obj/machinery/atmospherics/target_move, var/direction) + if(target_move) + if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through()) + user.remove_ventcrawl() + user.forceMove(target_move.loc) //handles entering and so on + user.visible_message("You hear something squeezing through the ducts.", "You climb out the ventilation system.") + else if(target_move.can_crawl_through()) + if(target_move.return_network(target_move) != return_network(src)) + user.remove_ventcrawl() + user.add_ventcrawl(target_move) + user.forceMove(target_move) + user.client.eye = target_move //if we don't do this, Byond only updates the eye every tick - required for smooth movement + if(world.time > user.next_play_vent) + user.next_play_vent = world.time+30 + playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3) + else + if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery) && src.can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent + user.remove_ventcrawl() + user.forceMove(src.loc) + user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.") + user.canmove = 0 + spawn(1) + user.canmove = 1 + +/obj/machinery/atmospherics/proc/can_crawl_through() + return 1 + +/obj/machinery/atmospherics/proc/findConnecting(var/direction) + for(var/obj/machinery/atmospherics/target in get_step(src,direction)) + if(target.initialize_directions & get_dir(target,src)) + if(isConnectable(target) && target.isConnectable(src)) + return target + +/obj/machinery/atmospherics/proc/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node1 || target == node2) + +/obj/machinery/atmospherics/pipe/manifold/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node3 || ..()) + +obj/machinery/atmospherics/trinary/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node3 || ..()) + +/obj/machinery/atmospherics/pipe/manifold4w/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node3 || target == node4 || ..()) + +/obj/machinery/atmospherics/tvalve/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node3 || ..()) + +/obj/machinery/atmospherics/pipe/cap/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node || ..()) + +/obj/machinery/atmospherics/portables_connector/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node || ..()) + +/obj/machinery/atmospherics/unary/isConnectable(var/obj/machinery/atmospherics/target) + return (target == node || ..()) diff --git a/code/modules/ventcrawl/ventcrawl_multiz.dm b/code/modules/ventcrawl/ventcrawl_multiz.dm new file mode 100644 index 0000000000..87ef8f9ba7 --- /dev/null +++ b/code/modules/ventcrawl/ventcrawl_multiz.dm @@ -0,0 +1,24 @@ +/obj/machinery/atmospherics/pipe/zpipe/up/verb/ventcrawl_move_up() + set name = "Ventcrawl Upwards" + set desc = "Climb up through a pipe." + set category = "Abilities" + set src = usr.loc + var/obj/machinery/atmospherics/target = check_ventcrawl(GetAbove(loc)) + if(target) ventcrawl_to(usr, target, UP) + +/obj/machinery/atmospherics/pipe/zpipe/down/verb/ventcrawl_move_down() + set name = "Ventcrawl Downwards" + set desc = "Climb down through a pipe." + set category = "Abilities" + set src = usr.loc + var/obj/machinery/atmospherics/target = check_ventcrawl(GetBelow(loc)) + if(target) ventcrawl_to(usr, target, DOWN) + +/obj/machinery/atmospherics/pipe/zpipe/proc/check_ventcrawl(var/turf/target) + if(!istype(target)) + return + if(node1 in target) + return node1 + if(node2 in target) + return node2 + return \ No newline at end of file diff --git a/code/modules/ventcrawl/ventcrawl_verb.dm b/code/modules/ventcrawl/ventcrawl_verb.dm new file mode 100644 index 0000000000..b49f22836d --- /dev/null +++ b/code/modules/ventcrawl/ventcrawl_verb.dm @@ -0,0 +1,7 @@ +/mob/living/proc/ventcrawl() + set name = "Crawl through Vent" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Abilities" + var/pipe = start_ventcrawl() + if(pipe) + handle_ventcrawl() diff --git a/code/unit_tests/zas_tests.dm b/code/unit_tests/zas_tests.dm index a28abaa881..cbf26f061f 100644 --- a/code/unit_tests/zas_tests.dm +++ b/code/unit_tests/zas_tests.dm @@ -44,7 +44,7 @@ return test_result if(expectation == UT_NORMAL) - + if(abs(temp - T20C) > 10) test_result["msg"] = "Temperature out of bounds: [temp] | [t_msg]" return test_result @@ -78,7 +78,7 @@ return 1 /datum/unit_test/zas_area_test/supply_centcomm - name = "ZAS: Supply Shuttle (CentComm)" + name = "ZAS: Supply Shuttle (CentCom)" area_path = /area/supply/dock /datum/unit_test/zas_area_test/emergency_shuttle @@ -95,7 +95,7 @@ /datum/unit_test/zas_area_test/cargo_maint name = "ZAS: Cargo Maintenance" - area_path = /area/maintenance/cargo + area_path = /area/maintenance/cargo /datum/unit_test/zas_area_test/eng_shuttle name = "ZAS: Construction Site Shuttle (Station)" diff --git a/html/changelog.html b/html/changelog.html index fd4010ec16..fda0a46275 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,50 @@ -->
+

19 September 2016

+

Anewbe updated:

+
    +
  • Blood Drain now heals internal damage, including broken bones and internal bleeding.
  • +
  • Adds the Command Secretary job.
  • +
  • CE hardsuit now has proper magboots and insulated gauntlets.
  • +
  • Powersinks should actually explode again, after a while.
  • +
+

MagmaRam updated:

+
    +
  • Lasers and energy projectiles in general now glow in the dark.
  • +
  • Robotic and prosthetic limbs can now be used in creation of simple robots, rather than just the robotic (lawed-chasis) limbs.
  • +
+

Zuhayr updated:

+
    +
  • Added /vg/ direct-action ventcrawling. You will now crawl through the actual pipe network, a step at a time. Have fun.
  • +
+ +

16 September 2016

+

Anewbe updated:

+
    +
  • Explosive implants should no longer gib the target if the setting is Localized Limb.
  • +
  • Lasercannon has 4 shots and fires slightly faster.
  • +
  • Lasercannon shots are slightly weaker to compensate for increased sustain.
  • +
  • Changes Unathi sprites slightly.
  • +
  • The advanced egun, laser carbine, and lasercannon now take up a bit more space in bags.
  • +
  • Prosthetic limbs and extremities no longer increase body temperature.
  • +
  • Ninja and Technomancer now require 5 players to start in either secret or voted.
  • +
  • Split skirts into 'skirts', which are just a skirt, and 'skirt outfits', which cover the upper body. Check your loadouts, they should remain otherwise unchanged.
  • +
  • Splints are no longer reusable.
  • +
  • Water is now more effective at dousing burning people.
  • +
  • Ninjas now vanish in a cloud of smoke, rather than exploding.
  • +
+

Chinsky updated:

+
    +
  • Added a hawaii shirt to loadout accessories. Can be attached to clothing like suit jackets etc. Can also be found in mixed wardrobes.
  • +
+

Yoshax updated:

+
    +
  • People bleed faster and more.
  • +
  • Splints are once again reusable and have been improved behind the scenes.
  • +
  • Removing splints will now correctly give you the splint used to splint the organ.
  • +
+

03 September 2016

Yosh updated: