diff --git a/.travis.yml b/.travis.yml index 8fb0e58f4e..e2bc4a5192 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ install: script: - shopt -s globstar - (! grep 'step_[xy]' maps/**/*.dmm) + - (! grep -Pn '( |\t|;|{)tag( ?)=' maps/**/*.dmm) - (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano) - (! grep -En "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm) - (! grep 'maps\\.*test.*' *.dme) diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm index 5620f51b3b..1d41a31209 100644 --- a/code/__defines/MC.dm +++ b/code/__defines/MC.dm @@ -27,6 +27,10 @@ if(current_step == this_step || (initial_step && !resumed)) /* So we start at st #define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current)) #define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current)) #define MC_AVERAGE_SLOW(average, current) (0.9 * (average) + 0.1 * (current)) + +#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current)) +#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current)) + #define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;} #define START_PROCESSING(Processor, Datum) if (!Datum.isprocessing) {Datum.isprocessing = 1;Processor.processing += Datum} diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 18c8cb1ca7..6d466e9930 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -306,3 +306,28 @@ //Some mob icon layering defines #define BODY_LAYER -100 + +// Clothing flags, organized in roughly top-bottom +#define EXAMINE_SKIPHELMET 0x0001 +#define EXAMINE_SKIPEARS 0x0002 +#define EXAMINE_SKIPEYEWEAR 0x0004 +#define EXAMINE_SKIPMASK 0x0008 +#define EXAMINE_SKIPJUMPSUIT 0x0010 +#define EXAMINE_SKIPTIE 0x0020 +#define EXAMINE_SKIPHOLSTER 0x0040 +#define EXAMINE_SKIPSUITSTORAGE 0x0080 +#define EXAMINE_SKIPBACKPACK 0x0100 +#define EXAMINE_SKIPGLOVES 0x0200 +#define EXAMINE_SKIPBELT 0x0400 +#define EXAMINE_SKIPSHOES 0x0800 + +// Body flags +#define EXAMINE_SKIPHEAD 0x0001 +#define EXAMINE_SKIPEYES 0x0002 +#define EXAMINE_SKIPFACE 0x0004 +#define EXAMINE_SKIPBODY 0x0008 +#define EXAMINE_SKIPGROIN 0x0010 +#define EXAMINE_SKIPARMS 0x0020 +#define EXAMINE_SKIPHANDS 0x0040 +#define EXAMINE_SKIPLEGS 0x0080 +#define EXAMINE_SKIPFEET 0x0100 \ No newline at end of file diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 8460f14fce..92c5477a0b 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -28,6 +28,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_ATOMS 15 #define INIT_ORDER_MACHINES 10 #define INIT_ORDER_SHUTTLES 3 +#define INIT_ORDER_DEFAULT 0 #define INIT_ORDER_LIGHTING 0 #define INIT_ORDER_AIR -1 #define INIT_ORDER_HOLOMAPS -5 @@ -37,8 +38,14 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G // Subsystem fire priority, from lowest to highest priority // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) - - #define FIRE_PRIORITY_OVERLAYS 500 +#define FIRE_PRIORITY_SHUTTLES 5 +#define FIRE_PRIORITY_ORBIT 8 +#define FIRE_PRIORITY_GARBAGE 15 +#define FIRE_PRIORITY_AIRFLOW 30 +#define FIRE_PRIORITY_AIR 35 +#define FIRE_PRIORITY_DEFAULT 50 +#define FIRE_PRIORITY_MACHINES 100 +#define FIRE_PRIORITY_OVERLAYS 500 // Macro defining the actual code applying our overlays lists to the BYOND overlays list. (I guess a macro for speed) // TODO - I don't really like the location of this macro define. Consider it. ~Leshana diff --git a/code/_helpers/events.dm b/code/_helpers/events.dm new file mode 100644 index 0000000000..74e047e811 --- /dev/null +++ b/code/_helpers/events.dm @@ -0,0 +1,15 @@ +/proc/get_station_areas(var/list/area/excluded_areas) + var/list/area/grand_list_of_areas = list() + // Assemble areas that all exists (See DM reference if you are confused about loop labels) + looping_station_areas: + for(var/parentpath in global.the_station_areas) + // Check its not excluded + for(var/excluded_path in excluded_areas) + if(ispath(parentpath, excluded_path)) + continue looping_station_areas + // Otherwise add it and all subtypes that exist on the map to our grand list + for(var/areapath in typesof(parentpath)) + var/area/A = locate(areapath) // Check if it actually exists + if(istype(A) && A.z in using_map.player_levels) + grand_list_of_areas += A + return grand_list_of_areas \ No newline at end of file diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm index e39b5e81b8..9ab541c80d 100644 --- a/code/controllers/Processes/planet.dm +++ b/code/controllers/Processes/planet.dm @@ -61,14 +61,40 @@ var/datum/controller/process/planet/planet_controller = null //Sun light needs changing if(P.needs_work & PLANET_PROCESS_SUN) P.needs_work &= ~PLANET_PROCESS_SUN - //Redraw sun overlay - var/new_range = P.sun["range"] + // Remove old value from corners + var/list/sunlit_corners = P.sunlit_corners + var/old_lum_r = -P.sun["lum_r"] + var/old_lum_g = -P.sun["lum_g"] + var/old_lum_b = -P.sun["lum_b"] + if(old_lum_r || old_lum_g || old_lum_b) + for(var/C in P.sunlit_corners) + var/datum/lighting_corner/LC = C + LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b) + SCHECK + sunlit_corners.Cut() + + // Calculate new values to apply var/new_brightness = P.sun["brightness"] var/new_color = P.sun["color"] - for(var/T in P.planet_floors) - var/turf/simulated/turf = T - turf.set_light(new_range, new_brightness, new_color) + var/lum_r = new_brightness * GetRedPart (new_color) / 255 + var/lum_g = new_brightness * GetGreenPart(new_color) / 255 + var/lum_b = new_brightness * GetBluePart (new_color) / 255 + var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs. + for(var/I in P.planet_floors) + var/turf/simulated/T = I + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + for(var/C in T.get_corners()) + var/datum/lighting_corner/LC = C + if(LC.update_gen != update_gen && LC.active) + sunlit_corners += LC + LC.update_gen = update_gen + LC.update_lumcount(lum_r, lum_g, lum_b) SCHECK + update_gen-- + P.sun["lum_r"] = lum_r + P.sun["lum_g"] = lum_g + P.sun["lum_b"] = lum_b //Temperature needs updating if(P.needs_work & PLANET_PROCESS_TEMP) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 961f657b2d..997e0fd3e0 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -385,7 +385,7 @@ var/datum/controller/master/Master = new() if (SS_flags & SS_NO_FIRE) subsystemstocheck -= SS continue - if (!(SS_flags & SS_TICKER) && (SS_flags & SS_KEEP_TIMING) && SS.last_fire + (SS.wait * 0.75) > world.time) + if ((SS_flags & (SS_TICKER|SS_KEEP_TIMING)) == SS_KEEP_TIMING && SS.last_fire + (SS.wait * 0.75) > world.time) continue SS.enqueue() . = 1 @@ -428,7 +428,7 @@ var/datum/controller/master/Master = new() // in those cases, so we just let them run) if (queue_node_flags & SS_NO_TICK_CHECK) if (queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker) - queue_node.queued_priority += queue_priority_count * 0.10 + queue_node.queued_priority += queue_priority_count * 0.1 queue_priority_count -= queue_node_priority queue_priority_count += queue_node.queued_priority current_tick_budget -= queue_node_priority @@ -446,26 +446,32 @@ var/datum/controller/master/Master = new() else tick_precentage = tick_remaining - current_ticklimit = TICK_USAGE + tick_precentage + // Reduce tick allocation for subsystems that overran on their last tick. + tick_precentage = max(tick_precentage*0.5, tick_precentage-queue_node.tick_overrun) + + current_ticklimit = round(TICK_USAGE + tick_precentage) if (!(queue_node_flags & SS_TICKER)) ran_non_ticker = TRUE ran = TRUE - tick_usage = TICK_USAGE + queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING) last_type_processed = queue_node queue_node.state = SS_RUNNING + tick_usage = TICK_USAGE var/state = queue_node.ignite(queue_node_paused) + tick_usage = TICK_USAGE - tick_usage + if (state == SS_RUNNING) state = SS_IDLE current_tick_budget -= queue_node_priority - tick_usage = TICK_USAGE - tick_usage + if (tick_usage < 0) tick_usage = 0 - + queue_node.tick_overrun = max(0, MC_AVG_FAST_UP_SLOW_DOWN(queue_node.tick_overrun, tick_usage-tick_precentage)) queue_node.state = state if (state == SS_PAUSED) @@ -494,11 +500,11 @@ var/datum/controller/master/Master = new() if (queue_node_flags & SS_TICKER) queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait) else if (queue_node_flags & SS_POST_FIRE_TIMING) - queue_node.next_fire = world.time + queue_node.wait + queue_node.next_fire = world.time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100)) else if (queue_node_flags & SS_KEEP_TIMING) queue_node.next_fire += queue_node.wait else - queue_node.next_fire = queue_node.queued_time + queue_node.wait + queue_node.next_fire = queue_node.queued_time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100)) queue_node.queued_time = 0 diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 437c10424b..dcb52a8cb3 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -1,9 +1,9 @@ /datum/controller/subsystem // Metadata; you should define these. name = "fire coderbus" //name of the subsystem - var/init_order = 0 //order of initialization. Higher numbers are initialized first, lower numbers later. Can be decimal and negative values. + var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Can be decimal and negative values. var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer. - var/priority = 50 //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep + var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again) var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire @@ -17,6 +17,7 @@ var/next_fire = 0 //scheduled world.time for next fire() var/cost = 0 //average time to execute var/tick_usage = 0 //average tick usage + var/tick_overrun = 0 //average tick overrun var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc. var/paused_ticks = 0 //ticks this ss is taking to run right now. var/paused_tick_usage //total tick_usage of all of our runs while pausing this run @@ -167,7 +168,7 @@ if(can_fire && !(SS_NO_FIRE & flags)) - msg = "[round(cost,1)]ms|[round(tick_usage,1)]%|[round(ticks,0.1)]\t[msg]" + msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]" else msg = "OFFLINE\t[msg]" diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm index 78cb7fa570..8cbe3afaab 100644 --- a/code/controllers/subsystems/air.dm +++ b/code/controllers/subsystems/air.dm @@ -9,7 +9,7 @@ SUBSYSTEM_DEF(air) name = "Air" init_order = INIT_ORDER_AIR - priority = 35 + priority = FIRE_PRIORITY_AIR wait = 2 SECONDS // seconds (We probably can speed this up actually) flags = SS_BACKGROUND // TODO - Should this really be background? It might be important. runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/controllers/subsystems/airflow.dm b/code/controllers/subsystems/airflow.dm index c98a02a5ce..4881113623 100644 --- a/code/controllers/subsystems/airflow.dm +++ b/code/controllers/subsystems/airflow.dm @@ -14,7 +14,7 @@ SUBSYSTEM_DEF(airflow) wait = 2 flags = SS_NO_INIT runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - priority = 30 + priority = FIRE_PRIORITY_AIRFLOW var/list/processing = list() var/list/currentrun = list() diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index b4d43a8d3f..a741869b5b 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -3,7 +3,7 @@ // SUBSYSTEM_DEF(garbage) name = "Garbage" - priority = 15 + priority = FIRE_PRIORITY_GARBAGE wait = 2 SECONDS flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm index f8c353c43d..f579de9563 100644 --- a/code/controllers/subsystems/machines.dm +++ b/code/controllers/subsystems/machines.dm @@ -12,7 +12,7 @@ SUBSYSTEM_DEF(machines) name = "Machines" - priority = 100 + priority = FIRE_PRIORITY_MACHINES init_order = INIT_ORDER_MACHINES flags = SS_KEEP_TIMING runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME diff --git a/code/controllers/subsystems/orbits.dm b/code/controllers/subsystems/orbits.dm index 80c16c9ce5..5cda1ce9dc 100644 --- a/code/controllers/subsystems/orbits.dm +++ b/code/controllers/subsystems/orbits.dm @@ -1,6 +1,6 @@ SUBSYSTEM_DEF(orbit) name = "Orbits" - priority = 8 // FIRE_PRIORITY_ORBIT + priority = FIRE_PRIORITY_ORBIT wait = 2 flags = SS_NO_INIT|SS_TICKER diff --git a/code/controllers/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm index 8751e0ffd7..61a4590890 100644 --- a/code/controllers/subsystems/shuttles.dm +++ b/code/controllers/subsystems/shuttles.dm @@ -8,7 +8,7 @@ var/global/datum/controller/subsystem/shuttles/shuttle_controller SUBSYSTEM_DEF(shuttles) name = "Shuttles" wait = 2 SECONDS - priority = 5 + priority = FIRE_PRIORITY_SHUTTLES init_order = INIT_ORDER_SHUTTLES flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index dda9aa4ed4..699c8ce9ee 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -172,6 +172,7 @@ cost = 40 containertype = "/obj/structure/closet/crate/secure" containername = "Security Crowd Control voidsuit crate" + access = access_armory /datum/supply_packs/voidsuits/security/alt name = "Security EVA Riot voidsuits" @@ -185,6 +186,7 @@ cost = 50 containertype = "/obj/structure/closet/crate/secure" containername = "Security EVA Riot voidsuit crate" + access = access_armory /datum/supply_packs/voidsuits/supply name = "Mining voidsuits" diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index 3bf53e55dc..6f7ec89322 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -17,6 +17,7 @@ var/datum/antagonist/renegade/renegades Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those without explicit exceptions apply to antagonists." flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE + can_use_aooc = FALSE hard_cap = 8 hard_cap_round = 12 diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm index 2ea752e3b7..8810fca7d0 100644 --- a/code/game/antagonist/station/thug.dm +++ b/code/game/antagonist/station/thug.dm @@ -15,3 +15,4 @@ var/datum/antagonist/thug/thugs Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those with explicit exceptions apply to antagonists." flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE + can_use_aooc = FALSE diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm index 4c96f5ce17..d0a1f54ed2 100644 --- a/code/game/antagonist/station/traitor.dm +++ b/code/game/antagonist/station/traitor.dm @@ -5,6 +5,7 @@ var/datum/antagonist/traitor/traitors id = MODE_TRAITOR protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director") flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + can_use_aooc = FALSE /datum/antagonist/traitor/auto id = MODE_AUTOTRAITOR diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index bbecbe5f97..4f17952e38 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -497,7 +497,7 @@ area/space/atmosalert() //names are used /area/syndicate_station - name = "\improper Independant Station" + name = "\improper Independent Station" icon_state = "yellow" requires_power = 0 flags = RAD_SHIELDED diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 2b2654c068..1df53f3d17 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -61,7 +61,7 @@ if(CLASS_LOWER) income = 0.50 //give them an account in the station database - var/money_amount = (rand(15,40) + rand(15,40)) * income * economic_modifier * ECO_MODIFIER //VOREStation Edit - Smoothed peaks. + var/money_amount = (rand(15,40) + rand(15,40)) * income * economic_modifier * (H.species.economic_modifier) //VOREStation Edit - Smoothed peaks. var/datum/money_account/M = create_account(H.real_name, money_amount, null) if(H.mind) var/remembered_info = "" diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 13a966f71b..503a289e50 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1105,15 +1105,20 @@ /obj/item/toy/plushie/therapy/blue = 2, /obj/item/toy/plushie/therapy/yellow = 2, /obj/item/toy/plushie/therapy/orange = 2, - /obj/item/toy/plushie/therapy/green = 2) - contraband = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 1 - /* Handbuzzer to be added later */) - premium = list(/obj/item/toy/plushie/nymph = 2, + /obj/item/toy/plushie/therapy/green = 2, + /obj/item/toy/plushie/nymph = 2, /obj/item/toy/plushie/mouse = 2, /obj/item/toy/plushie/kitten = 2, /obj/item/toy/plushie/lizard = 2, /obj/item/toy/plushie/spider = 2, /obj/item/toy/plushie/farwa = 2, + /obj/item/toy/plushie/corgi = 1, + /obj/item/toy/plushie/octopus = 1, + /obj/item/toy/plushie/face_hugger = 1, + /obj/item/toy/plushie/carp = 1, + /obj/item/toy/plushie/deer = 1, + /obj/item/toy/plushie/tabby_cat = 1) + premium = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 1, /obj/item/weapon/storage/trinketbox = 2) prices = list(/obj/item/weapon/storage/fancy/heartbox = 15, /obj/item/toy/bouquet = 10, @@ -1128,4 +1133,16 @@ /obj/item/toy/plushie/therapy/blue = 20, /obj/item/toy/plushie/therapy/yellow = 20, /obj/item/toy/plushie/therapy/orange = 20, - /obj/item/toy/plushie/therapy/green = 20) \ No newline at end of file + /obj/item/toy/plushie/therapy/green = 20, + /obj/item/toy/plushie/nymph = 35, + /obj/item/toy/plushie/mouse = 35, + /obj/item/toy/plushie/kitten = 35, + /obj/item/toy/plushie/lizard = 35, + /obj/item/toy/plushie/spider = 35, + /obj/item/toy/plushie/farwa = 35, + /obj/item/toy/plushie/corgi = 50, + /obj/item/toy/plushie/octopus = 50, + /obj/item/toy/plushie/face_hugger = 50, + /obj/item/toy/plushie/carp = 50, + /obj/item/toy/plushie/deer = 50, + /obj/item/toy/plushie/tabby_cat = 50) \ No newline at end of file diff --git a/code/game/objects/items/devices/locker_painter.dm b/code/game/objects/items/devices/locker_painter.dm index 9459927ffe..07c4cb3f1c 100644 --- a/code/game/objects/items/devices/locker_painter.dm +++ b/code/game/objects/items/devices/locker_painter.dm @@ -58,11 +58,30 @@ "Administrator" = list("open" = "capsecureopen", "closed" = "capsecure", "locked" = "capsecure1", "broken" = "capsecurebroken", "off" = "capsecureoff") ) + var/forbidden_types = list( + /obj/structure/closet/alien, + /obj/structure/closet/body_bag, + /obj/structure/closet/cabinet, + /obj/structure/closet/crate, + /obj/structure/closet/coffin, + /obj/structure/closet/fireaxecabinet, + /obj/structure/closet/hydrant, + /obj/structure/closet/medical_wall, + /obj/structure/closet/statue, + /obj/structure/closet/walllocker + ) + /obj/item/device/closet_painter/afterattack(atom/A, var/mob/user, proximity) if(!proximity) return + var/non_closet = 0 if(!istype(A,/obj/structure/closet)) + non_closet = 1 + for(var/ctype in forbidden_types) + if(istype(A,ctype)) + non_closet = 1 + if(non_closet) user << "\The [src] can only be used on closets." return diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 3931bec8ef..02a308555b 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -768,7 +768,7 @@ name = "space carp plushie" desc = "An adorable stuffed toy that resembles a space carp." icon = 'icons/obj/toy.dmi' - icon_state = "plushie/carp" + icon_state = "basecarp" attack_verb = list("bitten", "eaten", "fin slapped") var/bitesound = 'sound/weapons/bite.ogg' @@ -787,39 +787,49 @@ name = "Random Carp Plushie" desc = "This is a random plushie" icon = 'icons/obj/toy.dmi' - icon_state = "plushie/carp" + icon_state = "basecarp" /obj/random/carp_plushie/item_to_spawn() return pick(typesof(/obj/item/toy/plushie/carp)) //can pick any carp plushie, even the original. /obj/item/toy/plushie/carp/ice + name = "ice carp plushie" icon_state = "icecarp" /obj/item/toy/plushie/carp/silent + name = "monochrome carp plushie" icon_state = "silentcarp" /obj/item/toy/plushie/carp/electric + name = "electric carp plushie" icon_state = "electriccarp" /obj/item/toy/plushie/carp/gold + name = "golden carp plushie" icon_state = "goldcarp" /obj/item/toy/plushie/carp/toxin + name = "toxic carp plushie" icon_state = "toxincarp" /obj/item/toy/plushie/carp/dragon + name = "dragon carp plushie" icon_state = "dragoncarp" /obj/item/toy/plushie/carp/pink + name = "pink carp plushie" icon_state = "pinkcarp" /obj/item/toy/plushie/carp/candy + name = "candy carp plushie" icon_state = "candycarp" /obj/item/toy/plushie/carp/nebula + name = "nebula carp plushie" icon_state = "nebulacarp" /obj/item/toy/plushie/carp/void + name = "void carp plushie" icon_state = "voidcarp" //Large plushies. diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm index 856e7a5d8b..7dd29055f3 100644 --- a/code/game/objects/items/weapons/implants/implantcircuits.dm +++ b/code/game/objects/items/weapons/implants/implantcircuits.dm @@ -29,7 +29,7 @@ Function: Contains no innate functions until other components are added.
Special Features: Modular Circuitry- Can be loaded with specific modular circuitry in order to fulfill a wide possibility of functions.
- Integrity: Implant is not shielded from electromagnetic interferance, otherwise it is independant of subject's status."} + Integrity: Implant is not shielded from electromagnetic interference, otherwise it is independent of subject's status."} return dat /obj/item/weapon/implant/integrated_circuit/emp_act(severity) @@ -45,4 +45,4 @@ ..() /obj/item/weapon/implant/integrated_circuit/attack_self(mob/user) - IC.attack_self(user) \ No newline at end of file + IC.attack_self(user) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 5b20553430..2c4fa65abf 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -275,6 +275,7 @@ var/stacksize = min(S.amount,N.max_amount) N.amount = stacksize S.amount -= stacksize + N.update_icon() if(!S.amount) qdel(S) // todo: there's probably something missing here orient2hud(usr) diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 8bc362a1d7..1eaca16e76 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -57,12 +57,19 @@ source.thermal_conductivity = initial(source.thermal_conductivity) /turf/simulated/wall/proc/fail_smash(var/mob/user) - to_chat(user, "You smash against the wall!") + var/damage_lower = 25 + var/damage_upper = 75 if(isanimal(user)) var/mob/living/simple_animal/S = user playsound(src, S.attack_sound, 75, 1) + if(!(S.melee_damage_upper >= 10)) + to_chat(user, "You bounce against the wall.") + return FALSE + damage_lower = S.melee_damage_lower + damage_upper = S.melee_damage_upper + to_chat(user, "You smash against the wall!") user.do_attack_animation(src) - take_damage(rand(25,75)) + take_damage(rand(damage_lower,damage_upper)) /turf/simulated/wall/proc/success_smash(var/mob/user) to_chat(user, "You smash through the wall!") diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 28f8036a5a..118b873174 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1264,7 +1264,7 @@ var/datum/announcement/minor/admin_min_announcer = new usr << "AI [key_name(S, usr)]'s laws:" else if(isrobot(S)) var/mob/living/silicon/robot/R = S - usr << "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:" + usr << "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"]: laws:" else if (ispAI(S)) usr << "pAI [key_name(S, usr)]'s laws:" else diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm index f8bd40f076..7197635e5b 100644 --- a/code/modules/client/preference_setup/general/04_equipment.dm +++ b/code/modules/client/preference_setup/general/04_equipment.dm @@ -11,12 +11,14 @@ S["all_underwear_metadata"] >> pref.all_underwear_metadata S["backbag"] >> pref.backbag S["pdachoice"] >> pref.pdachoice + S["communicator_visibility"] >> pref.communicator_visibility /datum/category_item/player_setup_item/general/equipment/save_character(var/savefile/S) S["all_underwear"] << pref.all_underwear S["all_underwear_metadata"] << pref.all_underwear_metadata S["backbag"] << pref.backbag S["pdachoice"] << pref.pdachoice + S["communicator_visibility"] << pref.communicator_visibility // Moved from /datum/preferences/proc/copy_to() /datum/category_item/player_setup_item/general/equipment/copy_to_mob(var/mob/living/carbon/human/character) @@ -86,6 +88,7 @@ . += "
" . += "Backpack Type: [backbaglist[pref.backbag]]
" . += "PDA Type: [pdachoicelist[pref.pdachoice]]
" + . += "Communicator Visibility: [(pref.communicator_visibility) ? "Yes" : "No"]
" return jointext(.,null) @@ -139,5 +142,10 @@ if(new_metadata) set_metadata(underwear, gt, new_metadata) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["toggle_comm_visibility"]) + if(CanUseTopic(user)) + pref.communicator_visibility = !pref.communicator_visibility + return TOPIC_REFRESH + return ..() \ No newline at end of file diff --git a/code/modules/client/preference_setup/global/04_communicators.dm b/code/modules/client/preference_setup/global/04_communicators.dm deleted file mode 100644 index e0fc2c8e31..0000000000 --- a/code/modules/client/preference_setup/global/04_communicators.dm +++ /dev/null @@ -1,26 +0,0 @@ -/datum/category_item/player_setup_item/player_global/communicators - name = "Communicators" - sort_order = 4 - -/datum/category_item/player_setup_item/player_global/communicators/load_preferences(var/savefile/S) - S["communicator_visibility"] >> pref.communicator_visibility - - -/datum/category_item/player_setup_item/player_global/communicators/save_preferences(var/savefile/S) - S["communicator_visibility"] << pref.communicator_visibility - - -/datum/category_item/player_setup_item/player_global/communicators/sanitize_preferences() - pref.communicator_visibility = sanitize_integer(pref.communicator_visibility, 0, 1, initial(pref.communicator_visibility)) - -/datum/category_item/player_setup_item/player_global/communicators/content(var/mob/user) - . += "Communicator Identity:
" - . += "Visibility: [(pref.communicator_visibility) ? "Yes" : "No"]
" - -/datum/category_item/player_setup_item/player_global/communicators/OnTopic(var/href,var/list/href_list, var/mob/user) - if(href_list["toggle_comm_visibility"]) - if(CanUseTopic(user)) - pref.communicator_visibility = !pref.communicator_visibility - return TOPIC_REFRESH - - return ..() diff --git a/code/modules/client/preference_setup/global/05_ooc.dm b/code/modules/client/preference_setup/global/04_ooc.dm similarity index 98% rename from code/modules/client/preference_setup/global/05_ooc.dm rename to code/modules/client/preference_setup/global/04_ooc.dm index 1b9d45dc89..0150554250 100644 --- a/code/modules/client/preference_setup/global/05_ooc.dm +++ b/code/modules/client/preference_setup/global/04_ooc.dm @@ -1,6 +1,6 @@ /datum/category_item/player_setup_item/player_global/ooc name = "OOC" - sort_order = 5 + sort_order = 4 /datum/category_item/player_setup_item/player_global/ooc/load_preferences(var/savefile/S) S["ignored_players"] >> pref.ignored_players diff --git a/code/modules/client/preference_setup/global/06_media.dm b/code/modules/client/preference_setup/global/05_media.dm similarity index 99% rename from code/modules/client/preference_setup/global/06_media.dm rename to code/modules/client/preference_setup/global/05_media.dm index cd6a12a6f9..3551735bb9 100644 --- a/code/modules/client/preference_setup/global/06_media.dm +++ b/code/modules/client/preference_setup/global/05_media.dm @@ -4,7 +4,7 @@ /datum/category_item/player_setup_item/player_global/media name = "Media" - sort_order = 6 + sort_order = 5 /datum/category_item/player_setup_item/player_global/media/load_preferences(var/savefile/S) S["media_volume"] >> pref.media_volume diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 7272571cd4..6aac017f44 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -46,6 +46,12 @@ path = /obj/item/weapon/book/codex/corp_regs cost = 0 */ + +/datum/gear/utility/robutt + display_name = "a buyer's guide to artificial bodies" + path = /obj/item/weapon/book/codex/lore/robutt + cost = 0 + /datum/gear/utility/folder_blue display_name = "folder, blue" path = /obj/item/weapon/folder/blue diff --git a/code/modules/economy/economy_misc.dm b/code/modules/economy/economy_misc.dm index 1ca55ddf08..4dce5a62a8 100644 --- a/code/modules/economy/economy_misc.dm +++ b/code/modules/economy/economy_misc.dm @@ -47,17 +47,6 @@ #define GEAR_EVA 15 -/var/list/economic_species_modifier = list( - /datum/species/human = 10, - /datum/species/human/vatgrown = 10, - /datum/species/skrell = 12, - /datum/species/unathi = 7, - /datum/species/tajaran = 7, - /datum/species/teshari = 6, - /datum/species/diona = 4, - /datum/species/shapeshifter/promethean = 3 - ) - //---- The following corporations are friendly with NanoTrasen and loosely enable trade and travel: //Corporation NanoTrasen - Generalised / high tech research and phoron exploitation. //Corporation Vessel Contracting - Ship and station construction, materials research. diff --git a/code/modules/events/atmos_leak.dm b/code/modules/events/atmos_leak.dm index 0b9da559c9..e9fea3ff66 100644 --- a/code/modules/events/atmos_leak.dm +++ b/code/modules/events/atmos_leak.dm @@ -26,19 +26,7 @@ // gas_choices += "volatile_fuel" // Dangerous and no default atmos setup! gas_type = pick(gas_choices) - // Assemble areas that all exists (See DM reference if you are confused about loop labels) - var/list/area/grand_list_of_areas = list() - looping_station_areas: - for(var/parentpath in global.the_station_areas) - // Check its not excluded - for(var/excluded_path in excluded) - if(ispath(parentpath, excluded_path)) - continue looping_station_areas - // Otherwise add it and all subtypes that exist on the map to our grand list - for(var/areapath in typesof(parentpath)) - var/area/A = locate(areapath) // Check if it actually exists - if(istype(A) && A.z in using_map.player_levels) - grand_list_of_areas += A + var/list/area/grand_list_of_areas = get_station_areas(excluded) // Okay, now lets try and pick a target! Lets try 10 times, otherwise give up for(var/i in 1 to 10) diff --git a/code/modules/events/electrified_door.dm b/code/modules/events/electrified_door.dm new file mode 100644 index 0000000000..1a616e7123 --- /dev/null +++ b/code/modules/events/electrified_door.dm @@ -0,0 +1,33 @@ +/datum/event/electrified_door + var/obj/machinery/door/airlock/chosen_door + var/list/area/excluded = list( + /area/shuttle, + /area/crew_quarters + ) + +/datum/event/electrified_door/setup() + var/list/area/grand_list_of_areas = get_station_areas(excluded) + //try 10 times + for(var/i in 1 to 10) + var/area/A = pick(grand_list_of_areas) + var/list/obj/machinery/door/airlock/target_doors = list() + for(var/obj/machinery/door/airlock/target_door in A.contents) + target_doors += target_door + target_doors = shuffle(target_doors) + + for(var/obj/machinery/door/airlock/target_door in target_doors) + if(!target_door.isElectrified() && target_door.arePowerSystemsOn() && target_door.maxhealth == target_door.health) + chosen_door = target_door + return + +/datum/event/electrified_door/start() + + if(!chosen_door) + return + chosen_door.set_safeties(0) + if(severity >= EVENT_LEVEL_MODERATE) + chosen_door.electrify(-1) + chosen_door.lock() + chosen_door.health = chosen_door.maxhealth / 6 + chosen_door.aiControlDisabled = 1 + chosen_door.update_icon() diff --git a/code/modules/events/escaped_slimes.dm b/code/modules/events/escaped_slimes.dm new file mode 100644 index 0000000000..9cc2f5a7fc --- /dev/null +++ b/code/modules/events/escaped_slimes.dm @@ -0,0 +1,44 @@ +/datum/event/escaped_slimes + announceWhen = 90 + endWhen = 90 + 15 + 1 + var/spawncount + var/list/possible_slimes = list( + /mob/living/simple_animal/slime/purple, + /mob/living/simple_animal/slime/orange, + /mob/living/simple_animal/slime/metal, + /mob/living/simple_animal/slime/yellow, + /mob/living/simple_animal/slime/dark_purple, + /mob/living/simple_animal/slime/silver, + /mob/living/simple_animal/slime/ruby, + /mob/living/simple_animal/slime/cerulean, + /mob/living/simple_animal/slime/red, + /mob/living/simple_animal/slime/green, + /mob/living/simple_animal/slime/pink, + /mob/living/simple_animal/slime/gold, + /mob/living/simple_animal/slime/oil, + /mob/living/simple_animal/slime/emerald, + ) + + +/datum/event/escaped_slimes/setup() + announceWhen = rand(announceWhen, announceWhen + 60) + spawncount = rand(2 * severity, 4 * severity) //spiderlings only have a 50% chance to grow big and strong + +/datum/event/escaped_slimes/announce() + command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') + sleep(15) + command_announcement.Announce("The previously unidentified lifesigns have been identified as escaped slimes from Xenobiology. Secure any exterior access, including ducting and ventilation, taking care to return the slimes to their proper confinement.", "Lifesign Alert") + + +/datum/event/escaped_slimes/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + if(temp_vent.network && temp_vent.loc.z in using_map.station_levels) //borrowed from spiders event, but it works. Distribute the slimes only in rooms with vents + vents += temp_vent + + while((spawncount > 0) && vents.len) + var/obj/vent = pick(vents) + var/slime_type = pick(possible_slimes) + new slime_type(vent.loc, 1) + vents -= vent + spawncount-- diff --git a/code/modules/events/wallrot.dm b/code/modules/events/wallrot.dm index 096c7f8965..5aede8a894 100644 --- a/code/modules/events/wallrot.dm +++ b/code/modules/events/wallrot.dm @@ -1,20 +1,24 @@ -datum/event/wallrot/setup() +/datum/event/wallrot + var/turf/simulated/wall/center + +/datum/event/wallrot/setup() announceWhen = rand(0, 300) endWhen = announceWhen + 1 -datum/event/wallrot/announce() - command_announcement.Announce("Harmful fungi detected on the colony. Station structures may be contaminated.", "Biohazard Alert") + // 100 attempts + for(var/i=0, i<100, i++) + var/turf/candidate = locate(rand(1, world.maxx), rand(1, world.maxy), 1) + if(istype(candidate, /turf/simulated/wall)) + center = candidate + return 1 + return 0 -datum/event/wallrot/start() +/datum/event/wallrot/announce() + if(center) + command_announcement.Announce("Harmful fungi detected on the colony nearby [center.loc.name]. Station structures may be contaminated.", "Biohazard Alert") + +/datum/event/wallrot/start() spawn() - var/turf/simulated/wall/center = null - - // 100 attempts - for(var/i=0, i<100, i++) - var/turf/candidate = locate(rand(1, world.maxx), rand(1, world.maxy), 1) - if(istype(candidate, /turf/simulated/wall)) - center = candidate - if(center) // Make sure at least one piece of wall rots! center.rot() diff --git a/code/modules/events/window_break.dm b/code/modules/events/window_break.dm new file mode 100644 index 0000000000..786b2df424 --- /dev/null +++ b/code/modules/events/window_break.dm @@ -0,0 +1,73 @@ +/datum/event/window_break + var/obj/structure/window/chosen_window + var/list/obj/structure/window/collateral_windows + var/turf/chosen_location + var/list/area/excluded = list( + /area/shuttle, + /area/crew_quarters + ) + +/datum/event/window_break/setup() + var/list/area/grand_list_of_areas = get_station_areas(excluded) + //try 10 times + for(var/i in 1 to 10) + var/area/A = pick(grand_list_of_areas) + var/list/obj/structure/window/possible_target_windows = list() + for(var/obj/structure/window/target_window in A.contents) + possible_target_windows += target_window + possible_target_windows = shuffle(possible_target_windows) + + for(var/obj/structure/window/target_window in possible_target_windows) + //if() don't have any conditions, for isn't strictly necessary + chosen_window = target_window + chosen_location = chosen_window.loc + collateral_windows = gather_collateral_windows(chosen_window) + announceWhen = (collateral_windows.len + 1) * 20 + endWhen = announceWhen + 1 + return + +//TL;DR: breadth first search for all connected turfs with windows +/datum/event/window_break/proc/gather_collateral_windows(var/obj/structure/window/target_window) + var/list/turf/frontier_set = list(target_window.loc) + var/list/obj/structure/window/result_set = list() + var/list/turf/explored_set = list() + + while(frontier_set.len > 0) + var/turf/current = frontier_set[1] + frontier_set -= current + explored_set += current + + var/contains_windows = 0 + for(var/obj/structure/window/to_add in current.contents) + contains_windows = 1 + result_set += to_add + + if(contains_windows) + //add adjacent turfs to be checked for windows as well + var/turf/neighbor = locate(current.x + 1, current.y, current.z) + if(!(neighbor in frontier_set) && !(neighbor in explored_set)) + frontier_set += neighbor + neighbor = locate(current.x - 1, current.y, current.z) + if(!(neighbor in frontier_set) && !(neighbor in explored_set)) + frontier_set += neighbor + neighbor = locate(current.x, current.y + 1, current.z) + if(!(neighbor in frontier_set) && !(neighbor in explored_set)) + frontier_set += neighbor + neighbor = locate(current.x, current.y - 1, current.z) + if(!(neighbor in frontier_set) && !(neighbor in explored_set)) + frontier_set += neighbor + return result_set + + + +/datum/event/window_break/start() + if(!chosen_window) + return + chosen_window.shatter(0) + + for(var/obj/structure/window/current_collateral in collateral_windows) + sleep(rand(1,20)) + current_collateral.take_damage(current_collateral.health - (current_collateral.maxhealth / 5)) //set to 1/5th health + +/datum/event/window_break/announce() + command_announcement.Announce("Structural integrity of windows at [chosen_location.loc.name] is failing. Immediate repair or replacement is advised.", "Structural Alert") diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm new file mode 100644 index 0000000000..a9581341c5 --- /dev/null +++ b/code/modules/events/wormholes.dm @@ -0,0 +1,9 @@ +/datum/event/wormholes + startWhen = 0 + endWhen = 80 + +/datum/event/wormholes/start() + wormhole_event() + +/datum/event/wormholes/end() + command_announcement.Announce("There are no more space-time anomalies detected on the station.", "Anomaly Alert") diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 60a6b39da6..6e6ef84fd1 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -870,7 +870,7 @@ set_trait(TRAIT_YIELD,3) set_trait(TRAIT_POTENCY,1) set_trait(TRAIT_PRODUCT_ICON,"vine") - set_trait(TRAIT_PRODUCT_COLOUR,"#326B30") + set_trait(TRAIT_PRODUCT_COLOUR,"#3D8C3A") set_trait(TRAIT_PLANT_COLOUR,"#257522") set_trait(TRAIT_PLANT_ICON,"vine2") set_trait(TRAIT_FLESH_COLOUR,"#F22C2C") @@ -892,9 +892,9 @@ set_trait(TRAIT_PRODUCTION,6) set_trait(TRAIT_YIELD,3) set_trait(TRAIT_POTENCY,10) - set_trait(TRAIT_PRODUCT_ICON,"vine") - set_trait(TRAIT_PRODUCT_COLOUR,"#B4D4B9") - set_trait(TRAIT_PLANT_COLOUR,"#BAE8C1") + set_trait(TRAIT_PRODUCT_ICON,"vine2") + set_trait(TRAIT_PRODUCT_COLOUR,"#DBAC02") + set_trait(TRAIT_PLANT_COLOUR,"#21661E") set_trait(TRAIT_PLANT_ICON,"vine2") set_trait(TRAIT_WATER_CONSUMPTION, 6) diff --git a/code/modules/lore_codex/codex.dm b/code/modules/lore_codex/codex.dm index 7c5f071874..5f5f521267 100644 --- a/code/modules/lore_codex/codex.dm +++ b/code/modules/lore_codex/codex.dm @@ -25,6 +25,13 @@ icon_state = "codex" root_type = /datum/lore/codex/category/main_virgo_lore +/obj/item/weapon/book/codex/lore/robutt + name = "A Buyer's Guide to Artificial Bodies" + desc = "Recommended reading for the newly cyborgified, new positronics, and the upwardly-mobile FBP." + icon_state = "codex_robutt" + root_type = /datum/lore/codex/category/main_robutts + + /obj/item/weapon/book/codex/lore/news name = "Daedalus Pocket Newscaster" desc = "A regularly-updating compendium of articles on current events. Essential for new arrivals in the Vir system and anyone interested in politics." diff --git a/code/modules/lore_codex/robutt_data/bybrand.dm b/code/modules/lore_codex/robutt_data/bybrand.dm new file mode 100644 index 0000000000..c7d7bf3da7 --- /dev/null +++ b/code/modules/lore_codex/robutt_data/bybrand.dm @@ -0,0 +1,85 @@ +/datum/lore/codex/category/pros_by_brand + name = "Prosthetics By Brand" + data = "Here you'll find our analysis of the most popular and noteworthy brands of prosthetics. These analyses are performed by industry experts unconnected to the corporations and other entities responsible for the following designs." + children = list( + /datum/lore/codex/page/robo_unbranded, + /datum/lore/codex/page/robo_cyber, + /datum/lore/codex/page/robo_nt, + /datum/lore/codex/page/robo_wt, + /datum/lore/codex/page/robo_heph, + /datum/lore/codex/page/robo_xion, + /datum/lore/codex/page/robo_grayson, + /datum/lore/codex/page/robo_morph, + /datum/lore/codex/page/robo_bishop, + /datum/lore/codex/page/robo_zh, + /datum/lore/codex/page/robo_veymed, + ) + +/datum/lore/codex/page/robo_unbranded + name = "\"Unbranded\"" + data = "Based on hundreds of years of open-source development, \"Unbranded\" prosthetics are a low-price powered prosthesis option available throughout human space, even in the most desolate or newly settled systems. Occasionally, a popular unbranded design will be taken down due to claims of copyright infringement, but a new one invariably springs back up within a few months. Because Unbranded designs have a very loosely structured development process, bugs inevitably crop up, leading to a reputation for unreliability.\ +

\ + Unbranded prosthetics are extremely inexpensive but are sought out by those seriously dedicated to the Unbranded ethos. Due to their open-sourced nature, Unbranded prosthetics run the gamut of quality and style, though it's safe to assume that they're relatively poorly made. The ones that last longest on the Exonet tend to be glitchy; those that function are often removed on claims of copyright infringement." + +/datum/lore/codex/page/robo_cyber + name = "Cyber Solutions" + data = "Morpheus Cyberkinetics makes the cheapest functioning prosthetics on the market. Cyber Solutions makes the cheapest prosthetics, period. Notoriously buggy and poorly-constructed, Cyber Solutions has been the target of a number of class action lawsuits by positronics whose bodies had literally fallen apart on them. While their quality has improved slightly since their most recent lawsuit, Cyber Solutions parts remain so low-quality that the company refuses to use them for their own low-price drone lines. Some tinkerers have managed to improve the parts far beyond the factory quality, and in some Mercurial subgroups Cyber Solutions modding is considered an art form.\ +

\ + Cyber Solutions prosthetics are only recommended for the truly destitute and dedicated tinkers." + +/datum/lore/codex/page/robo_nt + name = "NanoTrasen" + data = "A fairly unremarkable prosthetic design, NanoTrasen health plans provide these as part of their famous corporate medical insurance. These are also provided to NanoTrasen-produced positronics at the end of their indenture and are considered fairly high quality for entry-level prosthesis. Outside of NanoTrasen facilities, NanoTrasen-brand prosthetics are fairly rare and not often sought out-- NanoTrasen's grey-black prosthetics are a visual sign of association with the company itself.\ +

\ + NanoTrasen prosthetics are a solid choice for any NanoTrasen employee. They're easy to come across in the event of a workplace accident and comfortable enough that many never feel the need to upgrade." + +/datum/lore/codex/page/robo_wt + name = "Ward-Takahashi GMB" + data = "The manufacturing giant's prosthetic line is functionally quite similar to Nanotrasen, but is directed at the consumer market and cheaper than Nanotrasen's own product. Aesthetically, of course, they are worlds apart, trading Nanotrasen's black gunmetal for rounded white plastic. The design endeavors to avoid the \"uncanny valley\" that plagues humaniform robot designs, by abstracting away the human shape into a series of connected ovals. Artists debate whether or not it succeeds, while normal people are more concerned with WT's tendency to accrue dirt and scratches with hard use.\ +

\ + Ward-Takahashi is popular through all economic classes, from poor to wealthy. Though it takes more wear-and-tear from heavy labor than dedicated industrial chassis, some use it for these tasks regardless." + +/datum/lore/codex/page/robo_heph + name = "Hephaestus Industries" + data = "Hephaestus joined the civilian prosthetic market in earnest after the First Contact War. Wartime amputees and fully-prosthetic Mechanized Division veterans found themselves looking for the Hephaestus parts that they had access to during the conflict. Hephaestus responded by producing the first civilian model of their rugged green prosthetics, leveraging their ties with SolGov to offer discounts to many of those returning from war. HI-Civilian is not quite as durable or easily maintained as the military model, to conform with most systems' legal restrictions on the capacities of prosthetic limbs, but maintains an unmatched reputation for resilience to damage and ease of repair.\ +

\ + Hephaestus prosthetics are somewhat expensive, but are a reasonable investment for many of average or above economic status. It has sufficient manual dexterity for most tasks, without sacrificing the rugged durability that made the brand popular." + +/datum/lore/codex/page/robo_xion + name = "Xion Manufacturing Group" + data = "Xion's prosthetic designs are normally seen fairly rarely outside of Xion's extensive mining facilities, but have managed to proliferate because of the sheer number of positronics it creates and employs. Xion's limbs are cheap and rugged, but come with a number of drawbacks. Even positronic users complain about Xion's lack of sensitivity, but more problematic still is Xion's habit of leasing out their prosthetics as they do the rest of their equipment. Most people find the idea of not owning their own body extremely distressing, and because of this (and because Xion spearheads most anti-Unbranded lawsuits) Xion and Xion-like prosthetic designs are frequently available on pirate sites.\ +

\ + Xion prosthetics are most appropriate for the poor and underpaid. More wealthy people, and those whose jobs require precision works, are encouraged to pick a more open brand." + +/datum/lore/codex/page/robo_grayson + name = "Grayson Manufacturing" + data = "Grayson is a new entrant into the prosthetics market. Their debut line is a rugged design built using polymers and alloys originally developed for Wulf Aeronautics, giving their parts a reputation for extremely solid construction. Unfortunately, the use of high-density materials in the construction process gives them an uncomfortable weight, something that Grayson has promised to correct in their next release. The parts are fairly cheap, but require a robotics specialist to put them together by hand before they're ready for use.\ +

\ + Grayson parts are appropriate for those of any income class, so long as they are willing to deal with the design's unwieldiness. This makes them most popular for those involved in construction or other manual labor, and some in police and private security have taken to using Grayson as a \"discount Hephaestus\"." + +/datum/lore/codex/page/robo_morph + name = "Morpheus Cyberkinetics" + data = "One of the two TSCs with the most investment in the prosthetics market, Morpheus' design ethos sets them far apart from Bishop Cybernetics. Morpheus chassis are supposed to be the cheapest and most streamlined prosthetic bodies imaginable. Due to their minimalist construction methods, the chassis is often called 'skeletal' or 'insectoid', the parts often remaining unpainted, with wiring being run externally, rather than through the joints. Morpheus was also the first company to pioneer the now-popular \"monitorhead\" design, replacing time and material-intensive facial sculpting with a single mass-produced monitor.\ +

\ + Morpheus prosthetics are a popular choice for the positronic underclass. Richer synthetics usually upgrade to a more aesthetically pleasing design, while most humans find the distinctly inhuman sensory response from Morpheus products unnerving." + +/datum/lore/codex/page/robo_bishop + name = "Bishop Cybernetics" + data = "Bishop is the other big-name prosthesis manufacturer. Despite their obviously mechanical appearance, Bishop products have a range of sensation rivaling that of Vey Medical, with proponents calling it even more comfortable and responsive. Simply occupying a Bishop chassis gives some the same sort of sensation one would get from a fast, well-maintained car or aircraft. Bishop products are most commonly sold in \"boutiques\" found throughout the richer regions of human space, and are custom-fit for the end-user's specifications.Externally, Bishop prosthetics have a distinctive chrome or airbrushed aluminum design, with carefully fitted blue lighting.\ +

\ + Bishop's exclusivity leads to them being most common among the wealthy, although upper-middle class technophiles have been known to invest in a high-quality prosthetic. \"Knock-offs\", usually chrome-plated NanoTrasen prosthetics with painted-on lines, are sometimes worn by poseurs." + +/datum/lore/codex/page/robo_zh + name = "Zeng-Hu Pharmaceuticals" + data = "Zeng-Hu produces most of the \"lifelike\" prosthetics on the market. Unfortunately for those looking to return to their lives after a catastrophic accident, Zeng-Hu only maintains its profit margins on this product line by cutting corners. Zeng-Hu synthskin is significantly thicker than human skin and has been described as \"rubbery\". Zeng-Hu bodies also have obvious seam lines at the joints to lessen the structural stress on the synthskin covering. Additionally, Zeng-Hu standard facial sculpts all look fairly similar, though custom orders often avoid this problem. Nonetheless, ZH parts are the only option most people have for lifelike prosthetic limbs, and are lifelike enough to pass for human to casual inspection.\ +

\ + Zeng-Hu is available to individuals of average means and is a popular choice for drones designed for social interaction, who will probably have been paid for by their creators." + +/datum/lore/codex/page/robo_veymed //the deed is done + name = "Vey-Medical" + data = "The most advanced humanoid prosthetic on the market, Vey-Med prides itself on its highly realistic synthskin, near-seamlessly integrated with the most sensitive tactile suite yet created (aside from that of Bishop, with whom they have a long-running friendly rivalry). Vey-Med seeks to be indistinguishable from a human body by both outside observers and by the patient themself, a point at which it succeeds handily.\ + The main downside to Vey-Med is its incredibly high pricetag-- easily comparable with that of a large house. Every Vey-Med piece is custom-sculpted for its individual owner, usually based on scans of the owner's previous body or the owner's family. Vey-Med also requires regular maintenance, lest the partially-organic synthskin that coats each piece begin to rot.\ + Many nouveau riche and lottery winners have splurged on a Vey-Med chassis, only to discover that they couldn't keep it maintained. Such individuals contribute to the large and semi-legal market of second, third, and fourth-hand Vey-Med chasses, which are cheaper than a store-bought one, but not by very much. Vey-Medical forbids resale of its prosthetics line, and works hard to shut down illicit sales. Potential buyers of a pre-owned Vey-Medical chassis should avoid deals that seem too good to be true, lest they discover that their new body is a Zeng-Hu with a layer of epoxy.\ +

\ + Vey-Med bodies are only accessible to the extremely wealthy, almost exclusively humans. Positronics find them unsettling in much the same way humans do Morpheus, and the idea of putting a drone in a Vey-Med body, if not a crude joke, is utterly ridiculous to anyone with any sort of sense. They are absolutely inappropriate for manual labor or combat, being fragile and usually fairly weak compared to other prosthetics." + diff --git a/code/modules/lore_codex/robutt_data/main_robutts.dm b/code/modules/lore_codex/robutt_data/main_robutts.dm new file mode 100644 index 0000000000..396a04883c --- /dev/null +++ b/code/modules/lore_codex/robutt_data/main_robutts.dm @@ -0,0 +1,7 @@ +/datum/lore/codex/category/main_robutts // The top-level categories for the robot guide + name = "Index" + data = "Temporary death, emancipation, and even basic body migration can be a stressful period in anyone's life. The prosthetics market is complicated, and many corporations view misleading or outright decieving potential clients as \"part of the game\". This Buyer's Guide was compiled in 2542 to serve as an easy reference to the most popular prosthetics available, with consideration paid to every use-case and price point. This is our 12th edition, and much has changed in the field of prosthetics since we first set out. We hope you find the information in this guide helpful." + children = list( + /datum/lore/codex/category/pros_by_brand, + /datum/lore/codex/category/other_information, + ) \ No newline at end of file diff --git a/code/modules/lore_codex/robutt_data/more.dm b/code/modules/lore_codex/robutt_data/more.dm new file mode 100644 index 0000000000..39bc4995af --- /dev/null +++ b/code/modules/lore_codex/robutt_data/more.dm @@ -0,0 +1,34 @@ +/datum/lore/codex/category/other_information + name = "More Information" + data = "Here you'll find articles designed to aid your decision making process, narrowing down the brands outlined in the main body." + children = list( + /datum/lore/codex/page/humansvbeeps, + /datum/lore/codex/page/posiage, + /datum/lore/codex/page/variants, + /datum/lore/codex/page/kitbashing, + ) + +/datum/lore/codex/page/humansvbeeps + name = "Humans vs Positronics vs Drones" + data = "Most brands are clearly associated with either humans (amputees or voluntary cyber-augmentation patients) or positronics. Despite the fact that MMI and posibrain interfaces are quite similar, and most brands are equally comfortable for both species, this stratification persists. The main reason for this is that human-seeming prosthetics are usually regarded as important for human mental well-being. Medical insurance often pays out more for humans than for positronics in the event of an accident, and humans are often more willing to pay higher prices for humanoid prosthetics. Some positronics regard this as discriminatory, and most believe that maintaining a divide between the two species does not help with social integration.\ +

\ + Drones completely eschew this divide-- their chassis are based on what is the most profitable for the group that maintains them. Usually, this means some sort of non-anthropomorphic lawbound chassis. When a humanoid body is required, it's usually the cheapest one available that meets the minimum requirements for the drone to do its job." + +/datum/lore/codex/page/posiage + name = "Positronics and Age" + data = "Young positronics are unlikely to have much in the way of expensive belongings, including prosthetics. Most positronics come into the working world outside of a well-defined familial structure and are still paying off the debt from their first body.\ + Even those who do come into a family mature very quickly, not providing time for relatives to save up for an expensive chassis before they begin adulthood and working life. Because of these logistical concerns, even a positronic who has been in a well-paying job for a few years is unable to afford a high-quality chassis.\ +

\ + Most positronics buy their second chassis at around 10 to 15 years of age, and it is at these age that positronics in more middling chassis come into being. Positronics who want a high-end body must save for decades while scrambling for advancement in a galaxy that is rather bigoted more often than not." + +/datum/lore/codex/page/variants + name = "Variants" + data = "Most prosthetic manufacturers produce more than one design, though they usually share significant design elements and exist in the same price-point. Monitor heads remain noticeably cheaper than proper heads, so those interested in penny-pinching will usually opt for a variant with a screen instead of a face." + +/datum/lore/codex/page/kitbashing + name = "Kitbashing" + data = "Different corporations' prosthetics are not designed to be slotted together.\ + There are exceptions: most industrial brands utilize a shared standard set of connectors, and of course there are Unbranded models that play well with any and all parts.\ + Nonetheless, attempting to splice together parts across these lines runs into a variety of technical problems. Most common are sensory and motor cross-wirings, leading to synthesia, uncontrollable jitters, and occasional paralysis. These are uncomfortable enough that most amateur bodymodders give up after one too many hallucinations. Certain combinations of parts run into structural issues-- putting a Hephestus torso on a pair of Morpheus legs is likely to deform those legs badly. Any cross-design kitbashing is likely to result in some level of structural instabilty and poor balance without hard work being put into the design.\ +

\ + Most of these can be addressed by a talented roboticist, but nonetheless most people tend to stick to a single brand of prosthetics. People who see their body's makeup as a means of self-expression, or as a machine to be optimized, are much more likely to take risks in pursuit of these goals." \ No newline at end of file diff --git a/code/modules/materials/material_synth.dm b/code/modules/materials/material_synth.dm index 86e3e16a2d..f7088839ff 100644 --- a/code/modules/materials/material_synth.dm +++ b/code/modules/materials/material_synth.dm @@ -12,6 +12,9 @@ desc = "A device that synthesises [material.display_name]." matter = null +/obj/item/stack/material/cyborg/update_strings() + return + /obj/item/stack/material/cyborg/plastic icon_state = "sheet-plastic" default_type = "plastic" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 9aac48a3e6..2941ca7b4b 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -1,22 +1,6 @@ /mob/living/carbon/human/examine(mob/user) - - var/skipgloves = 0 - var/skipsuitstorage = 0 - var/skipjumpsuit = 0 - var/skipshoes = 0 - var/skipmask = 0 - var/skiptie = 0 - var/skipholster = 0 - - var/skipears = 0 - var/skipeyes = 0 - var/skipface = 0 - var/skipchest = 0 - var/skipgroin = 0 - var/skiphands = 0 - var/skiplegs = 0 - var/skiparms = 0 - var/skipfeet = 0 + var/skip_gear = 0 + var/skip_body = 0 if(alpha <= 50) src.loc.examine(user) @@ -26,97 +10,101 @@ //exosuits and helmets obscure our view and stuff. if(wear_suit) - skipsuitstorage |= wear_suit.flags_inv & HIDESUITSTORAGE + if(wear_suit.flags_inv & HIDESUITSTORAGE) + skip_gear |= EXAMINE_SKIPSUITSTORAGE + if(wear_suit.flags_inv & HIDEJUMPSUIT) - skiparms |= 1 - skiplegs |= 1 - skipchest |= 1 - skipgroin |= 1 - skipjumpsuit |= 1 - skiptie |= 1 - skipholster |= 1 + skip_body |= EXAMINE_SKIPARMS | EXAMINE_SKIPLEGS | EXAMINE_SKIPBODY | EXAMINE_SKIPGROIN + skip_gear |= EXAMINE_SKIPJUMPSUIT | EXAMINE_SKIPTIE | EXAMINE_SKIPHOLSTER + else if(wear_suit.flags_inv & HIDETIE) - skiptie |= 1 - skipholster |= 1 + skip_gear |= EXAMINE_SKIPTIE | EXAMINE_SKIPHOLSTER + else if(wear_suit.flags_inv & HIDEHOLSTER) - skipholster |= 1 + skip_gear |= EXAMINE_SKIPHOLSTER + if(wear_suit.flags_inv & HIDESHOES) - skipshoes |= 1 - skipfeet |= 1 + skip_gear |= EXAMINE_SKIPSHOES + skip_body |= EXAMINE_SKIPFEET + if(wear_suit.flags_inv & HIDEGLOVES) - skipgloves |= 1 - skiphands |= 1 + skip_gear |= EXAMINE_SKIPGLOVES + skip_body |= EXAMINE_SKIPHANDS if(w_uniform) - skiplegs |= w_uniform.body_parts_covered & LEGS - skiparms |= w_uniform.body_parts_covered & ARMS - skipchest |= w_uniform.body_parts_covered & UPPER_TORSO - skipgroin |= w_uniform.body_parts_covered & LOWER_TORSO + if(w_uniform.body_parts_covered & LEGS) + skip_body |= EXAMINE_SKIPLEGS + if(w_uniform.body_parts_covered & ARMS) + skip_body |= EXAMINE_SKIPARMS + if(w_uniform.body_parts_covered & UPPER_TORSO) + skip_body |= EXAMINE_SKIPBODY + if(w_uniform.body_parts_covered & LOWER_TORSO) + skip_body |= EXAMINE_SKIPGROIN - if(gloves) - skiphands |= gloves.body_parts_covered & HANDS + if(gloves && (gloves.body_parts_covered & HANDS)) + skip_body |= EXAMINE_SKIPHANDS - if(shoes) - skipfeet |= shoes.body_parts_covered & FEET + if(shoes && (shoes.body_parts_covered & FEET)) + skip_body |= EXAMINE_SKIPFEET if(head) - skipmask |= head.flags_inv & HIDEMASK - skipeyes |= head.flags_inv & HIDEEYES - skipears |= head.flags_inv & HIDEEARS - skipface |= head.flags_inv & HIDEFACE + if(head.flags_inv & HIDEMASK) + skip_gear |= EXAMINE_SKIPMASK + if(head.flags_inv & HIDEEYES) + skip_gear |= EXAMINE_SKIPEYEWEAR + skip_body |= EXAMINE_SKIPEYES + if(head.flags_inv & HIDEEARS) + skip_gear |= EXAMINE_SKIPEARS + if(head.flags_inv & HIDEFACE) + skip_body |= EXAMINE_SKIPFACE - if(wear_mask) - skipface |= wear_mask.flags_inv & HIDEFACE + if(wear_mask && (wear_mask.flags_inv & HIDEFACE)) + skip_body |= EXAMINE_SKIPFACE //This is what hides what var/list/hidden = list( - BP_GROIN = skipgroin, - BP_TORSO = skipchest, - BP_HEAD = skipface, - BP_L_ARM = skiparms, - BP_R_ARM = skiparms, - BP_L_HAND= skiphands, - BP_R_HAND= skiphands, - BP_L_FOOT= skipfeet, - BP_R_FOOT= skipfeet, - BP_L_LEG = skiplegs, - BP_R_LEG = skiplegs) + BP_GROIN = skip_body & EXAMINE_SKIPGROIN, + BP_TORSO = skip_body & EXAMINE_SKIPBODY, + BP_HEAD = skip_body & EXAMINE_SKIPHEAD, + BP_L_ARM = skip_body & EXAMINE_SKIPARMS, + BP_R_ARM = skip_body & EXAMINE_SKIPARMS, + BP_L_HAND= skip_body & EXAMINE_SKIPHANDS, + BP_R_HAND= skip_body & EXAMINE_SKIPHANDS, + BP_L_FOOT= skip_body & EXAMINE_SKIPFEET, + BP_R_FOOT= skip_body & EXAMINE_SKIPFEET, + BP_L_LEG = skip_body & EXAMINE_SKIPLEGS, + BP_R_LEG = skip_body & EXAMINE_SKIPLEGS) - var/list/msg = list("*---------*\nThis is ") + var/list/msg = list("*---------*
This is ") - - var/datum/gender/T = gender_datums[get_visible_gender()] - - if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender - T = gender_datums[PLURAL] - - else if(species && species.ambiguous_genders) - var/can_detect_gender = FALSE - if(isobserver(user)) // Ghosts are all knowing. - can_detect_gender = TRUE - if(issilicon(user)) // Borgs are too because science. - can_detect_gender = TRUE - else if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.species && istype(species, H.species)) - can_detect_gender = TRUE - - if(!can_detect_gender) - T = gender_datums[PLURAL] // Species with ambiguous_genders will not show their true gender upon examine if the examiner is not also the same species. - else - if(icon) - msg += "\icon[icon] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated - - if(!T) - // Just in case someone VVs the gender to something strange. It'll runtime anyway when it hits usages, better to CRASH() now with a helpful message. - CRASH("Gender datum was null; key was '[(skipjumpsuit && skipface) ? PLURAL : gender]'") + if(icon) + msg += "\icon[icon] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated msg += "[src.name]" - if(!(skipjumpsuit && skipface)) - if(src.custom_species) + var/datum/gender/T = gender_datums[get_visible_gender()] + + if((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) //big suits/masks/helmets make it hard to tell their gender + T = gender_datums[PLURAL] + + else if(species && species.ambiguous_genders) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.species && !istype(species, H.species)) + T = gender_datums[PLURAL]// Species with ambiguous_genders will not show their true gender upon examine if the examiner is not also the same species. + if(!(issilicon(user) || isobserver(user))) // Ghosts and borgs are all knowing + T = gender_datums[PLURAL] + + if(!T) + // Just in case someone VVs the gender to something strange. It'll runtime anyway when it hits usages, better to CRASH() now with a helpful message. + CRASH("Gender datum was null; key was '[((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE)) ? PLURAL : gender]'") + + if(!((skip_gear & EXAMINE_SKIPJUMPSUIT) && (skip_body & EXAMINE_SKIPFACE))) + //VOREStation Add Start + if(custom_species) msg += ", a [src.custom_species]" else if(looks_synth) + //VOREStation Add End var/use_gender = "a synthetic" if(gender == MALE) use_gender = "an android" @@ -130,37 +118,41 @@ var/extra_species_text = species.get_additional_examine_text(src) if(extra_species_text) - msg += "[extra_species_text]
" + msg += "[extra_species_text]" msg += "
" //uniform - if(w_uniform && !skipjumpsuit && w_uniform.show_examine) + if(w_uniform && !(skip_gear & EXAMINE_SKIPJUMPSUIT) && w_uniform.show_examine) //Ties var/tie_msg - if(istype(w_uniform,/obj/item/clothing/under) && !skiptie) + if(istype(w_uniform,/obj/item/clothing/under) && !(skip_gear & EXAMINE_SKIPTIE)) var/obj/item/clothing/under/U = w_uniform if(U.accessories.len) - if(skipholster) - var/list/accessories_visible = new/list() //please let this fix the stupid fucking runtimes + var/list/accessories_visible = list() //please let this fix the stupid fucking runtimes + if(skip_gear & EXAMINE_SKIPHOLSTER) + for(var/obj/item/clothing/accessory/A in U.accessories) + if(A.show_examine && !istype(A, /obj/item/clothing/accessory/holster)) // If we're supposed to skip holsters, actually skip them + accessories_visible.Add(A) + else for(var/obj/item/clothing/accessory/A in U.accessories) if(A.concealed_holster == 0 && A.show_examine) accessories_visible.Add(A) - if(accessories_visible.len) - tie_msg += ". Attached to it is [english_list(accessories_visible)]" - else tie_msg += ". Attached to it is [english_list(U.accessories)]" + + if(accessories_visible.len) + tie_msg += " Attached to it is [english_list(accessories_visible)]." if(w_uniform.blood_DNA) - msg += "[T.He] [T.is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [w_uniform.name][tie_msg]!\n" + msg += "[T.He] [T.is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [w_uniform.name]![tie_msg]
" else - msg += "[T.He] [T.is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n" + msg += "[T.He] [T.is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].
" //head - if(head && head.show_examine) + if(head && !(skip_gear & EXAMINE_SKIPHELMET) && head.show_examine) if(head.blood_DNA) - msg += "[T.He] [T.is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] [(head.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [head.name] on [T.his] head!\n" + msg += "[T.He] [T.is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] [(head.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [head.name] on [T.his] head!
" else - msg += "[T.He] [T.is] wearing \icon[head] \a [head] on [T.his] head.\n" + msg += "[T.He] [T.is] wearing \icon[head] \a [head] on [T.his] head.
" //suit/armour if(wear_suit) @@ -168,102 +160,102 @@ if(istype(wear_suit,/obj/item/clothing/suit)) var/obj/item/clothing/suit/U = wear_suit if(U.accessories.len) - tie_msg += ". Attached to it is [english_list(U.accessories)]" + tie_msg += " Attached to it is [english_list(U.accessories)]." if(wear_suit.blood_DNA) - msg += "[T.He] [T.is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] [(wear_suit.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_suit.name]!\n" + msg += "[T.He] [T.is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] [(wear_suit.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_suit.name][tie_msg]!
" else - msg += "[T.He] [T.is] wearing \icon[wear_suit] \a [wear_suit][tie_msg].\n" + msg += "[T.He] [T.is] wearing \icon[wear_suit] \a [wear_suit].[tie_msg]
" //suit/armour storage - if(s_store && !skipsuitstorage && s_store.show_examine) + if(s_store && !(skip_gear & EXAMINE_SKIPSUITSTORAGE) && s_store.show_examine) if(s_store.blood_DNA) - msg += "[T.He] [T.is] carrying \icon[s_store] [s_store.gender==PLURAL?"some":"a"] [(s_store.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [s_store.name] on [T.his] [wear_suit.name]!\n" + msg += "[T.He] [T.is] carrying \icon[s_store] [s_store.gender==PLURAL?"some":"a"] [(s_store.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [s_store.name] on [T.his] [wear_suit.name]!
" else - msg += "[T.He] [T.is] carrying \icon[s_store] \a [s_store] on [T.his] [wear_suit.name].\n" + msg += "[T.He] [T.is] carrying \icon[s_store] \a [s_store] on [T.his] [wear_suit.name].
" //back - if(back && back.show_examine) + if(back && !(skip_gear & EXAMINE_SKIPBACKPACK) && back.show_examine) if(back.blood_DNA) - msg += "[T.He] [T.has] \icon[back] [back.gender==PLURAL?"some":"a"] [(back.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [back] on [T.his] back.\n" + msg += "[T.He] [T.has] \icon[back] [back.gender==PLURAL?"some":"a"] [(back.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [back] on [T.his] back.
" else - msg += "[T.He] [T.has] \icon[back] \a [back] on [T.his] back.\n" + msg += "[T.He] [T.has] \icon[back] \a [back] on [T.his] back.
" //left hand if(l_hand && l_hand.show_examine) if(l_hand.blood_DNA) - msg += "[T.He] [T.is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] [(l_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [l_hand.name] in [T.his] left hand!\n" + msg += "[T.He] [T.is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] [(l_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [l_hand.name] in [T.his] left hand!
" else - msg += "[T.He] [T.is] holding \icon[l_hand] \a [l_hand] in [T.his] left hand.\n" + msg += "[T.He] [T.is] holding \icon[l_hand] \a [l_hand] in [T.his] left hand.
" //right hand if(r_hand && r_hand.show_examine) if(r_hand.blood_DNA) - msg += "[T.He] [T.is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] [(r_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [r_hand.name] in [T.his] right hand!\n" + msg += "[T.He] [T.is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] [(r_hand.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [r_hand.name] in [T.his] right hand!
" else - msg += "[T.He] [T.is] holding \icon[r_hand] \a [r_hand] in [T.his] right hand.\n" + msg += "[T.He] [T.is] holding \icon[r_hand] \a [r_hand] in [T.his] right hand.
" //gloves - if(gloves && !skipgloves && gloves.show_examine) + if(gloves && !(skip_gear & EXAMINE_SKIPGLOVES) && gloves.show_examine) if(gloves.blood_DNA) - msg += "[T.He] [T.has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] [(gloves.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [gloves.name] on [T.his] hands!\n" + msg += "[T.He] [T.has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] [(gloves.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [gloves.name] on [T.his] hands!
" else - msg += "[T.He] [T.has] \icon[gloves] \a [gloves] on [T.his] hands.\n" - else if(blood_DNA) - msg += "[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!\n" + msg += "[T.He] [T.has] \icon[gloves] \a [gloves] on [T.his] hands.
" + else if(blood_DNA && !(skip_body & EXAMINE_SKIPHANDS)) + msg += "[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!
" //handcuffed? if(handcuffed && handcuffed.show_examine) if(istype(handcuffed, /obj/item/weapon/handcuffs/cable)) - msg += "[T.He] [T.is] \icon[handcuffed] restrained with cable!\n" + msg += "[T.He] [T.is] \icon[handcuffed] restrained with cable!
" else - msg += "[T.He] [T.is] \icon[handcuffed] handcuffed!\n" + msg += "[T.He] [T.is] \icon[handcuffed] handcuffed!
" //buckled if(buckled) - msg += "[T.He] [T.is] \icon[buckled] buckled to [buckled]!\n" + msg += "[T.He] [T.is] \icon[buckled] buckled to [buckled]!
" //belt - if(belt && belt.show_examine) + if(belt && !(skip_gear & EXAMINE_SKIPBELT) && belt.show_examine) if(belt.blood_DNA) - msg += "[T.He] [T.has] \icon[belt] [belt.gender==PLURAL?"some":"a"] [(belt.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [belt.name] about [T.his] waist!\n" + msg += "[T.He] [T.has] \icon[belt] [belt.gender==PLURAL?"some":"a"] [(belt.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [belt.name] about [T.his] waist!
" else - msg += "[T.He] [T.has] \icon[belt] \a [belt] about [T.his] waist.\n" + msg += "[T.He] [T.has] \icon[belt] \a [belt] about [T.his] waist.
" //shoes - if(shoes && !skipshoes && shoes.show_examine) + if(shoes && !(skip_gear & EXAMINE_SKIPSHOES) && shoes.show_examine) if(shoes.blood_DNA) - msg += "[T.He] [T.is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] [(shoes.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [shoes.name] on [T.his] feet!\n" + msg += "[T.He] [T.is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] [(shoes.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [shoes.name] on [T.his] feet!
" else - msg += "[T.He] [T.is] wearing \icon[shoes] \a [shoes] on [T.his] feet.\n" - else if(feet_blood_DNA) - msg += "[T.He] [T.has] [(feet_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained feet!\n" + msg += "[T.He] [T.is] wearing \icon[shoes] \a [shoes] on [T.his] feet.
" + else if(feet_blood_DNA && !(skip_body & EXAMINE_SKIPHANDS)) + msg += "[T.He] [T.has] [(feet_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained feet!
" //mask - if(wear_mask && !skipmask && wear_mask.show_examine) + if(wear_mask && !(skip_gear & EXAMINE_SKIPMASK) && wear_mask.show_examine) var/descriptor = "on [T.his] face" if(istype(wear_mask, /obj/item/weapon/grenade) && check_has_mouth()) descriptor = "in [T.his] mouth" if(wear_mask.blood_DNA) - msg += "[T.He] [T.has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] [(wear_mask.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_mask.name] [descriptor]!\n" + msg += "[T.He] [T.has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] [(wear_mask.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [wear_mask.name] [descriptor]!
" else - msg += "[T.He] [T.has] \icon[wear_mask] \a [wear_mask] [descriptor].\n" + msg += "[T.He] [T.has] \icon[wear_mask] \a [wear_mask] [descriptor].
" //eyes - if(glasses && !skipeyes && glasses.show_examine) + if(glasses && !(skip_gear & EXAMINE_SKIPEYEWEAR) && glasses.show_examine) if(glasses.blood_DNA) - msg += "[T.He] [T.has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] [(glasses.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [glasses] covering [T.his] eyes!\n" + msg += "[T.He] [T.has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] [(glasses.blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [glasses] covering [T.his] eyes!
" else - msg += "[T.He] [T.has] \icon[glasses] \a [glasses] covering [T.his] eyes.\n" + msg += "[T.He] [T.has] \icon[glasses] \a [glasses] covering [T.his] eyes.
" //left ear - if(l_ear && !skipears && l_ear.show_examine) - msg += "[T.He] [T.has] \icon[l_ear] \a [l_ear] on [T.his] left ear.\n" + if(l_ear && !(skip_gear & EXAMINE_SKIPEARS) && l_ear.show_examine) + msg += "[T.He] [T.has] \icon[l_ear] \a [l_ear] on [T.his] left ear.
" //right ear - if(r_ear && !skipears && r_ear.show_examine) - msg += "[T.He] [T.has] \icon[r_ear] \a [r_ear] on [T.his] right ear.\n" + if(r_ear && !(skip_gear & EXAMINE_SKIPEARS) && r_ear.show_examine) + msg += "[T.He] [T.has] \icon[r_ear] \a [r_ear] on [T.his] right ear.
" //ID if(wear_id && wear_id.show_examine) @@ -275,27 +267,27 @@ var/obj/item/weapon/card/id/idcard = wear_id id = idcard.registered_name if(id && (id != real_name) && (get_dist(src, usr) <= 1) && prob(10)) - msg += "[T.He] [T.is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...\n" + msg += "[T.He] [T.is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...
" else*/ - msg += "[T.He] [T.is] wearing \icon[wear_id] \a [wear_id].\n" + msg += "[T.He] [T.is] wearing \icon[wear_id] \a [wear_id].
" //Jitters if(is_jittery) if(jitteriness >= 300) - msg += "[T.He] [T.is] convulsing violently!\n" + msg += "[T.He] [T.is] convulsing violently!
" else if(jitteriness >= 200) - msg += "[T.He] [T.is] extremely jittery.\n" + msg += "[T.He] [T.is] extremely jittery.
" else if(jitteriness >= 100) - msg += "[T.He] [T.is] twitching ever so slightly.\n" + msg += "[T.He] [T.is] twitching ever so slightly.
" //splints for(var/organ in BP_ALL) var/obj/item/organ/external/o = get_organ(organ) if(o && o.splinted && o.splinted.loc == o) - msg += "[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!\n" + msg += "[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!
" if(suiciding) - msg += "[T.He] appears to have commited suicide... there is no hope of recovery.\n" + msg += "[T.He] appears to have commited suicide... there is no hope of recovery.
" msg += attempt_vr(src,"examine_weight",args) //VOREStation Code msg += attempt_vr(src,"examine_nutrition",args) //VOREStation Code @@ -305,56 +297,39 @@ msg += attempt_vr(src,"examine_nif",args) //VOREStation Code if(mSmallsize in mutations) - msg += "[T.He] [T.is] small halfling!\n" + msg += "[T.He] [T.is] very short!
" - var/distance = get_dist(usr,src) - if(istype(usr, /mob/observer/dead) || usr.stat == 2) // ghosts can see anything - distance = 1 if (src.stat) - msg += "[T.He] [T.is]n't responding to anything around [T.him] and seems to be asleep.\n" - if((stat == 2 || src.losebreath) && distance <= 3) - msg += "[T.He] [T.does] not appear to be breathing.\n" - if(istype(usr, /mob/living/carbon/human) && !usr.stat && Adjacent(usr)) - usr.visible_message("[usr] checks [src]'s pulse.", "You check [src]'s pulse.") + msg += "[T.He] [T.is]n't responding to anything around [T.him] and seems to be asleep.
" + if((stat == 2 || src.losebreath) && get_dist(user, src) <= 3) + msg += "[T.He] [T.does] not appear to be breathing.
" + if(istype(user, /mob/living/carbon/human) && !user.stat && Adjacent(user)) + user.visible_message("[usr] checks [src]'s pulse.", "You check [src]'s pulse.") spawn(15) - if(distance <= 1 && usr.stat != 1) + if(isobserver(user) || (Adjacent(user) && !user.stat)) // If you're a corpse then you can't exactly check their pulse, but ghosts can see anything if(pulse == PULSE_NONE) - usr << "[T.He] [T.has] no pulse[src.client ? "" : " and [T.his] soul has departed"]..." + to_chat(user, "[T.He] [T.has] no pulse[src.client ? "" : " and [T.his] soul has departed"]...") else - usr << "[T.He] [T.has] a pulse!" + to_chat(user, "[T.He] [T.has] a pulse!") if(fire_stacks) - msg += "[T.He] [T.is] covered in some liquid.\n" + msg += "[T.He] [T.is] covered in some liquid.
" if(on_fire) - msg += "[T.He] [T.is] on fire!.\n" - msg += "" - - /* - if(nutrition < 100) - msg += "[T.He] [T.is] severely malnourished.\n" - else if(nutrition >= 500) - /*if(usr.nutrition < 100) - msg += "[T.He] [T.is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" - else*/ - msg += "[T.He] [T.is] quite chubby.\n" - */ - - msg += "" + msg += "[T.He] [T.is] on fire!.
" var/ssd_msg = species.get_ssd(src) - if(stat != DEAD) - if(ssd_msg && (!should_have_organ("brain") || has_brain())) - if(!key) - msg += "[T.He] [T.is] [ssd_msg]. It doesn't look like [T.he] [T.is] waking up anytime soon.\n" - else if(!client) - msg += "[T.He] [T.is] [ssd_msg].\n" - - if(client && ((client.inactivity / 10) / 60 > 10)) //10 Minutes - msg += "\[Inactive for [round((client.inactivity/10)/60)] minutes\]\n" - else if(disconnect_time) - msg += "\[Disconnected/ghosted [round(((world.realtime - disconnect_time)/10)/60)] minutes ago\]\n" - - + if(ssd_msg && (!should_have_organ("brain") || has_brain()) && stat != DEAD) + if(!key) + msg += "[T.He] [T.is] [ssd_msg]. It doesn't look like [T.he] [T.is] waking up anytime soon.
" + else if(!client) + msg += "[T.He] [T.is] [ssd_msg].
" + //VOREStation Add Start + if(client && ((client.inactivity / 10) / 60 > 10)) //10 Minutes + msg += "\[Inactive for [round((client.inactivity/10)/60)] minutes\]\n" + else if(disconnect_time) + msg += "\[Disconnected/ghosted [round(((world.realtime - disconnect_time)/10)/60)] minutes ago\]\n" + //VOREStation Add End + var/list/wound_flavor_text = list() var/list/is_bleeding = list() var/applying_pressure = "" @@ -366,9 +341,9 @@ var/obj/item/organ/external/E = organs_by_name[organ_tag] if(!E) - wound_flavor_text["[organ_descriptor]"] = "[T.He] [T.is] missing [T.his] [organ_descriptor].\n" + wound_flavor_text["[organ_descriptor]"] = "[T.He] [T.is] missing [T.his] [organ_descriptor].
" else if(E.is_stump()) - wound_flavor_text["[organ_descriptor]"] = "[T.He] [T.has] a stump where [T.his] [organ_descriptor] should be.\n" + wound_flavor_text["[organ_descriptor]"] = "[T.He] [T.has] a stump where [T.his] [organ_descriptor] should be.
" else continue @@ -377,13 +352,14 @@ if((temp.organ_tag in hidden) && hidden[temp.organ_tag]) continue //Organ is hidden, don't talk about it if(temp.status & ORGAN_DESTROYED) - wound_flavor_text["[temp.name]"] = "[T.He] [T.is] missing [T.his] [temp.name].\n" + wound_flavor_text["[temp.name]"] = "[T.He] [T.is] missing [T.his] [temp.name].
" continue + if(!looks_synth && temp.robotic == ORGAN_ROBOT) if(!(temp.brute_dam + temp.burn_dam)) - wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name].\n" + wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name].
" else - wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!\n" + wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!
" continue else if(temp.wounds.len > 0 || temp.open) if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ]) @@ -395,7 +371,7 @@ wound_flavor_text["[temp.name]"] = "" if(temp.dislocated == 2) wound_flavor_text["[temp.name]"] += "[T.His] [temp.joint] is dislocated!
" - if(((temp.status & ORGAN_BROKEN) && temp.brute_dam > temp.min_broken_damage) || (temp.status & ORGAN_MUTATED)) + if(temp.brute_dam > temp.min_broken_damage || (temp.status & (ORGAN_BROKEN | ORGAN_MUTATED))) wound_flavor_text["[temp.name]"] += "[T.His] [temp.name] is dented and swollen!
" if(temp.germ_level > INFECTION_LEVEL_TWO && !(temp.status & ORGAN_DEAD)) @@ -403,8 +379,8 @@ else if(temp.status & ORGAN_DEAD) wound_flavor_text["[temp.name]"] += "[T.His] [temp.name] looks rotten!
" - if(!wound_flavor_text["[temp.name]"] && (temp.status & ORGAN_BLEEDING)) - is_bleeding["[temp.name]"] = "[T.His] [temp.name] is bleeding!
" + if(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].
" @@ -414,58 +390,51 @@ for(var/limb in is_bleeding) msg += is_bleeding[limb] for(var/implant in get_visible_implants(0)) - msg += "[src] [T.has] \a [implant] sticking out of [T.his] flesh!\n" + msg += "[src] [T.has] \a [implant] sticking out of [T.his] flesh!
" if(digitalcamo) - msg += "[T.He] [T.is] repulsively uncanny!\n" + msg += "[T.He] [T.is] repulsively uncanny!
" - if(hasHUD(usr,"security")) - var/perpname = "wot" + if(hasHUD(user,"security")) + var/perpname = name var/criminal = "None" if(wear_id) - var/obj/item/weapon/card/id/I = wear_id.GetID() - if(I) + if(istype(wear_id, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = wear_id perpname = I.registered_name - else - perpname = name - else - perpname = name + else if(istype(wear_id, /obj/item/device/pda)) + var/obj/item/device/pda/P = wear_id + perpname = P.owner - if(perpname) - for (var/datum/data/record/E in data_core.general) - if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if(R.fields["id"] == E.fields["id"]) - criminal = R.fields["criminal"] + for (var/datum/data/record/R in data_core.security) + if(R.fields["name"] == perpname) + criminal = R.fields["criminal"] - msg += "Criminal status: \[[criminal]\]\n" - msg += "Security records: \[View\] \[Add comment\]\n" + msg += "Criminal status: \[[criminal]\]
" + msg += "Security records: \[View\] \[Add comment\]
" - if(hasHUD(usr,"medical")) - var/perpname = "wot" + if(hasHUD(user,"medical")) + var/perpname = name var/medical = "None" if(wear_id) - if(istype(wear_id,/obj/item/weapon/card/id)) - perpname = wear_id:registered_name - else if(istype(wear_id,/obj/item/device/pda)) - var/obj/item/device/pda/tempPda = wear_id - perpname = tempPda.owner - else - perpname = src.name + if(istype(wear_id, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = wear_id + perpname = I.registered_name + else if(istype(wear_id, /obj/item/device/pda)) + var/obj/item/device/pda/P = wear_id + perpname = P.owner - for (var/datum/data/record/E in data_core.general) - if (E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.general) - if (R.fields["id"] == E.fields["id"]) - medical = R.fields["p_stat"] + for (var/datum/data/record/R in data_core.medical) + if (R.fields["name"] == perpname) + medical = R.fields["p_stat"] - msg += "Physical status: \[[medical]\]\n" - msg += "Medical records: \[View\] \[Add comment\]\n" + msg += "Physical status: \[[medical]\]
" + msg += "Medical records: \[View\] \[Add comment\]
" if(print_flavor_text()) - msg += "[print_flavor_text()]\n" + msg += "[print_flavor_text()]
" // VOREStation Start if(ooc_notes) @@ -473,12 +442,12 @@ // VOREStation End msg += "*---------*

" msg += applying_pressure - if (pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + if(pose) + if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!] pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "[T.He] [pose]" - user << jointext(msg, null) + to_chat(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) @@ -490,8 +459,6 @@ return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/sechud) if("medical") return istype(H.glasses, /obj/item/clothing/glasses/hud/health) - else - return 0 else if(istype(M, /mob/living/silicon/robot)) var/mob/living/silicon/robot/R = M switch(hudtype) @@ -499,7 +466,4 @@ return R.hudmode == "Security" if("medical") return R.hudmode == "Medical" - else - return 0 - else - return 0 + return 0 diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm index 9484ca8aed..0457c7b584 100644 --- a/code/modules/mob/living/carbon/human/npcs.dm +++ b/code/modules/mob/living/carbon/human/npcs.dm @@ -13,3 +13,4 @@ name = "Pun Pun" real_name = name w_uniform = new /obj/item/clothing/under/punpun(src) + regenerate_icons() diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 4cf3f92f59..6ba8f5fc9f 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -5,84 +5,84 @@ /datum/species // Descriptors and strings. - var/name // Species name. - var/name_plural // Pluralized name (since "[name]s" is not always valid) - var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen. + var/name // Species name. + var/name_plural // Pluralized name (since "[name]s" is not always valid) + var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen. // Icon/appearance vars. - var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. - var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. + var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. + var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. - var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons. - var/fire_icon_state = "humanoid" // The icon_state used inside OnFire.dmi for when on fire. - var/suit_storage_icon = 'icons/mob/belt_mirror.dmi' // Icons used for worn items in suit storage slot. + var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons. + var/fire_icon_state = "humanoid" // The icon_state used inside OnFire.dmi for when on fire. + var/suit_storage_icon = 'icons/mob/belt_mirror.dmi' // Icons used for worn items in suit storage slot. // Damage overlay and masks. var/damage_overlays = 'icons/mob/human_races/masks/dam_human.dmi' var/damage_mask = 'icons/mob/human_races/masks/dam_mask_human.dmi' var/blood_mask = 'icons/mob/human_races/masks/blood_human.dmi' - var/prone_icon // If set, draws this from icobase when mob is prone. - var/blood_color = "#A10808" // Red. - var/flesh_color = "#FFC896" // Pink. - var/base_color // Used by changelings. Should also be used for icon previews. + var/prone_icon // If set, draws this from icobase when mob is prone. + var/blood_color = "#A10808" // Red. + var/flesh_color = "#FFC896" // Pink. + var/base_color // Used by changelings. Should also be used for icon previews. - var/tail // Name of tail state in species effects icon file. - var/tail_animation // If set, the icon to obtain tail animation states from. + var/tail // Name of tail state in species effects icon file. + var/tail_animation // If set, the icon to obtain tail animation states from. var/tail_hair - var/icon_scale = 1 // Makes the icon larger/smaller. + var/icon_scale = 1 // Makes the icon larger/smaller. - var/race_key = 0 // Used for mob icon cache string. - var/icon/icon_template // Used for mob icon generation for non-32x32 species. + var/race_key = 0 // Used for mob icon cache string. + var/icon/icon_template // Used for mob icon generation for non-32x32 species. var/mob_size = MOB_MEDIUM var/show_ssd = "fast asleep" var/virus_immune - var/short_sighted // Permanent weldervision. - var/blood_volume = 560 // Initial blood volume. - var/bloodloss_rate = 1 // Multiplier for how fast a species bleeds out. Higher = Faster - var/hunger_factor = 0.05 // Multiplier for hunger. - var/active_regen_mult = 1 // Multiplier for 'Regenerate' power speed, in human_powers.dm + var/short_sighted // Permanent weldervision. + var/blood_volume = 560 // Initial blood volume. + var/bloodloss_rate = 1 // Multiplier for how fast a species bleeds out. Higher = Faster + var/hunger_factor = 0.05 // Multiplier for hunger. + var/active_regen_mult = 1 // Multiplier for 'Regenerate' power speed, in human_powers.dm - var/taste_sensitivity = TASTE_NORMAL // How sensitive the species is to minute tastes. + var/taste_sensitivity = TASTE_NORMAL // How sensitive the species is to minute tastes. var/min_age = 17 var/max_age = 70 // Language/culture vars. - var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers. - var/language = LANGUAGE_GALCOM // Default racial language, if any. - var/species_language = LANGUAGE_GALCOM // Used on the Character Setup screen - var/list/secondary_langs = list() // The names of secondary languages that are available to this species. - var/list/speech_sounds // A list of sounds to potentially play when speaking. - var/list/speech_chance // The likelihood of a speech sound playing. - var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation - var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator + var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers. + var/language = LANGUAGE_GALCOM // Default racial language, if any. + var/species_language = LANGUAGE_GALCOM // Used on the Character Setup screen + var/list/secondary_langs = list() // The names of secondary languages that are available to this species. + var/list/speech_sounds // A list of sounds to potentially play when speaking. + var/list/speech_chance // The likelihood of a speech sound playing. + var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation + var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator //Soundy emotey things. var/scream_verb = "screams" - var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace! - var/female_scream_sound //= 'sound/goonstation/voice/female_scream.ogg' Removed due to licensing, replace! + var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace! + var/female_scream_sound //= 'sound/goonstation/voice/female_scream.ogg' Removed due to licensing, replace! var/male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') var/female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') var/male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' var/female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' // Combat vars. - var/total_health = 100 // Point at which the mob will enter crit. - var/list/unarmed_types = list( // Possible unarmed attacks that the mob will use in combat, + var/total_health = 100 // Point at which the mob will enter crit. + var/list/unarmed_types = list( // Possible unarmed attacks that the mob will use in combat, /datum/unarmed_attack, /datum/unarmed_attack/bite ) - var/list/unarmed_attacks = null // For empty hand harm-intent attack - var/brute_mod = 1 // Physical damage multiplier. - var/burn_mod = 1 // Burn damage multiplier. - var/oxy_mod = 1 // Oxyloss modifier - var/toxins_mod = 1 // Toxloss modifier - var/radiation_mod = 1 // Radiation modifier - var/flash_mod = 1 // Stun from blindness modifier. - var/chemOD_mod = 1 // Damage modifier for overdose - var/vision_flags = SEE_SELF // Same flags as glasses. + var/list/unarmed_attacks = null // For empty hand harm-intent attack + var/brute_mod = 1 // Physical damage multiplier. + var/burn_mod = 1 // Burn damage multiplier. + var/oxy_mod = 1 // Oxyloss modifier + var/toxins_mod = 1 // Toxloss modifier + var/radiation_mod = 1 // Radiation modifier + var/flash_mod = 1 // Stun from blindness modifier. + var/chemOD_mod = 1 // Damage modifier for overdose + var/vision_flags = SEE_SELF // Same flags as glasses. // Death vars. var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human @@ -95,23 +95,23 @@ var/cloning_modifier = /datum/modifier/cloning_sickness // Environment tolerance/life processes vars. - var/reagent_tag //Used for metabolizing reagents. - var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. - var/poison_type = "phoron" // Poisonous air. - var/exhale_type = "carbon_dioxide" // Exhaled gas type. + var/reagent_tag //Used for metabolizing reagents. + var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. + var/poison_type = "phoron" // Poisonous air. + var/exhale_type = "carbon_dioxide" // Exhaled gas type. - var/body_temperature = 310.15 // Species will try to stabilize at this temperature. (also affects temperature processing) + var/body_temperature = 310.15 // Species will try to stabilize at this temperature. (also affects temperature processing) // Cold - var/cold_level_1 = 260 // Cold damage level 1 below this point. - var/cold_level_2 = 200 // Cold damage level 2 below this point. - var/cold_level_3 = 120 // Cold damage level 3 below this point. + var/cold_level_1 = 260 // Cold damage level 1 below this point. + var/cold_level_2 = 200 // Cold damage level 2 below this point. + var/cold_level_3 = 120 // Cold damage level 3 below this point. - var/breath_cold_level_1 = 240 // Cold gas damage level 1 below this point. - var/breath_cold_level_2 = 180 // Cold gas damage level 2 below this point. - var/breath_cold_level_3 = 100 // Cold gas damage level 3 below this point. + var/breath_cold_level_1 = 240 // Cold gas damage level 1 below this point. + var/breath_cold_level_2 = 180 // Cold gas damage level 2 below this point. + var/breath_cold_level_3 = 100 // Cold gas damage level 3 below this point. - var/cold_discomfort_level = 285 // Aesthetic messages about feeling chilly. + var/cold_discomfort_level = 285 // Aesthetic messages about feeling chilly. var/list/cold_discomfort_strings = list( "You feel chilly.", "You shiver suddenly.", @@ -119,15 +119,15 @@ ) // Hot - var/heat_level_1 = 360 // Heat damage level 1 above this point. - var/heat_level_2 = 400 // Heat damage level 2 above this point. - var/heat_level_3 = 1000 // Heat damage level 3 above this point. + var/heat_level_1 = 360 // Heat damage level 1 above this point. + var/heat_level_2 = 400 // Heat damage level 2 above this point. + var/heat_level_3 = 1000 // Heat damage level 3 above this point. - var/breath_heat_level_1 = 380 // Heat gas damage level 1 below this point. - var/breath_heat_level_2 = 450 // Heat gas damage level 2 below this point. - var/breath_heat_level_3 = 1250 // Heat gas damage level 3 below this point. + var/breath_heat_level_1 = 380 // Heat gas damage level 1 below this point. + var/breath_heat_level_2 = 450 // Heat gas damage level 2 below this point. + var/breath_heat_level_3 = 1250 // Heat gas damage level 3 below this point. - var/heat_discomfort_level = 315 // Aesthetic messages about feeling warm. + var/heat_discomfort_level = 315 // Aesthetic messages about feeling warm. var/list/heat_discomfort_strings = list( "You feel sweat drip down your neck.", "You feel uncomfortably warm.", @@ -135,13 +135,13 @@ ) - var/passive_temp_gain = 0 // Species will gain this much temperature every second - var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. - var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. - var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. - var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. - var/light_dam // If set, mob will be damaged in light over this value and heal in light below its negative. - var/minimum_breath_pressure = 16 // Minimum required pressure for breath, in kPa + var/passive_temp_gain = 0 // Species will gain this much temperature every second + var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. + var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. + var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. + var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. + var/light_dam // If set, mob will be damaged in light over this value and heal in light below its negative. + var/minimum_breath_pressure = 16 // Minimum required pressure for breath, in kPa var/metabolic_rate = 1 @@ -149,52 +149,55 @@ // HUD data vars. var/datum/hud_data/hud var/hud_type - var/health_hud_intensity = 1 // This modifies how intensely the health hud is colored. + var/health_hud_intensity = 1 // This modifies how intensely the health hud is colored. // Body/form vars. - var/list/inherent_verbs // Species-specific verbs. - var/has_fine_manipulation = 1 // Can use small items. - var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation. - var/darksight = 2 // Native darksight distance. - var/flags = 0 // Various specific features. - var/appearance_flags = 0 // Appearance/display related features. - var/spawn_flags = 0 // Flags that specify who can spawn as this species + var/list/inherent_verbs // Species-specific verbs. + var/has_fine_manipulation = 1 // Can use small items. + var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation. + var/darksight = 2 // Native darksight distance. + var/flags = 0 // Various specific features. + var/appearance_flags = 0 // Appearance/display related features. + var/spawn_flags = 0 // Flags that specify who can spawn as this species - var/slowdown = 0 // Passive movement speed malus (or boost, if negative) + var/slowdown = 0 // Passive movement speed malus (or boost, if negative) var/obj/effect/decal/cleanable/blood/tracks/move_trail = /obj/effect/decal/cleanable/blood/tracks/footprints // What marks are left when walking var/list/skin_overlays = list() - var/has_floating_eyes = 0 // Whether the eyes can be shown above other icons - var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting - var/water_movement = 0 // How much faster or slower the species is in water - var/snow_movement = 0 // How much faster or slower the species is on snow + var/has_floating_eyes = 0 // Whether the eyes can be shown above other icons + var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting + var/water_movement = 0 // How much faster or slower the species is in water + var/snow_movement = 0 // How much faster or slower the species is on snow - var/item_slowdown_mod = 1 // How affected by item slowdown the species is. - var/primitive_form // Lesser form, if any (ie. monkey for humans) - var/greater_form // Greater form, if any, ie. human for monkeys. + var/item_slowdown_mod = 1 // How affected by item slowdown the species is. + var/primitive_form // Lesser form, if any (ie. monkey for humans) + var/greater_form // Greater form, if any, ie. human for monkeys. var/holder_type - var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people. - var/rarity_value = 1 // Relative rarity/collector value for this species. - // Determines the organs that the species spawns with and - var/list/has_organ = list( // which required-organ checks are conducted. - O_HEART = /obj/item/organ/internal/heart, - O_LUNGS = /obj/item/organ/internal/lungs, - O_LIVER = /obj/item/organ/internal/liver, - O_KIDNEYS = /obj/item/organ/internal/kidneys, - O_BRAIN = /obj/item/organ/internal/brain, + var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people. + + var/rarity_value = 1 // Relative rarity/collector value for this species. + var/economic_modifier = 2 // How much money this species makes + + // Determines the organs that the species spawns with and + var/list/has_organ = list( // which required-organ checks are conducted. + O_HEART = /obj/item/organ/internal/heart, + O_LUNGS = /obj/item/organ/internal/lungs, + O_LIVER = /obj/item/organ/internal/liver, + O_KIDNEYS = /obj/item/organ/internal/kidneys, + O_BRAIN = /obj/item/organ/internal/brain, O_APPENDIX = /obj/item/organ/internal/appendix, - O_EYES = /obj/item/organ/internal/eyes + O_EYES = /obj/item/organ/internal/eyes ) - var/vision_organ // If set, this organ is required for vision. Defaults to "eyes" if the species has them. + var/vision_organ // If set, this organ is required for vision. Defaults to "eyes" if the species has them. var/list/has_limbs = list( - BP_TORSO = list("path" = /obj/item/organ/external/chest), - BP_GROIN = list("path" = /obj/item/organ/external/groin), - BP_HEAD = list("path" = /obj/item/organ/external/head), - BP_L_ARM = list("path" = /obj/item/organ/external/arm), - BP_R_ARM = list("path" = /obj/item/organ/external/arm/right), - BP_L_LEG = list("path" = /obj/item/organ/external/leg), - BP_R_LEG = list("path" = /obj/item/organ/external/leg/right), + BP_TORSO = list("path" = /obj/item/organ/external/chest), + BP_GROIN = list("path" = /obj/item/organ/external/groin), + BP_HEAD = list("path" = /obj/item/organ/external/head), + BP_L_ARM = list("path" = /obj/item/organ/external/arm), + BP_R_ARM = list("path" = /obj/item/organ/external/arm/right), + BP_L_LEG = list("path" = /obj/item/organ/external/leg), + BP_R_LEG = list("path" = /obj/item/organ/external/leg/right), BP_L_HAND = list("path" = /obj/item/organ/external/hand), BP_R_HAND = list("path" = /obj/item/organ/external/hand/right), BP_L_FOOT = list("path" = /obj/item/organ/external/foot), @@ -202,12 +205,12 @@ ) var/list/genders = list(MALE, FEMALE) - var/ambiguous_genders = FALSE // If true, people examining a member of this species whom are not also the same species will see them as gender neutral. Because aliens. + var/ambiguous_genders = FALSE // If true, people examining a member of this species whom are not also the same species will see them as gender neutral. Because aliens. // Bump vars - var/bump_flag = HUMAN // What are we considered to be when bumped? - var/push_flags = ~HEAVY // What can we push? - var/swap_flags = ~HEAVY // What can we swap place with? + var/bump_flag = HUMAN // What are we considered to be when bumped? + var/push_flags = ~HEAVY // What can we push? + var/swap_flags = ~HEAVY // What can we swap place with? var/pass_flags = 0 @@ -283,9 +286,9 @@ if((organ in H.organs) || (organ in H.internal_organs)) qdel(organ) - if(H.organs) H.organs.Cut() - if(H.internal_organs) H.internal_organs.Cut() - if(H.organs_by_name) H.organs_by_name.Cut() + if(H.organs) H.organs.Cut() + if(H.internal_organs) H.internal_organs.Cut() + if(H.organs_by_name) H.organs_by_name.Cut() if(H.internal_organs_by_name) H.internal_organs_by_name.Cut() H.organs = list() diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index b2d839f762..740d72987f 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -35,11 +35,14 @@ var/datum/species/shapeshifter/promethean/prometheans male_cough_sounds = list('sound/effects/slime_squish.ogg') female_cough_sounds = list('sound/effects/slime_squish.ogg') + min_age = 1 + max_age = 10 + + economic_modifier = 3 + //gluttonous = 1 // VOREStation Edit. Redundant feature. virus_immune = 1 blood_volume = 560 - min_age = 1 - max_age = 10 brute_mod = 0.75 burn_mod = 2 oxy_mod = 0 diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index f2adbcee31..fe21426805 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -10,8 +10,12 @@ secondary_langs = list(LANGUAGE_SCHECHI, LANGUAGE_SKRELLIAN) name_language = LANGUAGE_SCHECHI species_language = LANGUAGE_SCHECHI + min_age = 12 max_age = 45 + + economic_modifier = 6 + health_hud_intensity = 3 male_cough_sounds = list('sound/effects/mob_effects/tesharicougha.ogg','sound/effects/mob_effects/tesharicoughb.ogg') diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 500829d6fc..f941d65de8 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -12,8 +12,12 @@ species_language = LANGUAGE_SOL_COMMON secondary_langs = list(LANGUAGE_SOL_COMMON, LANGUAGE_TERMINUS) name_language = null // Use the first-name last-name generator rather than a language scrambler + min_age = 17 max_age = 130 + + economic_modifier = 10 + health_hud_intensity = 1.5 spawn_flags = SPECIES_CAN_JOIN @@ -52,6 +56,8 @@ min_age = 32 max_age = 260 + economic_modifier = 7 + blurb = "A heavily reptillian species, Unathi hail from the \ Uuosa-Eso system, which roughly translates to 'burning mother'.

Coming from a harsh, inhospitable \ planet, they mostly hold ideals of honesty, virtue, proficiency and bravery above all \ @@ -155,6 +161,8 @@ min_age = 17 max_age = 80 + economic_modifier = 7 + blurb = "The Tajaran are a mammalian species resembling roughly felines, hailing from Meralar in the Rarkajar system. \ While reaching to the stars independently from outside influences, the humans engaged them in peaceful trade contact \ and have accelerated the fledgling culture into the interstellar age. Their history is full of war and highly fractious \ @@ -239,6 +247,8 @@ min_age = 19 max_age = 130 + economic_modifier = 12 + darksight = 4 flash_mod = 1.2 chemOD_mod = 0.9 @@ -314,6 +324,8 @@ min_age = 1 max_age = 300 + economic_modifier = 4 + blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \ species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \ there is no effective upper limit to the number that can fuse in gestalt, and reports exist of the Epsilon Ursae \ diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e4eaa51963..8c0bb87d61 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -567,7 +567,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() return //Wearing a suit that prevents uniform rendering //Build a uniform sprite - overlays_standing[UNIFORM_LAYER] = w_uniform.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_w_uniform_str, default_icon = INV_W_UNIFORM_DEF_ICON, default_layer = UNIFORM_LAYER) + overlays_standing[UNIFORM_LAYER] = w_uniform.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_w_uniform_str, default_icon = INV_W_UNIFORM_DEF_ICON, default_layer = UNIFORM_LAYER) apply_layer(UNIFORM_LAYER) /mob/living/carbon/human/update_inv_wear_id() @@ -583,7 +583,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(w_uniform && istype(w_uniform, /obj/item/clothing/under)) var/obj/item/clothing/under/U = w_uniform if(U.displays_id) - overlays_standing[ID_LAYER] = wear_id.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_wear_id_str, default_icon = INV_WEAR_ID_DEF_ICON, default_layer = ID_LAYER) + overlays_standing[ID_LAYER] = wear_id.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_id_str, default_icon = INV_WEAR_ID_DEF_ICON, default_layer = ID_LAYER) apply_layer(ID_LAYER) @@ -596,7 +596,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!gloves) return //No gloves, no reason to be here. - overlays_standing[GLOVES_LAYER] = gloves.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_gloves_str, default_icon = INV_GLOVES_DEF_ICON, default_layer = GLOVES_LAYER) + overlays_standing[GLOVES_LAYER] = gloves.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_GLOVES_DEF_ICON, default_layer = GLOVES_LAYER) apply_layer(GLOVES_LAYER) @@ -609,7 +609,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!glasses) return //Not wearing glasses, no need to update anything. - overlays_standing[GLASSES_LAYER] = glasses.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_gloves_str, default_icon = INV_EYES_DEF_ICON, default_layer = GLASSES_LAYER) + overlays_standing[GLASSES_LAYER] = glasses.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_EYES_DEF_ICON, default_layer = GLASSES_LAYER) apply_layer(GLASSES_LAYER) @@ -629,11 +629,11 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/image/both = image(icon = 'icons/effects/effects.dmi', icon_state = "nothing", layer = BODY_LAYER+EARS_LAYER) if(l_ear) - var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) both.add_overlay(standing) if(r_ear) - var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) both.add_overlay(standing) overlays_standing[EARS_LAYER] = both @@ -657,7 +657,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() shoe_layer = SHOES_LAYER_ALT //NB: the use of a var for the layer on this one - overlays_standing[shoe_layer] = shoes.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_shoes_str, default_icon = INV_FEET_DEF_ICON, default_layer = shoe_layer) + overlays_standing[shoe_layer] = shoes.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_shoes_str, default_icon = INV_FEET_DEF_ICON, default_layer = shoe_layer) apply_layer(SHOES_LAYER) apply_layer(SHOES_LAYER_ALT) @@ -689,7 +689,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!head) return //No head item, why bother. - overlays_standing[HEAD_LAYER] = head.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_head_str, default_icon = INV_HEAD_DEF_ICON, default_layer = HEAD_LAYER) + overlays_standing[HEAD_LAYER] = head.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_head_str, default_icon = INV_HEAD_DEF_ICON, default_layer = HEAD_LAYER) apply_layer(HEAD_LAYER) @@ -711,7 +711,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() belt_layer = BELT_LAYER_ALT //NB: this uses a var from above - overlays_standing[belt_layer] = belt.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_belt_str, default_icon = INV_BELT_DEF_ICON, default_layer = belt_layer) + overlays_standing[belt_layer] = belt.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_belt_str, default_icon = INV_BELT_DEF_ICON, default_layer = belt_layer) apply_layer(belt_layer) @@ -730,7 +730,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!wear_suit) return //No point, no suit. - overlays_standing[SUIT_LAYER] = wear_suit.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_wear_suit_str, default_icon = INV_SUIT_DEF_ICON, default_layer = SUIT_LAYER) + overlays_standing[SUIT_LAYER] = wear_suit.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_suit_str, default_icon = INV_SUIT_DEF_ICON, default_layer = SUIT_LAYER) apply_layer(SUIT_LAYER) @@ -746,7 +746,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!wear_mask || (head && head.flags_inv & HIDEMASK)) return //Why bother, nothing in mask slot. - overlays_standing[FACEMASK_LAYER] = wear_mask.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_wear_mask_str, default_icon = INV_MASK_DEF_ICON, default_layer = FACEMASK_LAYER) + overlays_standing[FACEMASK_LAYER] = wear_mask.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_mask_str, default_icon = INV_MASK_DEF_ICON, default_layer = FACEMASK_LAYER) apply_layer(FACEMASK_LAYER) @@ -759,7 +759,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!back) return //Why do anything - overlays_standing[BACK_LAYER] = back.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_back_str, default_icon = INV_BACK_DEF_ICON, default_layer = BACK_LAYER) + overlays_standing[BACK_LAYER] = back.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_back_str, default_icon = INV_BACK_DEF_ICON, default_layer = BACK_LAYER) apply_layer(BACK_LAYER) @@ -792,7 +792,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!handcuffed) return //Not cuffed, why bother - overlays_standing[HANDCUFF_LAYER] = handcuffed.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_handcuffed_str, default_icon = INV_HCUFF_DEF_ICON, default_layer = HANDCUFF_LAYER) + overlays_standing[HANDCUFF_LAYER] = handcuffed.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_handcuffed_str, default_icon = INV_HCUFF_DEF_ICON, default_layer = HANDCUFF_LAYER) apply_layer(HANDCUFF_LAYER) @@ -805,7 +805,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!legcuffed) return //Not legcuffed, why bother. - overlays_standing[LEGCUFF_LAYER] = legcuffed.make_worn_icon(body_type = species.get_bodytype(), slot_name = slot_legcuffed_str, default_icon = INV_LCUFF_DEF_ICON, default_layer = LEGCUFF_LAYER) + overlays_standing[LEGCUFF_LAYER] = legcuffed.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_legcuffed_str, default_icon = INV_LCUFF_DEF_ICON, default_layer = LEGCUFF_LAYER) apply_layer(LEGCUFF_LAYER) @@ -818,7 +818,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!r_hand) return //No hand, no bother. - overlays_standing[R_HAND_LAYER] = r_hand.make_worn_icon(body_type = species.get_bodytype(), inhands = TRUE, slot_name = slot_r_hand_str, default_icon = INV_R_HAND_DEF_ICON, default_layer = R_HAND_LAYER) + overlays_standing[R_HAND_LAYER] = r_hand.make_worn_icon(body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_r_hand_str, default_icon = INV_R_HAND_DEF_ICON, default_layer = R_HAND_LAYER) apply_layer(R_HAND_LAYER) @@ -831,7 +831,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!l_hand) return //No hand, no bother. - overlays_standing[L_HAND_LAYER] = l_hand.make_worn_icon(body_type = species.get_bodytype(), inhands = TRUE, slot_name = slot_l_hand_str, default_icon = INV_L_HAND_DEF_ICON, default_layer = L_HAND_LAYER) + overlays_standing[L_HAND_LAYER] = l_hand.make_worn_icon(body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_l_hand_str, default_icon = INV_L_HAND_DEF_ICON, default_layer = L_HAND_LAYER) apply_layer(L_HAND_LAYER) diff --git a/code/modules/mob/living/simple_animal/aliens/mimic.dm b/code/modules/mob/living/simple_animal/aliens/mimic.dm index 8230256086..c13e1721ce 100644 --- a/code/modules/mob/living/simple_animal/aliens/mimic.dm +++ b/code/modules/mob/living/simple_animal/aliens/mimic.dm @@ -48,6 +48,12 @@ ..() qdel(src) +/mob/living/simple_animal/hostile/mimic/MouseEntered(location, control, params) + ..() + closeToolTip(usr) + // ideally, we'd remove the code in ..() that opens the tooltip, + // but then we'd need to duplicate all the other code in ..() + // // Crate Mimic // @@ -194,4 +200,4 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca if(istype(L)) if(prob(15)) L.Weaken(1) - L.visible_message("\the [src] knocks down \the [L]!") \ No newline at end of file + L.visible_message("\the [src] knocks down \the [L]!") diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 4580643574..74cb11b970 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -756,6 +756,7 @@ /mob/living/simple_animal/death(gibbed, deathmessage = "dies!") density = 0 //We don't block even if we did before walk(src, 0) //We stop any background-processing walks + resting = 0 //We can rest in peace later. if(faction_friends.len) faction_friends -= src diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index b10decab9a..9d16617a67 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -1206,6 +1206,8 @@ Note that amputating the affected organ does in fact remove the infection from t victim.organs -= src victim.organs_by_name[organ_tag] = null // Remove from owner's vars. + status |= ORGAN_CUT_AWAY //Checked during surgeries to reattach it + //Robotic limbs explode if sabotaged. if(is_robotic && sabotaged) victim.visible_message( diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm index 97c7847fde..061ae73398 100644 --- a/code/modules/planet/planet.dm +++ b/code/modules/planet/planet.dm @@ -12,7 +12,8 @@ var/datum/weather_holder/weather_holder var/sun_position = 0 // 0 means midnight, 1 means noon. - var/list/sun = list("range","brightness","color") + var/list/sun = list("range","brightness","color","lum_r","lum_g","lum_b") + var/list/datum/lighting_corner/sunlit_corners = list() var/expected_z_levels = list() var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index df1f24eec2..391b83fe0c 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -84,7 +84,7 @@ /datum/surgery_step/limb/connect/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/E = target.get_organ(target_zone) - return E && !E.is_stump() && (E.status & ORGAN_DESTROYED) + return E && !E.is_stump() && (E.status & ORGAN_CUT_AWAY) /datum/surgery_step/limb/connect/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/E = target.get_organ(target_zone) @@ -95,11 +95,8 @@ var/obj/item/organ/external/E = target.get_organ(target_zone) user.visible_message("[user] has connected tendons and muscles in [target]'s [E.amputation_point] with [tool].", \ "You have connected tendons and muscles in [target]'s [E.amputation_point] with [tool].") - E.status &= ~ORGAN_DESTROYED - if(E.children) - for(var/obj/item/organ/external/C in E.children) - C.status &= ~ORGAN_DESTROYED - target.update_icons_body(FALSE) + E.status &= ~ORGAN_CUT_AWAY + target.update_icons_body() target.updatehealth() target.UpdateDamageIcon() diff --git a/html/changelog.html b/html/changelog.html index e81411a62c..6f16ef8461 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,27 @@ -->
+

19 April 2018

+

Anewbe updated:

+ +

Woodrat updated:

+ +

lorwp updated:

+ +

01 April 2018

Anewbe updated: