diff --git a/.travis.yml b/.travis.yml index 432d4093149..2ccfc698015 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ language: c sudo: false env: - BYOND_MAJOR="510" - BYOND_MINOR="1346" - MACRO_COUNT=986 + BYOND_MAJOR="511" + BYOND_MINOR="1381" + MACRO_COUNT=875 cache: directories: diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index 92dd6f5d517..4a4c29dcfbc 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -132,7 +132,7 @@ obj/var/phoronproof = 0 eye_blurry = min(eye_blurry+1.5,50) if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) src << "You are blinded!" - eye_blind += 20 + Blind(20) /mob/living/carbon/human/proc/pl_head_protected() //Checks if the head is adequately sealed. diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index 8115790c506..cd0c9955c13 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -123,4 +123,6 @@ var/list/be_special_flags = list( //casting costs #define Sp_RECHARGE "recharge" #define Sp_CHARGES "charges" -#define Sp_HOLDVAR "holdervar" \ No newline at end of file +#define Sp_HOLDVAR "holdervar" + +#define CHANGELING_STASIS_COST 20 \ No newline at end of file diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index eb572aa0e29..0a8598d21f1 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -33,7 +33,7 @@ #define PROXMOVE 0x80 // Does this object require proximity checking in Enter()? //Flags for items (equipment) -#define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equiped to slot_suit or slot_head. +#define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head. #define STOPPRESSUREDAMAGE 0x2 // Counts towards pressure protection. Note that like temperature protection, body_parts_covered is considered here as well. #define AIRTIGHT 0x4 // Functions with internals. #define NOSLIP 0x8 // Prevents from slipping on wet floors, in space, etc. diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 09f5e81ca00..f85ac5e7d4a 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -69,6 +69,11 @@ #define COLOR_PALE_RED_GRAY "#CC9090" #define COLOR_PALE_PURPLE_GRAY "#BDA2BA" #define COLOR_PURPLE_GRAY "#A2819E" +#define COLOR_RED_LIGHT "#FF3333" +#define COLOR_DEEP_SKY_BLUE "#00e1ff" + + + // Shuttles. diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 1dc64363558..ef00eed3341 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -148,6 +148,12 @@ #define INCAPACITATION_DISABLED (INCAPACITATION_KNOCKDOWN|INCAPACITATION_STUNNED) #define INCAPACITATION_ALL (~INCAPACITATION_NONE) +#define MODIFIER_STACK_FORBID 1 // Disallows stacking entirely. +#define MODIFIER_STACK_EXTEND 2 // Disallows a second instance, but will extend the first instance if possible. +#define MODIFIER_STACK_ALLOWED 3 // Multiple instances are allowed. + +#define MODIFIER_GENETIC 0 // Modifiers with this flag will be copied to mobs who get cloned. + // Bodyparts and organs. #define O_MOUTH "mouth" #define O_EYES "eyes" @@ -200,4 +206,10 @@ #define TASTE_SENSITIVE 2 //anything below 7% #define TASTE_NORMAL 1 //anything below 15% #define TASTE_DULL 0.5 //anything below 30% -#define TASTE_NUMB 0.1 //anything below 150% \ No newline at end of file +#define TASTE_NUMB 0.1 //anything below 150% + +// If they're in an FBP, what braintype. +#define FBP_NONE "" +#define FBP_CYBORG "Cyborg" +#define FBP_POSI "Positronic" +#define FBP_DRONE "Drone" \ No newline at end of file diff --git a/code/__defines/planets.dm b/code/__defines/planets.dm new file mode 100644 index 00000000000..e8f526382e5 --- /dev/null +++ b/code/__defines/planets.dm @@ -0,0 +1,15 @@ +#define WEATHER_CLEAR "clear" +#define WEATHER_OVERCAST "overcast" +#define WEATHER_LIGHT_SNOW "light snow" +#define WEATHER_SNOW "snow" +#define WEATHER_BLIZZARD "blizzard" +#define WEATHER_RAIN "rain" +#define WEATHER_STORM "storm" +#define WEATHER_HAIL "hail" +#define WEATHER_WINDY "windy" +#define WEATHER_HOT "hot" +#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on. + +#define PLANET_PROCESS_WEATHER 0x1 +#define PLANET_PROCESS_SUN 0x2 +#define PLANET_PROCESS_TEMP 0x4 \ No newline at end of file diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 1531a67d5b4..b59857c8f6b 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -284,7 +284,7 @@ if(M.loc && M.locs[1] in hearturfs) mobs |= M - else if(M.stat == DEAD) + else if(M.stat == DEAD && !M.forbid_seeing_deadchat) switch(type) if(1) //Audio messages use ghost_ears if(M.is_preference_enabled(/datum/client_preference/ghost_ears)) diff --git a/code/_macros.dm b/code/_macros.dm index 1038b6a2e46..463a7da26d9 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -42,6 +42,8 @@ #define isxeno(A) istype(A, /mob/living/simple_animal/xeno) +#define isopenspace(A) istype(A, /turf/simulated/open) + #define isweakref(A) istype(A, /weakref) #define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index 71eff4a3920..3602a524811 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -45,49 +45,61 @@ screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" /obj/screen/movable/proc/encode_screen_X(X) - if(X > usr.client.view+1) - . = "EAST-[usr.client.view*2 + 1-X]" - else if(X < usr.client.view+1) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist + if(X > view_dist+1) + . = "EAST-[view_dist *2 + 1-X]" + else if(X < view_dist +1) . = "WEST+[X-1]" else . = "CENTER" /obj/screen/movable/proc/decode_screen_X(X) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist //Find EAST/WEST implementations if(findtext(X,"EAST-")) var/num = text2num(copytext(X,6)) //Trim EAST- if(!num) num = 0 - . = usr.client.view*2 + 1 - num + . = view_dist*2 + 1 - num else if(findtext(X,"WEST+")) var/num = text2num(copytext(X,6)) //Trim WEST+ if(!num) num = 0 . = num+1 else if(findtext(X,"CENTER")) - . = usr.client.view+1 + . = view_dist+1 /obj/screen/movable/proc/encode_screen_Y(Y) - if(Y > usr.client.view+1) - . = "NORTH-[usr.client.view*2 + 1-Y]" - else if(Y < usr.client.view+1) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist + if(Y > view_dist+1) + . = "NORTH-[view_dist*2 + 1-Y]" + else if(Y < view_dist+1) . = "SOUTH+[Y-1]" else . = "CENTER" /obj/screen/movable/proc/decode_screen_Y(Y) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist if(findtext(Y,"NORTH-")) var/num = text2num(copytext(Y,7)) //Trim NORTH- if(!num) num = 0 - . = usr.client.view*2 + 1 - num + . = view_dist*2 + 1 - num else if(findtext(Y,"SOUTH+")) var/num = text2num(copytext(Y,7)) //Time SOUTH+ if(!num) num = 0 . = num+1 else if(findtext(Y,"CENTER")) - . = usr.client.view+1 + . = view_dist+1 //Debug procs /client/proc/test_movable_UI() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 88e69696bfe..b41dd9c57b6 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -84,6 +84,9 @@ avoid code duplication. This includes items that may sometimes act as a standard playsound(loc, hitsound, 50, 1, -1) var/power = force + for(var/datum/modifier/M in user.modifiers) + if(!isnull(M.outgoing_melee_damage_percent)) + power *= M.outgoing_melee_damage_percent if(HULK in user.mutations) power *= 2 return target.hit_with_weapon(src, user, power, hit_zone) diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm index b3b556d7bd1..7b446b4d2d5 100644 --- a/code/controllers/Processes/planet.dm +++ b/code/controllers/Processes/planet.dm @@ -2,16 +2,77 @@ var/datum/controller/process/planet/planet_controller = null /datum/controller/process/planet var/list/planets = list() + var/list/z_to_planet = list() /datum/controller/process/planet/setup() - name = "planet" + name = "planet controller" planet_controller = src - schedule_interval = 600 // every minute + schedule_interval = 1 MINUTE + var/list/planet_datums = typesof(/datum/planet) - /datum/planet for(var/P in planet_datums) var/datum/planet/NP = new P() planets.Add(NP) + allocateTurfs() + +/datum/controller/process/planet/proc/allocateTurfs() + for(var/turf/simulated/OT in outdoor_turfs) + for(var/datum/planet/P in planets) + if(OT.z in P.expected_z_levels) + P.planet_floors += OT + break + outdoor_turfs.Cut() //Why were you in there INCORRECTLY? + + for(var/turf/unsimulated/wall/planetary/PW in planetary_walls) + for(var/datum/planet/P in planets) + if(PW.type == P.planetary_wall_type) + P.planet_walls += PW + break + planetary_walls.Cut() + +/datum/controller/process/planet/proc/unallocateTurf(var/turf/T) + for(var/planet in planets) + var/datum/planet/P = planet + if(T.z in P.expected_z_levels) + P.planet_floors -= T + /datum/controller/process/planet/doWork() + if(outdoor_turfs.len || planetary_walls.len) + allocateTurfs() + for(var/datum/planet/P in planets) - P.process(schedule_interval / 10) \ No newline at end of file + P.process(schedule_interval / 10) + SCHECK //Your process() really shouldn't take this long... + //Weather style needs redrawing + if(P.needs_work & PLANET_PROCESS_WEATHER) + P.needs_work &= ~PLANET_PROCESS_WEATHER + var/image/new_overlay = image(icon = P.weather_holder.current_weather.icon, icon_state = P.weather_holder.current_weather.icon_state, layer = LIGHTING_LAYER - 1) + //Redraw weather icons + for(var/T in P.planet_floors) + var/turf/simulated/turf = T + turf.overlays -= turf.weather_overlay + turf.weather_overlay = new_overlay + turf.overlays += turf.weather_overlay + SCHECK + + //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"] + 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) + SCHECK + + //Temperature needs updating + if(P.needs_work & PLANET_PROCESS_TEMP) + P.needs_work &= ~PLANET_PROCESS_TEMP + //Set new temperatures + for(var/W in P.planet_walls) + var/turf/unsimulated/wall/planetary/wall = W + wall.set_temperature(P.weather_holder.temperature) + SCHECK diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 6039dd66123..57f22472551 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -156,6 +156,8 @@ var/list/gamemode_cache = list() var/slime_delay = 0 var/animal_delay = 0 + var/footstep_volume = 0 + var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database @@ -768,6 +770,8 @@ var/list/gamemode_cache = list() if("animal_delay") config.animal_delay = value + if("footstep_volume") + config.footstep_volume = text2num(value) if("use_loyalty_implants") config.use_loyalty_implants = 1 diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index ee361c9888f..f0d3cc3341c 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -25,7 +25,7 @@ usr.client.debug_variables(antag) message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.") -/client/proc/debug_controller(controller in list("Master","Ticker","Ticker Process","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano","Chemistry","Vote","Xenobio")) +/client/proc/debug_controller(controller in list("Master","Ticker","Ticker Process","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano","Chemistry","Vote","Xenobio","Planets")) set category = "Debug" set name = "Debug Controller" set desc = "Debug the various periodic loop controllers for the game (be careful!)" @@ -98,5 +98,8 @@ if("Xenobio") debug_variables(xenobio_controller) feedback_add_details("admin_verb", "DXenobio") + if("Planets") + debug_variables(planet_controller) + feedback_add_details("admin_verb", "DPlanets") message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index d40fd4fa5a3..274c0c0903d 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -184,6 +184,10 @@ G.fields["real_rank"] = H.mind.assigned_role G.fields["rank"] = assignment G.fields["age"] = H.age + if(H.get_FBP_type()) + G.fields["brain_type"] = H.get_FBP_type() + else + G.fields["brain_type"] = "Organic" G.fields["fingerprint"] = md5(H.dna.uni_identity) G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" @@ -201,11 +205,19 @@ M.fields["b_type"] = H.b_type M.fields["b_dna"] = H.dna.unique_enzymes M.fields["id_gender"] = gender2text(H.identifying_gender) + if(H.get_FBP_type()) + M.fields["brain_type"] = H.get_FBP_type() + else + M.fields["brain_type"] = "Organic" if(H.med_record && !jobban_isbanned(H, "Records")) M.fields["notes"] = H.med_record //Security Record var/datum/data/record/S = CreateSecurityRecord(H.real_name, id) + if(H.get_FBP_type()) + S.fields["brain_type"] = H.get_FBP_type() + else + S.fields["brain_type"] = "Organic" if(H.sec_record && !jobban_isbanned(H, "Records")) S.fields["notes"] = H.sec_record @@ -218,6 +230,10 @@ L.fields["fingerprint"] = md5(H.dna.uni_identity) L.fields["sex"] = gender2text(H.gender) L.fields["id_gender"] = gender2text(H.identifying_gender) + if(H.get_FBP_type()) + L.fields["brain_type"] = H.get_FBP_type() + else + L.fields["brain_type"] = "Organic" L.fields["b_type"] = H.b_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.SE // Used in respawning @@ -426,6 +442,7 @@ G.fields["real_rank"] = "Unassigned" G.fields["sex"] = "Unknown" G.fields["age"] = "Unknown" + G.fields["brain_type"] = "Unknown" G.fields["fingerprint"] = "Unknown" G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" @@ -447,6 +464,7 @@ R.name = "Security Record #[id]" R.fields["name"] = name R.fields["id"] = id + R.fields["brain_type"] = "Unknown" R.fields["criminal"] = "None" R.fields["mi_crim"] = "None" R.fields["mi_crim_d"] = "No minor crime convictions." @@ -467,6 +485,7 @@ M.fields["b_type"] = "AB+" M.fields["b_dna"] = md5(name) M.fields["id_gender"] = "Unknown" + M.fields["brain_type"] = "Unknown" M.fields["mi_dis"] = "None" M.fields["mi_dis_d"] = "No minor disabilities have been declared." M.fields["ma_dis"] = "None" diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm index d6427f063f2..0c7fd3f4eda 100644 --- a/code/datums/supplypacks/contraband.dm +++ b/code/datums/supplypacks/contraband.dm @@ -32,6 +32,17 @@ containername = "Special Ops crate" contraband = 1 +/datum/supply_packs/supply/moghes + name = "Moghes imports" + contains = list( + /obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew = 2, + /obj/item/weapon/reagent_containers/food/snacks/unajerky = 4 + ) + cost = 25 + containertype = /obj/structure/closet/crate + containername = "Moghes imports crate" + contraband = 1 + /datum/supply_packs/security/bolt_rifles_mosin name = "Surplus militia rifles" contains = list( diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm index 41a1779322b..34b20a9f48d 100644 --- a/code/datums/uplink/visible_weapons.dm +++ b/code/datums/uplink/visible_weapons.dm @@ -100,6 +100,11 @@ item_cost = 40 path = /obj/item/weapon/gun/energy/ionrifle +/datum/uplink_item/item/visible_weapons/ionpistol + name = "Ion Pistol" + item_cost = 25 + path = /obj/item/weapon/gun/energy/ionrifle/pistol + /datum/uplink_item/item/visible_weapons/xray name = "Xray Gun" item_cost = 85 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index b511c9befd2..fe9f99b0328 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -115,12 +115,7 @@ else if(isturf(hit_atom)) src.throwing = 0 var/turf/T = hit_atom - if(T.density) - spawn(2) - step(src, turn(src.last_move, 180)) - if(istype(src,/mob/living)) - var/mob/living/M = src - M.turf_collision(T, speed) + T.hitby(src,speed) //decided whether a movable atom being thrown can pass through the turf it is in. /atom/movable/proc/hit_check(var/speed) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index e06f774a834..a28dd27036e 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -210,7 +210,6 @@ /obj/machinery/computer/scan_consolenew name = "DNA Modifier Access Console" desc = "Scan DNA." - icon = 'icons/obj/computer.dmi' icon_keyboard = "med_key" icon_screen = "dna" density = 1 diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index a60faeb8308..e54eb3c1cd0 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -13,12 +13,15 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/isabsorbing = 0 var/geneticpoints = 5 var/max_geneticpoints = 5 + var/readapts = 1 + var/max_readapts = 2 var/list/purchased_powers = list() var/mimicing = "" var/cloaked = 0 var/armor_deployed = 0 //This is only used for changeling_generic_equip_all_slots() at the moment. var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name. var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too. + var/last_shriek = null // world.time when the ling last used a shriek. /datum/changeling/New(var/gender=FEMALE) ..() @@ -60,6 +63,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E if(!mind.changeling) mind.changeling = new /datum/changeling(gender) verbs += /datum/changeling/proc/EvolutionMenu + verbs += /mob/proc/changeling_respec add_language("Changeling") var/lesser_form = !ishuman(src) @@ -153,6 +157,46 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E //STINGS// //They get a pretty header because there's just so fucking many of them ;_; ////////// +turf/proc/AdjacentTurfsRangedSting() + //Yes this is snowflakey, but I couldn't get it to work any other way.. -Luke + var/list/allowed = list( + /obj/structure/table, + /obj/structure/closet, + /obj/structure/frame, + /obj/structure/target_stake, + /obj/structure/cable, + /obj/structure/disposalpipe, + /obj/machinery/ + ) + + var/L[] = new() + for(var/turf/simulated/t in oview(src,1)) + var/add = 1 + if(t.density) + add = 0 + if(add && LinkBlocked(src,t)) + add = 0 + if(add && TurfBlockedNonWindow(t)) + add = 0 + for(var/obj/O in t) + if(!O.density) + add = 1 + break + if(istype(O, /obj/machinery/door)) + //not sure why this doesn't fire on LinkBlocked() + add = 0 + break + for(var/type in allowed) + if (istype(O, type)) + add = 1 + break + if(!add) + break + if(add) + L.Add(t) + return L + + /mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) if(M.loc == src.loc) return 1 //target and source are in the same thing @@ -160,7 +204,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E src << "We cannot reach \the [M] with a sting!" return 0 //One is inside, the other is outside something. // Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising - if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail + if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail src << "We cannot find a path to sting \the [M] by!" return 0 return 1 diff --git a/code/game/gamemodes/changeling/generic_equip_procs.dm b/code/game/gamemodes/changeling/generic_equip_procs.dm index e8ed12a446b..9c73a4e3d22 100644 --- a/code/game/gamemodes/changeling/generic_equip_procs.dm +++ b/code/game/gamemodes/changeling/generic_equip_procs.dm @@ -32,7 +32,7 @@ return 1 if(M.head || M.wear_suit) //Make sure our slots aren't full - src << "We require nothing to be on our head, and we cannot wear any external suits." + src << "We require nothing to be on our head, and we cannot wear any external suits, or shoes." return 0 var/obj/item/clothing/suit/A = new armor_type(src) @@ -140,7 +140,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["w_uniform"] if(!M.w_uniform && t) @@ -150,7 +150,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["gloves"] if(!M.gloves && t) @@ -160,7 +160,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["shoes"] if(!M.shoes && t) @@ -170,7 +170,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["belt"] if(!M.belt && t) @@ -180,7 +180,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["glasses"] if(!M.glasses && t) @@ -190,7 +190,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_mask"] if(!M.wear_mask && t) @@ -200,7 +200,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["back"] if(!M.back && t) @@ -210,7 +210,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_suit"] if(!M.wear_suit && t) @@ -220,7 +220,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_id"] if(!M.wear_id && t) @@ -230,7 +230,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 10cb5f9fbbe..396e6faf347 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -72,7 +72,12 @@ if(src.nutrition < 400) src.nutrition = min((src.nutrition + T.nutrition), 400) changeling.chem_charges += 10 - src.verbs += /mob/proc/changeling_respec + if(changeling.readapts <= 0) + changeling.readapts = 0 //SANITYYYYYY + changeling.readapts++ + if(changeling.readapts > changeling.max_readapts) + changeling.readapts = changeling.max_readapts + src << "We can now re-adapt, reverting our evolution so that we may start anew, if needed." var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts) diff --git a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm index 3068f1eee56..c173ba55acc 100644 --- a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm +++ b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm @@ -24,7 +24,7 @@ if(held_item == null) if(src.mind.changeling.recursive_enhancement) - if(changeling_generic_weapon(/obj/item/weapon/electric_hand/efficent)) + if(changeling_generic_weapon(/obj/item/weapon/electric_hand/efficent,0)) src << "We will shock others more efficently." return 1 else diff --git a/code/game/gamemodes/changeling/powers/blind_sting.dm b/code/game/gamemodes/changeling/powers/blind_sting.dm index e098c98f034..41b14478b3d 100644 --- a/code/game/gamemodes/changeling/powers/blind_sting.dm +++ b/code/game/gamemodes/changeling/powers/blind_sting.dm @@ -26,7 +26,7 @@ src << "They will be deprived of sight for longer." spawn(duration) T.disabilities &= ~NEARSIGHTED - T.eye_blind = 10 + T.Blind(10) T.eye_blurry = 20 feedback_add_details("changeling_powers","BS") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/boost_range.dm b/code/game/gamemodes/changeling/powers/boost_range.dm index fd15d94daec..a22130484ca 100644 --- a/code/game/gamemodes/changeling/powers/boost_range.dm +++ b/code/game/gamemodes/changeling/powers/boost_range.dm @@ -18,11 +18,11 @@ if(!changeling) return 0 changeling.chem_charges -= 10 - src << "Your throat adjusts to launch the sting." + to_chat(src, "Your throat adjusts to launch the sting.") var/range = 2 if(src.mind.changeling.recursive_enhancement) range = range + 3 - src << "We can fire our next sting from five squares away." + to_chat(src, "We can fire our next sting from five squares away.") changeling.sting_range = range src.verbs -= /mob/proc/changeling_boost_range spawn(5) diff --git a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm index fd72524e5a2..a9b323465c3 100644 --- a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm +++ b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm @@ -2,12 +2,24 @@ name = "Delayed Toxic Sting" desc = "We silently sting a biological, causing a significant amount of toxins after a few minutes, allowing us to not \ implicate ourselves." - helptext = "The toxin takes effect in about two minutes. The sting has a three minute cooldown between uses." + helptext = "The toxin takes effect in about two minutes. Multiple applications within the two minutes will not cause increased toxicity." enhancedtext = "The toxic damage is doubled." ability_icon_state = "ling_sting_del_toxin" genomecost = 1 verbpath = /mob/proc/changeling_delayed_toxic_sting +/datum/modifier/delayed_toxin_sting + name = "delayed toxin injection" + hidden = TRUE + stacks = MODIFIER_STACK_FORBID + on_expired_text = "You feel a burning sensation flowing through your veins!" + +/datum/modifier/delayed_toxin_sting/on_expire() + holder.adjustToxLoss(rand(20, 30)) + +/datum/modifier/delayed_toxin_sting/strong/on_expire() + holder.adjustToxLoss(rand(40, 60)) + /mob/proc/changeling_delayed_toxic_sting() set category = "Changeling" set name = "Delayed Toxic Sting (20)" @@ -19,21 +31,13 @@ T.attack_log += text("\[[time_stamp()]\] Was delayed toxic stung by [key_name(src)]") src.attack_log += text("\[[time_stamp()]\] Used delayed toxic sting on [key_name(T)]") msg_admin_attack("[key_name(T)] was delayed toxic stung by [key_name(src)]") - var/i = rand(20,30) + + var/type_to_give = /datum/modifier/delayed_toxin_sting if(src.mind.changeling.recursive_enhancement) - i = i * 2 + type_to_give = /datum/modifier/delayed_toxin_sting/strong src << "Our toxin will be extra potent, when it strikes." - spawn(2 MINUTES) - if(T) //We might not exist in two minutes, for whatever reason. - T << "You feel a burning sensation flowing through your veins!" - while(i) - T.adjustToxLoss(1) - i-- - sleep(2 SECONDS) - src.verbs -= /mob/proc/changeling_delayed_toxic_sting - spawn(3 MINUTES) - src << "We are ready to use our delayed toxic string once more." - src.verbs |= /mob/proc/changeling_delayed_toxic_sting + + T.add_modifier(type_to_give, 2 MINUTES) feedback_add_details("changeling_powers","DTS") diff --git a/code/game/gamemodes/changeling/powers/endoarmor.dm b/code/game/gamemodes/changeling/powers/endoarmor.dm index 4052568a50e..536aef26ce3 100644 --- a/code/game/gamemodes/changeling/powers/endoarmor.dm +++ b/code/game/gamemodes/changeling/powers/endoarmor.dm @@ -6,9 +6,18 @@ isVerb = 0 verbpath = /mob/proc/changeling_endoarmor +/datum/modifier/endoarmor + name = "endoarmor" + desc = "We have hard plating underneath our skin, making us more durable." + + on_created_text = "We feel protective plating form underneath our skin." + on_expired_text = "Our protective armor underneath our skin fades as we absorb it." + max_health_flat = 50 + //Increases macimum chemical storage /mob/proc/changeling_endoarmor() if(ishuman(src)) var/mob/living/carbon/human/H = src - H.maxHealth += 50 + H.add_modifier(/datum/modifier/endoarmor) + // H.maxHealth += 50 return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/enfeebling_string.dm b/code/game/gamemodes/changeling/powers/enfeebling_string.dm index 5370a682009..b7a6c569572 100644 --- a/code/game/gamemodes/changeling/powers/enfeebling_string.dm +++ b/code/game/gamemodes/changeling/powers/enfeebling_string.dm @@ -1,13 +1,29 @@ /datum/power/changeling/enfeebling_string name = "Enfeebling String" desc = "We sting a biological with a potent toxin that will greatly weaken them for a short period of time." - helptext = "Lowers the maximum health of the victim for a few minutes. This sting will also warn them of this. Has a \ - five minute coodown between uses." - enhancedtext = "Maximum health is lowered further." + helptext = "Lowers the maximum health of the victim for a few minutes, as well as making them more frail and weak. This sting will also warn them of this." + enhancedtext = "Maximum health and outgoing melee damage is lowered further. Incoming damage is increased." ability_icon_state = "ling_sting_enfeeble" genomecost = 1 verbpath = /mob/proc/changeling_enfeebling_string +/datum/modifier/enfeeble + name = "enfeebled" + desc = "You feel really weak and frail for some reason." + + stacks = MODIFIER_STACK_EXTEND + max_health_percent = 0.7 + outgoing_melee_damage_percent = 0.75 + incoming_damage_percent = 1.1 + on_created_text = "You feel a small prick and you feel extremly weak!" + on_expired_text = "You no longer feel extremly weak." + +// Now YOU'RE the Teshari! +/datum/modifier/enfeeble/strong + max_health_percent = 0.5 + outgoing_melee_damage_percent = 0.5 + incoming_damage_percent = 1.35 + /mob/proc/changeling_enfeebling_string() set category = "Changeling" set name = "Enfeebling Sting (30)" @@ -23,22 +39,10 @@ src.attack_log += text("\[[time_stamp()]\] Used enfeebling sting on [key_name(T)]") msg_admin_attack("[key_name(T)] was enfeebling stung by [key_name(src)]") - - var/effect = 30 //percent + var/type_to_give = /datum/modifier/enfeeble if(src.mind.changeling.recursive_enhancement) - effect = effect + 20 + type_to_give = /datum/modifier/enfeeble/strong src << "We make them extremely weak." - var/health_to_take_away = H.maxHealth * (effect / 100) - - H.maxHealth -= health_to_take_away - H << "You feel a small prick and you feel extremly weak!" - src.verbs -= /mob/proc/changeling_enfeebling_string - spawn(5 MINUTES) - src.verbs |= /mob/proc/changeling_enfeebling_string - src << "Our enfeebling string is ready to be used once more." - if(H) //Just incase we stop existing in five minutes for whatever reason. - H.maxHealth += health_to_take_away - if(!H.stat) //It'd be weird to no longer feel weak when you're dead. - H << "You no longer feel extremly weak." + H.add_modifier(type_to_give, 2 MINUTES) feedback_add_details("changeling_powers","ES") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm index 3875a4b4fa5..38d200cad56 100644 --- a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm +++ b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm @@ -2,11 +2,20 @@ name = "Epinephrine Overdose" desc = "We evolve additional sacs of adrenaline throughout our body." helptext = "We can instantly recover from stuns and reduce the effect of future stuns, but we will suffer toxicity in the long term. Can be used while unconscious." - enhancedtext = "Constant recovery from stuns for thirty seconds." + enhancedtext = "Immunity from most disabling effects for 30 seconds." ability_icon_state = "ling_epinepherine_overdose" genomecost = 2 verbpath = /mob/proc/changeling_epinephrine_overdose +/datum/modifier/unstoppable + name = "unstoppable" + desc = "We feel limitless amounts of energy surge in our veins. Nothing can stop us!" + + stacks = MODIFIER_STACK_EXTEND + on_created_text = "We feel unstoppable!" + on_expired_text = "We feel our newfound energy fade..." + disable_duration_percent = 0 + //Recover from stuns. /mob/proc/changeling_epinephrine_overdose() set category = "Changeling" @@ -30,18 +39,7 @@ C.reagents.add_reagent("epinephrine", 20) if(src.mind.changeling.recursive_enhancement) - src << "We feel unstoppable." - spawn(1) - var/i = 30 - while(i) - C.SetParalysis(0) - C.SetStunned(0) - C.SetWeakened(0) - C.lying = 0 - C.update_canmove() - i-- - sleep(10) - src << "We feel our newfound energy fade." + C.add_modifier(/datum/modifier/unstoppable, 30 SECONDS) feedback_add_details("changeling_powers","UNS") return 1 diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm index f106d9167fb..138cd156e38 100644 --- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm +++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm @@ -18,7 +18,7 @@ var/global/list/changeling_fabricated_clothing = list( helptext = "The disguise we create offers no defensive ability. Each equipment slot that is empty will be filled with fabricated equipment. \ To remove our new fabricated clothing, use this ability again." ability_icon_state = "ling_fabricate_clothing" - genomecost = 2 + genomecost = 1 verbpath = /mob/proc/changeling_fabricate_clothing //Grows biological versions of chameleon clothes. diff --git a/code/game/gamemodes/changeling/powers/fake_death.dm b/code/game/gamemodes/changeling/powers/fake_death.dm index dee603fc4a9..765dbb51e61 100644 --- a/code/game/gamemodes/changeling/powers/fake_death.dm +++ b/code/game/gamemodes/changeling/powers/fake_death.dm @@ -12,7 +12,7 @@ set category = "Changeling" set name = "Regenerative Stasis (20)" - var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) + var/datum/changeling/changeling = changeling_power(CHANGELING_STASIS_COST,1,100,DEAD) if(!changeling) return @@ -28,6 +28,7 @@ C.update_canmove() C.remove_changeling_powers() + changeling.chem_charges -= CHANGELING_STASIS_COST if(C.suiciding) C.suiciding = 0 @@ -35,7 +36,9 @@ if(C.stat != DEAD) C.adjustOxyLoss(C.maxHealth * 2) - spawn(rand(800,2000)) + C.forbid_seeing_deadchat = TRUE + + spawn(rand(2 MINUTES, 4 MINUTES)) //The ling will now be able to choose when to revive src.verbs += /mob/proc/changeling_revive src << "We are ready to rise. Use the Revive verb when you are ready." diff --git a/code/game/gamemodes/changeling/powers/rapid_regen.dm b/code/game/gamemodes/changeling/powers/rapid_regen.dm index eddf83292ed..2eb628b8f6c 100644 --- a/code/game/gamemodes/changeling/powers/rapid_regen.dm +++ b/code/game/gamemodes/changeling/powers/rapid_regen.dm @@ -35,7 +35,7 @@ C.species.create_organs(C) C.restore_all_organs() C.blinded = 0 - C.eye_blind = 0 + C.SetBlinded(0) C.eye_blurry = 0 C.ear_deaf = 0 C.ear_damage = 0 diff --git a/code/game/gamemodes/changeling/powers/respec.dm b/code/game/gamemodes/changeling/powers/respec.dm index 7910ceaf7c5..66f13e720f1 100644 --- a/code/game/gamemodes/changeling/powers/respec.dm +++ b/code/game/gamemodes/changeling/powers/respec.dm @@ -6,9 +6,14 @@ var/datum/changeling/changeling = changeling_power(0,0,100) if(!changeling) return + if(src.mind.changeling.readapts <= 0) + to_chat(src, "We must first absorb another compatable creature!") + src.mind.changeling.readapts = 0 + return src.remove_changeling_powers() //First, remove the verbs. var/datum/changeling/ling_datum = src.mind.changeling + ling_datum.readapts-- ling_datum.purchased_powers = list() //Then wipe all the powers we bought. ling_datum.geneticpoints = ling_datum.max_geneticpoints //Now refund our points to the maximum. ling_datum.chem_recharge_rate = 0.5 //If glands were bought, revert that upgrade. @@ -17,13 +22,10 @@ ling_datum.chem_storage = 50 if(ishuman(src)) var/mob/living/carbon/human/H = src - H.does_not_breathe = 0 //If self respiration was bought, revert that too. - H.maxHealth = initial(H.maxHealth) //Revert endoarmor too. + // H.does_not_breathe = 0 //If self respiration was bought, revert that too. + H.remove_modifiers_of_type(/datum/modifier/endoarmor) //Revert endoarmor too. src.make_changeling() //And give back our freebies. src << "We have removed our evolutions from this form, and are now ready to readapt." ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])") - - //Now to lose the verb, so no unlimited resets. - src.verbs -= /mob/proc/changeling_respec \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 2f0b9c57e75..c640e353925 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -41,6 +41,10 @@ current_limb.undislocate() current_limb.open = 0 + BITSET(H.hud_updateflag, HEALTH_HUD) + BITSET(H.hud_updateflag, STATUS_HUD) + BITSET(H.hud_updateflag, LIFE_HUD) + C.halloss = 0 C.shock_stage = 0 //Pain C << "We have regenerated." @@ -48,8 +52,12 @@ C.mind.changeling.purchased_powers -= C feedback_add_details("changeling_powers","CR") C.stat = CONSCIOUS + C.forbid_seeing_deadchat = FALSE C.timeofdeath = null src.verbs -= /mob/proc/changeling_revive // re-add our changeling powers C.make_changeling() + + + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index 2b8af49eb6f..37e7f67fe04 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -35,6 +35,14 @@ src << "You can't speak!" return 0 + if(world.time < (changeling.last_shriek + 10 SECONDS) ) + to_chat(src, "We are still recovering from our last shriek...") + return 0 + + if(!isturf(loc)) + to_chat(src, "Shrieking here would be a bad idea.") + return 0 + src.break_cloak() //No more invisible shrieking changeling.chem_charges -= 20 @@ -47,6 +55,8 @@ message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (JMP).") log_game("[key_name(src)] used Resonant Shriek.") + visible_message("[src] appears to shout.") + for(var/mob/living/M in range(range, src)) if(iscarbon(M)) if(!M.mind || !M.mind.changeling) @@ -55,7 +65,7 @@ M << "You hear an extremely loud screeching sound! It \ [pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you." M.adjustEarDamage(0,30) - M.confused += 20 + M.Confuse(20) M << sound('sound/effects/screech.ogg') M.attack_log += text("\[[time_stamp()]\] Was affected by [key_name(src)]'s Resonant Shriek.") else @@ -73,11 +83,7 @@ L.on = 1 L.broken() -/* src.verbs -= /mob/proc/changeling_resonant_shriek - spawn(30 SECONDS) - src << "We are ready to use our resonant shriek once more." - src.verbs |= /mob/proc/changeling_resonant_shriek -Ability Cooldowns don't work properly right now, need to redo this when they are */ + changeling.last_shriek = world.time feedback_add_details("changeling_powers","RS") return 1 @@ -101,6 +107,14 @@ Ability Cooldowns don't work properly right now, need to redo this when they are src << "You can't speak!" return 0 + if(world.time < (changeling.last_shriek + 10 SECONDS) ) + to_chat(src, "We are still recovering from our last shriek...") + return 0 + + if(!isturf(loc)) + to_chat(src, "Shrieking here would be a bad idea.") + return 0 + src.break_cloak() //No more invisible shrieking changeling.chem_charges -= 20 @@ -117,6 +131,8 @@ Ability Cooldowns don't work properly right now, need to redo this when they are src << "We are extra loud." src.mind.changeling.recursive_enhancement = 0 + visible_message("[src] appears to shout.") + src.attack_log += text("\[[time_stamp()]\] Used Dissonant Shriek.") message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (JMP).") log_game("[key_name(src)] used Dissonant Shriek.") @@ -126,9 +142,6 @@ Ability Cooldowns don't work properly right now, need to redo this when they are L.broken() empulse(get_turf(src), range_heavy, range_light, 1) -/* src.verbs -= /mob/proc/changeling_dissonant_shriek - spawn(30 SECONDS) - src << "We are ready to use our dissonant shriek once more." - src.verbs |= /mob/proc/changeling_dissonant_shriek -Ability Cooldowns don't work properly right now, need to redo this when they are */ + changeling.last_shriek = world.time + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 236af69f5fd..37a99452102 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -13,6 +13,10 @@ var/datum/changeling/changeling = changeling_power(5,1,0) if(!changeling) return + if(!isturf(loc)) + to_chat(src, "Transforming here would be a bad idea.") + return 0 + var/list/names = list() for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) names += "[DNA.name]" diff --git a/code/game/gamemodes/changeling/powers/visible_camouflage.dm b/code/game/gamemodes/changeling/powers/visible_camouflage.dm index 00e31cc932d..167f6f41b9b 100644 --- a/code/game/gamemodes/changeling/powers/visible_camouflage.dm +++ b/code/game/gamemodes/changeling/powers/visible_camouflage.dm @@ -3,7 +3,7 @@ desc = "We rapidly shape the color of our skin and secrete easily reversible dye on our clothes, to blend in with our surroundings. \ We are undetectable, so long as we move slowly.(Toggle)" helptext = "Running, and performing most acts will reveal us. Our chemical regeneration is halted while we are hidden." - enhancedtext = "True invisiblity while cloaked." + enhancedtext = "Can run while hidden." ability_icon_state = "ling_camoflage" genomecost = 3 verbpath = /mob/proc/changeling_visible_camouflage @@ -31,20 +31,35 @@ var/old_regen_rate = H.mind.changeling.chem_recharge_rate H << "We vanish from sight, and will remain hidden, so long as we move carefully." - H.set_m_intent("walk") H.mind.changeling.cloaked = 1 H.mind.changeling.chem_recharge_rate = 0 animate(src,alpha = 255, alpha = 10, time = 10) + var/must_walk = TRUE if(src.mind.changeling.recursive_enhancement) - H.invisibility = INVISIBILITY_OBSERVER - src << "We are now truly invisible." + must_walk = FALSE + to_chat(src, "We may move at our normal speed while hidden.") + + if(must_walk) + H.set_m_intent("walk") + + var/remain_cloaked = TRUE + while(remain_cloaked) //This loop will keep going until the player uncloaks. + sleep(1 SECOND) // Sleep at the start so that if something invalidates a cloak, it will drop immediately after the check and not in one second. + + if(H.m_intent != "walk" && must_walk) // Moving too fast uncloaks you. + remain_cloaked = 0 + if(!H.mind.changeling.cloaked) + remain_cloaked = 0 + if(H.stat) // Dead or unconscious lings can't stay cloaked. + remain_cloaked = 0 + if(H.incapacitated(INCAPACITATION_DISABLED)) // Stunned lings also can't stay cloaked. + remain_cloaked = 0 - while(H.m_intent == "walk" && H.mind.changeling.cloaked && !H.stat) //This loop will keep going until the player uncloaks. if(mind.changeling.chem_recharge_rate != 0) //Without this, there is an exploit that can be done, if one buys engorged chem sacks while cloaked. old_regen_rate += mind.changeling.chem_recharge_rate //Unfortunately, it has to occupy this part of the proc. This fixes it while at the same time mind.changeling.chem_recharge_rate = 0 //making sure nobody loses out on their bonus regeneration after they're done hiding. - sleep(10) + H.invisibility = initial(invisibility) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 5868bf4b599..cecb7b87c7b 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -49,7 +49,7 @@ desc = "A hood worn by the followers of Nar-Sie." flags_inv = HIDEFACE body_parts_covered = HEAD - armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0) + armor = list(melee = 50, bullet = 30, laser = 50, energy = 80, bomb = 25, bio = 10, rad = 0) cold_protection = HEAD min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0 @@ -73,7 +73,7 @@ icon_state = "cultrobes" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) - armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0) + armor = list(melee = 50, bullet = 30, laser = 50, energy = 80, bomb = 25, bio = 10, rad = 0) flags_inv = HIDEJUMPSUIT siemens_coefficient = 0 @@ -95,7 +95,7 @@ name = "cult helmet" desc = "A space worthy helmet used by the followers of Nar-Sie." icon_state = "cult_helmet" - armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30) + armor = list(melee = 60, bullet = 50, laser = 30, energy = 80, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 /obj/item/clothing/head/helmet/space/cult/cultify() @@ -108,7 +108,7 @@ w_class = ITEMSIZE_NORMAL allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency/oxygen,/obj/item/device/suit_cooling_unit) slowdown = 1 - armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30) + armor = list(melee = 60, bullet = 50, laser = 30, energy = 80, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 flags_inv = HIDEGLOVES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 61f177eae55..027b61333ec 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -958,7 +958,7 @@ var/list/sacrificed = list() if(N) continue C.eye_blurry += 50 - C.eye_blind += 20 + C.Blind(20) if(prob(5)) C.disabilities |= NEARSIGHTED if(prob(10)) @@ -981,7 +981,7 @@ var/list/sacrificed = list() if(N) continue C.eye_blurry += 30 - C.eye_blind += 10 + C.Blind(10) //talismans is weaker. affected += C C.show_message("You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 2d43e67f243..b9418bfea9b 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -7,20 +7,13 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' /datum/game_mode/heist name = "Heist" config_tag = "heist" - required_players = 8 - required_players_secret = 8 - required_enemies = 3 + required_players = 15 + required_players_secret = 15 + required_enemies = 4 round_description = "An unidentified bluespace signature is approaching the station!" extended_round_description = "The Company's majority control of phoron in the system has marked the \ station to be a highly valuable target for many competing organizations and individuals. Being a \ colony of sizable population and considerable wealth causes it to often be the target of various \ attempts of robbery, fraud and other malicious actions." end_on_antag_death = 0 - antag_tags = list(MODE_RAIDER) - -/datum/game_mode/heist/check_finished() - if(!..()) - var/datum/shuttle/multi_shuttle/skipjack = shuttle_controller.shuttles["Skipjack"] - if (skipjack && skipjack.returned_home) - return 1 - return 0 + antag_tags = list(MODE_RAIDER) \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index e2f6b8a56cc..098f9fd3292 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -12,9 +12,9 @@ var/list/nuke_disks = list() colony of sizable population and considerable wealth causes it to often be the target of various \ attempts of robbery, fraud and other malicious actions." config_tag = "mercenary" - required_players = 8 - required_players_secret = 8 - required_enemies = 3 + required_players = 15 + required_players_secret = 15 + required_enemies = 4 end_on_antag_death = 0 var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level diff --git a/code/game/gamemodes/technomancer/equipment.dm b/code/game/gamemodes/technomancer/equipment.dm index 5c440d0dcd8..8d1fb4c6ad1 100644 --- a/code/game/gamemodes/technomancer/equipment.dm +++ b/code/game/gamemodes/technomancer/equipment.dm @@ -191,6 +191,7 @@ icon_state = "scepter" force = 15 slot_flags = SLOT_BELT + attack_verb = list("beaten", "smashed", "struck", "whacked") /obj/item/weapon/scepter/attack_self(mob/living/carbon/human/user) var/obj/item/item_to_test = user.get_other_hand(src) diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm index fa9985b1b6b..453469619cf 100644 --- a/code/game/gamemodes/technomancer/instability.dm +++ b/code/game/gamemodes/technomancer/instability.dm @@ -285,4 +285,4 @@ to_chat(H, "The purple glow makes you feel strange...") H.adjust_instability(outgoing_instability) - set_light(distance, distance * 2, l_color = "#C26DDE") + set_light(distance, distance * 4, l_color = "#C26DDE") diff --git a/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm b/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm index 431e72a32f8..3c65a9503fc 100644 --- a/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm @@ -25,7 +25,7 @@ if(is_ally(L)) continue - var/damage_to_inflict = max(L.health / L.maxHealth, 0) // Otherwise, those in crit would actually be healed. + var/damage_to_inflict = max(L.health / L.getMaxHealth(), 0) // Otherwise, those in crit would actually be healed. var/armor_factor = abs(L.getarmor(null, "energy") - 100) armor_factor = armor_factor / 100 diff --git a/code/game/gamemodes/technomancer/spells/dispel.dm b/code/game/gamemodes/technomancer/spells/dispel.dm index 87edf6a6212..10f258bf582 100644 --- a/code/game/gamemodes/technomancer/spells/dispel.dm +++ b/code/game/gamemodes/technomancer/spells/dispel.dm @@ -21,5 +21,6 @@ for(var/obj/item/weapon/inserted_spell/I in target) I.on_expire(dispelled = 1) log_and_message_admins("dispelled [I] on [target].") + target.remove_modifiers_of_type(/datum/modifier/technomancer) user.adjust_instability(10) qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/illusion.dm b/code/game/gamemodes/technomancer/spells/illusion.dm index 12f04db48c2..50a9bf5da74 100644 --- a/code/game/gamemodes/technomancer/spells/illusion.dm +++ b/code/game/gamemodes/technomancer/spells/illusion.dm @@ -93,6 +93,9 @@ var/walking = 0 var/step_delay = 10 +/mob/living/simple_animal/illusion/update_icon() // We don't want the appearance changing AT ALL unless by copy_appearance(). + return + /mob/living/simple_animal/illusion/proc/copy_appearance(var/atom/movable/thing_to_copy) if(!thing_to_copy) return 0 diff --git a/code/game/gamemodes/technomancer/spells/insert/asphyxiation.dm b/code/game/gamemodes/technomancer/spells/insert/asphyxiation.dm index 555ff9f5592..84b0b22931a 100644 --- a/code/game/gamemodes/technomancer/spells/insert/asphyxiation.dm +++ b/code/game/gamemodes/technomancer/spells/insert/asphyxiation.dm @@ -32,7 +32,7 @@ warned_victim = predict_crit(pulses, H, 0) sleep(4 SECONDS) H.adjustOxyLoss(5) - var/health_lost = H.maxHealth - H.getOxyLoss() + H.getToxLoss() + H.getFireLoss() + H.getBruteLoss() + H.getCloneLoss() + var/health_lost = H.getMaxHealth() - H.getOxyLoss() + H.getToxLoss() + H.getFireLoss() + H.getBruteLoss() + H.getCloneLoss() H.adjustOxyLoss(round(abs(health_lost * 0.25))) //world << "Inflicted [round(abs(health_lost * 0.25))] damage!" pulses-- @@ -62,7 +62,7 @@ pulses_remaining-- return .(pulses_remaining, victim, previous_damage) // Now check if our damage predictions are going to cause the victim to go into crit if no healing occurs. - if(previous_damage + health_lost >= victim.maxHealth) // We're probably going to hardcrit + if(previous_damage + health_lost >= victim.getMaxHealth()) // We're probably going to hardcrit victim << "A feeling of immense dread starts to overcome you as everything starts \ to fade to black..." //world << "Predicted hardcrit." diff --git a/code/game/gamemodes/technomancer/spells/insert/corona.dm b/code/game/gamemodes/technomancer/spells/insert/corona.dm deleted file mode 100644 index 0ecd700732f..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/corona.dm +++ /dev/null @@ -1,42 +0,0 @@ -/datum/technomancer/spell/corona - name = "Corona" - desc = "Causes the victim to glow very brightly, which while harmless in itself, makes it easier for them to be hit. The \ - bright glow also makes it very difficult to be stealthy. The effect lasts for one minute." - spell_power_desc = "Enemies become even easier to hit." - cost = 50 - obj_path = /obj/item/weapon/spell/insert/corona - ability_icon_state = "tech_corona" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/corona - name = "corona" - desc = "How brillient!" - icon_state = "radiance" - cast_methods = CAST_RANGED - aspect = ASPECT_LIGHT - light_color = "#D9D900" - spell_light_intensity = 5 - spell_light_range = 3 - inserting = /obj/item/weapon/inserted_spell/corona - - -/obj/item/weapon/inserted_spell/corona - var/evasion_reduction = 2 // We store this here because spell power may change when the spell expires. - -/obj/item/weapon/inserted_spell/corona/on_insert() - spawn(1) - if(isliving(host)) - var/mob/living/L = host - evasion_reduction = round(2 * spell_power_at_creation, 1) - L.evasion -= evasion_reduction - L.visible_message("You start to glow very brightly!") - spawn(1 MINUTE) - if(src) - on_expire() - -/obj/item/weapon/inserted_spell/corona/on_expire() - if(isliving(host)) - var/mob/living/L = host - L.evasion += evasion_reduction - L << "Your glow has ended." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/haste.dm b/code/game/gamemodes/technomancer/spells/insert/haste.dm deleted file mode 100644 index 30422cef3f4..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/haste.dm +++ /dev/null @@ -1,36 +0,0 @@ -/datum/technomancer/spell/haste - name = "Haste" - desc = "Allows the target to run at speeds that should not be possible for an ordinary being. For five seconds, the target \ - runs extremly fast, and cannot be slowed by any means." - spell_power_desc = "Duration is scaled up." - cost = 100 - obj_path = /obj/item/weapon/spell/insert/haste - ability_icon_state = "tech_haste" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/haste - name = "haste" - desc = "Now you can outrun a Teshari!" - icon_state = "haste" - cast_methods = CAST_RANGED - aspect = ASPECT_FORCE - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/haste - -/obj/item/weapon/inserted_spell/haste/on_insert() - spawn(1) - if(isliving(host)) - var/mob/living/L = host - L.force_max_speed = 1 - L << "You suddenly find it much easier to move." - L.adjust_instability(10) - spawn(round(5 SECONDS * spell_power_at_creation, 1)) - if(src) - on_expire() - -/obj/item/weapon/inserted_spell/haste/on_expire() - if(isliving(host)) - var/mob/living/L = host - L.force_max_speed = 0 - L << "You feel slow again." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm deleted file mode 100644 index 38e4ef47205..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm +++ /dev/null @@ -1,39 +0,0 @@ -/datum/technomancer/spell/repel_missiles - name = "Repel Missiles" - desc = "Places a repulsion field around you, which attempts to deflect incoming bullets and lasers, making them 30% less likely \ - to hit you. The field lasts for five minutes and can be granted to yourself or an ally." - spell_power_desc = "Projectiles will be more likely to be deflected." - cost = 25 - obj_path = /obj/item/weapon/spell/insert/repel_missiles - ability_icon_state = "tech_repelmissiles" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/repel_missiles - name = "repel missiles" - desc = "Use it before they start shooting at you!" - icon_state = "generic" - cast_methods = CAST_RANGED - aspect = ASPECT_FORCE - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/repel_missiles - -/obj/item/weapon/inserted_spell/repel_missiles - var/evasion_increased = 2 // We store this here because spell power may change when the spell expires. - -/obj/item/weapon/inserted_spell/repel_missiles/on_insert() - spawn(1) - if(isliving(host)) - var/mob/living/L = host - evasion_increased = round(2 * spell_power_at_creation, 1) - L.evasion += evasion_increased - L << "You have a repulsion field around you, which will attempt to deflect projectiles." - spawn(5 MINUTES) - if(src) - on_expire() - -/obj/item/weapon/inserted_spell/repel_missiles/on_expire() - if(isliving(host)) - var/mob/living/L = host - L.evasion -= evasion_increased - L << "Your repulsion field has expired." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/corona.dm b/code/game/gamemodes/technomancer/spells/modifier/corona.dm new file mode 100644 index 00000000000..74a06855d9f --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/corona.dm @@ -0,0 +1,33 @@ +/datum/technomancer/spell/corona + name = "Corona" + desc = "Causes the victim to glow very brightly, which while harmless in itself, makes it easier for them to be hit. The \ + bright glow also makes it very difficult to be stealthy. The effect lasts for one minute." + cost = 50 + obj_path = /obj/item/weapon/spell/modifier/corona + ability_icon_state = "tech_corona" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/corona + name = "corona" + desc = "How brillient!" + icon_state = "radiance" + cast_methods = CAST_RANGED + aspect = ASPECT_LIGHT + light_color = "#D9D900" + spell_light_intensity = 5 + spell_light_range = 3 + modifier_type = /datum/modifier/technomancer/corona + modifier_duration = 1 MINUTE + +/datum/modifier/technomancer/corona + name = "corona" + desc = "You appear to be glowing really bright. It doesn't seem to hurt, however hiding will be impossible." + mob_overlay_state = "corona" + + on_created_text = "You start to glow very brightly!" + on_expired_text = "Your glow has ended." + evasion = -2 + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/corona/tick() + holder.break_cloak() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/haste.dm b/code/game/gamemodes/technomancer/spells/modifier/haste.dm new file mode 100644 index 00000000000..7f7c1045b36 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/haste.dm @@ -0,0 +1,28 @@ +/datum/technomancer/spell/haste + name = "Haste" + desc = "Allows the target to run at speeds that should not be possible for an ordinary being. For five seconds, the target \ + runs extremly fast, and cannot be slowed by any means." + cost = 100 + obj_path = /obj/item/weapon/spell/modifier/haste + ability_icon_state = "tech_haste" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/haste + name = "haste" + desc = "Now you can outrun a Teshari!" + icon_state = "haste" + cast_methods = CAST_RANGED + aspect = ASPECT_FORCE + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/haste + modifier_duration = 5 SECONDS + +/datum/modifier/technomancer/haste + name = "haste" + desc = "Moving is almost effortless!" + mob_overlay_state = "haste" + + on_created_text = "You suddenly find it much easier to move." + on_expired_text = "You feel slow again." + haste = TRUE + stacks = MODIFIER_STACK_EXTEND \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/modifier.dm b/code/game/gamemodes/technomancer/spells/modifier/modifier.dm new file mode 100644 index 00000000000..b0a5c93747f --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/modifier.dm @@ -0,0 +1,31 @@ +/obj/item/weapon/spell/modifier + name = "modifier template" + desc = "Tell a coder if you can read this in-game." + icon_state = "purify" + cast_methods = CAST_MELEE + var/modifier_type = null + var/modifier_duration = null // Will last forever by default. Final duration may differ due to 'spell power' +// var/spell_color = "#03A728" + var/spell_light_intensity = 2 + var/spell_light_range = 3 + +/obj/item/weapon/spell/modifier/New() + ..() + set_light(spell_light_range, spell_light_intensity, l_color = light_color) + +/obj/item/weapon/spell/modifier/on_melee_cast(atom/hit_atom, mob/user) + if(istype(hit_atom, /mob/living)) + on_add_modifier(hit_atom) + +/obj/item/weapon/spell/modifier/on_ranged_cast(atom/hit_atom, mob/user) + if(istype(hit_atom, /mob/living)) + on_add_modifier(hit_atom) + + +/obj/item/weapon/spell/modifier/proc/on_add_modifier(var/mob/living/L) + var/duration = modifier_duration + if(duration) + duration = round(duration * calculate_spell_power(1.0), 1) + L.add_modifier(modifier_type, duration) + log_and_message_admins("has casted [src] on [L].") + qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm new file mode 100644 index 00000000000..d267ecce889 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm @@ -0,0 +1,28 @@ +/datum/technomancer/spell/repel_missiles + name = "Repel Missiles" + desc = "Places a repulsion field around you, which attempts to deflect incoming bullets and lasers, making them 30% less likely \ + to hit you. The field lasts for 10 minutes and can be granted to yourself or an ally." + cost = 25 + obj_path = /obj/item/weapon/spell/modifier/repel_missiles + ability_icon_state = "tech_repelmissiles" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/repel_missiles + name = "repel missiles" + desc = "Use it before they start shooting at you!" + icon_state = "generic" + cast_methods = CAST_RANGED + aspect = ASPECT_FORCE + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/repel_missiles + modifier_duration = 10 MINUTES + +/datum/modifier/technomancer/repel_missiles + name = "repel_missiles" + desc = "A repulsion field can always be useful to have." + mob_overlay_state = "repel_missiles" + + on_created_text = "You have a repulsion field around you, which will attempt to deflect projectiles." + on_expired_text = "Your repulsion field has expired." + evasion = 3 + stacks = MODIFIER_STACK_EXTEND \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm index c56df4f26e2..90a352c95f4 100644 --- a/code/game/gamemodes/technomancer/spells/resurrect.dm +++ b/code/game/gamemodes/technomancer/spells/resurrect.dm @@ -32,7 +32,7 @@ user << "You stab \the [L] with a hidden integrated hypo, attempting to bring them back..." if(istype(L, /mob/living/simple_animal)) var/mob/living/simple_animal/SM = L - SM.health = SM.maxHealth / 3 + SM.health = SM.getMaxHealth() / 3 SM.stat = CONSCIOUS dead_mob_list -= SM living_mob_list += SM diff --git a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm index eafb167dd42..be978e7ee44 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm @@ -20,10 +20,10 @@ /obj/item/weapon/spell/spawner/darkness/New() ..() - set_light(6, -5, l_color = "#FFFFFF") + set_light(6, -20, l_color = "#FFFFFF") /obj/effect/temporary_effect/darkness name = "darkness" time_to_die = 2 MINUTES new_light_range = 6 - new_light_power = -5 \ No newline at end of file + new_light_power = -20 \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm b/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm index 7cf36ebabfb..0e7e96104c1 100644 --- a/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm +++ b/code/game/gamemodes/technomancer/spells/summon/summon_creature.dm @@ -62,4 +62,4 @@ // Now we hurt their new pal, because being forcefully abducted by teleportation can't be healthy. - summoned.health = round(summoned.maxHealth * 0.7) \ No newline at end of file + summoned.health = round(summoned.getMaxHealth() * 0.7) \ No newline at end of file diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 1e4398546c5..e7bb56347e0 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -27,11 +27,13 @@ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/device/pda/bar(H), slot_belt) if(has_alt_title(H, alt_title,"Bartender")) + var/obj/item/weapon/permit/gun/bar/permit = new(H) if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/permit/gun/bar(H), slot_l_hand) + H.equip_to_slot_or_del(permit, slot_l_hand) else - H.equip_to_slot_or_del(new /obj/item/weapon/permit/gun/bar(H.back), slot_in_backpack) - return 1 + H.equip_to_slot_or_del(permit, slot_in_backpack) + permit.set_name(H.real_name) + return 1 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 9ca5c327fa9..8bfb5760a22 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -375,6 +375,7 @@ var/global/datum/controller/occupations/job_master job.equip_backpack(H) job.equip_survival(H) job.apply_fingerprints(H) + H.equip_post_job() //If some custom items could not be equipped before, try again now. for(var/thing in custom_equip_leftovers) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index f69f5f6b2ae..f54d069b9d4 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -68,10 +68,12 @@ anchored = 1 circuit = /obj/item/weapon/circuitboard/sleeper var/mob/living/carbon/human/occupant = null - var/list/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin") + var/list/available_chemicals = list("inaprovaline" = "Inaprovaline", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin") var/obj/item/weapon/reagent_containers/glass/beaker = null var/filtering = 0 var/obj/machinery/sleep_console/console + var/stasis_level = 0 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1) + var/stasis_choices = list("Complete (1%)" = 100, "Deep (10%)" = 10, "Moderate (20%)" = 5, "Light (50%)" = 2, "None (100%)" = 0) use_power = 1 idle_power_usage = 15 @@ -98,18 +100,23 @@ /obj/machinery/sleeper/process() if(stat & (NOPOWER|BROKEN)) return + if(occupant) + occupant.Stasis(stasis_level) + if(stasis_level >= 100 && occupant.timeofdeath) + occupant.timeofdeath += 1 SECOND + + if(filtering > 0) + if(beaker) + if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) + var/pumped = 0 + for(var/datum/reagent/x in occupant.reagents.reagent_list) + occupant.reagents.trans_to_obj(beaker, 3) + pumped++ + if(ishuman(occupant)) + occupant.vessel.trans_to_obj(beaker, pumped + 1) + else + toggle_filter() - if(filtering > 0) - if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - var/pumped = 0 - for(var/datum/reagent/x in occupant.reagents.reagent_list) - occupant.reagents.trans_to_obj(beaker, 3) - pumped++ - if(ishuman(occupant)) - occupant.vessel.trans_to_obj(beaker, pumped + 1) - else - toggle_filter() /obj/machinery/sleeper/update_icon() icon_state = "sleeper_[occupant ? "1" : "0"]" @@ -154,6 +161,13 @@ data["beaker"] = -1 data["filtering"] = filtering + var/stasis_level_name = "Error!" + for(var/N in stasis_choices) + if(stasis_choices[N] == stasis_level) + stasis_level_name = N + break + data["stasis"] = stasis_level_name + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper UI", 600, 600, state = state) @@ -182,12 +196,20 @@ if(occupant && occupant.stat != DEAD) if(href_list["chemical"] in available_chemicals) // Your hacks are bad and you should feel bad inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"])) + if(href_list["change_stasis"]) + var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in stasis_choices + if(new_stasis && CanUseTopic(usr, default_state) == STATUS_INTERACTIVE) + stasis_level = stasis_choices[new_stasis] return 1 /obj/machinery/sleeper/attackby(var/obj/item/I, var/mob/user) add_fingerprint(user) - if(default_deconstruction_screwdriver(user, I)) + if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + if(G.affecting) + go_in(G.affecting, user) + else if(default_deconstruction_screwdriver(user, I)) return else if(default_deconstruction_crowbar(user, I)) return @@ -201,6 +223,28 @@ user << "\The [src] has a beaker already." return +/obj/machinery/sleeper/verb/move_eject() + set name = "Eject occupant" + set category = "Object" + set src in oview(1) + if(usr == occupant) + switch(usr.stat) + if(DEAD) + return + if(UNCONSCIOUS) + usr << "You struggle through the haze to hit the eject button. This will take a couple of minutes..." + sleep(2 MINUTES) + if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already + return + go_out() + if(CONSCIOUS) + go_out() + else + if(usr.stat != 0) + return + go_out() + add_fingerprint(usr) + /obj/machinery/sleeper/MouseDrop_T(var/mob/target, var/mob/user) if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target)) return @@ -261,6 +305,7 @@ if(occupant.client) occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE + occupant.Stasis(0) occupant.loc = src.loc occupant = null for(var/atom/movable/A in src) // In case an object was dropped inside or something diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index bba12887a9b..b1cf9bac081 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -301,6 +301,15 @@ occupantData["reagents"] = reagentData + var/ingestedData[0] + if(H.ingested.reagent_list.len >= 1) + for(var/datum/reagent/R in H.ingested.reagent_list) + ingestedData[++ingestedData.len] = list("name" = R.name, "amount" = R.volume) + else + ingestedData = null + + occupantData["ingested"] = ingestedData + var/extOrganData[0] for(var/obj/item/organ/external/E in H.organs) var/organData[0] @@ -394,7 +403,7 @@ P.info += "Time of scan: [worldtime2stationtime(world.time)]

" P.info += "[printing_text]" P.info += "

Notes:
" - P.name = "Body Scan - [href_list["name"]]" + P.name = "Body Scan - [href_list["name"]] ([worldtime2stationtime(world.time)])" printing = null printing_text = null @@ -457,9 +466,13 @@ dat += "[extra_font]\tBlood Level %: [blood_percent] ([blood_volume] units)
" if(occupant.reagents) - for(var/datum/reagent/R in occupant.reagents) + for(var/datum/reagent/R in occupant.reagents.reagent_list) dat += "Reagent: [R.name], Amount: [R.volume]
" + if(occupant.ingested) + for(var/datum/reagent/R in occupant.ingested.reagent_list) + dat += "Stomach: [R.name], Amount: [R.volume]
" + dat += "
" dat += "" dat += "" diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 83c6f81e305..546e6acd885 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -72,7 +72,6 @@ obj/machinery/air_sensor/Destroy() ..() /obj/machinery/computer/general_air_control - icon = 'icons/obj/computer.dmi' icon_keyboard = "atmos_key" icon_screen = "tank" name = "Computer" diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 31c8fe78197..1aadf981c4f 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -232,6 +232,8 @@ mob/living/proc/near_camera() return TRACKING_TERMINATE if(digitalcamo) return TRACKING_TERMINATE + if(alpha < 127) // For lings and possible future alpha-based cloaks. + return TRACKING_TERMINATE if(istype(loc,/obj/effect/dummy)) return TRACKING_TERMINATE diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index de81fbb0fac..cf657e1c10d 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/aifixer name = "\improper AI system integrity restorer" - icon = 'icons/obj/computer.dmi' icon_keyboard = "rd_key" icon_screen = "ai-fixer" light_color = "#a97faa" @@ -102,7 +101,7 @@ return 1 if (href_list["fix"]) src.active = 1 - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-on") + src.overlays += image(icon, "ai-fixer-on") while (src.occupant.health < 100) src.occupant.adjustOxyLoss(-1) src.occupant.adjustFireLoss(-1) @@ -114,13 +113,13 @@ src.occupant.lying = 0 dead_mob_list -= src.occupant living_mob_list += src.occupant - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + src.overlays -= image(icon, "ai-fixer-404") + src.overlays += image(icon, "ai-fixer-full") src.occupant.add_ai_verbs() src.updateUsrDialog() sleep(10) src.active = 0 - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") + src.overlays -= image(icon, "ai-fixer-on") src.add_fingerprint(usr) @@ -135,8 +134,8 @@ if(occupant) if(occupant.stat) - overlays += image('icons/obj/computer.dmi', "ai-fixer-404", overlay_layer) + overlays += image(icon, "ai-fixer-404", overlay_layer) else - overlays += image('icons/obj/computer.dmi', "ai-fixer-full", overlay_layer) + overlays += image(icon, "ai-fixer-full", overlay_layer) else - overlays += image('icons/obj/computer.dmi', "ai-fixer-empty", overlay_layer) + overlays += image(icon, "ai-fixer-empty", overlay_layer) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 9f1b7afb383..3826eb3c942 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -4,7 +4,6 @@ /obj/machinery/computer/atmoscontrol name = "\improper Central Atmospherics Computer" - icon = 'icons/obj/computer.dmi' icon_keyboard = "generic_key" icon_screen = "comm_logs" light_color = "#00b000" diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 75ba732950a..db932f8cd08 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/cloning name = "cloning control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "med_key" icon_screen = "dna" light_color = "#315ab4" diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 6eae870cfd4..b51fa788ab9 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -85,6 +85,7 @@ if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) dat += "
Organ
Name: [active1.fields["name"]] \ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n" if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) dat += "Gender identity: [active2.fields["id_gender"]]
" diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index e8fe96ae6c8..3d0235fab95 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -2,7 +2,6 @@ /obj/machinery/computer/prisoner name = "prisoner management console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "security_key" icon_screen = "explosive" light_color = "#a91515" diff --git a/code/game/machinery/computer/prisonshuttle.dm b/code/game/machinery/computer/prisonshuttle.dm index 1c54fb0f4ce..8c435f58459 100644 --- a/code/game/machinery/computer/prisonshuttle.dm +++ b/code/game/machinery/computer/prisonshuttle.dm @@ -12,7 +12,6 @@ var/prison_shuttle_timeleft = 0 /obj/machinery/computer/prison_shuttle name = "prison shuttle control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "security_key" icon_screen = "syndishuttle" light_color = "#00ffff" diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index ca56ce168df..4d29a56b89a 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,7 +1,6 @@ /obj/machinery/computer/robotics name = "robotics control console" desc = "Used to remotely lockdown or detonate linked cyborgs." - icon = 'icons/obj/computer.dmi' icon_keyboard = "tech_key" icon_screen = "robot" light_color = "#a97faa" diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 54c94d86848..465884b2caa 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -127,6 +127,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ @@ -612,5 +613,4 @@ What a mess.*/ ..(severity) /obj/machinery/computer/secure_data/detective_computer - icon = 'icons/obj/computer.dmi' icon_state = "messyfiles" diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 1a67778fdf6..bd9c66dbaed 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -93,6 +93,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index cb0f8a5552a..0a337f4df8f 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -13,7 +13,6 @@ var/specops_shuttle_timeleft = 0 /obj/machinery/computer/specops_shuttle name = "special operations shuttle control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "security_key" icon_screen = "syndishuttle" light_color = "#00ffff" diff --git a/code/game/machinery/computer/supply.dm b/code/game/machinery/computer/supply.dm index d390a7f1633..4bcc43bbecf 100644 --- a/code/game/machinery/computer/supply.dm +++ b/code/game/machinery/computer/supply.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/supplycomp name = "supply control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "tech_key" icon_screen = "supply" light_color = "#b88b2e" @@ -13,7 +12,6 @@ /obj/machinery/computer/ordercomp name = "supply ordering console" - icon = 'icons/obj/computer.dmi' icon_screen = "request" circuit = /obj/item/weapon/circuitboard/ordercomp var/temp = null diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index d36f03b5252..ba7193b69bb 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -12,7 +12,6 @@ var/syndicate_elite_shuttle_timeleft = 0 /obj/machinery/computer/syndicate_elite_shuttle name = "elite syndicate squad shuttle control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "syndie_key" icon_screen = "syndishuttle" light_color = "#00ffff" diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm index 57a662db46f..bb4228397dd 100644 --- a/code/game/machinery/computer3/computers/medical.dm +++ b/code/game/machinery/computer3/computers/medical.dm @@ -95,6 +95,7 @@ dat += "
Name: [active1.fields["name"]] \ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Fingerprint: [active1.fields["fingerprint"]]
\n \ diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm index a314bed2736..6b77a274bf5 100644 --- a/code/game/machinery/computer3/computers/security.dm +++ b/code/game/machinery/computer3/computers/security.dm @@ -134,6 +134,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index d1ab11e7067..5d0f707ae88 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -96,7 +96,7 @@ occupantData["name"] = occupant.name occupantData["stat"] = occupant.stat occupantData["health"] = occupant.health - occupantData["maxHealth"] = occupant.maxHealth + occupantData["maxHealth"] = occupant.getMaxHealth() occupantData["minHealth"] = config.health_threshold_dead occupantData["bruteLoss"] = occupant.getBruteLoss() occupantData["oxyLoss"] = occupant.getOxyLoss() diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 6441a5e72ae..672a6a425b7 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -534,7 +534,7 @@ time_entered = world.time if(ishuman(M) && applies_stasis) var/mob/living/carbon/human/H = M - H.in_stasis = 1 + H.Stasis(1000) // Book keeping! var/turf/location = get_turf(src) @@ -602,7 +602,7 @@ set_occupant(usr) if(ishuman(usr) && applies_stasis) var/mob/living/carbon/human/H = occupant - H.in_stasis = 1 + H.Stasis(1000) icon_state = occupied_icon_state @@ -638,7 +638,7 @@ occupant.forceMove(get_turf(src)) if(ishuman(occupant) && applies_stasis) var/mob/living/carbon/human/H = occupant - H.in_stasis = 0 + H.Stasis(0) set_occupant(null) icon_state = base_icon_state diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 6aeecfc8e5d..e78cba35688 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -777,7 +777,7 @@ About the new airlock wires panel: src.welded = 1 else src.welded = null - playsound(src, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 75, 1) src.update_icon() return else @@ -802,7 +802,7 @@ About the new airlock wires panel: cable.plugin(src, user) else if(!repairing && istype(C, /obj/item/weapon/crowbar)) if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) ) - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + playsound(src.loc, 'sound/items/Crowbar.ogg', 75, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.") if(do_after(user,40)) to_chat(user,"You removed the airlock electronics!") @@ -895,9 +895,9 @@ About the new airlock wires panel: //if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator if(arePowerSystemsOn()) - playsound(src.loc, open_sound_powered, 100, 1) + playsound(src.loc, open_sound_powered, 75, 1) else - playsound(src.loc, open_sound_unpowered, 100, 1) + playsound(src.loc, open_sound_unpowered, 75, 1) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) src.closeOther.close() @@ -992,9 +992,9 @@ About the new airlock wires panel: use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people has_beeped = 0 if(arePowerSystemsOn()) - playsound(src.loc, open_sound_powered, 100, 1) + playsound(src.loc, open_sound_powered, 75, 1) else - playsound(src.loc, open_sound_unpowered, 100, 1) + playsound(src.loc, open_sound_unpowered, 75, 1) for(var/turf/turf in locs) var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf) if(killthis) diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index 209e3bb228f..3d899377cca 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -12,6 +12,7 @@ desc = "That looks like it doesn't open easily." icon = 'icons/obj/doors/rapid_pdoor.dmi' icon_state = null + min_force = 20 //minimum amount of force needed to damage the door with a melee weapon // Icon states for different shutter types. Simply change this instead of rewriting the update_icon proc. var/icon_state_open = null @@ -78,7 +79,10 @@ // Proc: force_toggle() // Parameters: None // Description: Opens or closes the door, depending on current state. No checks are done inside this proc. -/obj/machinery/door/blast/proc/force_toggle() +/obj/machinery/door/blast/proc/force_toggle(var/forced = 0, mob/user as mob) + if (forced) + playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1) + if(src.density) src.force_open() else @@ -91,7 +95,7 @@ /obj/machinery/door/blast/attackby(obj/item/weapon/C as obj, mob/user as mob) src.add_fingerprint(user) if(istype(C, /obj/item/weapon)) // For reasons unknown, sometimes C is actually not what it is advertised as, like a mob. - if(C.pry == 1) // Can we pry it open with something, like a crowbar/fireaxe/lingblade? + if(C.pry == 1 && (user.a_intent != I_HURT || (stat & BROKEN))) // Can we pry it open with something, like a crowbar/fireaxe/lingblade? if(istype(C,/obj/item/weapon/material/twohanded/fireaxe)) // Fireaxes need to be in both hands to pry. var/obj/item/weapon/material/twohanded/fireaxe/F = C if(!F.wielded) @@ -100,7 +104,8 @@ // If we're at this point, it's a fireaxe in both hands or something else that doesn't care for twohanding. if(((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating )) - force_toggle() + force_toggle(1, user) + else usr << "[src]'s motors resist your effort." return @@ -123,15 +128,33 @@ usr << "You don't have enough sheets to repair this! You need at least [amt] sheets." + else if(src.density) + var/obj/item/weapon/W = C + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(W.damtype == BRUTE || W.damtype == BURN) + user.do_attack_animation(src) + if(W.force < min_force) + user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.") + else + user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!") + playsound(src.loc, hitsound, 100, 1) + take_damage(W.force*0.35) //it's a blast door, it should take a while. -Luke + return + // Proc: open() // Parameters: None // Description: Opens the door. Does necessary checks. Automatically closes if autoclose is true -/obj/machinery/door/blast/open() - if (src.operating || (stat & BROKEN || stat & NOPOWER)) - return - force_open() - if(autoclose) +/obj/machinery/door/blast/open(var/forced = 0) + if(forced) + force_open() + return 1 + else + if (src.operating || (stat & BROKEN || stat & NOPOWER)) + return 1 + force_open() + + if(autoclose && src.operating && !(stat & BROKEN || stat & NOPOWER)) spawn(150) close() return 1 diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 185de7f06db..cd38f9f1ceb 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -312,6 +312,8 @@ /obj/machinery/door/examine(mob/user) . = ..() + if(src.health <= 0) + user << "\The [src] is broken!" if(src.health < src.maxhealth / 4) user << "\The [src] looks like it's about to break!" else if(src.health < src.maxhealth / 2) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index ae48142b4d2..a18edbc5fa5 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -78,7 +78,7 @@ C.traits = new() C.nameVar = "grey" I.add_product(C) - + /obj/machinery/smartfridge/secure/medbay name = "\improper Refrigerated Medicine Storage" @@ -139,6 +139,7 @@ icon_state = "drying_rack" icon_on = "drying_rack_on" icon_off = "drying_rack" + icon_panel = "drying_rack-panel" /obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj) if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/)) @@ -260,7 +261,7 @@ locked = -1 user << "You short out the product lock on [src]." return 1 - + /obj/machinery/smartfridge/proc/stock(obj/item/O) var/hasRecord = FALSE //Check to see if this passes or not. for(var/datum/stored_item/I in item_records) @@ -273,7 +274,7 @@ item.add_product(O) item_records.Add(item) nanomanager.update_uis(src) - + /obj/machinery/smartfridge/proc/vend(datum/stored_item/I) I.get_product(get_turf(src)) nanomanager.update_uis(src) @@ -357,7 +358,7 @@ if (!throw_item) continue break - + if(!throw_item) return 0 spawn(0) diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index ffe30bf3fd8..1e10e03f4f8 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -7,7 +7,7 @@ energy_drain = 20 range = MELEE equip_cooldown = 50 - var/mob/living/carbon/occupant = null + var/mob/living/carbon/human/occupant = null var/datum/global_iterator/pr_mech_sleeper var/inject_amount = 10 required_type = /obj/mecha/medical @@ -28,7 +28,7 @@ Exit(atom/movable/O) return 0 - action(var/mob/living/carbon/target) + action(var/mob/living/carbon/human/target) if(!action_checks(target)) return if(!istype(target)) @@ -56,6 +56,7 @@ target.forceMove(src) occupant = target target.reset_view(src) + occupant.Stasis(3) /* if(target.client) target.client.perspective = EYE_PERSPECTIVE @@ -80,6 +81,7 @@ occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE */ + occupant.Stasis(0) occupant = null pr_mech_sleeper.stop() set_ready_state(1) diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index a6da9bfa000..00a0654cc12 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/mecha name = "Exosuit Control" - icon = 'icons/obj/computer.dmi' icon_keyboard = "rd_key" icon_screen = "mecha" light_color = "#a97faa" diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 967c03252f3..6aec830c899 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -95,7 +95,7 @@ holder.icon_state = "hudhealth-100" C.images += holder else - holder.icon_state = RoundHealth((patient.health-config.health_threshold_crit)/(patient.maxHealth-config.health_threshold_crit)*100) + holder.icon_state = RoundHealth((patient.health-config.health_threshold_crit)/(patient.getMaxHealth()-config.health_threshold_crit)*100) C.images += holder holder = patient.hud_list[STATUS_HUD] diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 7950200137d..f456a95d734 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -74,7 +74,12 @@ add_fingerprint(user) unbuckle_mob() - if(buckle_mob(M)) + //can't buckle unless you share locs so try to move M to the obj. + if(M.loc != src.loc) + step_towards(M, src) + + . = buckle_mob(M) + if(.) if(M == user) M.visible_message(\ "[M.name] buckles themselves to [src].",\ diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 1450fa94ce5..4d77da4ae93 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -77,14 +77,20 @@ /obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location) ..() if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - if(!ishuman(usr)) return + if(!ishuman(usr)) return 0 if(opened) return 0 if(contents.len) return 0 visible_message("[usr] folds up the [src.name]") - new item_path(get_turf(src)) + var/folded = new item_path(get_turf(src)) spawn(0) qdel(src) - return + return folded + +/obj/structure/closet/body_bag/relaymove(mob/user,direction) + if(src.loc != get_turf(src)) + src.loc.relaymove(user,direction) + else + ..() /obj/structure/closet/body_bag/proc/get_occupants() var/list/occupants = list() @@ -109,34 +115,43 @@ /obj/item/bodybag/cryobag name = "stasis bag" - desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant, especially useful if short on time or in \ - a hostile enviroment." + desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ + especially useful if short on time or in a hostile enviroment." icon = 'icons/obj/cryobag.dmi' icon_state = "bodybag_folded" item_state = "bodybag_cryo_folded" origin_tech = list(TECH_BIO = 4) + var/obj/item/weapon/reagent_containers/syringe/syringe /obj/item/bodybag/cryobag/attack_self(mob/user) var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc) R.add_fingerprint(user) + if(syringe) + R.syringe = syringe + syringe = null qdel(src) /obj/structure/closet/body_bag/cryobag name = "stasis bag" - desc = "A non-reusable plastic bag designed to prevent additional damage to an occupant, especially useful if short on time or in \ - a hostile enviroment." + desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ + especially useful if short on time or in a hostile enviroment." icon = 'icons/obj/cryobag.dmi' item_path = /obj/item/bodybag/cryobag store_misc = 0 store_items = 0 var/used = 0 var/obj/item/weapon/tank/tank = null + var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1) + var/obj/item/weapon/reagent_containers/syringe/syringe /obj/structure/closet/body_bag/cryobag/New() tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened. ..() /obj/structure/closet/body_bag/cryobag/Destroy() + if(syringe) + qdel(syringe) + syringe = null qdel(tank) tank = null ..() @@ -151,11 +166,19 @@ O.desc = "Pretty useless now.." qdel(src) +/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) + . = ..() + if(. && syringe) + var/obj/item/bodybag/cryobag/folded = . + folded.syringe = syringe + syringe = null + /obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM) if(ishuman(AM)) var/mob/living/carbon/human/H = AM - H.in_stasis = 1 + H.Stasis(stasis_level) src.used = 1 + inject_occupant(H) if(istype(AM, /obj/item/organ)) var/obj/item/organ/O = AM @@ -167,7 +190,7 @@ /obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM) if(ishuman(AM)) var/mob/living/carbon/human/H = AM - H.in_stasis = 0 + H.Stasis(0) if(istype(AM, /obj/item/organ)) var/obj/item/organ/O = AM @@ -181,10 +204,19 @@ return tank.air_contents ..() +/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H) + if(!syringe) + return + + if(H.reagents) + syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD) + /obj/structure/closet/body_bag/cryobag/examine(mob/user) ..() if(Adjacent(user)) //The bag's rather thick and opaque from a distance. user << "You peer into \the [src]." + if(syringe) + user << "It has a syringe added to it." for(var/mob/living/L in contents) L.examine(user) @@ -196,5 +228,28 @@ var/obj/item/device/healthanalyzer/analyzer = W for(var/mob/living/L in contents) analyzer.attack(L,user) + + else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) + if(syringe) + to_chat(user,"\The [src] already has an injector! Remove it first.") + else + var/obj/item/weapon/reagent_containers/syringe/syringe = W + to_chat(user,"You insert \the [syringe] into \the [src], and it locks into place.") + user.unEquip(syringe) + src.syringe = syringe + syringe.loc = null + for(var/mob/living/carbon/human/H in contents) + inject_occupant(H) + break + + else if(istype(W,/obj/item/weapon/screwdriver)) + if(syringe) + if(used) + to_chat(user,"The injector cannot be removed now that the stasis bag has been used!") + else + syringe.forceMove(src.loc) + to_chat(user,"You pry \the [syringe] out of \the [src].") + syringe = null + else ..() diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 674e746c28b..667adfc712f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1105,6 +1105,8 @@ var/global/list/obj/item/device/pda/PDAs = list() if(M.stat == DEAD && M.client && (M.is_preference_enabled(/datum/client_preference/ghost_ears))) // src.client is so that ghosts don't have to listen to mice if(istype(M, /mob/new_player)) continue + if(M.forbid_seeing_deadchat) + continue M.show_message("PDA Message - [owner] -> [P.owner]: [t]") if(!conversations.Find("\ref[P]")) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index 8bfe2dffca2..42c8e4949b7 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -212,6 +212,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() alert_called = 0 update_icon() ui_interact(user) + if(video_source) + watch_video(user) // Proc: MouseDrop() //Same thing PDAs do @@ -1032,7 +1034,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(!Adjacent(user) || !video_source) return user.set_machine(video_source) user.reset_view(video_source) - user << "Now viewing video session. To leave camera view: OOC -> Cancel Camera View" + to_chat(user,"Now viewing video session. To leave camera view, close the communicator window OR: OOC -> Cancel Camera View") + to_chat(user,"To return to an active video session, use the communicator in your hand.") spawn(0) while(user.machine == video_source && Adjacent(user)) var/turf/T = get_turf(video_source) diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index b553f4416ce..62d7e7b311c 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -92,8 +92,8 @@ flash_strength *= H.species.flash_mod if(flash_strength > 0) - H.confused = max(H.confused, flash_strength + 5) - H.eye_blind = max(H.eye_blind, flash_strength) + H.Confuse(flash_strength + 5) + H.Blind(flash_strength) H.eye_blurry = max(H.eye_blurry, flash_strength + 5) H.flash_eyes() H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun. diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 1bd7f9349ad..74d9a4b8ed2 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -65,10 +65,12 @@ var/global/list/default_medbay_channels = list( ..() wires = new(src) internal_channels = default_internal_channels.Copy() + listening_objects += src /obj/item/device/radio/Destroy() qdel(wires) wires = null + listening_objects -= src if(radio_controller) radio_controller.remove_object(src, frequency) for (var/ch_name in channels) @@ -474,7 +476,6 @@ var/global/list/default_medbay_channels = list( /obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null) - if (broadcasting) if(get_dist(src, M) <= canhear_range) talk_into(M, msg,null,verb,speaking) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 243d301289b..5d883784aa0 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -69,7 +69,7 @@ REAGENT SCANNER user.show_message("Analyzing Results for [M]:") user.show_message("Overall Status: dead") else - user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.maxHealth)*100) ]% healthy"]") + user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]") user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1) user.show_message(" Damage Specifics: [OX] - [TX] - [BU] - [BR]") user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1) diff --git a/code/game/objects/items/devices/translator.dm b/code/game/objects/items/devices/translator.dm index 90fb43724ed..5de1ba13961 100644 --- a/code/game/objects/items/devices/translator.dm +++ b/code/game/objects/items/devices/translator.dm @@ -47,6 +47,9 @@ var/mob/living/L = loc + if(!language) + return //Borgs were causing runtimes when passing language=null + if (language && (language.flags & NONVERBAL)) return //Not gonna translate sign language diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 15f33103225..db4e890d604 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -155,7 +155,7 @@ singular_name = "advanced trauma kit" desc = "An advanced trauma kit for severe injuries." icon_state = "traumakit" - heal_brute = 0 + heal_brute = 5 origin_tech = list(TECH_BIO = 1) /obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) @@ -213,7 +213,7 @@ singular_name = "advanced burn kit" desc = "An advanced treatment kit for severe burns." icon_state = "burnkit" - heal_burn = 0 + heal_burn = 5 origin_tech = list(TECH_BIO = 1) diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 10a847b4695..d404b5cd445 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -39,7 +39,7 @@ RSF playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) if (mode == 1) mode = 2 - user << "Changed dispensing mode to 'Drinking Glass'" + user << "Changed dispensing mode to 'Drinking Glass:Pint'" return if (mode == 2) mode = 3 @@ -82,7 +82,7 @@ RSF product = new /obj/item/clothing/mask/smokable/cigarette() used_energy = 10 if(2) - product = new /obj/item/weapon/reagent_containers/food/drinks/glass2() + product = new /obj/item/weapon/reagent_containers/food/drinks/glass2/pint() used_energy = 50 if(3) product = new /obj/item/weapon/paper() diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 76c4f9e7688..ee2d2f2c57a 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -399,21 +399,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM ..() name = "empty [initial(name)]" -/obj/item/clothing/mask/smokable/pipe/light(var/flavor_text = "[usr] lights the [name].") - if(!src.lit && src.smoketime) - src.lit = 1 - damtype = "fire" - icon_state = icon_on - item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - processing_objects.Add(src) - if(ismob(loc)) - var/mob/living/M = loc - M.update_inv_wear_mask(0) - M.update_inv_l_hand(0) - M.update_inv_r_hand(1) - /obj/item/clothing/mask/smokable/pipe/attack_self(mob/user as mob) if(lit == 1) if(user.a_intent == I_HURT) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 1190d7f8120..62941c24f08 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -41,6 +41,8 @@ user << "You need to have a firm grip on [C] before you can put \the [src] on!" /obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user) + if(user == target) + return 1 if(istype(user, /mob/living/silicon/robot)) if(user.Adjacent(target)) return 1 diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm index cf55cbd7067..db24be3c0af 100644 --- a/code/game/objects/items/weapons/implants/implantcircuits.dm +++ b/code/game/objects/items/weapons/implants/implantcircuits.dm @@ -38,7 +38,10 @@ IC.examine(user) /obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user) - if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) ) + if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) || istype(O, /obj/item/weapon/cell/device) ) IC.attackby(O, user) else - ..() \ No newline at end of file + ..() + +/obj/item/weapon/implant/integrated_circuit/attack_self(mob/user) + IC.attack_self(user) \ No newline at end of file diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index b13b5e6ac22..87b635ce50e 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -7,7 +7,7 @@ /obj/item/weapon/material/kitchen/utensil w_class = ITEMSIZE_TINY thrown_force_divisor = 1 - origin_tech = "materials=1" + origin_tech = list(TECH_MATERIAL = 1) attack_verb = list("attacked", "stabbed", "poked") sharp = 1 edge = 1 diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 593b1d92376..9545504f84e 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -64,7 +64,7 @@ edge = 1 force_divisor = 0.15 // 9 when wielded with hardness 60 (steel) matter = list(DEFAULT_WALL_MATERIAL = 12000) - origin_tech = "materials=1" + origin_tech = list(TECH_MATERIAL = 1) attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") /obj/item/weapon/material/knife/suicide_act(mob/user) diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm new file mode 100644 index 00000000000..1041fb5d1fd --- /dev/null +++ b/code/game/objects/items/weapons/material/material_armor.dm @@ -0,0 +1,263 @@ +#define MATERIAL_ARMOR_COEFFICENT 0.05 +/* +SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM. +This class of armor takes armor and appearance data from a material "datum". +They are also fragile based on material data and many can break/smash apart when hit. + +Materials has a var called protectiveness which plays a major factor in how good it is for armor. +With the coefficent being 0.05, this is how strong different levels of protectiveness are (for melee) +For bullets and lasers, material hardness and reflectivity also play a major role, respectively. + + +Protectiveness | Armor % + 0 = 0% + 5 = 20% + 10 = 33% + 15 = 42% + 20 = 50% + 25 = 55% + 30 = 60% + 40 = 66% + 50 = 71% + 60 = 75% + 70 = 77% + 80 = 80% +*/ + + +// Putting these at /clothing/ level saves a lot of code duplication in armor/helmets/gauntlets/etc +/obj/item/clothing + var/material/material = null // Why isn't this a datum? + var/applies_material_color = TRUE + var/unbreakable = FALSE + var/default_material = null // Set this to something else if you want material attributes on init. + var/material_armor_modifer = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor) + +/obj/item/clothing/New(var/newloc, var/material_key) + ..(newloc) + if(!material_key) + material_key = default_material + if(material_key) // May still be null if a material was not specified as a default. + set_material(material_key) + +/obj/item/clothing/Destroy() + processing_objects -= src + ..() + +/obj/item/clothing/get_material() + return material + +// Debating if this should be made an /obj/item/ proc. +/obj/item/clothing/proc/set_material(var/new_material) + material = get_material_by_name(new_material) + if(!material) + qdel(src) + else + name = "[material.display_name] [initial(name)]" + health = round(material.integrity/10) + if(applies_material_color) + color = material.icon_colour + if(material.products_need_process()) + processing_objects |= src + update_armor() + +// This is called when someone wearing the object gets hit in some form (melee, bullet_act(), etc). +// Note that this cannot change if someone gets hurt, as it merely reacts to being hit. +/obj/item/clothing/proc/clothing_impact(var/obj/source, var/damage) + if(material && damage) + material_impact(source, damage) + +/obj/item/clothing/proc/material_impact(var/obj/source, var/damage) + if(!material || unbreakable) + return + + if(istype(source, /obj/item/projectile)) + var/obj/item/projectile/P = source + if(P.pass_flags & PASSGLASS) + if(material.opacity - 0.3 <= 0) + return // Lasers ignore 'fully' transparent material. + + if(material.is_brittle()) + health = 0 + else if(!prob(material.hardness)) + health-- + + if(health <= 0) + shatter() + +/obj/item/clothing/proc/shatter() + if(!material) + return + var/turf/T = get_turf(src) + T.visible_message("\The [src] [material.destruction_desc]!") + if(istype(loc, /mob/living)) + var/mob/living/M = loc + M.drop_from_inventory(src) + if(material.shard_type == SHARD_SHARD) // Wearing glass armor is a bad idea. + var/obj/item/weapon/material/shard/S = material.place_shard(T) + M.embed(S) + + playsound(src, "shatter", 70, 1) + qdel(src) + +// Might be best to make ablative vests a material armor using a new material to cut down on this copypaste. +/obj/item/clothing/suit/armor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + if(!material) // No point checking for reflection. + return ..() + + if(material.reflectivity) + if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam)) + var/obj/item/projectile/P = damage_source + + if(P.reflected) // Can't reflect twice + return ..() + + var/reflectchance = (40 * material.reflectivity) - round(damage/3) + reflectchance *= material_armor_modifer + if(!(def_zone in list(BP_TORSO, BP_GROIN))) + reflectchance /= 2 + if(P.starting && prob(reflectchance)) + visible_message("\The [user]'s [src.name] reflects [attack_text]!") + + // Find a turf near or on the original location to bounce to + var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/turf/curloc = get_turf(user) + + // redirect the projectile + P.redirect(new_x, new_y, curloc, user) + P.reflected = 1 + + return PROJECTILE_CONTINUE // complete projectile permutation + +/proc/calculate_material_armor(amount) + var/result = 1 - MATERIAL_ARMOR_COEFFICENT * amount / (1 + MATERIAL_ARMOR_COEFFICENT * abs(amount)) + result = result * 100 + result = abs(result - 100) + return round(result) + + +/obj/item/clothing/proc/update_armor() + if(material) + var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0 + + melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer) + + bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifer) * 0.7) + + laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifer) * 0.7) + if(material.opacity != 1) + laser_armor *= max(material.opacity - 0.3, 0) // Glass and such has an opacity of 0.3, but lasers should go through glass armor entirely. + + energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.4) + + bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5) + + // Makes sure the numbers stay capped. + for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor)) + number = between(0, number, 100) + + armor["melee"] = melee_armor + armor["bullet"] = bullet_armor + armor["laser"] = laser_armor + armor["energy"] = energy_armor + armor["bomb"] = bomb_armor + + if(!isnull(material.conductivity)) + siemens_coefficient = between(0, material.conductivity / 10, 10) + slowdown = between(0, round(material.weight / 10, 0.1), 6) + +/obj/item/clothing/suit/armor/material + name = "armor" + default_material = DEFAULT_WALL_MATERIAL + +/obj/item/clothing/suit/armor/material/makeshift + name = "sheet armor" + desc = "This appears to be two 'sheets' of a material held together by cable. If the sheets are strong, this could be rather protective." + icon_state = "material_armor_makeshift" + +/obj/item/clothing/suit/armor/material/makeshift/durasteel + default_material = "durasteel" + +/obj/item/clothing/suit/armor/material/makeshift/glass + default_material = "glass" + +// Used to craft sheet armor, and possibly other things in the Future(tm). +/obj/item/weapon/material/armor_plating + name = "armor plating" + desc = "A sheet designed to protect something." + icon = 'icons/obj/items.dmi' + icon_state = "armor_plate" + unbreakable = TRUE + force_divisor = 0.05 // Really bad as a weapon. + thrown_force_divisor = 0.2 + var/wired = FALSE + +/obj/item/weapon/material/armor_plating/attackby(var/obj/O, mob/user) + if(istype(O, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/S = O + if(wired) + to_chat(user, "This already has enough wires on it.") + return + if(S.use(20)) + to_chat(user, "You attach several wires to \the [src]. Now it needs another plate.") + wired = TRUE + icon_state = "[initial(icon_state)]_wired" + return + else + to_chat(user, "You need more wire for that.") + return + if(istype(O, /obj/item/weapon/material/armor_plating)) + var/obj/item/weapon/material/armor_plating/second_plate = O + if(!wired && !second_plate.wired) + to_chat(user, "You need something to hold the two pieces of plating together.") + return + if(second_plate.material != src.material) + to_chat(user, "Both plates need to be the same type of material.") + return + user.drop_from_inventory(src) + user.drop_from_inventory(second_plate) + var/obj/item/clothing/suit/armor/material/makeshift/new_armor = new(null, src.material.name) + user.put_in_hands(new_armor) + qdel(second_plate) + qdel(src) + else + ..() + + +// Used to craft the makeshift helmet +/obj/item/clothing/head/helmet/bucket + name = "bucket" + desc = "It's a bucket with a large hole cut into it. You could wear it on your head and look really stupid." + flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR + icon_state = "bucket" + armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/head/helmet/bucket/attackby(var/obj/O, mob/user) + if(istype(O, /obj/item/stack/material)) + var/obj/item/stack/material/S = O + if(S.use(2)) + to_chat(user, "You apply some [S.material.use_name] to \the [src]. Hopefully it'll make the makeshift helmet stronger.") + var/obj/item/clothing/head/helmet/material/makeshift/helmet = new(null, S.material.name) + user.put_in_hands(helmet) + user.drop_from_inventory(src) + qdel(src) + return + else + to_chat(user, "You don't have enough material to build a helmet!") + else + ..() + +/obj/item/clothing/head/helmet/material + name = "helmet" + flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR + default_material = DEFAULT_WALL_MATERIAL + +/obj/item/clothing/head/helmet/material/makeshift + name = "bucket" + desc = "A bucket with plating applied to the outside. Very crude, but could potentially be rather protective, if \ + it was plated with something strong." + icon_state = "material_armor_makeshift" + +/obj/item/clothing/head/helmet/material/makeshift/durasteel + default_material = "durasteel" \ No newline at end of file diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm index 5edd1c77b57..2d85bc0a663 100644 --- a/code/game/objects/items/weapons/material/misc.dm +++ b/code/game/objects/items/weapons/material/misc.dm @@ -29,7 +29,7 @@ w_class = ITEMSIZE_SMALL sharp = 1 edge = 1 - origin_tech = "materials=2;combat=1" + origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1) attack_verb = list("chopped", "torn", "cut") applies_material_colour = 0 @@ -99,5 +99,5 @@ throw_range = 3 w_class = ITEMSIZE_LARGE slot_flags = SLOT_BACK - origin_tech = "materials=2;combat=2" + origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 2) attack_verb = list("chopped", "sliced", "cut", "reaped") diff --git a/code/game/objects/items/weapons/permits.dm b/code/game/objects/items/weapons/permits.dm index bb0ebfdd0c2..8008959460a 100644 --- a/code/game/objects/items/weapons/permits.dm +++ b/code/game/objects/items/weapons/permits.dm @@ -32,4 +32,9 @@ /obj/item/weapon/permit/gun/bar name = "bar shotgun permit" - desc = "A card indicating that the owner is allowed to carry a shotgun in the bar." \ No newline at end of file + desc = "A card indicating that the owner is allowed to carry a shotgun in the bar." + +/obj/item/weapon/permit/drone + name = "drone identification card" + desc = "A card issued by the EIO, indicating that the owner is a Drone Intelligence. Drones are mandated to carry this card within SolGov space, by law." + icon_state = "drone" \ No newline at end of file diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm index a9f2a15deaf..9b4cb3ca9bc 100644 --- a/code/game/objects/items/weapons/policetape.dm +++ b/code/game/objects/items/weapons/policetape.dm @@ -2,12 +2,12 @@ /obj/item/taperoll name = "tape roll" icon = 'icons/policetape.dmi' - icon_state = "rollstart" + icon_state = "tape" w_class = ITEMSIZE_SMALL var/turf/start var/turf/end var/tape_type = /obj/item/tape - var/icon_base + var/icon_base = "tape" var/apply_tape = FALSE @@ -33,7 +33,7 @@ var/list/tape_roll_applications = list() var/lifted = 0 var/crumpled = 0 var/tape_dir = 0 - var/icon_base + var/icon_base = "tape" /obj/item/tape/update_icon() //Possible directional bitflags: 0 (AIRLOCK), 1 (NORTH), 2 (SOUTH), 4 (EAST), 8 (WEST), 3 (VERTICAL), 12 (HORIZONTAL) @@ -60,22 +60,20 @@ var/list/tape_roll_applications = list() /obj/item/taperoll/police name = "police tape" desc = "A roll of police tape used to block off crime scenes from the public." - icon_state = "police" tape_type = /obj/item/tape/police - icon_base = "police" + color = COLOR_RED_LIGHT /obj/item/tape/police name = "police tape" desc = "A length of police tape. Do not cross." req_access = list(access_security) - icon_base = "police" + color = COLOR_RED_LIGHT /obj/item/taperoll/engineering name = "engineering tape" desc = "A roll of engineering tape used to block off working areas from the public." - icon_state = "engineering" tape_type = /obj/item/tape/engineering - icon_base = "engineering" + color = COLOR_YELLOW /obj/item/taperoll/engineering/applied apply_tape = TRUE @@ -84,28 +82,31 @@ var/list/tape_roll_applications = list() name = "engineering tape" desc = "A length of engineering tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) - icon_base = "engineering" + color = COLOR_YELLOW /obj/item/taperoll/atmos name = "atmospherics tape" desc = "A roll of atmospherics tape used to block off working areas from the public." - icon_state = "atmos" tape_type = /obj/item/tape/atmos - icon_base = "atmos" + color = COLOR_DEEP_SKY_BLUE /obj/item/tape/atmos name = "atmospherics tape" desc = "A length of atmospherics tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) - icon_base = "atmos" + color = COLOR_DEEP_SKY_BLUE /obj/item/taperoll/update_icon() overlays.Cut() + var/image/overlay = image(icon = src.icon) + overlay.appearance_flags = RESET_COLOR if(ismob(loc)) if(!start) - overlays += "start" + overlay.icon_state = "start" else - overlays += "stop" + overlay.icon_state = "stop" + overlays += overlay + /obj/item/taperoll/dropped(mob/user) update_icon() diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index b6fc2f42511..04e5aa909bf 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -163,6 +163,15 @@ overlays = null qdel(src) +/obj/item/weapon/ducttape/attackby(var/obj/item/I, var/mob/user) + if(!(istype(src, /obj/item/weapon/handcuffs/cable/tape) || istype(src, /obj/item/clothing/mask/muzzle/tape))) + return ..() + else + user.drop_from_inventory(I) + I.loc = src + qdel(I) + to_chat(user, "You place \the [I] back into \the [src].") + /obj/item/weapon/ducttape/afterattack(var/A, mob/user, flag, params) if(!in_range(user, A) || istype(A, /obj/machinery/door) || !stuck) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 1080e1b8fbe..8c4067187fe 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -401,7 +401,7 @@ user.sdisabilities |= BLIND else if (E.damage >= E.min_bruised_damage) user << "You go blind!" - user.eye_blind = 5 + user.Blind(5) user.eye_blurry = 5 user.disabilities |= NEARSIGHTED spawn(100) diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index cd11af34000..e6abdcb366e 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -8,7 +8,7 @@ desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off." throwforce = 0 w_class = ITEMSIZE_NORMAL - origin_tech = "materials=1" + origin_tech = list(TECH_MATERIAL = 1) matter = list(DEFAULT_WALL_MATERIAL = 18750) var/deployed = 0 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index bd280787827..42ee6af2e3e 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -77,34 +77,44 @@ return return + /obj/structure/morgue/attack_hand(mob/user as mob) if (src.connected) - for(var/atom/movable/A as mob|obj in src.connected.loc) - if (!( A.anchored )) - A.forceMove(src) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src.connected) - src.connected = null + close() else - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, src.dir) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, src.dir) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.connected.loc) - src.connected.icon_state = "morguet" - src.connected.set_dir(src.dir) - else - qdel(src.connected) - src.connected = null + open() src.add_fingerprint(user) update() return + +/obj/structure/morgue/proc/close() + for(var/atom/movable/A as mob|obj in src.connected.loc) + if (!( A.anchored )) + A.forceMove(src) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + qdel(src.connected) + src.connected = null + + +/obj/structure/morgue/proc/open() + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + src.connected = new /obj/structure/m_tray( src.loc ) + step(src.connected, src.dir) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, src.dir) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "morgue0" + for(var/atom/movable/A as mob|obj in src) + A.forceMove(src.connected.loc) + src.connected.icon_state = "morguet" + src.connected.set_dir(src.dir) + else + qdel(src.connected) + src.connected = null + + /obj/structure/morgue/attackby(P as obj, mob/user as mob) if (istype(P, /obj/item/weapon/pen)) var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text @@ -123,21 +133,8 @@ /obj/structure/morgue/relaymove(mob/user as mob) if (user.stat) return - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, EAST) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, EAST) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.connected.loc) - src.connected.icon_state = "morguet" - else - qdel(src.connected) - src.connected = null - return - + if (user in src.occupants) + open() /* * Morgue tray diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index 779f76fc933..2170ea30194 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -37,6 +37,7 @@ var/list/flooring_types var/descriptor = "tiles" var/flags var/can_paint + var/list/footstep_sounds = list() // key=species name, value = list of soundss /decl/flooring/grass name = "grass" @@ -90,6 +91,12 @@ var/list/flooring_types build_type = /obj/item/stack/tile/carpet damage_temperature = T0C+200 flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_CROWBAR | TURF_CAN_BURN + footstep_sounds = list("human" = list( + 'sound/effects/footstep/carpet1.ogg', + 'sound/effects/footstep/carpet2.ogg', + 'sound/effects/footstep/carpet3.ogg', + 'sound/effects/footstep/carpet4.ogg', + 'sound/effects/footstep/carpet5.ogg')) /decl/flooring/carpet/blue name = "carpet" @@ -107,6 +114,12 @@ var/list/flooring_types flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK | TURF_CAN_BURN build_type = /obj/item/stack/tile/floor can_paint = 1 + footstep_sounds = list("human" = list( + 'sound/effects/footstep/floor1.ogg', + 'sound/effects/footstep/floor2.ogg', + 'sound/effects/footstep/floor3.ogg', + 'sound/effects/footstep/floor4.ogg', + 'sound/effects/footstep/floor5.ogg')) /decl/flooring/linoleum name = "linoleum" @@ -193,6 +206,12 @@ var/list/flooring_types descriptor = "planks" build_type = /obj/item/stack/tile/wood flags = TURF_CAN_BREAK | TURF_IS_FRAGILE | TURF_REMOVE_SCREWDRIVER + footstep_sounds = list("human" = list( + 'sound/effects/footstep/wood1.ogg', + 'sound/effects/footstep/wood2.ogg', + 'sound/effects/footstep/wood3.ogg', + 'sound/effects/footstep/wood4.ogg', + 'sound/effects/footstep/wood5.ogg')) /decl/flooring/reinforced name = "reinforced floor" diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 3a7c1afdf0d..336a34b2fe3 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -13,6 +13,12 @@ var/base_desc = "The naked hull." var/base_icon = 'icons/turf/flooring/plating.dmi' var/base_icon_state = "plating" + var/static/list/base_footstep_sounds = list("human" = list( + 'sound/effects/footstep/plating1.ogg', + 'sound/effects/footstep/plating2.ogg', + 'sound/effects/footstep/plating3.ogg', + 'sound/effects/footstep/plating4.ogg', + 'sound/effects/footstep/plating5.ogg')) // Flooring data. var/flooring_override @@ -33,10 +39,13 @@ floortype = initial_flooring if(floortype) set_flooring(get_flooring_data(floortype)) + else + footstep_sounds = base_footstep_sounds /turf/simulated/floor/proc/set_flooring(var/decl/flooring/newflooring) make_plating(defer_icon_update = 1) flooring = newflooring + footstep_sounds = newflooring.footstep_sounds update_icon(1) levelupdate() @@ -53,6 +62,7 @@ desc = base_desc icon = base_icon icon_state = base_icon_state + footstep_sounds = base_footstep_sounds if(flooring) if(flooring.build_type && place_product) diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index da694061571..75c7e680835 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -31,17 +31,19 @@ var/list/outdoor_turfs = list() /turf/simulated/floor/Destroy() if(outdoors) - outdoor_turfs.Remove(src) + planet_controller.unallocateTurf(src) ..() -/turf/simulated/floor/proc/update_icon_edge() +/turf/simulated/proc/update_icon_edge() if(edge_blending_priority) for(var/checkdir in cardinal) var/turf/simulated/T = get_step(src, checkdir) if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state) var/cache_key = "[T.get_edge_icon_state()]-[checkdir]" if(!turf_edge_cache[cache_key]) - turf_edge_cache[cache_key] = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir) + var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir) + I.plane = 0 + turf_edge_cache[cache_key] = I overlays += turf_edge_cache[cache_key] /turf/simulated/proc/get_edge_icon_state() diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 77eb419ed13..781ddeeb7f7 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -35,7 +35,16 @@ water_breath.temperature = above_air.temperature return water_breath else - return null // Lying down means they're submerged, which means no air. + var/gasid = "carbon_dioxide" + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H.species && H.species.exhale_type) + gasid = H.species.exhale_type + var/datum/gas_mixture/water_breath = new() + var/datum/gas_mixture/above_air = return_air() + water_breath.adjust_gas(gasid, BREATH_MOLES) // They have no oxygen, but non-zero moles and temp + water_breath.temperature = above_air.temperature + return water_breath return return_air() // Otherwise their head is above the water, so get the air from the atmosphere instead. /turf/simulated/floor/water/Entered(atom/movable/AM, atom/oldloc) @@ -94,7 +103,7 @@ return /mob/living/water_act(amount) - adjust_fire_stacks(amount * 5) + adjust_fire_stacks(-amount * 5) for(var/atom/movable/AM in contents) AM.water_act(amount) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c13b4606d36..3f2e0064f22 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -26,6 +26,8 @@ var/movement_cost = 0 // How much the turf slows down movement, if any. + var/list/footstep_sounds = null + /turf/New() ..() for(var/atom/movable/AM as mob|obj in src) @@ -145,6 +147,9 @@ var/const/enterloopsanity = 100 else if(!is_space()) M.inertia_dir = 0 M.make_floating(0) + if(isliving(M)) + var/mob/living/L = M + L.handle_footstep(src) ..() var/objects = 0 if(A && (A.flags & PROXMOVE)) @@ -243,3 +248,11 @@ var/const/enterloopsanity = 100 /turf/proc/update_blood_overlays() return +// Called when turf is hit by a thrown object +/turf/hitby(atom/movable/AM as mob|obj, var/speed) + if(src.density) + spawn(2) + step(AM, turn(AM.last_move, 180)) + if(isliving(AM)) + var/mob/living/M = AM + M.turf_collision(src, speed) diff --git a/code/game/turfs/unsimulated/planetary.dm b/code/game/turfs/unsimulated/planetary.dm index ce4ffa44c0f..7d9159d04a1 100644 --- a/code/game/turfs/unsimulated/planetary.dm +++ b/code/game/turfs/unsimulated/planetary.dm @@ -27,6 +27,15 @@ var/list/planetary_walls = list() planetary_walls.Remove(src) ..() +/turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature) + if(new_temperature == temperature) + return + temperature = new_temperature + // Force ZAS to reconsider our connections because our temperature has changed + if(connections) + connections.erase_all() + air_master.mark_for_update(src) + // Normal station/earth air. /turf/unsimulated/wall/planetary/normal oxygen = MOLES_O2STANDARD @@ -55,3 +64,4 @@ var/list/planetary_walls = list() oxygen = MOLES_O2STANDARD nitrogen = MOLES_N2STANDARD temperature = 310.92 // About 37.7C / 100F + diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index ec84ee42329..6e23d74bbb6 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -127,7 +127,7 @@ suiciding = 1 viewers(src) << "[src] is powering down. It looks like \he's trying to commit suicide." //put em at -175 - adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + adjustOxyLoss(max(getMaxHealth() * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) updatehealth() /mob/living/silicon/robot/verb/suicide() @@ -147,7 +147,7 @@ suiciding = 1 viewers(src) << "[src] is powering down. It looks like \he's trying to commit suicide." //put em at -175 - adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + adjustOxyLoss(max(getMaxHealth() * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) updatehealth() /mob/living/silicon/pai/verb/suicide() diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index affa55ce107..439e1f1b7f2 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -249,7 +249,11 @@ "Anything Legal Considered", "New Toy", "Me, I'm Always Counting", - "Just Five More Minutes" + "Just Five More Minutes", + "Are You Feeling It", + "Great White Snark", + "No Shirt No Shoes", + "Callsign" ) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index ffea7b7fab7..099aa439787 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -408,6 +408,7 @@ projectile_type = /obj/item/projectile/chameleon charge_meter = 0 charge_cost = 48 //uses next to no power, since it's just holograms + battery_lock = 1 var/obj/item/projectile/copy_projectile var/global/list/gun_choices diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 497b145190b..e3d781df297 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -347,7 +347,9 @@ body_parts_covered = FACE|EYES sprite_sheets = list( "Teshari" = 'icons/mob/species/seromi/masks.dmi', - "Vox" = 'icons/mob/species/vox/masks.dmi' + "Vox" = 'icons/mob/species/vox/masks.dmi', + "Tajara" = 'icons/mob/species/tajaran/mask.dmi', + "Unathi" = 'icons/mob/species/unathi/mask.dmi' ) var/voicechange = 0 diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 137cab1a01d..4fb748f73ae 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -132,7 +132,7 @@ BLIND // can't see anything eye = !eye if(eye) - icon_state = "[icon_state]_r" + icon_state = "[icon_state]_1" else icon_state = initial(icon_state) update_clothing_icon() @@ -395,14 +395,15 @@ BLIND // can't see anything toggleable = 1 action_button_name = "Toggle Goggles" vision_flags = SEE_MOBS - see_invisible = INVISIBILITY_LEVEL_TWO + see_invisible = SEE_INVISIBLE_NOLIGHTING + emp_act(severity) if(istype(src.loc, /mob/living/carbon/human)) var/mob/living/carbon/human/M = src.loc M << "\red The Optical Thermal Scanner overloads and blinds you!" if(M.glasses == src) - M.eye_blind = 3 + M.Blind(3) M.eye_blurry = 5 // Don't cure being nearsighted if(!(M.disabilities & NEARSIGHTED)) diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 978a5c13e60..5a311c51724 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -6,10 +6,6 @@ flags_inv = HIDEFACE|BLOCKHAIR body_parts_covered = FACE|HEAD w_class = ITEMSIZE_SMALL - sprite_sheets = list( - "Tajara" = 'icons/mob/species/tajaran/mask.dmi', - "Unathi" = 'icons/mob/species/unathi/mask.dmi', - ) /obj/item/clothing/mask/balaclava/tactical name = "green balaclava" @@ -18,10 +14,6 @@ item_state_slots = list(slot_r_hand_str = "bandgreen", slot_l_hand_str = "bandgreen") flags_inv = HIDEFACE|BLOCKHAIR w_class = ITEMSIZE_SMALL - sprite_sheets = list( - "Tajara" = 'icons/mob/species/tajaran/mask.dmi', - "Unathi" = 'icons/mob/species/unathi/mask.dmi', - ) /obj/item/clothing/mask/luchador name = "Luchador Mask" diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index ff0f8ae0776..e23c3c0c264 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -34,7 +34,7 @@ item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | PHORONGUARD allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank) phoronproof = 1 - slowdown = 2 + slowdown = 0.5 armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 100, rad = 50) siemens_coefficient = 0.2 heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index d08726371a9..f0903123205 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -80,6 +80,9 @@ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam)) var/obj/item/projectile/P = damage_source + if(P.reflected) // Can't reflect twice + return ..() + var/reflectchance = 40 - round(damage/3) if(!(def_zone in list(BP_TORSO, BP_GROIN))) reflectchance /= 2 diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm index d9dc2f2e540..5d734c9d95a 100644 --- a/code/modules/clothing/under/accessories/holster.dm +++ b/code/modules/clothing/under/accessories/holster.dm @@ -76,10 +76,12 @@ /obj/item/clothing/accessory/holster/on_attached(obj/item/clothing/under/S, mob/user as mob) ..() - has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb + if(has_suit) + has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb /obj/item/clothing/accessory/holster/on_removed(mob/user as mob) - has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb + if(has_suit) + has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb ..() //For the holster hotkey @@ -105,7 +107,7 @@ if(!H.holstered) var/obj/item/W = usr.get_active_hand() if(!istype(W, /obj/item)) - usr << "You need your gun equiped to holster it." + usr << "You need your gun equipped to holster it." return H.holster(W, usr) else diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index e09c062ab01..d0f9a8165cb 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -41,9 +41,11 @@ i++ /datum/event/carp_migration/end() - for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp) - if(!C.stat) - var/turf/T = get_turf(C) - if(istype(T, /turf/space)) - if(!prob(25)) - qdel(C) \ No newline at end of file + spawn(0) + for(var/mob/living/simple_animal/hostile/C in spawned_carp) + if(!C.stat) + var/turf/T = get_turf(C) + if(istype(T, /turf/space)) + if(prob(75)) + qdel(C) + sleep(1) \ No newline at end of file diff --git a/code/modules/genetics/side_effects.dm b/code/modules/genetics/side_effects.dm index dcb5b4e4990..f3a9efb6d2b 100644 --- a/code/modules/genetics/side_effects.dm +++ b/code/modules/genetics/side_effects.dm @@ -72,7 +72,7 @@ finish(mob/living/carbon/human/H) if(!H.reagents.has_reagent("anti_toxin")) - H.confused += 100 + H.Confuse(100) proc/trigger_side_effect(mob/living/carbon/human/H) spawn diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm index eb18581551b..ff0b95f3653 100644 --- a/code/modules/holodeck/HolodeckControl.dm +++ b/code/modules/holodeck/HolodeckControl.dm @@ -18,23 +18,57 @@ var/mob/last_to_emag = null var/last_change = 0 var/last_gravity_change = 0 - var/list/supported_programs = list( \ - "Empty Court" = "emptycourt", \ - "Basketball Court" = "basketball", \ - "Thunderdome Court" = "thunderdomecourt", \ - "Boxing Ring"="boxingcourt", \ - "Beach" = "beach", \ - "Desert" = "desert", \ - "Space" = "space", \ - "Picnic Area" = "picnicarea", \ - "Snow Field" = "snowfield", \ - "Theatre" = "theatre", \ - "Meeting Hall" = "meetinghall", \ - "Courtroom" = "courtroom", \ - "Turn Off" = "turnoff" \ + + var/area/projection_area = /area/holodeck/alphadeck + var/current_program + var/powerdown_program = "Turn Off" + var/default_program = "Empty Court" + + var/list/supported_programs = list( + "Empty Court" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')), + "Boxing Ring" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')), + "Basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')), + "Thunderdome" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')), + "Beach" = new/datum/holodeck_program(/area/holodeck/source_beach), + "Desert" = new/datum/holodeck_program(/area/holodeck/source_desert, + list( + 'sound/effects/wind/wind_2_1.ogg', + 'sound/effects/wind/wind_2_2.ogg', + 'sound/effects/wind/wind_3_1.ogg', + 'sound/effects/wind/wind_4_1.ogg', + 'sound/effects/wind/wind_4_2.ogg', + 'sound/effects/wind/wind_5_1.ogg' + ) + ), + "Snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield, + list( + 'sound/effects/wind/wind_2_1.ogg', + 'sound/effects/wind/wind_2_2.ogg', + 'sound/effects/wind/wind_3_1.ogg', + 'sound/effects/wind/wind_4_1.ogg', + 'sound/effects/wind/wind_4_2.ogg', + 'sound/effects/wind/wind_5_1.ogg' + ) + ), + "Space" = new/datum/holodeck_program(/area/holodeck/source_space, + list( + 'sound/ambience/ambispace.ogg', + 'sound/music/main.ogg', + 'sound/music/space.ogg', + 'sound/music/traitor.ogg', + ) + ), + "Picnic Area" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')), + "Theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre), + "Meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall), + "Courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')), + "Turn Off" = new/datum/holodeck_program(/area/holodeck/source_plating, list()) + ) + + var/list/restricted_programs = list( + "Burnoff Test Simulation" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()), + "Wildlife Simulation" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()) ) - var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp") - var/current_program = "turnoff" /obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob) return src.attack_hand(user) @@ -59,10 +93,10 @@ var/restricted_program_list[0] for(var/P in supported_programs) - program_list[++program_list.len] = list("name" = P, "program" = supported_programs[P]) + program_list[++program_list.len] = P for(var/P in restricted_programs) - restricted_program_list[++restricted_program_list.len] = list("name" = P, "program" = restricted_programs[P]) + restricted_program_list[++restricted_program_list.len] = P data["supportedPrograms"] = program_list data["restrictedPrograms"] = restricted_program_list @@ -93,9 +127,9 @@ if(href_list["program"]) var/prog = href_list["program"] - if(prog in holodeck_programs) - loadProgram(holodeck_programs[prog]) - current_program = href_list["program"] + if(prog in (supported_programs + restricted_programs)) + loadProgram(prog) + current_program = prog else if(href_list["AIoverride"]) if(!issilicon(usr)) @@ -150,7 +184,10 @@ /obj/machinery/computer/HolodeckControl/New() ..() - linkedholodeck = locate(/area/holodeck/alphadeck) + current_program = powerdown_program + linkedholodeck = locate(projection_area) + if(!linkedholodeck) + world << "Holodeck computer at [x],[y],[z] failed to locate projection area." //This could all be done better, but it works for now. /obj/machinery/computer/HolodeckControl/Destroy() @@ -185,7 +222,7 @@ if(!checkInteg(linkedholodeck)) damaged = 1 - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) active = 0 use_power = 1 for(var/mob/M in range(10,src)) @@ -227,9 +264,9 @@ //Why is it called toggle if it doesn't toggle? /obj/machinery/computer/HolodeckControl/proc/togglePower(var/toggleOn = 0) if(toggleOn) - loadProgram(holodeck_programs["emptycourt"], 0) + loadProgram(default_program, 0) else - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) if(!linkedholodeck.has_gravity) linkedholodeck.gravitychange(1,linkedholodeck) @@ -238,9 +275,18 @@ use_power = 1 -/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/datum/holodeck_program/HP, var/check_delay = 1) +/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/prog, var/check_delay = 1) + if(!prog) + return + + var/datum/holodeck_program/HP + if(prog in supported_programs) + HP = supported_programs[prog] + else if(prog in restricted_programs) + HP = restricted_programs[prog] if(!HP) return + var/area/A = locate(HP.target) if(!A) return @@ -324,7 +370,7 @@ /obj/machinery/computer/HolodeckControl/proc/emergencyShutdown() //Turn it back to the regular non-holographic room - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) if(!linkedholodeck.has_gravity) linkedholodeck.gravitychange(1,linkedholodeck) diff --git a/code/modules/holodeck/HolodeckPrograms.dm b/code/modules/holodeck/HolodeckPrograms.dm index 9cb77f2a4bd..4ae4361a21c 100644 --- a/code/modules/holodeck/HolodeckPrograms.dm +++ b/code/modules/holodeck/HolodeckPrograms.dm @@ -1,46 +1,3 @@ -var/global/list/holodeck_programs = list( - "emptycourt" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')), - "boxingcourt" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')), - "basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')), - "thunderdomecourt" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')), - "beach" = new/datum/holodeck_program(/area/holodeck/source_beach), - "desert" = new/datum/holodeck_program(/area/holodeck/source_desert, - list( - 'sound/effects/wind/wind_2_1.ogg', - 'sound/effects/wind/wind_2_2.ogg', - 'sound/effects/wind/wind_3_1.ogg', - 'sound/effects/wind/wind_4_1.ogg', - 'sound/effects/wind/wind_4_2.ogg', - 'sound/effects/wind/wind_5_1.ogg' - ) - ), - "snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield, - list( - 'sound/effects/wind/wind_2_1.ogg', - 'sound/effects/wind/wind_2_2.ogg', - 'sound/effects/wind/wind_3_1.ogg', - 'sound/effects/wind/wind_4_1.ogg', - 'sound/effects/wind/wind_4_2.ogg', - 'sound/effects/wind/wind_5_1.ogg' - ) - ), - "space" = new/datum/holodeck_program(/area/holodeck/source_space, - list( - 'sound/ambience/ambispace.ogg', - 'sound/music/main.ogg', - 'sound/music/space.ogg', - 'sound/music/traitor.ogg', - ) - ), - "picnicarea" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')), - "theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre), - "meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall), - "courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')), - "burntest" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()), - "wildlifecarp" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()), - "turnoff" = new/datum/holodeck_program(/area/holodeck/source_plating, list()) - ) - /datum/holodeck_program var/target var/list/ambience = null diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index c404f615812..7089c19d515 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -8,7 +8,7 @@ #define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box. #define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD. -#define IC_FORMAT_STRING "\" +#define IC_FORMAT_STRING "\" #define IC_FORMAT_NUMBER "\" #define IC_FORMAT_REF "\" #define IC_FORMAT_LIST "\" diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index 88b804f80a3..5c49e1817c7 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -107,6 +107,7 @@ for(var/obj/item/integrated_circuit/circuit in contents) HTML += "[circuit.name] | " HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " if(circuit.removable) HTML += "\[Remove\]" HTML += "
" @@ -223,9 +224,10 @@ if(proximity) var/scanned = FALSE for(var/obj/item/integrated_circuit/input/sensor/S in contents) - S.set_pin_data(IC_OUTPUT, 1, weakref(target)) - S.check_then_do_work() - scanned = TRUE +// S.set_pin_data(IC_OUTPUT, 1, weakref(target)) +// S.check_then_do_work() + if(S.scan(target)) + scanned = TRUE if(scanned) visible_message("\The [user] waves \the [src] around [target].") diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 87bb4cd182f..1593297734d 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -6,6 +6,7 @@ a creative player the means to solve many problems. Circuits are held inside an /obj/item/integrated_circuit/examine(mob/user) . = ..() external_examine(user) + interact(user) // This should be used when someone is examining while the case is opened. /obj/item/integrated_circuit/proc/internal_examine(mob/user) @@ -86,16 +87,14 @@ a creative player the means to solve many problems. Circuits are held inside an var/HTML = list() HTML += "[src.name]" HTML += "
" - HTML += "" + HTML += "
" HTML += "
\[Refresh\] | " HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " HTML += "\[Remove\]
" HTML += "" - //HTML += "" - //HTML += "" - //HTML += "" HTML += "" HTML += "" HTML += "" @@ -212,6 +211,16 @@ a creative player the means to solve many problems. Circuits are held inside an if(href_list["rename"]) rename_component(usr) + if(href_list["scan"]) + if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) + var/obj/item/device/integrated_electronics/debugger/D = held_item + if(D.accepting_refs) + D.afterattack(src, usr, TRUE) + else + to_chat(usr, "The Debugger's 'ref scanner' needs to be on.") + else + to_chat(usr, "You need a Debugger set to 'ref' mode to do that.") + if(href_list["autopulse"]) if(autopulse != -1) autopulse = !autopulse @@ -260,10 +269,10 @@ a creative player the means to solve many problems. Circuits are held inside an return TRUE // Battery has enough. return FALSE // Not enough power. -/obj/item/integrated_circuit/proc/check_then_do_work() +/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE) if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam. return - if(power_draw_per_use) + if(power_draw_per_use && !ignore_power) if(!check_power()) power_fail() return diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 8220162be72..a8759174411 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -160,7 +160,7 @@ data_to_show = A.name to_chat(user, "You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].") else if(io.io_type == PULSE_CHANNEL) - io.holder.check_then_do_work() + io.holder.check_then_do_work(ignore_power = TRUE) to_chat(user, "You pulse \the [io.holder]'s [io].") io.holder.interact(user) // This is to update the UI. diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm index c6134f9bd1d..059c699e502 100644 --- a/code/modules/integrated_electronics/subtypes/arithmetic.dm +++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm @@ -1,9 +1,18 @@ //These circuits do simple math. /obj/item/integrated_circuit/arithmetic complexity = 1 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("compute") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ compute", "\ on computed") category_text = "Arithmetic" autopulse = 1 power_draw_per_use = 5 // Math is pretty cheap. @@ -30,9 +39,9 @@ if(isnum(I.data)) result = result + I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // -Subtracting- // @@ -58,9 +67,9 @@ if(isnum(I.data)) result = result - I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // *Multiply* // @@ -86,9 +95,9 @@ if(isnum(I.data)) result = result * I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // /Division/ // @@ -114,9 +123,9 @@ if(isnum(I.data) && I.data != 0) //No runtimes here. result = result / I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) //^ Exponent ^// @@ -134,9 +143,9 @@ if(isnum(A.data) && isnum(B.data)) result = A.data ** B.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // +-Sign-+ // @@ -159,9 +168,9 @@ else result = 0 - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Round // @@ -183,9 +192,9 @@ else result = round(A.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Absolute // @@ -204,9 +213,9 @@ if(isnum(I.data)) result = abs(I.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Averaging // @@ -229,9 +238,9 @@ if(inputs_used) result = result / inputs_used - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Pi, because why the hell not? // /obj/item/integrated_circuit/arithmetic/pi @@ -242,9 +251,9 @@ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/pi/do_work() - var/datum/integrated_io/output/O = outputs[1] - O.data = 3.14159 - O.push_data() + set_pin_data(IC_OUTPUT, 1, 3.14159) + push_data() + activate_pin(2) // Random // /obj/item/integrated_circuit/arithmetic/random @@ -253,20 +262,20 @@ extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \ for outputs of 1, 2, or 3. H being the higher number is not strictly required." icon_state = "random" - inputs = list("L","H") + inputs = list("\ L","\ H") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/random/do_work() var/result = 0 - var/datum/integrated_io/L = inputs[1] - var/datum/integrated_io/H = inputs[2] + var/L = get_pin_data(IC_INPUT, 1) + var/H = get_pin_data(IC_INPUT, 2) - if(isnum(L.data) && isnum(H.data)) - result = rand(L.data, H.data) + if(isnum(L) && isnum(H)) + result = rand(L, H) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Square Root // @@ -274,7 +283,7 @@ name = "square root circuit" desc = "This outputs the square root of a number you put in." icon_state = "square_root" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/square_root/do_work() @@ -284,9 +293,9 @@ if(isnum(I.data)) result = sqrt(I.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // % Modulo % // @@ -294,17 +303,17 @@ name = "modulo circuit" desc = "Gets the remainder of A / B." icon_state = "modulo" - inputs = list("A", "B") + inputs = list("\ A", "\ B") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/modulo/do_work() var/result = 0 - var/datum/integrated_io/input/A = inputs[1] - var/datum/integrated_io/input/B = inputs[2] - if(isnum(A.data) && isnum(B.data) && B.data != 0) - result = A.data % B.data + var/A = get_pin_data(IC_INPUT, 1) + var/B = get_pin_data(IC_INPUT, 2) + if(isnum(A) && isnum(B) && B != 0) + result = A % B - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm index 9e04e24db51..431faa241f9 100644 --- a/code/modules/integrated_electronics/subtypes/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -3,7 +3,7 @@ complexity = 2 inputs = list("input") outputs = list("output") - activators = list("convert") + activators = list("\ convert", "\ on convert") category_text = "Converter" autopulse = 1 power_draw_per_use = 10 @@ -16,89 +16,113 @@ name = "number to string" desc = "This circuit can convert a number variable into a string." icon_state = "num-string" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/num2text/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && isnum(incoming.data)) - result = num2text(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = num2text(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/text2num name = "string to number" desc = "This circuit can convert a string variable into a number." icon_state = "string-num" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/text2num/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = text2num(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = text2num(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/ref2text name = "reference to string" desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference." icon_state = "ref-string" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/ref2text/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - var/atom/A = incoming.data_as_type(/atom) - result = A && A.name + pull_data() + var/atom/A = get_pin_data(IC_INPUT, 1) + if(A && istype(A)) + result = A.name - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/lowercase name = "lowercase string converter" desc = "this will cause a string to come out in all lowercase." icon_state = "lowercase" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/lowercase/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = lowertext(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = lowertext(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/uppercase name = "uppercase string converter" desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE." icon_state = "uppercase" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/uppercase/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = uppertext(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = uppertext(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/concatenatior name = "concatenatior" - desc = "This joins many strings together to get one big string." + desc = "This joins many strings or numbers together to get one big string." complexity = 4 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("concatenate") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ concatenate", "\ on concatenated") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/concatenatior/do_work() @@ -107,70 +131,70 @@ I.pull_data() if(istext(I.data)) result = result + I.data + else if(!isnull(I.data) && num2text(I.data)) + result = result + num2text(I.data) var/datum/integrated_io/outgoing = outputs[1] outgoing.data = result outgoing.push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/radians2degrees name = "radians to degrees converter" desc = "Converts radians to degrees." - inputs = list("radian") - outputs = list("degrees") + inputs = list("\ radian") + outputs = list("\ degrees") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/radians2degrees/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - incoming.pull_data() - if(incoming.data && isnum(incoming.data)) - result = ToDegrees(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = ToDegrees(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/degrees2radians name = "degrees to radians converter" desc = "Converts degrees to radians." - inputs = list("degrees") - outputs = list("radians") + inputs = list("\ degrees") + outputs = list("\ radians") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/degrees2radians/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - incoming.pull_data() - if(incoming.data && isnum(incoming.data)) - result = ToRadians(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = ToRadians(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/abs_to_rel_coords name = "abs to rel coordinate converter" desc = "Easily convert absolute coordinates to relative coordinates with this." complexity = 4 - inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)") - outputs = list("X (rel)", "Y (rel)") - activators = list("compute rel coordinates") + inputs = list("\ X1", "\ Y1", "\ X2", "\ Y2") + outputs = list("\ X", "\ Y") + activators = list("\ compute rel coordinates", "\ on convert") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() - var/datum/integrated_io/x1 = inputs[1] - var/datum/integrated_io/y1 = inputs[2] + var/x1 = get_pin_data(IC_INPUT, 1) + var/y1 = get_pin_data(IC_INPUT, 2) - var/datum/integrated_io/x2 = inputs[3] - var/datum/integrated_io/y2 = inputs[4] + var/x2 = get_pin_data(IC_INPUT, 3) + var/y2 = get_pin_data(IC_INPUT, 4) - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] + if(x1 && y1 && x2 && y2) + set_pin_data(IC_OUTPUT, 1, x1 - x2) + set_pin_data(IC_OUTPUT, 2, y1 - y2) - if(x1.data && y1.data && x2.data && y2.data) - result_x.data = x1.data - x2.data - result_y.data = y1.data - y2.data - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() \ No newline at end of file + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/input_output.dm b/code/modules/integrated_electronics/subtypes/input_output.dm index baa5738d4ea..456fae889f2 100644 --- a/code/modules/integrated_electronics/subtypes/input_output.dm +++ b/code/modules/integrated_electronics/subtypes/input_output.dm @@ -14,28 +14,27 @@ can_be_asked_input = 1 inputs = list() outputs = list() - activators = list("on pressed") + activators = list("\ on pressed") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use. - var/datum/integrated_io/A = activators[1] - if(A.linked.len) - for(var/datum/integrated_io/activate/target in A.linked) - target.holder.check_then_do_work() to_chat(user, "You press the button labeled '[src.name]'.") + activate_pin(1) /obj/item/integrated_circuit/input/toggle_button name = "toggle button" desc = "It toggles on, off, on, off..." icon_state = "toggle_button" complexity = 1 + can_be_asked_input = 1 inputs = list() - outputs = list("on" = 0) - activators = list("on toggle") + outputs = list("\ on" = 0) + activators = list("\ on toggle") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto. set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1)) + push_data() activate_pin(1) to_chat(user, "You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].") @@ -46,19 +45,17 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("number entered") - activators = list("on entered") + outputs = list("\ number entered") + activators = list("\ on entered") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user) var/new_input = input(user, "Enter a number, please.","Number pad") as null|num if(isnum(new_input) && CanInteract(user, physical_state)) - var/datum/integrated_io/O = outputs[1] - O.data = new_input - O.push_data() - var/datum/integrated_io/A = activators[1] - A.push_data() + set_pin_data(IC_OUTPUT, 1, new_input) + push_data() + activate_pin(1) /obj/item/integrated_circuit/input/textpad name = "text pad" @@ -67,49 +64,43 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("string entered") - activators = list("on entered") + outputs = list("\ string entered") + activators = list("\ on entered") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user) var/new_input = input(user, "Enter some words, please.","Number pad") as null|text if(istext(new_input) && CanInteract(user, physical_state)) - var/datum/integrated_io/O = outputs[1] - O.data = new_input - O.push_data() - var/datum/integrated_io/A = activators[1] - A.push_data() + set_pin_data(IC_OUTPUT, 1, new_input) + push_data() + activate_pin(1) /obj/item/integrated_circuit/input/med_scanner name = "integrated medical analyser" desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is." icon_state = "medscan" complexity = 4 - inputs = list("target ref") - outputs = list("total health %", "total missing health") - activators = list("scan") + inputs = list("\ target") + outputs = list("\ total health %", "\ total missing health") + activators = list("\ scan", "\ on scanned") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) power_draw_per_use = 40 /obj/item/integrated_circuit/input/med_scanner/do_work() - var/datum/integrated_io/I = inputs[1] - var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human) + var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. - var/total_health = round(H.health/H.maxHealth, 0.1)*100 - var/missing_health = H.maxHealth - H.health + var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 + var/missing_health = H.getMaxHealth() - H.health - var/datum/integrated_io/total = outputs[1] - var/datum/integrated_io/missing = outputs[2] + set_pin_data(IC_OUTPUT, 1, total_health) + set_pin_data(IC_OUTPUT, 2, missing_health) - total.data = total_health - missing.data = missing_health - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/adv_med_scanner name = "integrated advanced medical analyser" @@ -117,48 +108,39 @@ This type is much more precise, allowing the machine to know much more about the target than a normal analyzer." icon_state = "medscan_adv" complexity = 12 - inputs = list("target ref") + inputs = list("\ target") outputs = list( - "total health %", - "total missing health", - "brute damage", - "burn damage", - "tox damage", - "oxy damage", - "clone damage" + "\ total health %", + "\ total missing health", + "\ brute damage", + "\ burn damage", + "\ tox damage", + "\ oxy damage", + "\ clone damage" ) - activators = list("scan") + activators = list("\ scan", "\ on scanned") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4) power_draw_per_use = 80 /obj/item/integrated_circuit/input/adv_med_scanner/do_work() - var/datum/integrated_io/I = inputs[1] - var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human) + var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. - var/total_health = round(H.health/H.maxHealth, 0.1)*100 - var/missing_health = H.maxHealth - H.health + var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 + var/missing_health = H.getMaxHealth() - H.health - var/datum/integrated_io/total = outputs[1] - var/datum/integrated_io/missing = outputs[2] - var/datum/integrated_io/brute = outputs[3] - var/datum/integrated_io/burn = outputs[4] - var/datum/integrated_io/tox = outputs[5] - var/datum/integrated_io/oxy = outputs[6] - var/datum/integrated_io/clone = outputs[7] + set_pin_data(IC_OUTPUT, 1, total_health) + set_pin_data(IC_OUTPUT, 2, missing_health) + set_pin_data(IC_OUTPUT, 3, H.getBruteLoss()) + set_pin_data(IC_OUTPUT, 4, H.getFireLoss()) + set_pin_data(IC_OUTPUT, 5, H.getToxLoss()) + set_pin_data(IC_OUTPUT, 6, H.getOxyLoss()) + set_pin_data(IC_OUTPUT, 7, H.getCloneLoss()) - total.data = total_health - missing.data = missing_health - brute.data = H.getBruteLoss() - burn.data = H.getFireLoss() - tox.data = H.getToxLoss() - oxy.data = H.getOxyLoss() - clone.data = H.getCloneLoss() - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/local_locator name = "local locator" @@ -222,9 +204,9 @@ Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin." icon_state = "signal" complexity = 4 - inputs = list("frequency","code") + inputs = list("\ frequency","\ code") outputs = list() - activators = list("send signal","on signal received") + activators = list("\ send signal","\ on signal sent", "\ on signal received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2) power_draw_idle = 5 @@ -237,11 +219,9 @@ /obj/item/integrated_circuit/input/signaler/initialize() ..() set_frequency(frequency) - var/datum/integrated_io/new_freq = inputs[1] - var/datum/integrated_io/new_code = inputs[2] // Set the pins so when someone sees them, they won't show as null - new_freq.data = frequency - new_code.data = code + set_pin_data(IC_INPUT, 1, frequency) + set_pin_data(IC_INPUT, 2, code) /obj/item/integrated_circuit/input/signaler/Destroy() if(radio_controller) @@ -250,12 +230,12 @@ . = ..() /obj/item/integrated_circuit/input/signaler/on_data_written() - var/datum/integrated_io/new_freq = inputs[1] - var/datum/integrated_io/new_code = inputs[2] - if(isnum(new_freq.data) && new_freq.data > 0) - set_frequency(new_freq.data) - if(isnum(new_code.data)) - code = new_code.data + var/new_freq = get_pin_data(IC_INPUT, 1) + var/new_code = get_pin_data(IC_INPUT, 2) + if(isnum(new_freq) && new_freq > 0) + set_frequency(new_freq) + if(isnum(new_code)) + code = new_code /obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal. @@ -267,6 +247,7 @@ signal.encryption = code signal.data["message"] = "ACTIVATE" radio_connection.post_signal(src, signal) + activate_pin(2) /obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency) if(!frequency) @@ -280,11 +261,11 @@ radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) /obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal) - var/datum/integrated_io/new_code = inputs[2] + var/new_code = get_pin_data(IC_INPUT, 2) var/code = 0 - if(isnum(new_code.data)) - code = new_code.data + if(isnum(new_code)) + code = new_code if(!signal) return 0 if(signal.encryption != code) @@ -292,8 +273,7 @@ if(signal.source == src) // Don't trigger ourselves. return 0 - var/datum/integrated_io/A = activators[2] - A.push_data() + activate_pin(3) for(var/mob/O in hearers(1, get_turf(src))) O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) @@ -306,9 +286,9 @@ will pulse whatever's connected to it. Pulsing the first activation pin will send a message." icon_state = "signal" complexity = 4 - inputs = list("target EPv2 address", "data to send", "secondary text") - outputs = list("address received", "data received", "secondary text received") - activators = list("send data", "on data received") + inputs = list("\ target EPv2 address", "\ data to send", "\ secondary text") + outputs = list("\ address received", "\ data received", "\ secondary text received") + activators = list("\ send data", "\ on data received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2) power_draw_per_use = 50 @@ -318,7 +298,7 @@ ..() exonet = new(src) exonet.make_address("EPv2_circuit-\ref[src]") - desc += "
This circuit's EPv2 address is: [exonet.address]." + desc += "
This circuit's EPv2 address is: [exonet.address]" /obj/item/integrated_circuit/input/EPv2/Destroy() if(exonet) @@ -327,64 +307,60 @@ ..() /obj/item/integrated_circuit/input/EPv2/do_work() - var/datum/integrated_io/target_address = inputs[1] - var/datum/integrated_io/message = inputs[2] - var/datum/integrated_io/text = inputs[3] - if(istext(target_address.data)) - exonet.send_message(target_address.data, message.data, text.data) + var/target_address = get_pin_data(IC_INPUT, 1) + var/message = get_pin_data(IC_INPUT, 2) + var/text = get_pin_data(IC_INPUT, 3) + + if(target_address && istext(target_address)) + exonet.send_message(target_address, message, text) /obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text) - var/datum/integrated_io/message_received = outputs[1] - var/datum/integrated_io/data_received = outputs[2] - var/datum/integrated_io/text_received = outputs[3] + set_pin_data(IC_OUTPUT, 1, origin_address) + set_pin_data(IC_OUTPUT, 2, message) + set_pin_data(IC_OUTPUT, 3, text) - var/datum/integrated_io/A = activators[2] - A.push_data() - - message_received.write_data_to_pin(origin_address) - data_received.write_data_to_pin(message) - text_received.write_data_to_pin(text) - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) //This circuit gives information on where the machine is. /obj/item/integrated_circuit/input/gps name = "global positioning system" desc = "This allows you to easily know the position of a machine containing this device." + extended_desc = "The GPS's coordinates it gives is absolute, not relative." icon_state = "gps" complexity = 4 inputs = list() - outputs = list("X (abs)", "Y (abs)") - activators = list("get coordinates") + outputs = list("\ X", "\ Y") + activators = list("\ get coordinates", "\ on get coordinates") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 /obj/item/integrated_circuit/input/gps/do_work() var/turf/T = get_turf(src) - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] - result_x.data = null - result_y.data = null + set_pin_data(IC_OUTPUT, 1, null) + set_pin_data(IC_OUTPUT, 2, null) if(!T) return - result_x.data = T.x - result_y.data = T.y + set_pin_data(IC_OUTPUT, 1, T.x) + set_pin_data(IC_OUTPUT, 2, T.y) - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/microphone name = "microphone" desc = "Useful for spying on people or for voice activated machines." + extended_desc = "This will automatically translate most languages it hears to Galactic Common. \ + The first activation pin is always pulsed when the circuit hears someone talk, while the second one \ + is only triggered if it hears someone speaking a language other than Galactic Common." icon_state = "recorder" complexity = 8 inputs = list() - outputs = list("speaker \", "message \") - activators = list("on message received") + outputs = list("\ speaker", "\ message") + activators = list("\ on message received", "\ on translation") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -397,42 +373,45 @@ ..() /obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) - var/datum/integrated_io/V = outputs[1] - var/datum/integrated_io/O = outputs[2] - var/datum/integrated_io/A = activators[1] + var/translated = FALSE if(M && msg) if(speaking) if(!speaking.machine_understands) msg = speaking.scramble(msg) - V.data = M.GetVoice() - O.data = msg - A.push_data() + if(!istype(speaking, /datum/language/common)) + translated = TRUE + set_pin_data(IC_OUTPUT, 1, M.GetVoice()) + set_pin_data(IC_OUTPUT, 2, msg) - for(var/datum/integrated_io/output/out in outputs) - out.push_data() - - A.push_data() + push_data() + activate_pin(1) + if(translated) + activate_pin(2) /obj/item/integrated_circuit/input/sensor name = "sensor" desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face." + extended_desc = "If 'ignore storage' pin is set to 1, the sensor will disregard scanning various storage containers such as backpacks." icon_state = "recorder" complexity = 12 - inputs = list() - outputs = list("scanned ref \") - activators = list("on scanned") + inputs = list("\ ignore storage" = 1) + outputs = list("\ scanned") + activators = list("\ on scanned") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 120 -/obj/item/integrated_circuit/input/sensor/do_work() - // Because this gets called by attack(), all this needs to do is pulse the activator. - for(var/datum/integrated_io/output/O in outputs) - O.push_data() - var/datum/integrated_io/activate/A = activators[1] - A.push_data() +/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A) + var/ignore_bags = get_pin_data(IC_INPUT, 1) + if(ignore_bags) + if(istype(A, /obj/item/weapon/storage)) + return FALSE + set_pin_data(IC_OUTPUT, 1, weakref(A)) + push_data() + activate_pin(1) + return TRUE /obj/item/integrated_circuit/output category_text = "Output" @@ -441,9 +420,9 @@ name = "small screen" desc = "This small screen can display a single piece of data, when the machine is examined closely." icon_state = "screen" - inputs = list("displayed data") + inputs = list("\ displayed data") outputs = list() - activators = list("load data") + activators = list("\ load data") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 10 autopulse = 1 @@ -497,7 +476,7 @@ complexity = 4 inputs = list() outputs = list() - activators = list("toggle light") + activators = list("\ toggle light") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH var/light_toggled = 0 var/light_brightness = 3 @@ -519,18 +498,18 @@ power_draw_idle = light_toggled ? light_brightness * 2 : 0 /obj/item/integrated_circuit/output/light/advanced/update_lighting() - var/datum/integrated_io/R = inputs[1] - var/datum/integrated_io/G = inputs[2] - var/datum/integrated_io/B = inputs[3] - var/datum/integrated_io/brightness = inputs[4] + var/R = get_pin_data(IC_INPUT, 1) + var/G = get_pin_data(IC_INPUT, 2) + var/B = get_pin_data(IC_INPUT, 3) + var/brightness = get_pin_data(IC_INPUT, 4) - if(isnum(R.data) && isnum(G.data) && isnum(B.data) && isnum(brightness.data)) - R.data = Clamp(R.data, 0, 255) - G.data = Clamp(G.data, 0, 255) - B.data = Clamp(B.data, 0, 255) - brightness.data = Clamp(brightness.data, 0, 6) - light_rgb = rgb(R.data, G.data, B.data) - light_brightness = brightness.data + if(isnum(R) && isnum(G) && isnum(B) && isnum(brightness)) + R = Clamp(R, 0, 255) + G = Clamp(G, 0, 255) + B = Clamp(B, 0, 255) + brightness = Clamp(brightness, 0, 6) + light_rgb = rgb(R, G, B) + light_brightness = brightness ..() @@ -544,10 +523,10 @@ icon_state = "light_adv" complexity = 8 inputs = list( - "R", - "G", - "B", - "Brightness" + "\ R", + "\ G", + "\ B", + "\ Brightness" ) outputs = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH @@ -563,9 +542,9 @@ complexity = 8 cooldown_per_use = 4 SECONDS inputs = list( - "sound ID", - "volume", - "frequency" + "\ sound ID", + "\ volume", + "\ frequency" ) outputs = list() activators = list("play sound") diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm index beb44bf5354..759b1586eb4 100644 --- a/code/modules/integrated_electronics/subtypes/logic.dm +++ b/code/modules/integrated_electronics/subtypes/logic.dm @@ -4,7 +4,7 @@ extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE." complexity = 3 outputs = list("result") - activators = list("compare", "on true result", "on false result") + activators = list("\ compare", "\ on true result", "\ on false result") category_text = "Logic" autopulse = 1 power_draw_per_use = 1 @@ -14,19 +14,17 @@ check_then_do_work() /obj/item/integrated_circuit/logic/do_work() - var/datum/integrated_io/O = outputs[1] - var/datum/integrated_io/T = activators[2] - var/datum/integrated_io/F = activators[3] - O.push_data() - if(O.data) - T.push_data() + push_data() + if(get_pin_data(IC_INPUT, 1)) + activate_pin(1) else - F.push_data() + activate_pin(2) /obj/item/integrated_circuit/logic/binary - inputs = list("A","B") + inputs = list("\ A","\ B") /obj/item/integrated_circuit/logic/binary/do_work() + pull_data() var/datum/integrated_io/A = inputs[1] var/datum/integrated_io/B = inputs[2] var/datum/integrated_io/O = outputs[1] @@ -37,9 +35,10 @@ return FALSE /obj/item/integrated_circuit/logic/unary - inputs = list("A") + inputs = list("\ A") /obj/item/integrated_circuit/logic/unary/do_work() + pull_data() var/datum/integrated_io/A = inputs[1] var/datum/integrated_io/O = outputs[1] O.data = do_check(A) ? TRUE : FALSE diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index 65bae751e00..4ee51451790 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -11,12 +11,12 @@ complexity = 20 w_class = ITEMSIZE_NORMAL inputs = list( - "target X rel", - "target Y rel" + "\ target X rel", + "\ target Y rel" ) outputs = list() activators = list( - "fire" + "\ fire" ) var/obj/item/weapon/gun/installed_gun = null spawn_flags = IC_SPAWN_RESEARCH diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index 7b3256e06b9..3480a83a4a4 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -11,9 +11,9 @@ some power is lost due to ineffiency." w_class = ITEMSIZE_SMALL complexity = 16 - inputs = list("target ref") - outputs = list("target cell charge", "target cell max charge", "target cell percentage") - activators = list("transmit") + inputs = list("\ target") + outputs = list("\ target cell charge", "\ target cell max charge", "\ target cell percentage") + activators = list("\ transmit") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3) power_draw_per_use = 500 // Inefficency has to come from somewhere. diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index d0c26baf663..e3b69d31cd4 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -43,39 +43,39 @@ flags = OPENCONTAINER complexity = 20 cooldown_per_use = 6 SECONDS - inputs = list("target ref", "injection amount" = 5) + inputs = list("\ target", "\ injection amount" = 5) outputs = list() - activators = list("inject") + activators = list("\ inject") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 /obj/item/integrated_circuit/reagent/injector/proc/inject_amount() - var/datum/integrated_io/amount = inputs[2] - if(isnum(amount.data)) - return Clamp(amount.data, 0, 30) + var/amount = get_pin_data(IC_INPUT, 2) + if(isnum(amount)) + return Clamp(amount, 0, 30) /obj/item/integrated_circuit/reagent/injector/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing - var/datum/integrated_io/target = inputs[1] - var/atom/movable/AM = target.data_as_type(/atom/movable) + var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(!istype(AM)) //Invalid input return if(!reagents.total_volume) // Empty return if(AM.can_be_injected_by(src)) if(isliving(AM)) + var/mob/living/L = AM var/turf/T = get_turf(AM) - T.visible_message("[src] is trying to inject [AM]!") + T.visible_message("[src] is trying to inject [L]!") sleep(3 SECONDS) - if(!AM.can_be_injected_by(src)) + if(!L.can_be_injected_by(src)) return var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(target, inject_amount(), CHEM_BLOOD) - message_admins("[src] injected \the [AM] with [trans]u of [contained].") + var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD) + message_admins("[src] injected \the [L] with [trans]u of [contained].") to_chat(AM, "You feel a tiny prick!") - visible_message("[src] injects [AM]!") + visible_message("[src] injects [L]!") else reagents.trans_to(AM, inject_amount()) @@ -88,9 +88,9 @@ outside the machine if it is next to the machine. Note that this cannot be used on entities." flags = OPENCONTAINER complexity = 8 - inputs = list("source ref", "target ref", "injection amount" = 10) + inputs = list("\ source", "\ target", "\ injection amount" = 10) outputs = list() - activators = list("transfer reagents") + activators = list("\ transfer reagents", "\ on transfer") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 @@ -103,10 +103,9 @@ transfer_amount = amount.data /obj/item/integrated_circuit/reagent/pump/do_work() - var/datum/integrated_io/A = inputs[1] - var/datum/integrated_io/B = inputs[2] - var/atom/movable/source = A.data_as_type(/atom/movable) - var/atom/movable/target = B.data_as_type(/atom/movable) + var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable) + if(!istype(source) || !istype(target)) //Invalid input return var/turf/T = get_turf(src) @@ -117,10 +116,11 @@ return if(!source.is_open_container() || !target.is_open_container()) return - if(!source.reagents.get_free_space() || !target.reagents.get_free_space()) + if(!target.reagents.get_free_space()) return source.reagents.trans_to(target, transfer_amount) + activate_pin(2) /obj/item/integrated_circuit/reagent/storage name = "reagent storage" diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index c159522e974..a90a3f57a36 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -8,17 +8,16 @@ cannot see the target, it will not be able to calculate the correct direction." icon_state = "numberpad" complexity = 25 - inputs = list("target ref") - outputs = list("dir") - activators = list("calculate dir") + inputs = list("\ target") + outputs = list("\ dir") + activators = list("\ calculate dir", "\ on calculated") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5) power_draw_per_use = 40 /obj/item/integrated_circuit/smart/basic_pathfinder/do_work() var/datum/integrated_io/I = inputs[1] - var/datum/integrated_io/O = outputs[1] - O.data = null + set_pin_data(IC_OUTPUT, 1, null) if(!isweakref(I.data)) return @@ -28,6 +27,6 @@ if(!(A in view(get_turf(src)))) return // Can't see the target. var/desired_dir = get_dir(get_turf(src), A) - if(desired_dir) - O.data = desired_dir - O.push_data() \ No newline at end of file + + set_pin_data(IC_OUTPUT, 1, desired_dir) + push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm index 72766c0c48c..322ee2f9e09 100644 --- a/code/modules/integrated_electronics/subtypes/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -12,16 +12,15 @@ This circuit is set to send a pulse after a delay of two seconds." icon_state = "delay-20" var/delay = 2 SECONDS - activators = list("incoming pulse","outgoing pulse") + activators = list("\ incoming","\ outgoing") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 /obj/item/integrated_circuit/time/delay/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor. It'll delay the entire thing - var/datum/integrated_io/out_pulse = activators[2] sleep(delay) - out_pulse.push_data() + activate_pin(2) /obj/item/integrated_circuit/time/delay/five_sec name = "five-sec delay circuit" @@ -60,14 +59,13 @@ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse." icon_state = "delay" - inputs = list("delay time") + inputs = list("\ delay time") spawn_flags = IC_SPAWN_RESEARCH /obj/item/integrated_circuit/time/delay/custom/do_work() - var/datum/integrated_io/delay_input = inputs[1] - if(delay_input.data && isnum(delay_input.data) ) - var/new_delay = min(delay_input.data, 1) - new_delay = max(new_delay, 36000) //An hour. + var/delay_input = get_pin_data(IC_INPUT, 1) + if(delay_input && isnum(delay_input) ) + var/new_delay = between(1, delay_input, 36000) //An hour. delay = new_delay ..() @@ -80,8 +78,8 @@ var/ticks_to_pulse = 4 var/ticks_completed = 0 var/is_running = FALSE - inputs = list("enable ticking") - activators = list("outgoing pulse") + inputs = list("\ enable ticking" = 0) + activators = list("\ outgoing pulse") spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -91,8 +89,8 @@ . = ..() /obj/item/integrated_circuit/time/ticker/on_data_written() - var/datum/integrated_io/do_tick = inputs[1] - if(do_tick.data && !is_running) + var/do_tick = get_pin_data(IC_INPUT, 1) + if(do_tick && !is_running) is_running = TRUE processing_objects |= src else if(is_running) @@ -108,8 +106,7 @@ ticks_completed -= ticks_to_pulse else ticks_completed = 0 - var/datum/integrated_io/pulser = activators[1] - pulser.push_data() + activate_pin(1) /obj/item/integrated_circuit/time/ticker/fast name = "fast ticker" @@ -134,20 +131,16 @@ desc = "Tells you what the local time is, specific to your station or planet." icon_state = "clock" inputs = list() - outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)") + outputs = list("\ time", "\ hours", "\ minutes", "\ seconds") + activators = list("\ get time","\ on time got") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/time/clock/do_work() - var/datum/integrated_io/time = outputs[1] - var/datum/integrated_io/hour = outputs[2] - var/datum/integrated_io/min = outputs[3] - var/datum/integrated_io/sec = outputs[4] + set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") ) + set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) ) + set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) ) + set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) ) - time.data = time2text(station_time_in_ticks, "hh:mm:ss") - hour.data = text2num(time2text(station_time_in_ticks, "hh")) - min.data = text2num(time2text(station_time_in_ticks, "mm")) - sec.data = text2num(time2text(station_time_in_ticks, "ss")) - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() \ No newline at end of file + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm index b1a19f4a406..72d779b6218 100644 --- a/code/modules/integrated_electronics/subtypes/trig.dm +++ b/code/modules/integrated_electronics/subtypes/trig.dm @@ -1,9 +1,18 @@ //These circuits do not-so-simple math. /obj/item/integrated_circuit/trig complexity = 1 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("compute") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ compute", "\ on computed") category_text = "Trig" extended_desc = "Input and output are in degrees." autopulse = 1 @@ -19,19 +28,19 @@ name = "sin circuit" desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A." icon_state = "sine" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/sine/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = sin(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = sin(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cosine // @@ -39,19 +48,19 @@ name = "cos circuit" desc = "Outputs the cosine of A." icon_state = "cosine" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosine/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = cos(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = cos(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Tangent // @@ -59,19 +68,19 @@ name = "tan circuit" desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance." icon_state = "tangent" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/tangent/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Tan(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Tan(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cosecant // @@ -79,19 +88,19 @@ name = "csc circuit" desc = "Outputs the cosecant of A." icon_state = "cosecant" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosecant/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Csc(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Csc(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Secant // @@ -100,19 +109,19 @@ name = "sec circuit" desc = "Outputs the secant of A. Has nothing to do with the security department." icon_state = "secant" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/secant/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Sec(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Sec(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cotangent // @@ -121,16 +130,16 @@ name = "cot circuit" desc = "Outputs the cotangent of A." icon_state = "cotangent" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cotangent/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Cot(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Cot(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() \ No newline at end of file + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/lore_codex/lore_data/species.dm b/code/modules/lore_codex/lore_data/species.dm index fa8c6d96152..54d72e07182 100644 --- a/code/modules/lore_codex/lore_data/species.dm +++ b/code/modules/lore_codex/lore_data/species.dm @@ -38,16 +38,11 @@ /datum/lore/codex/page/unathi name = "Unathi" - data = "The author wishes to apologize to the reader, as they currently lack enough knowledge of the Unathi to write about them, as they are \ - rather rare inside Vir." // Replace this when Anewbe finishes the lizard rewrite. - /* - data = "Raging in from Moghes, the Unathi are a race of tall, reptilian humanoids that possess both crocodile-like and serpent-like features. \ - They are a proud, warlike species that favors honor and strength, their home, Moghes, is a desert planet but was once believed to be full of life. \ - Of all the currently known sentient species, the Unathi are the most unequal in gender with females tending to be property of the males. Most Unathi \ - outside of Moghes tend to be exiles however, and with influence of other species the gender difference is not nearly as pronounced. Unathi were \ - humanity's second contact, and despite their aggressive nature, seem to get along well enough with humanity, though are often considered to be \ - 'second-class' citizens and are rarely seen in jobs other than where muscle is needed." // This probably needs to be updated. - */ + data = "The Unathi are a race of tall, reptilian humanoids that possess a blend of serpentine features reminiscent of crocodiles. \ + They are a proud, religious species that favors honor and strength, and originate from the desert planet of Moghes. \ + The Unathi follow a religious code known as the Unity, and they carry this with them on their travels. \ + Unathi once fought a serious war against SolGov, and as a result are often considered to be second-class citizens, \ + rarely seen in jobs that don't require a little muscle." /datum/lore/codex/page/tajaran name = "Tajaran" diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 11f6021c75b..68fb129108e 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -10,6 +10,7 @@ recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/weapon/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]") if(integrity>=50) recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 4610b4e00fe..921b28d733e 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -90,10 +90,12 @@ var/list/name_to_material var/ignition_point // K, point at which the material catches on fire. var/melting_point = 1800 // K, walls will take damage if they're next to a fire hotter than this var/integrity = 150 // General-use HP value for products. + var/protectiveness = 10 // How well this material works as armor. Higher numbers are better, diminishing returns applies. var/opacity = 1 // Is the material transparent? 0.5< makes transparent walls/doors. - var/reflectivity = 0 // How reflective to light is the material? Currently used for laser defense. + var/reflectivity = 0 // How reflective to light is the material? Currently used for laser reflection and defense. var/explosion_resistance = 5 // Only used by walls currently. var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn. + var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10. var/list/composite_material // If set, object matter var will be a list containing these values. // Placeholder vars for the time being, todo properly integrate windows/light tiles/rods. @@ -103,7 +105,7 @@ var/list/name_to_material var/list/window_options = list() // Damage values. - var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. + var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. Also used for bullet protection in armor. var/weight = 20 // Determines blunt damage/throwforce for weapons. // Noise when someone is faceplanted onto a table made of this material. @@ -236,6 +238,7 @@ var/list/name_to_material icon_colour = "#00FFE1" opacity = 0.4 reflectivity = 0.6 + conductivity = 1 shard_type = SHARD_SHARD tableslam_noise = 'sound/effects/Glasshit.ogg' hardness = 100 @@ -247,6 +250,7 @@ var/list/name_to_material icon_colour = "#EDD12F" weight = 24 hardness = 40 + conductivity = 41 stack_origin_tech = list(TECH_MATERIAL = 4) sheet_singular_name = "ingot" sheet_plural_name = "ingots" @@ -261,6 +265,7 @@ var/list/name_to_material icon_colour = "#D1E6E3" weight = 22 hardness = 50 + conductivity = 63 stack_origin_tech = list(TECH_MATERIAL = 3) sheet_singular_name = "ingot" sheet_plural_name = "ingots" @@ -304,6 +309,8 @@ var/list/name_to_material shard_type = SHARD_STONE_PIECE weight = 22 hardness = 55 + protectiveness = 5 // 20% + conductivity = 5 door_icon_base = "stone" sheet_singular_name = "brick" sheet_plural_name = "bricks" @@ -320,6 +327,8 @@ var/list/name_to_material name = DEFAULT_WALL_MATERIAL stack_type = /obj/item/stack/material/steel integrity = 150 + conductivity = 11 // Assuming this is carbon steel, it would actually be slightly less conductive than iron, but lets ignore that. + protectiveness = 10 // 33% icon_base = "solid" icon_reinf = "reinf_over" icon_colour = "#666666" @@ -355,6 +364,8 @@ var/list/name_to_material explosion_resistance = 25 hardness = 80 weight = 23 + protectiveness = 20 // 50% + conductivity = 13 // For the purposes of balance. stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo @@ -370,6 +381,7 @@ var/list/name_to_material explosion_resistance = 75 hardness = 100 weight = 28 + protectiveness = 60 // 75% reflectivity = 0.7 // Not a perfect mirror, but close. stack_origin_tech = list(TECH_MATERIAL = 8) composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug @@ -377,6 +389,7 @@ var/list/name_to_material /material/plasteel/titanium name = "titanium" stack_type = null + conductivity = 2.38 icon_base = "metal" door_icon_base = "metal" icon_colour = "#D1E6E3" @@ -393,6 +406,8 @@ var/list/name_to_material tableslam_noise = 'sound/effects/Glasshit.ogg' hardness = 30 weight = 15 + protectiveness = 0 // 0% + conductivity = 1 // Glass shards don't conduct. door_icon_base = "stone" destruction_desc = "shatters" window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2) @@ -483,7 +498,7 @@ var/list/name_to_material tableslam_noise = 'sound/effects/Glasshit.ogg' hardness = 40 weight = 30 - stack_origin_tech = "materials=2" + stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 2, "glass" = SHEET_MATERIAL_AMOUNT) window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2) created_window = /obj/structure/window/reinforced @@ -526,6 +541,8 @@ var/list/name_to_material icon_colour = "#CCCCCC" hardness = 10 weight = 12 + protectiveness = 5 // 20% + conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator. melting_point = T0C+371 //assuming heat resistant plastic stack_origin_tech = list(TECH_MATERIAL = 3) @@ -556,12 +573,14 @@ var/list/name_to_material stack_type = /obj/item/stack/material/mhydrogen icon_colour = "#E6C5DE" stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5) + conductivity = 100 /material/platinum name = "platinum" stack_type = /obj/item/stack/material/platinum icon_colour = "#9999FF" weight = 27 + conductivity = 9.43 stack_origin_tech = list(TECH_MATERIAL = 2) sheet_singular_name = "ingot" sheet_plural_name = "ingots" @@ -571,6 +590,7 @@ var/list/name_to_material stack_type = /obj/item/stack/material/iron icon_colour = "#5C5454" weight = 22 + conductivity = 10 sheet_singular_name = "ingot" sheet_plural_name = "ingots" @@ -585,6 +605,7 @@ var/list/name_to_material explosion_resistance = 200 // Hull plating. hardness = 500 weight = 500 + protectiveness = 80 // 80% // Likewise. /material/alienalloy/elevatorium @@ -603,6 +624,8 @@ var/list/name_to_material shard_can_repair = 0 // you can't weld splinters back into planks hardness = 15 weight = 18 + protectiveness = 8 // 28% + conductivity = 1 melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood ignition_point = T0C+288 stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1) @@ -634,6 +657,7 @@ var/list/name_to_material icon_colour = "#AAAAAA" hardness = 1 weight = 1 + protectiveness = 0 // 0% ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough melting_point = T0C+232 //temperature at which cardboard walls would be destroyed stack_origin_tech = list(TECH_MATERIAL = 1) @@ -650,6 +674,7 @@ var/list/name_to_material integrity = 1 hardness = 1 weight = 1 + protectiveness = 0 // 0% stack_origin_tech = list(TECH_MATERIAL = 1) melting_point = T0C+1 destruction_desc = "crumples" @@ -662,6 +687,7 @@ var/list/name_to_material door_icon_base = "wood" ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% flags = MATERIAL_PADDING /material/cult @@ -695,6 +721,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+300 melting_point = T0C+300 + protectiveness = 3 // 13% /material/carpet name = "carpet" @@ -706,6 +733,7 @@ var/list/name_to_material melting_point = T0C+300 sheet_singular_name = "tile" sheet_plural_name = "tiles" + protectiveness = 1 // 4% /material/cotton name = "cotton" @@ -714,7 +742,9 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% +// This all needs to be OOP'd and use inheritence if its ever used in the future. /material/cloth_teal name = "teal" display_name ="teal" @@ -723,6 +753,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_black name = "black" @@ -732,6 +763,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_green name = "green" @@ -741,6 +773,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_puple name = "purple" @@ -750,6 +783,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_blue name = "blue" @@ -759,6 +793,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_beige name = "beige" @@ -768,6 +803,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/cloth_lime name = "lime" @@ -777,6 +813,7 @@ var/list/name_to_material flags = MATERIAL_PADDING ignition_point = T0C+232 melting_point = T0C+300 + protectiveness = 1 // 4% /material/toy_foam name = "foam" @@ -787,4 +824,5 @@ var/list/name_to_material melting_point = T0C+300 icon_colour = "#ff9900" hardness = 1 - weight = 1 \ No newline at end of file + weight = 1 + protectiveness = 0 // 0% \ No newline at end of file diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ore.dm index 128dc173328..e531e5208f3 100644 --- a/code/modules/mining/ore.dm +++ b/code/modules/mining/ore.dm @@ -37,7 +37,7 @@ var/mob/living/carbon/human/H = hit_atom if(istype(H) && H.has_eyes() && prob(85)) H << "Some of \the [src] gets in your eyes!" - H.eye_blind += 5 + H.Blind(5) H.eye_blurry += 10 spawn(1) if(istype(loc, /turf/)) qdel(src) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 07562ad190d..4384151cbd4 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -212,7 +212,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." - if(stat == DEAD) + if(stat == DEAD && !forbid_seeing_deadchat) announce_ghost_joinleave(ghostize(1)) else var/response @@ -223,7 +223,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return src.client.admin_ghost() else - response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body") + response = alert(src, "Are you -sure- you want to ghost?\n(You are alive, or otherwise have the potential to become alive. If you ghost, you won't be able to play this round until you respawn as a new character! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body") if(response != "Ghost") return resting = 1 diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index fdb0b012ef8..3a451bff448 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -101,7 +101,7 @@ /mob/living/silicon/ai/special_mentions() return list("AI") // AI door! -// Converts specific characters, like *, |, and _ to formatted output. +// Converts specific characters, like +, |, and _ to formatted output. /mob/proc/say_emphasis(var/message) message = encode_html_emphasis(message, "|", "i") message = encode_html_emphasis(message, "+", "b") diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 85942fcb4e9..44e0d002808 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -24,7 +24,7 @@ /datum/language/unathi name = LANGUAGE_UNATHI - desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi." + desc = "The common language of the Moghes Hegemony, composed of sibilant hisses and rattles. Spoken natively by Unathi." speech_verb = "hisses" ask_verb = "hisses" exclaim_verb = "roars" @@ -60,7 +60,7 @@ flags = WHITELISTED syllables = list("mrr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", "mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", - "ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", + "ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", "hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra") /datum/language/tajaran/get_random_name(var/gender) diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 8c61b68a3ea..873934c0c70 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -70,10 +70,10 @@ /mob/living/bot/updatehealth() if(status_flags & GODMODE) - health = maxHealth + health = getMaxHealth() stat = CONSCIOUS else - health = maxHealth - getFireLoss() - getBruteLoss() + health = getMaxHealth() - getFireLoss() - getBruteLoss() oxyloss = 0 toxloss = 0 cloneloss = 0 @@ -104,9 +104,9 @@ user << "You need to unlock the controls first." return else if(istype(O, /obj/item/weapon/weldingtool)) - if(health < maxHealth) + if(health < getMaxHealth()) if(open) - health = min(maxHealth, health + 10) + health = min(getMaxHealth(), health + 10) user.visible_message("[user] repairs [src].","You repair [src].") else user << "Unable to repair with the maintenance panel closed." @@ -224,7 +224,7 @@ /mob/living/bot/proc/getPatrolTurf() var/minDist = INFINITY var/obj/machinery/navbeacon/targ = locate() in get_turf(src) - + if(!targ) for(var/obj/machinery/navbeacon/N in navbeacons) if(!N.codes["patrol"]) diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index a7764d3d1dc..fd48b912a0d 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -73,11 +73,11 @@ // Eyes and blindness. if(!has_eyes()) - eye_blind = 1 + SetBlinded(1) blinded = 1 eye_blurry = 1 else if(eye_blind) - eye_blind = max(eye_blind-1,0) + AdjustBlinded(-1) blinded = 1 else if(eye_blurry) eye_blurry = max(eye_blurry-1, 0) diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 3f41f21ce55..bac50b1e626 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -76,7 +76,7 @@ if(ingested) ingested.metabolize() if(bloodstr) bloodstr.metabolize() - confused = max(0, confused - 1) + AdjustConfused(-1) // decrement dizziness counter, clamped to 0 if(resting) dizziness = max(0, dizziness - 5) @@ -110,7 +110,7 @@ if(31 to INFINITY) emp_damage = 30//Let's not overdo it if(21 to 30)//High level of EMP damage, unable to see, hear, or speak - eye_blind = 1 + SetBlinded(1) blinded = 1 ear_deaf = 1 silent = 1 @@ -123,7 +123,7 @@ if(20) alert = 0 blinded = 0 - eye_blind = 0 + SetBlinded(0) ear_deaf = 0 silent = 0 emp_damage -= 1 diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index 14c8efbbadd..6b07140211f 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -1,11 +1,11 @@ -/mob/living/carbon/human/verb/give(var/mob/living/target in view(1)-usr) +/mob/living/carbon/human/verb/give(var/mob/living/carbon/target in view(1)-usr) set category = "IC" set name = "Give" // TODO : Change to incapacitated() on merge. - if(src.stat || src.lying || src.resting || src.buckled) + if(src.stat || src.lying || src.resting || src.handcuffed) return - if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null) + if(!istype(target) || target.stat || target.lying || target.resting || target.handcuffed || target.client == null) return var/obj/item/I = src.get_active_hand() diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index ee0c867ffb6..b4a47d2e47f 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -41,6 +41,13 @@ species.handle_death(src) animate_tail_stop() + //Handle snowflake ling stuff. + if(mind && mind.changeling) + // If the ling is capable of revival, don't allow them to see deadchat. + if(mind.changeling.chem_charges >= CHANGELING_STASIS_COST) + if(mind.changeling.max_geneticpoints >= 0) // Absorbed lings don't count, as they can't revive. + forbid_seeing_deadchat = TRUE + //Handle brain slugs. var/obj/item/organ/external/Hd = get_organ(BP_HEAD) var/mob/living/simple_animal/borer/B diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 1c4f4e841e3..66abc50cabe 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -88,6 +88,7 @@ if(mind.changeling) stat("Chemical Storage", mind.changeling.chem_charges) stat("Genetic Damage Time", mind.changeling.geneticdamage) + stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]") /mob/living/carbon/human/ex_act(severity) if(!blinded) @@ -1496,3 +1497,11 @@ /mob/living/carbon/human/is_muzzled() return (wear_mask && (istype(wear_mask, /obj/item/clothing/mask/muzzle) || istype(src.wear_mask, /obj/item/weapon/grenade))) +// Called by job_controller. Makes drones start with a permit, might be useful for other people later too. +/mob/living/carbon/human/equip_post_job() + var/braintype = get_FBP_type() + if(braintype == FBP_DRONE) + var/turf/T = get_turf(src) + var/obj/item/weapon/permit/drone/permit = new(T) + permit.set_name(real_name) + equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index fa3d19ebabe..30ee7c64d6e 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -2,7 +2,7 @@ /mob/living/carbon/human/updatehealth() if(status_flags & GODMODE) - health = maxHealth + health = getMaxHealth() stat = CONSCIOUS return @@ -14,10 +14,10 @@ total_brute += O.brute_dam total_burn += O.burn_dam - health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute + health = getMaxHealth() - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute //TODO: fix husking - if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) + if( ((getMaxHealth() - total_burn) < config.health_threshold_dead) && stat == DEAD) ChangeToHusk() return @@ -42,7 +42,7 @@ if(should_have_organ("brain")) var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"] if(sponge) - sponge.damage = min(max(amount, 0),(maxHealth*2)) + sponge.damage = min(max(amount, 0),(getMaxHealth()*2)) brainloss = sponge.damage else brainloss = 200 @@ -56,7 +56,7 @@ if(should_have_organ("brain")) var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"] if(sponge) - brainloss = min(sponge.damage,maxHealth*2) + brainloss = min(sponge.damage,getMaxHealth()*2) else brainloss = 200 else @@ -99,16 +99,32 @@ /mob/living/carbon/human/adjustBruteLoss(var/amount) amount = amount*species.brute_mod if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_brute_damage_percent)) + amount *= M.incoming_brute_damage_percent take_overall_damage(amount, 0) else + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent heal_overall_damage(-amount, 0) BITSET(hud_updateflag, HEALTH_HUD) /mob/living/carbon/human/adjustFireLoss(var/amount) amount = amount*species.burn_mod if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_fire_damage_percent)) + amount *= M.incoming_fire_damage_percent take_overall_damage(0, amount) else + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent heal_overall_damage(0, -amount) BITSET(hud_updateflag, HEALTH_HUD) @@ -118,8 +134,16 @@ var/obj/item/organ/external/O = get_organ(organ_name) if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_brute_damage_percent)) + amount *= M.incoming_brute_damage_percent O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) else + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. O.heal_damage(-amount, 0, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT)) @@ -131,8 +155,16 @@ var/obj/item/organ/external/O = get_organ(organ_name) if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_fire_damage_percent)) + amount *= M.incoming_fire_damage_percent O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) else + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. O.heal_damage(0, -amount, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT)) @@ -153,6 +185,26 @@ wearing_rig.notify_ai("Warning: user consciousness failure. Mobility control passed to integrated intelligence system.") ..() +/mob/living/carbon/human/proc/Stasis(amount) + if((species.flags & NO_SCAN) || isSynthetic()) + in_stasis = 0 + else + in_stasis = amount + +/mob/living/carbon/human/proc/getStasis() + if((species.flags & NO_SCAN) || isSynthetic()) + return 0 + + return in_stasis + +//This determines if, RIGHT NOW, the life() tick is being skipped due to stasis +/mob/living/carbon/human/proc/inStasisNow() + var/stasisValue = getStasis() + if(stasisValue && (life_tick % stasisValue)) + return 1 + + return 0 + /mob/living/carbon/human/getCloneLoss() if((species.flags & NO_SCAN) || isSynthetic()) cloneloss = 0 @@ -400,11 +452,25 @@ This function restores all organs. if(BRUTE) damageoverlaytemp = 20 damage = damage*species.brute_mod + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + damage *= M.incoming_damage_percent + if(!isnull(M.incoming_brute_damage_percent)) + damage *= M.incoming_brute_damage_percent + if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) UpdateDamageIcon() if(BURN) damageoverlaytemp = 20 damage = damage*species.burn_mod + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + damage *= M.incoming_damage_percent + if(!isnull(M.incoming_brute_damage_percent)) + damage *= M.incoming_fire_damage_percent + if(organ.take_damage(0, damage, sharp, edge, used_weapon)) UpdateDamageIcon() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 86bbdebc15e..61b13316b84 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -27,6 +27,11 @@ emp_act if(!P.nodamage) organ.add_autopsy_data("[P.name]", P.damage) + // Tell clothing we're wearing that it got hit by a bullet/laser/etc + var/list/clothing = get_clothing_list_organ(organ) + for(var/obj/item/clothing/C in clothing) + C.clothing_impact(P, P.damage) + //Shrapnel if(P.can_embed()) var/armor = getarmor_organ(organ, "bullet") @@ -130,6 +135,15 @@ emp_act return siemens_coefficient +// Returns a list of clothing that is currently covering def_zone. +/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type) + var/list/results = list() + var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) + for(var/obj/item/clothing/C in clothing_items) + if(istype(C) && (C.body_parts_covered & def_zone.body_part)) + results.Add(C) + return results + //this proc returns the armour value for a particular external organ. /mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type) if(!type || !def_zone) return 0 @@ -231,10 +245,6 @@ emp_act var/soaked = get_armor_soak(hit_zone, "melee", I.armor_penetration) - if(soaked >= effective_force) - src << "Your armor absorbs the force of [I.name]!" - return - var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].") standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone) @@ -246,9 +256,14 @@ emp_act if(!affecting) return 0 - if(soaked >= effective_force) - return 0 + // Allow clothing to respond to being hit. + // This is done up here so that clothing damage occurs even if fully blocked. + var/list/clothing = get_clothing_list_organ(affecting) + for(var/obj/item/clothing/C in clothing) + C.clothing_impact(I, effective_force) + if(soaked >= round(effective_force*0.8)) + effective_force -= round(effective_force*0.8) // Handle striking to cripple. if(user.a_intent == I_DISARM) effective_force *= 0.5 //reduced effective force... @@ -309,12 +324,15 @@ emp_act return 1 /mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked, var/soaked) - if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100 || soaked > effective_force) + if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100) return 0 if(W.damtype != BRUTE) return 0 + if(soaked >= round(effective_force*0.8)) + effective_force -= round(effective_force*0.8) + //want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100 if(prob(dislocate_chance * (100 - blocked)/100)) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 0a1817e6b2d..636d6af7920 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -93,3 +93,5 @@ mob_swap_flags = ~HEAVY var/identifying_gender // In case the human identifies as another gender than it's biological + + var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7682f675b08..cb49001d3c9 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -90,6 +90,24 @@ return 0 +// Returns a string based on what kind of brain the FBP has. +/mob/living/carbon/human/proc/get_FBP_type() + if(!isSynthetic()) + return FBP_NONE + var/obj/item/organ/internal/brain/B + B = internal_organs_by_name[O_BRAIN] + if(B) // Incase we lost our brain for some reason, like if we got decapped. + if(istype(B, /obj/item/organ/internal/mmi_holder)) + var/obj/item/organ/internal/mmi_holder/mmi_holder = B + if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/posibrain)) + return FBP_POSI + else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/robot)) + return FBP_DRONE + else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi)) // This needs to come last because inheritence. + return FBP_CYBORG + + return FBP_NONE + #undef HUMAN_EATING_NO_ISSUE #undef HUMAN_EATING_NO_MOUTH #undef HUMAN_EATING_BLOCKED_MOUTH diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 2ffec342883..98f8f81d9c7 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -13,9 +13,15 @@ handle_embedded_objects() //Moving with objects stuck in you can cause bad times. if(force_max_speed) - return -3 // Returning -1 will actually result in a slowdown for Teshari. + return -3 - var/health_deficiency = (maxHealth - health) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.haste) && M.haste == TRUE) + return -3 // Returning -1 will actually result in a slowdown for Teshari. + if(!isnull(M.slowdown)) + tally += M.slowdown + + var/health_deficiency = (getMaxHealth() - health) if(health_deficiency >= 40) tally += (health_deficiency / 25) if(can_feel_pain()) @@ -80,9 +86,7 @@ if(T && T.movement_cost) tally += T.movement_cost - if(species.item_slowdown_halved) - if(item_tally > 0) - item_tally *= 0.5 + item_tally *= species.item_slowdown_mod tally += item_tally @@ -140,3 +144,36 @@ prob_slip = round(prob_slip) return(prob_slip) + +// Handle footstep sounds +/mob/living/carbon/human/handle_footstep(var/turf/T) + if(!config.footstep_volume || !T.footstep_sounds || !T.footstep_sounds.len) + return + // Future Upgrades - Multi species support + var/list/footstep_sounds = T.footstep_sounds["human"] + if(!footstep_sounds) + return + + var/S = pick(footstep_sounds) + if(!S) return + + // Only play every other step while running + if(m_intent == "run" && step_count++ % 2 == 0) + return + + var/volume = config.footstep_volume + // Reduce volume while walking or barefoot + if(!shoes || m_intent != "run") + volume *= 0.5 + + if(!has_organ(BP_L_FOOT) && !has_organ(BP_R_FOOT)) + return // no feet = no footsteps + + if(buckled || lying || throwing) + return // people flying, lying down or sitting do not step + + if(!has_gravity(src) && prob(75)) + return // Far less likely to make noise in no gravity + + playsound(T, S, volume, FALSE) + return diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index e6563a28a1b..2738686c38a 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -62,8 +62,12 @@ voice = GetVoice() + var/stasis = inStasisNow() + if(getStasis() > 2) + Sleeping(20) + //No need to update all of these procs if the guy is dead. - if(stat != DEAD && !in_stasis) + if(stat != DEAD && !stasis) //Updates the number of stored chemicals for powers handle_changeling() @@ -82,7 +86,6 @@ if(!client) species.handle_npc(src) - if(!handle_some_updates()) return //We go ahead and process them 5 times for HUD images and other stuff though. @@ -97,7 +100,7 @@ return 1 /mob/living/carbon/human/breathe() - if(!in_stasis) + if(!inStasisNow()) ..() // Calculate how vulnerable the human is to under- and overpressure. @@ -207,7 +210,7 @@ /mob/living/carbon/human/handle_mutations_and_radiation() - if(in_stasis) + if(inStasisNow()) return if(getFireLoss()) @@ -789,7 +792,7 @@ /mob/living/carbon/human/handle_chemicals_in_body() - if(in_stasis) + if(inStasisNow()) return if(reagents) @@ -971,18 +974,18 @@ vision = internal_organs_by_name[species.vision_organ] if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. - eye_blind = 0 + SetBlinded(0) blinded = 0 eye_blurry = 0 else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind. - eye_blind = 1 + SetBlinded(1) blinded = 1 eye_blurry = 1 else //You have the requisite organs if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own blinded = 1 else if(eye_blind) // Blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) + AdjustBlinded(-1) blinded = 1 else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster eye_blurry = max(eye_blurry-3, 0) @@ -1339,7 +1342,7 @@ if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING /mob/living/carbon/human/handle_random_events() - if(in_stasis) + if(inStasisNow()) return // Puke if toxloss is too high @@ -1536,7 +1539,7 @@ if(stat == DEAD) holder.icon_state = "-100" // X_X else - holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(maxHealth-config.health_threshold_crit)*100) + holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(getMaxHealth()-config.health_threshold_crit)*100) hud_list[HEALTH_HUD] = holder if (BITTEST(hud_updateflag, LIFE_HUD)) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 8a8650aa9ba..f547cba9fcb 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -133,7 +133,7 @@ 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/item_slowdown_halved = 0 // If this is on, they're not as affected by item weights for slowdown + 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 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 5015e19940d..e49236af940 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -34,19 +34,21 @@ ambiguous_genders = TRUE gluttonous = 1 slowdown = 0.5 - brute_mod = 0.9 - burn_mod = 0.9 + brute_mod = 0.85 + burn_mod = 0.85 + metabolic_rate = 0.85 + item_slowdown_mod = 0.5 num_alternate_languages = 3 secondary_langs = list(LANGUAGE_UNATHI) name_language = LANGUAGE_UNATHI health_hud_intensity = 2.5 - min_age = 18 - max_age = 60 + min_age = 32 + max_age = 260 blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ - Uuosa-Eso system, which roughly translates to 'burning mother'.

Coming from a harsh, radioactive \ - desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \ + 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 \ else, frequently even their own lives. They prefer warmer temperatures than most species and \ their native tongue is a heavy hissing laungage called Sinta'Unathi." @@ -62,9 +64,34 @@ appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR flesh_color = "#34AF10" + blood_color = "#b3cbc3" + base_color = "#066000" reagent_tag = IS_UNATHI - base_color = "#066000" + + has_limbs = list( + BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi), + BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi), + BP_HEAD = list("path" = /obj/item/organ/external/head/unathi), + 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), + BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right) + ) + + //No kidneys or appendix + has_organ = list( + O_HEART = /obj/item/organ/internal/heart/unathi, + O_LUNGS = /obj/item/organ/internal/lungs/unathi, + O_LIVER = /obj/item/organ/internal/liver/unathi, + O_BRAIN = /obj/item/organ/internal/brain/unathi, + O_EYES = /obj/item/organ/internal/eyes, + ) + heat_discomfort_level = 295 heat_discomfort_strings = list( @@ -229,6 +256,7 @@ secondary_langs = list(LANGUAGE_ROOTGLOBAL) name_language = LANGUAGE_ROOTLOCAL health_hud_intensity = 2.5 + item_slowdown_mod = 0.25 min_age = 1 max_age = 300 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a84a2889dc5..1924bd5e78f 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -131,10 +131,11 @@ Please contact me on #coderbus IRC. ~Carn x #define LEGCUFF_LAYER 23 #define L_HAND_LAYER 24 #define R_HAND_LAYER 25 -#define FIRE_LAYER 26 //If you're on fire -#define WATER_LAYER 27 //If you're submerged in water. -#define TARGETED_LAYER 28 //BS12: Layer for the target overlay from weapon targeting system -#define TOTAL_LAYERS 29 +#define MODIFIER_EFFECTS_LAYER 26 +#define FIRE_LAYER 27 //If you're on fire +#define WATER_LAYER 28 //If you're submerged in water. +#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system +#define TOTAL_LAYERS 30 ////////////////////////////////// /mob/living/carbon/human @@ -1118,6 +1119,18 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() +/mob/living/carbon/human/update_modifier_visuals(var/update_icons=1) + overlays_standing[MODIFIER_EFFECTS_LAYER] = null + var/image/effects = new() + for(var/datum/modifier/M in modifiers) + if(M.mob_overlay_state) + var/image/I = image("icon" = 'icons/mob/modifier_effects.dmi', "icon_state" = M.mob_overlay_state) + effects.overlays += I + + overlays_standing[MODIFIER_EFFECTS_LAYER] = effects + + if(update_icons) + update_icons() /mob/living/carbon/human/update_fire(var/update_icons=1) overlays_standing[FIRE_LAYER] = null diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 7bbc4110dde..0f393a9417d 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -80,7 +80,7 @@ src.blinded = null - health = maxHealth - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + health = getMaxHealth() - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) if(health < 0 && stat != DEAD) death() @@ -118,7 +118,7 @@ if (src.stuttering) src.stuttering = 0 if (src.eye_blind) - src.eye_blind = 0 + SetBlinded(0) src.blinded = 1 if (src.ear_deaf > 0) src.ear_deaf = 0 diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 3c0bfbdbadd..5fdea4a0e6f 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -81,7 +81,7 @@ var/tally = 0 - var/health_deficiency = (maxHealth - health) + var/health_deficiency = (getMaxHealth() - health) if(health_deficiency >= 30) tally += (health_deficiency / 25) if (bodytemperature < 183.222) @@ -146,7 +146,7 @@ ..() statpanel("Status") - stat(null, "Health: [round((health / maxHealth) * 100)]%") + stat(null, "Health: [round((health / getMaxHealth()) * 100)]%") stat(null, "Intent: [a_intent]") if (client.statpanel == "Status") diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm index 933596ef5e2..9e20d49a442 100644 --- a/code/modules/mob/living/carbon/metroid/powers.dm +++ b/code/modules/mob/living/carbon/metroid/powers.dm @@ -21,7 +21,7 @@ return "I cannot feed on other slimes..." if (!Adjacent(M)) return "This subject is too far away..." - if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD) + if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.getMaxHealth() * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD) return "This subject does not have an edible life energy..." for(var/mob/living/carbon/slime/met in view()) if(met.Victim == M && met != src) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 552319e6fe4..0fa139c36f1 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -11,10 +11,13 @@ /mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/used_weapon = null, var/sharp = 0, var/edge = 0) if(Debug2) world.log << "## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]." - if(!damage || (blocked >= 100) || soaked >= damage) + if(!damage || (blocked >= 100)) return 0 if(soaked) - damage -= soaked + if(soaked >= round(damage*0.8)) + damage -= round(damage*0.8) + else + damage -= soaked blocked = (100-blocked)/100 switch(damagetype) if(BRUTE) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 9271167d40d..2209c630084 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -10,6 +10,8 @@ return var/datum/gas_mixture/environment = loc.return_air() + handle_modifiers() // Do this early since it might affect other things later. + if(stat != DEAD) //Breathing, if applicable handle_breathing() @@ -148,9 +150,9 @@ /mob/living/proc/handle_disabilities() //Eyes if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own - eye_blind = max(eye_blind, 1) + SetBlinded(1) else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) + AdjustBlinded(-1) else if(eye_blurry) //blurry eyes heal slowly eye_blurry = max(eye_blurry-1, 0) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ab55807be8d..0b47ba7870f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -150,9 +150,9 @@ default behaviour is: /mob/living/verb/succumb() set hidden = 1 - if ((src.health < 0 && src.health > (5-src.maxHealth))) // Health below Zero but above 5-away-from-death, as before, but variable - src.adjustOxyLoss(src.health + src.maxHealth * 2) // Deal 2x health in OxyLoss damage, as before but variable. - src.health = src.maxHealth - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss() + if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable + src.adjustOxyLoss(src.health + src.getMaxHealth() * 2) // Deal 2x health in OxyLoss damage, as before but variable. + src.health = src.getMaxHealth() - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss() src << "\blue You have given up life and succumbed to death." @@ -161,7 +161,7 @@ default behaviour is: health = 100 stat = CONSCIOUS else - health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss + health = getMaxHealth() - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss //This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually @@ -223,14 +223,38 @@ default behaviour is: /mob/living/proc/adjustBruteLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - bruteloss = min(max(bruteloss + amount, 0),(maxHealth*2)) + + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_brute_damage_percent)) + amount *= M.incoming_brute_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + + bruteloss = min(max(bruteloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/getOxyLoss() return oxyloss /mob/living/proc/adjustOxyLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - oxyloss = min(max(oxyloss + amount, 0),(maxHealth*2)) + + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_oxy_damage_percent)) + amount *= M.incoming_oxy_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + + oxyloss = min(max(oxyloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/setOxyLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode @@ -241,7 +265,19 @@ default behaviour is: /mob/living/proc/adjustToxLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - toxloss = min(max(toxloss + amount, 0),(maxHealth*2)) + + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_tox_damage_percent)) + amount *= M.incoming_tox_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + + toxloss = min(max(toxloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/setToxLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode @@ -255,14 +291,37 @@ default behaviour is: /mob/living/proc/adjustFireLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - fireloss = min(max(fireloss + amount, 0),(maxHealth*2)) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_fire_damage_percent)) + amount *= M.incoming_fire_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + + fireloss = min(max(fireloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/getCloneLoss() return cloneloss /mob/living/proc/adjustCloneLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - cloneloss = min(max(cloneloss + amount, 0),(maxHealth*2)) + + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_clone_damage_percent)) + amount *= M.incoming_clone_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + + cloneloss = min(max(cloneloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/setCloneLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode @@ -273,7 +332,7 @@ default behaviour is: /mob/living/proc/adjustBrainLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - brainloss = min(max(brainloss + amount, 0),(maxHealth*2)) + brainloss = min(max(brainloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/setBrainLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode @@ -284,18 +343,117 @@ default behaviour is: /mob/living/proc/adjustHalLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode - halloss = min(max(halloss + amount, 0),(maxHealth*2)) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + amount *= M.incoming_damage_percent + if(!isnull(M.incoming_hal_damage_percent)) + amount *= M.incoming_hal_damage_percent + if(!isnull(M.disable_duration_percent)) + amount *= M.incoming_hal_damage_percent + else if(amount < 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_healing_percent)) + amount *= M.incoming_healing_percent + halloss = min(max(halloss + amount, 0),(getMaxHealth()*2)) /mob/living/proc/setHalLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode halloss = amount +// Use this to get a mob's max health whenever possible. Reading maxHealth directly will give inaccurate results if any modifiers exist. /mob/living/proc/getMaxHealth() - return maxHealth + var/result = maxHealth + for(var/datum/modifier/M in modifiers) + if(!isnull(M.max_health_flat)) + result += M.max_health_flat + // Second loop is so we can get all the flat adjustments first before multiplying, otherwise the result will be different. + for(var/datum/modifier/M in modifiers) + if(!isnull(M.max_health_percent)) + result *= M.max_health_percent + return result /mob/living/proc/setMaxHealth(var/newMaxHealth) maxHealth = newMaxHealth +/mob/living/Stun(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustStunned(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/Weaken(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustWeakened(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/Paralyse(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustParalysis(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/Sleeping(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustSleeping(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/Confuse(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustConfused(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/Blind(amount) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + +/mob/living/AdjustBlinded(amount) + if(amount > 0) + for(var/datum/modifier/M in modifiers) + if(!isnull(M.disable_duration_percent)) + amount = round(amount * M.disable_duration_percent) + ..(amount) + // ++++ROCKDTBEN++++ MOB PROCS //END /mob/proc/get_contents() @@ -433,7 +591,7 @@ default behaviour is: // fix blindness and deafness blinded = 0 - eye_blind = 0 + SetBlinded(0) eye_blurry = 0 ear_deaf = 0 ear_damage = 0 @@ -570,6 +728,9 @@ default behaviour is: for(var/mob/living/carbon/slime/M in view(1,src)) M.UpdateFeed(src) +/mob/living/proc/handle_footstep(turf/T) + return FALSE + /mob/living/verb/resist() set name = "Resist" set category = "IC" @@ -797,6 +958,11 @@ default behaviour is: update_icons() return canmove +// Adds overlays for specific modifiers. +// You'll have to add your own implementation for non-humans currently, just override this proc. +/mob/living/proc/update_modifier_visuals() + return + /mob/living/proc/update_water() // Involves overlays for humans. Maybe we'll get submerged sprites for borgs in the future? return @@ -804,3 +970,7 @@ default behaviour is: if(isSynthetic()) return FALSE return TRUE + +// Called by job_controller. +/mob/living/proc/equip_post_job() + return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 8a49ed8922b..66e1278e225 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -107,6 +107,11 @@ var/absorb = run_armor_check(def_zone, P.check_armour, P.armor_penetration) var/proj_sharp = is_sharp(P) var/proj_edge = has_edge(P) + + if ((proj_sharp || proj_edge) && (soaked >= round(P.damage*0.8))) + proj_sharp = 0 + proj_edge = 0 + if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour))) proj_sharp = 0 proj_edge = 0 @@ -167,13 +172,11 @@ var/soaked = get_armor_soak(hit_zone, "melee") var/blocked = run_armor_check(hit_zone, "melee") - //If the armor absorbs all of the damage, skip the damage calculation and the blood - if(!(soaked > effective_force)) - standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone) + standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone) - if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too - var/turf/simulated/location = get_turf(src) - if(istype(location)) location.add_blood_floor(src) + if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too + var/turf/simulated/location = get_turf(src) + if(istype(location)) location.add_blood_floor(src) return blocked @@ -186,13 +189,14 @@ if(HULK in user.mutations) effective_force *= 2 - //Armor soak - if(soaked >= effective_force) - return 0 - //Apply weapon damage var/weapon_sharp = is_sharp(I) var/weapon_edge = has_edge(I) + + if(getsoak(hit_zone, "melee",) - (I.armor_penetration/5) > round(effective_force*0.8)) //soaking a hit turns sharp attacks into blunt ones + weapon_sharp = 0 + weapon_edge = 0 + if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones weapon_sharp = 0 weapon_edge = 0 @@ -251,7 +255,7 @@ if(!O || !src) return if(O.sharp) //Projectile is suitable for pinning. - if(soaked >= throw_damage) //Don't embed if it didn't actually damage + if(soaked >= round(throw_damage*0.8)) return //Handles embedding for non-humans and simple_animals. @@ -435,3 +439,11 @@ hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1) client.screen += hud_used.hide_actions_toggle + +// Returns a number to determine if something is harder or easier to hit than normal. +/mob/living/proc/get_evasion() + var/result = evasion // First we get the 'base' evasion. Generally this is zero. + for(var/datum/modifier/M in modifiers) + if(!isnull(M.evasion)) + result += M.evasion + return result diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index e6b7f2979df..d8913e7b5b8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -2,7 +2,7 @@ see_invisible = SEE_INVISIBLE_LIVING //Health and life related vars - var/maxHealth = 100 //Maximum health that should be possible. + var/maxHealth = 100 //Maximum health that should be possible. Avoid adjusting this if you can, and instead use modifiers datums. var/health = 100 //A mob's health var/hud_updateflag = 0 diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 1aef4eca81e..80c0dbc505a 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -141,7 +141,7 @@ proc/get_radio_key_from_channel(var/channel) //Redirect to say_dead if talker is dead if(stat) - if(stat == DEAD) + if(stat == DEAD && !forbid_seeing_deadchat) return say_dead(message) return @@ -308,7 +308,7 @@ proc/get_radio_key_from_channel(var/channel) if(M && src) //If we still exist, when the spawn processes var/dst = get_dist(get_turf(M),get_turf(src)) - if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc) + if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc) M << speech_bubble M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm index 349f27114b0..8c12226e3d3 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm @@ -1,7 +1,6 @@ /obj/machinery/computer/drone_control name = "Maintenance Drone Control" desc = "Used to monitor the station's drone population and the assembler that services them." - icon = 'icons/obj/computer.dmi' icon_keyboard = "power_key" icon_screen = "power" req_access = list(access_engine_equip) diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 9dacf9924c4..a9464c595e8 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -98,7 +98,7 @@ else //Not stunned. src.stat = 0 - confused = max(0, confused - 1) + AdjustConfused(-1) else //Dead. src.blinded = 1 @@ -107,7 +107,7 @@ if (src.stuttering) src.stuttering-- if (src.eye_blind) - src.eye_blind-- + src.AdjustBlinded(-1) src.blinded = 1 if (src.ear_deaf > 0) src.ear_deaf-- diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm index 1b051e029f4..58a81ca7a7d 100644 --- a/code/modules/mob/living/silicon/robot/robot_damage.dm +++ b/code/modules/mob/living/silicon/robot/robot_damage.dm @@ -1,9 +1,9 @@ /mob/living/silicon/robot/updatehealth() if(status_flags & GODMODE) - health = maxHealth + health = getMaxHealth() stat = CONSCIOUS return - health = maxHealth - (getBruteLoss() + getFireLoss()) + health = getMaxHealth() - (getBruteLoss() + getFireLoss()) return /mob/living/silicon/robot/getBruteLoss() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 738e9969676..40b18525282 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -63,16 +63,16 @@ switch(severity) if(1) src.take_organ_damage(0,20,emp=1) - confused = (min(confused + 5, 30)) + Confuse(5) if(2) src.take_organ_damage(0,15,emp=1) - confused = (min(confused + 4, 30)) + Confuse(4) if(3) src.take_organ_damage(0,10,emp=1) - confused = (min(confused + 3, 30)) + Confuse(3) if(4) src.take_organ_damage(0,5,emp=1) - confused = (min(confused + 2, 30)) + Confuse(2) flash_eyes(affect_silicon = 1) src << "*BZZZT*" src << "Warning: Electromagnetic pulse detected." @@ -148,7 +148,7 @@ // this function shows the health of the AI in the Status panel /mob/living/silicon/proc/show_system_integrity() if(!src.stat) - stat(null, text("System integrity: [round((health/maxHealth)*100)]%")) + stat(null, text("System integrity: [round((health/getMaxHealth())*100)]%")) else stat(null, text("Systems nonfunctional")) diff --git a/code/modules/mob/living/simple_animal/aliens/drone.dm b/code/modules/mob/living/simple_animal/aliens/drone.dm index 3d1ae1bd02d..06de6b4d141 100644 --- a/code/modules/mob/living/simple_animal/aliens/drone.dm +++ b/code/modules/mob/living/simple_animal/aliens/drone.dm @@ -17,7 +17,7 @@ response_help = "pokes" response_disarm = "gently pushes aside" response_harm = "hits" - + a_intent = I_HURT ranged = 1 rapid = 1 @@ -99,16 +99,16 @@ src.visible_message("\red \icon[src] [src] suddenly lights up, and additional targetting vanes slide into place.") hostile = 1 - if(health / maxHealth > 0.9) + if(health / getMaxHealth() > 0.9) icon_state = "drone3" explode_chance = 0 - else if(health / maxHealth > 0.7) + else if(health / getMaxHealth() > 0.7) icon_state = "drone2" explode_chance = 0 - else if(health / maxHealth > 0.5) + else if(health / getMaxHealth() > 0.5) icon_state = "drone1" explode_chance = 0.5 - else if(health / maxHealth > 0.3) + else if(health / getMaxHealth() > 0.3) icon_state = "drone0" explode_chance = 5 else if(health > 0) diff --git a/code/modules/mob/living/simple_animal/animals/spiderbot.dm b/code/modules/mob/living/simple_animal/animals/spiderbot.dm index 1bb202d1a03..95b7e81a177 100644 --- a/code/modules/mob/living/simple_animal/animals/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/animals/spiderbot.dm @@ -95,10 +95,10 @@ if (istype(O, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = O if (WT.remove_fuel(0)) - if(health < maxHealth) + if(health < getMaxHealth()) health += pick(1,1,1,2,2,3) - if(health > maxHealth) - health = maxHealth + if(health > getMaxHealth()) + health = getMaxHealth() add_fingerprint(user) src.visible_message("\The [user] has spot-welded some of the damage to \the [src]!") else diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm index c24100476cc..1cc1a85108b 100644 --- a/code/modules/mob/living/simple_animal/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -57,7 +57,7 @@ /mob/living/simple_animal/construct/attack_generic(var/mob/user) if(istype(user, /mob/living/simple_animal/construct/builder)) - if(health < maxHealth) + if(health < getMaxHealth()) adjustBruteLoss(-5) user.visible_message("\The [user] mends some of \the [src]'s wounds.") else @@ -68,9 +68,9 @@ /mob/living/simple_animal/construct/examine(mob/user) ..(user) var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" - if (src.health < src.maxHealth) + if (src.health < src.getMaxHealth()) msg += "" - if (src.health >= src.maxHealth/2) + if (src.health >= src.getMaxHealth()/2) msg += "It looks slightly dented.\n" else msg += "It looks severely dented!\n" diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index 05087c40368..7b5e77f5c39 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -170,7 +170,7 @@ T.forceMove(src) //put shade in stone T.status_flags |= GODMODE T.canmove = 0 - T.health = T.maxHealth + T.health = T.getMaxHealth() src.icon_state = "soulstone2" T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form" diff --git a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm index 79f389821e7..ae700d60b76 100644 --- a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm +++ b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm @@ -75,7 +75,7 @@ /mob/living/simple_animal/hostile/mecha/Life() . = ..() if(!.) return - if((health < maxHealth*0.3) && prob(10)) + if((health < getMaxHealth()*0.3) && prob(10)) sparks.start() /mob/living/simple_animal/hostile/mecha/bullet_act() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index af20f042019..3ad6260813a 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -234,8 +234,8 @@ density = 1 //Overhealth - else if(health > maxHealth) - health = maxHealth + else if(health > getMaxHealth()) + health = getMaxHealth() /mob/living/simple_animal/update_icon() ..() @@ -534,7 +534,7 @@ if(istype(O, /obj/item/stack/medical)) if(stat != DEAD) var/obj/item/stack/medical/MED = O - if(health < maxHealth) + if(health < getMaxHealth()) if(MED.amount >= 1) adjustBruteLoss(-MED.heal_brute) MED.amount -= 1 @@ -602,7 +602,7 @@ ..() if(statpanel("Status") && show_stat_health) - stat(null, "Health: [round((health / maxHealth) * 100)]%") + stat(null, "Health: [round((health / getMaxHealth()) * 100)]%") /mob/living/simple_animal/lay_down() ..() @@ -645,10 +645,10 @@ adjustBruteLoss(30) /mob/living/simple_animal/adjustBruteLoss(damage) - health = Clamp(health - damage, 0, maxHealth) + health = Clamp(health - damage, 0, getMaxHealth()) /mob/living/simple_animal/adjustFireLoss(damage) - health = Clamp(health - damage, 0, maxHealth) + health = Clamp(health - damage, 0, getMaxHealth()) // Check target_mob if worthy of attack (i.e. check if they are dead or empty mecha) /mob/living/simple_animal/proc/SA_attackable(target_mob) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 714bde7096a..f16af92a740 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -804,6 +804,30 @@ sleeping = max(sleeping + amount,0) return +/mob/proc/Confuse(amount) + confused = max(max(confused,amount),0) + return + +/mob/proc/SetConfused(amount) + confused = max(amount,0) + return + +/mob/proc/AdjustConfused(amount) + confused = max(confused + amount,0) + return + +/mob/proc/Blind(amount) + eye_blind = max(max(eye_blind,amount),0) + return + +/mob/proc/SetBlinded(amount) + eye_blind = max(amount,0) + return + +/mob/proc/AdjustBlinded(amount) + eye_blind = max(eye_blind + amount,0) + return + /mob/proc/Resting(amount) facing_dir = null resting = max(max(resting,amount),0) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 1901902c80d..a63590acf8b 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -207,3 +207,4 @@ var/list/active_genes=list() var/mob_size = MOB_MEDIUM + var/forbid_seeing_deadchat = FALSE // Used for lings to not see deadchat, and to have ghosting behave as if they were not really dead. diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index f3cd084ffac..80f68b979d5 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -170,7 +170,7 @@ if(announce) assailant.visible_message("[assailant] covers [affecting]'s eyes!") if(affecting.eye_blind < 3) - affecting.eye_blind = 3 + affecting.Blind(3) /obj/item/weapon/grab/attack_self() return s_click(hud) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 4327840a478..ba5b24dbe70 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -390,10 +390,16 @@ proc/is_blind(A) else name = realname + if(subject && subject.forbid_seeing_deadchat && !subject.client.holder) + return // Can't talk in deadchat if you can't see it. + for(var/mob/M in player_list) if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_mentor(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname + if(M.forbid_seeing_deadchat && !M.client.holder) + continue + if(subject) if(M.is_key_ignored(subject.client.key)) // If we're ignored, do nothing. continue diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 476a8b68105..a553d4309ca 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -199,7 +199,7 @@ if(S.victim == mob) return - if(mob.stat==DEAD && isliving(mob)) + if(mob.stat==DEAD && isliving(mob) && !mob.forbid_seeing_deadchat) mob.ghostize() return diff --git a/code/modules/mob/modifiers.dm b/code/modules/mob/modifiers.dm new file mode 100644 index 00000000000..8e1f9e2f6fe --- /dev/null +++ b/code/modules/mob/modifiers.dm @@ -0,0 +1,131 @@ +// This is a datum that tells the mob that something is affecting them. +// The advantage of using this datum verses just setting a variable on the mob directly, is that there is no risk of two different procs overwriting +// each other, or other weirdness. An excellent example is adjusting max health. + +/datum/modifier + var/name = null // Mostly used to organize, might show up on the UI in the Future(tm) + var/desc = null // Ditto. + var/icon_state = null // See above. + var/mob/living/holder = null // The mob that this datum is affecting. + var/expire_at = null // world.time when holder's Life() will remove the datum. If null, it lasts forever or until it gets deleted by something else. + var/on_created_text = null // Text to show to holder upon being created. + var/on_expired_text = null // Text to show to holder when it expires. + var/hidden = FALSE // If true, it will not show up on the HUD in the Future(tm) + var/stacks = MODIFIER_STACK_FORBID // If true, attempts to add a second instance of this type will refresh expire_at instead. + var/flags = 0 // Flags for the modifier, see mobs.dm defines for more details. + + var/light_color = null // If set, the mob possessing the modifier will glow in this color. Not implemented yet. + var/light_range = null // How far the light for the above var goes. Not implemented yet. + var/light_intensity = null // Ditto. Not implemented yet. + var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented. + + // Now for all the different effects. + // Percentage modifiers are expressed as a multipler. (e.g. +25% damage should be written as 1.25) + var/max_health_flat // Adjusts max health by a flat (e.g. +20) amount. Note this is added to base health. + var/max_health_percent // Adjusts max health by a percentage (e.g. -30%). + var/disable_duration_percent // Adjusts duration of 'disables' (stun, weaken, paralyze, confusion, sleep, halloss, etc) Setting to 0 will grant immunity. + var/incoming_damage_percent // Adjusts all incoming damage. + var/incoming_brute_damage_percent // Only affects bruteloss. + var/incoming_fire_damage_percent // Only affects fireloss. + var/incoming_tox_damage_percent // Only affects toxloss. + var/incoming_oxy_damage_percent // Only affects oxyloss. + var/incoming_clone_damage_percent // Only affects cloneloss. + var/incoming_hal_damage_percent // Only affects halloss. + var/incoming_healing_percent // Adjusts amount of healing received. + var/outgoing_melee_damage_percent // Adjusts melee damage inflicted by holder by a percentage. Affects attacks by melee weapons and hand-to-hand. + var/slowdown // Negative numbers speed up, positive numbers slow down movement. + var/haste // If set to 1, the mob will be 'hasted', which makes it ignore slowdown and go really fast. + var/evasion // Positive numbers reduce the odds of being hit by 15% each. Negative numbers increase the odds. + +/datum/modifier/New(var/new_holder) + holder = new_holder + ..() + +// Checks to see if this datum should continue existing. +/datum/modifier/proc/check_if_valid() + if(expire_at && expire_at < world.time) // Is our time up? + src.expire() + +/datum/modifier/proc/expire(var/silent = FALSE) + if(on_expired_text && !silent) + to_chat(holder, on_expired_text) + on_expire() + holder.modifiers.Remove(src) + if(mob_overlay_state) // We do this after removing ourselves from the list so that the overlay won't remain. + holder.update_modifier_visuals() + qdel(src) + +// Override this for special effects when it gets removed. +/datum/modifier/proc/on_expire() + return + +// Called every Life() tick. Override for special behaviour. +/datum/modifier/proc/tick() + return + +/mob/living + var/list/modifiers = list() // A list of modifier datums, which can adjust certain mob numbers. + +/mob/living/Destroy() + remove_all_modifiers(TRUE) + ..() + +// Called by Life(). +/mob/living/proc/handle_modifiers() + if(!modifiers.len) // No work to do. + return + // Get rid of anything we shouldn't have. + for(var/datum/modifier/M in modifiers) + M.check_if_valid() + // Remaining modifiers will now receive a tick(). This is in a second loop for safety in order to not tick() an expired modifier. + for(var/datum/modifier/M in modifiers) + M.tick() + +// Call this to add a modifier to a mob. First argument is the modifier type you want, second is how long it should last, in ticks. +// The SECONDS/MINUTES macro is very helpful for this. E.g. M.add_modifier(/datum/modifier/example, 5 MINUTES) +/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null) + // First, check if the mob already has this modifier. + for(var/datum/modifier/M in modifiers) + if(istype(modifier_type, M)) + switch(M.stacks) + if(MODIFIER_STACK_FORBID) + return // Stop here. + if(MODIFIER_STACK_ALLOWED) + break // No point checking anymore. + if(MODIFIER_STACK_EXTEND) + // Not allow to add a second instance, but we can try to prolong the first instance. + if(expire_at && world.time + expire_at > M.expire_at) + M.expire_at = world.time + expire_at + return + + // If we're at this point, the mob doesn't already have it, or it does but stacking is allowed. + var/datum/modifier/mod = new modifier_type(src) + if(expire_at) + mod.expire_at = world.time + expire_at + if(mod.on_created_text) + to_chat(src, mod.on_created_text) + modifiers.Add(mod) + if(mod.mob_overlay_state) + update_modifier_visuals() + +// Removes a specific instance of modifier +/mob/living/proc/remove_specific_modifier(var/datum/modifier/M, var/silent = FALSE) + M.expire(silent) + +// Removes all modifiers of a type +/mob/living/proc/remove_modifiers_of_type(var/modifier_type, var/silent = FALSE) + for(var/datum/modifier/M in modifiers) + if(istype(M, modifier_type)) + M.expire(silent) + +// Removes all modifiers, useful if the mob's being deleted +/mob/living/proc/remove_all_modifiers(var/silent = FALSE) + for(var/datum/modifier/M in modifiers) + M.expire(silent) + +// Checks if the mob has a modifier type. +/mob/living/proc/has_modifier_of_type(var/modifier_type) + for(var/datum/modifier/M in modifiers) + if(istype(M, modifier_type)) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm index e76c6516aa7..0ed4e5364a5 100644 --- a/code/modules/multiz/basic.dm +++ b/code/modules/multiz/basic.dm @@ -11,25 +11,43 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S qdel(src) // The storage of connections between adjacent levels means some bitwise magic is needed. -proc/HasAbove(var/z) +/proc/HasAbove(var/z) if(z >= world.maxz || z > 16 || z < 1) return 0 return z_levels & (1 << (z - 1)) -proc/HasBelow(var/z) +/proc/HasBelow(var/z) if(z > world.maxz || z > 17 || z < 2) return 0 return z_levels & (1 << (z - 2)) // Thankfully, no bitwise magic is needed here. -proc/GetAbove(var/atom/atom) +/proc/GetAbove(var/atom/atom) var/turf/turf = get_turf(atom) if(!turf) return null return HasAbove(turf.z) ? get_step(turf, UP) : null -proc/GetBelow(var/atom/atom) +/proc/GetBelow(var/atom/atom) var/turf/turf = get_turf(atom) if(!turf) return null return HasBelow(turf.z) ? get_step(turf, DOWN) : null + +/proc/GetConnectedZlevels(z) + . = list(z) + for(var/level = z, HasBelow(level), level--) + . |= level-1 + for(var/level = z, HasAbove(level), level++) + . |= level+1 + +proc/AreConnectedZLevels(var/zA, var/zB) + return zA == zB || (zB in GetConnectedZlevels(zA)) + +/proc/get_zstep(ref, dir) + if(dir == UP) + . = GetAbove(ref) + else if (dir == DOWN) + . = GetBelow(ref) + else + . = get_step(ref, dir) \ No newline at end of file diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 586b6242602..122e1aa4cda 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -3,34 +3,38 @@ set category = "IC" if(zMove(UP)) - to_chat(usr, "You move upwards.") + to_chat(src, "You move upwards.") /mob/verb/down() set name = "Move Down" set category = "IC" if(zMove(DOWN)) - to_chat(usr, "You move down.") + to_chat(src, "You move down.") /mob/proc/zMove(direction) if(eyeobj) return eyeobj.zMove(direction) if(!can_ztravel()) - to_chat(usr, "You lack means of travel in that direction.") + to_chat(src, "You lack means of travel in that direction.") return + var/turf/start = loc + if(!istype(start)) + to_chat(src, "You are unable to move from here.") + return 0 + var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) - if(!destination) - to_chat(usr, "There is nothing of interest in this direction.") + to_chat(src, "There is nothing of interest in this direction.") + return 0 + + if(!start.CanZPass(src, direction)) + to_chat(src, "\The [start] is in the way.") return 0 - var/turf/start = get_turf(src) - if(!start.CanZPass(src, direction)) - to_chat(usr, "\The [start] is in the way.") - return 0 if(!destination.CanZPass(src, direction)) - to_chat(usr, "\The [destination] blocks your way.") + to_chat(src, "\The [destination] blocks your way.") return 0 var/area/area = get_area(src) @@ -46,12 +50,12 @@ to_chat(src, "You gave up on pulling yourself up.") return 0 else - to_chat(usr, "Gravity stops you from moving upward.") + to_chat(src, "Gravity stops you from moving upward.") return 0 for(var/atom/A in destination) if(!A.CanPass(src, start, 1.5, 0)) - to_chat(usr, "\The [A] blocks you.") + to_chat(src, "\The [A] blocks you.") return 0 Move(destination) return 1 @@ -61,14 +65,14 @@ if(destination) forceMove(destination) else - to_chat(usr, "There is nothing of interest in this direction.") + to_chat(src, "There is nothing of interest in this direction.") /mob/observer/eye/zMove(direction) var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) if(destination) setLoc(destination) else - to_chat(usr, "There is nothing of interest in this direction.") + to_chat(src, "There is nothing of interest in this direction.") /mob/proc/can_ztravel() return 0 diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 1cb5b9b4da7..7c1fee0525e 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe dir = SOUTH initialize_directions = SOUTH + // node1 is the connection on the same Z + // node2 is the connection on the other Z + var/minimum_temperature_difference = 300 var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No @@ -48,7 +51,7 @@ obj/machinery/atmospherics/pipe/zpipe/New() invisibility = i ? 101 : 0 update_icon() -obj/machinery/atmospherics/pipe/up/process() +obj/machinery/atmospherics/pipe/zpipe/process() if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle ..() else @@ -78,10 +81,10 @@ obj/machinery/atmospherics/pipe/zpipe/proc/burst() qdel(src) // NOT qdel. obj/machinery/atmospherics/pipe/zpipe/proc/normalize_dir() - if(dir==3) - set_dir(1) - else if(dir==12) - set_dir(4) + if(dir == (NORTH|SOUTH)) + set_dir(NORTH) + else if(dir == (EAST|WEST)) + set_dir(EAST) obj/machinery/atmospherics/pipe/zpipe/Destroy() if(node1) @@ -94,6 +97,7 @@ obj/machinery/atmospherics/pipe/zpipe/pipeline_expansion() return list(node1, node2) obj/machinery/atmospherics/pipe/zpipe/update_icon() + color = pipe_color return obj/machinery/atmospherics/pipe/zpipe/disconnect(obj/machinery/atmospherics/reference) diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm index 57278082764..18bb91a9e46 100644 --- a/code/modules/multiz/structures.dm +++ b/code/modules/multiz/structures.dm @@ -122,10 +122,6 @@ allowed_directions = UP|DOWN icon_state = "ladder11" - - - - /obj/structure/stairs name = "Stairs" desc = "Stairs leading to another deck. Not too useful if the gravity goes out." diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 8389df7112b..b6845d076f1 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -36,6 +36,11 @@ ..() mover.fall() +// Called when thrown object lands on this turf. +/turf/simulated/open/hitby(var/atom/movable/AM, var/speed) + . = ..() + AM.fall() + /turf/simulated/open/proc/update() below = GetBelow(src) turf_changed_event.register(below, src, /turf/simulated/open/update_icon) @@ -82,7 +87,7 @@ return var/obj/item/stack/rods/R = C if (R.use(1)) - user << "Constructing support lattice ..." + to_chat(user, "Constructing support lattice ...") playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) ReplaceWithLattice() return @@ -99,7 +104,7 @@ ChangeTurf(/turf/simulated/floor/airless) return else - user << "The plating is going to need some support." + to_chat(user, "The plating is going to need some support.") //To lay cable. if(istype(C, /obj/item/stack/cable_coil)) diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 0f5ea190f26..c6670d2a30e 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -37,7 +37,7 @@ var/const/CE_STABLE_THRESHOLD = 0.5 // Takes care blood loss and regeneration /mob/living/carbon/human/handle_blood() - if(in_stasis) + if(inStasisNow()) return if(!should_have_organ(O_HEART)) diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 6514092dfc0..1390c89b291 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -35,7 +35,7 @@ if (. >= 2) if(prob(1)) owner.custom_pain("Your feel very dizzy for a moment!",0) - owner.confused = max(owner.confused, 2) + owner.Confuse(2) /obj/item/organ/internal/brain/proc/replace_self_with(replace_path) var/mob/living/carbon/human/tmp_owner = owner diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm index 2a2b8305d3c..4febf8f4790 100644 --- a/code/modules/organs/internal/eyes.dm +++ b/code/modules/organs/internal/eyes.dm @@ -72,7 +72,7 @@ if(is_bruised()) owner.eye_blurry = 20 if(is_broken()) - owner.eye_blind = 20 + owner.Blind(20) /obj/item/organ/internal/eyes/handle_germ_effects() . = ..() //Up should return an infection level as an integer diff --git a/code/modules/organs/internal/liver.dm b/code/modules/organs/internal/liver.dm index daa0a88f76c..6b7459500b6 100644 --- a/code/modules/organs/internal/liver.dm +++ b/code/modules/organs/internal/liver.dm @@ -53,6 +53,6 @@ if(prob(1)) owner.custom_pain("There's a sharp pain in your upper-right abdomen!",1) if (. >= 2) - if(prob(1) && owner.getToxLoss() < owner.maxHealth*0.3) + if(prob(1) && owner.getToxLoss() < owner.getMaxHealth()*0.3) //owner << "" //Toxins provide their own messages for pain owner.adjustToxLoss(5) //Not realistic to PA but there are basically no 'real' liver infections diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 63c6da64098..20390a35553 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -492,7 +492,7 @@ This function completely restores a damaged organ to perfect condition. //Burn damage can cause fluid loss due to blistering and cook-off if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT)) - var/fluid_loss = 0.75 * (damage/(owner.maxHealth - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100) + var/fluid_loss = 0.75 * (damage/(owner.getMaxHealth() - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100) owner.remove_blood(fluid_loss) // first check whether we can widen an existing wound @@ -882,7 +882,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(!clean) // Throw limb around. if(src && istype(loc,/turf)) - throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) dir = 2 if(DROPLIMB_BURN) new /obj/effect/decal/cleanable/ash(get_turf(victim)) @@ -901,19 +901,19 @@ Note that amputating the affected organ does in fact remove the infection from t gore.basecolor = use_blood_colour gore.update_icon() - gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) for(var/obj/item/organ/I in internal_organs) I.removed() if(istype(loc,/turf)) - I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) for(var/obj/item/I in src) if(I.w_class <= ITEMSIZE_SMALL) qdel(I) continue I.loc = get_turf(src) - I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) qdel(src) diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 244c0b79719..cfc0910901c 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -165,7 +165,7 @@ if(is_bruised()) owner.eye_blurry = 20 if(is_broken()) - owner.eye_blind = 20 + owner.Blind(20) /obj/item/organ/internal/liver name = "liver" diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 25db1953d67..69d14c1dd16 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -44,6 +44,14 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ var/parts = BP_ALL //Defines what parts said brand can replace on a body. var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator. +/datum/robolimb/unbranded_monitor + company = "Unbranded Monitor" + desc = "A generic unbranded interpretation of a popular prosthetic head model. It looks rudimentary and cheaply constructed." + icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi' + parts = list(BP_HEAD) + monitor_styles = standard_monitor_styles + unavailable_to_build = 1 + /datum/robolimb/nanotrasen company = "NanoTrasen" desc = "A simple but efficient robotic limb, created by NanoTrasen." diff --git a/code/modules/organs/subtypes/unathi.dm b/code/modules/organs/subtypes/unathi.dm new file mode 100644 index 00000000000..212330577ce --- /dev/null +++ b/code/modules/organs/subtypes/unathi.dm @@ -0,0 +1,50 @@ +/obj/item/organ/external/chest/unathi + max_damage = 100 + min_broken_damage = 40 + encased = "upper ribplates" + +/obj/item/organ/external/groin/unathi + max_damage = 100 + min_broken_damage = 40 + encased = "lower ribplates" + +/obj/item/organ/external/head/unathi + max_damage = 75 + min_broken_damage = 35 + eye_icon = "eyes_s" + force = 5 + throwforce = 10 + + +/obj/item/organ/internal/heart/unathi + icon_state = "unathi_heart-on" + dead_icon = "unath_heart-off" + +/obj/item/organ/internal/lungs/unathi + color = "#b3cbc3" + +/obj/item/organ/internal/liver/unathi + name = "filtration organ" + icon_state = "unathi_liver" + +//Unathi liver acts as kidneys, too. +/obj/item/organ/internal/liver/unathi/process() + ..() + if(!owner) return + + var/datum/reagent/coffee = locate(/datum/reagent/drink/coffee) in owner.reagents.reagent_list + if(coffee) + if(is_bruised()) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + else if(is_broken()) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) + + var/datum/reagent/sugar = locate(/datum/reagent/sugar) in owner.reagents.reagent_list + if(sugar) + if(is_bruised()) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + else if(is_broken()) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) + +/obj/item/organ/internal/brain/unathi + color = "#b3cbc3" \ No newline at end of file diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm index 53a07f228bf..4c308ca9306 100644 --- a/code/modules/planet/planet.dm +++ b/code/modules/planet/planet.dm @@ -12,8 +12,17 @@ var/datum/weather_holder/weather_holder var/sun_position = 0 // 0 means midnight, 1 means noon. + var/list/sun = list("range","brightness","color") var/expected_z_levels = list() + var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary + + var/turf/simulated/floor/planet_floors = list() + var/turf/unsimulated/wall/planetary/planet_walls = list() + + + var/needs_work = 0 // Bitflags to signal to the planet controller these need (properly deferrable) work. Flags defined in controller. + /datum/planet/New() ..() weather_holder = new(src) @@ -31,17 +40,13 @@ /datum/planet/proc/update_sun() sun_last_process = world.time - /datum/planet/proc/update_weather() if(weather_holder) weather_holder.process() /datum/planet/proc/update_sun_deferred(var/new_range, var/new_brightness, var/new_color) - set background = 1 - set waitfor = 0 - var/i = 0 - for(var/turf/simulated/floor/T in outdoor_turfs) - T.set_light(new_range, new_brightness, new_color) - i++ - if(i % 30 == 0) - sleep(1) + sun["range"] = new_range + sun["brightness"] = new_brightness + sun["color"] = new_color + needs_work |= PLANET_PROCESS_SUN + diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index 303d05f5091..e35646ce7fc 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -10,6 +10,7 @@ var/datum/planet/sif/planet_sif = null Its center of government is the equatorial city and site of first settlement, New Reykjavik." // Ripped straight from the wiki. current_time = new /datum/time/sif() // 32 hour clocks are nice. expected_z_levels = list(1) // To be changed when real map is finished. + planetary_wall_type = /turf/unsimulated/wall/planetary/sif /datum/planet/sif/New() ..() @@ -104,3 +105,197 @@ var/datum/planet/sif/planet_sif = null /proc/get_sif_time() if(planet_sif) return planet_sif.current_time + +//Weather definitions +/datum/weather_holder/sif + temperature = T0C + allowed_weather_types = list( + WEATHER_CLEAR = new /datum/weather/sif/clear(), + WEATHER_OVERCAST = new /datum/weather/sif/overcast(), + WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(), + WEATHER_SNOW = new /datum/weather/sif/snow(), + WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(), + WEATHER_RAIN = new /datum/weather/sif/rain(), + WEATHER_STORM = new /datum/weather/sif/storm(), + WEATHER_HAIL = new /datum/weather/sif/hail(), + WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon() + ) + roundstart_weather_chances = list( + WEATHER_CLEAR = 30, + WEATHER_OVERCAST = 30, + WEATHER_LIGHT_SNOW = 20, + WEATHER_SNOW = 5, + WEATHER_BLIZZARD = 5, + WEATHER_RAIN = 5, + WEATHER_STORM = 2.5, + WEATHER_HAIL = 2.5 + ) + +datum/weather/sif + name = "sif base" + temp_high = 243.15 // -20c + temp_low = 233.15 // -30c + +/datum/weather/sif/clear + name = "clear" + transition_chances = list( + WEATHER_CLEAR = 60, + WEATHER_OVERCAST = 40 + ) + +/datum/weather/sif/overcast + name = "overcast" + light_modifier = 0.8 + transition_chances = list( + WEATHER_CLEAR = 25, + WEATHER_OVERCAST = 50, + WEATHER_LIGHT_SNOW = 10, + WEATHER_SNOW = 5, + WEATHER_RAIN = 5, + WEATHER_HAIL = 5 + ) + +/datum/weather/sif/light_snow + name = "light snow" + icon_state = "snowfall_light" + temp_high = 238.15 // -25c + temp_low = 228.15 // -35c + light_modifier = 0.7 + transition_chances = list( + WEATHER_OVERCAST = 20, + WEATHER_LIGHT_SNOW = 50, + WEATHER_SNOW = 25, + WEATHER_HAIL = 5 + ) + +/datum/weather/sif/snow + name = "moderate snow" + icon_state = "snowfall_med" + temp_high = 233.15 // -30c + temp_low = 223.15 // -40c + light_modifier = 0.5 + transition_chances = list( + WEATHER_LIGHT_SNOW = 20, + WEATHER_SNOW = 50, + WEATHER_BLIZZARD = 20, + WEATHER_HAIL = 5, + WEATHER_OVERCAST = 5 + ) + +/datum/weather/sif/snow/process_effects() + for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) + if(S.z in holder.our_planet.expected_z_levels) + for(var/dir_checked in cardinal) + var/turf/simulated/floor/T = get_step(S, dir_checked) + if(istype(T)) + if(istype(T, /turf/simulated/floor/outdoors) && prob(33)) + T.chill() + +/datum/weather/sif/blizzard + name = "blizzard" + icon_state = "snowfall_heavy" + temp_high = 223.15 // -40c + temp_low = 203.15 // -60c + light_modifier = 0.3 + transition_chances = list( + WEATHER_SNOW = 45, + WEATHER_BLIZZARD = 40, + WEATHER_HAIL = 10, + WEATHER_OVERCAST = 5 + ) + +/datum/weather/sif/blizzard/process_effects() + for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) + if(S.z in holder.our_planet.expected_z_levels) + for(var/dir_checked in cardinal) + var/turf/simulated/floor/T = get_step(S, dir_checked) + if(istype(T)) + if(istype(T, /turf/simulated/floor/outdoors) && prob(50)) + T.chill() + +/datum/weather/sif/rain + name = "rain" + icon_state = "rain" + light_modifier = 0.5 + transition_chances = list( + WEATHER_OVERCAST = 25, + WEATHER_LIGHT_SNOW = 10, + WEATHER_RAIN = 50, + WEATHER_STORM = 10, + WEATHER_HAIL = 5 + ) + +/datum/weather/sif/rain/process_effects() + for(var/mob/living/L in living_mob_list) + if(L.z in holder.our_planet.expected_z_levels) + var/turf/T = get_turf(L) + if(!T.outdoors) + return // They're indoors, so no need to rain on them. + + L.adjust_fire_stacks(-5) + to_chat(L, "Rain falls on you.") + +/datum/weather/sif/storm + name = "storm" + icon_state = "storm" + temp_high = 233.15 // -30c + temp_low = 213.15 // -50c + light_modifier = 0.3 + transition_chances = list( + WEATHER_RAIN = 45, + WEATHER_STORM = 40, + WEATHER_HAIL = 10, + WEATHER_OVERCAST = 5 + ) + +/datum/weather/sif/rain/process_effects() + for(var/mob/living/L in living_mob_list) + if(L.z in holder.our_planet.expected_z_levels) + var/turf/T = get_turf(L) + if(!T.outdoors) + return // They're indoors, so no need to rain on them. + + L.adjust_fire_stacks(-10) + to_chat(L, "Rain falls on you, drenching you in water.") + +/datum/weather/sif/hail + name = "hail" + icon_state = "hail" + temp_high = 233.15 // -30c + temp_low = 213.15 // -50c + light_modifier = 0.3 + transition_chances = list( + WEATHER_RAIN = 45, + WEATHER_STORM = 10, + WEATHER_HAIL = 40, + WEATHER_OVERCAST = 5 + ) + +/datum/weather/sif/hail/process_effects() + for(var/mob/living/L in living_mob_list) + if(L.z in holder.our_planet.expected_z_levels) + var/turf/T = get_turf(L) + if(!T.outdoors) + return // They're indoors, so no need to pelt them with ice. + + var/target_zone = pick(BP_ALL) + var/amount_blocked = L.run_armor_check(target_zone, "melee") + var/amount_soaked = L.get_armor_soak(target_zone, "melee") + + if(amount_blocked >= 100) + return // No need to apply damage. + + if(amount_soaked >= 10) + return // No need to apply damage. + + L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail") + to_chat(L, "The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!") + +/datum/weather/sif/blood_moon + name = "blood moon" + light_modifier = 0.5 + light_color = "#FF0000" + transition_chances = list( + WEATHER_BLOODMOON = 100 + ) + diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm index c98383a2425..5e392be7969 100644 --- a/code/modules/planet/weather.dm +++ b/code/modules/planet/weather.dm @@ -1,15 +1,3 @@ -#define WEATHER_CLEAR "clear" -#define WEATHER_OVERCAST "overcast" -#define WEATHER_LIGHT_SNOW "light snow" -#define WEATHER_SNOW "snow" -#define WEATHER_BLIZZARD "blizzard" -#define WEATHER_RAIN "rain" -#define WEATHER_STORM "storm" -#define WEATHER_HAIL "hail" -#define WEATHER_WINDY "windy" -#define WEATHER_HOT "hot" -#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on. - /datum/weather_holder var/datum/planet/our_planet = null var/datum/weather/current_weather = null @@ -19,7 +7,6 @@ var/list/allowed_weather_types = list() var/list/roundstart_weather_chances = list() var/next_weather_shift = null - var/planetary_wall_type = null // Which walls to look for when updating temperature. /datum/weather_holder/New(var/source) ..() @@ -54,55 +41,15 @@ current_weather.process_effects() /datum/weather_holder/proc/update_icon_effects() - set background = 1 - set waitfor = 0 - if(current_weather) - for(var/turf/simulated/floor/T in outdoor_turfs) - if(T.z in our_planet.expected_z_levels) - T.overlays -= T.weather_overlay - T.weather_overlay = image(icon = current_weather.icon, icon_state = current_weather.icon_state, layer = LIGHTING_LAYER - 1) - T.overlays += T.weather_overlay + our_planet.needs_work |= PLANET_PROCESS_WEATHER /datum/weather_holder/proc/update_temperature() temperature = Interpolate(current_weather.temp_low, current_weather.temp_high, weight = our_planet.sun_position) - - for(var/turf/unsimulated/wall/planetary/wall in planetary_walls) - if(ispath(wall.type, planetary_wall_type)) - wall.temperature = temperature - for(var/dir in cardinal) - var/turf/simulated/T = get_step(wall, dir) - if(istype(T)) - if(T.zone) - T.zone.rebuild() - + our_planet.needs_work |= PLANET_PROCESS_TEMP /datum/weather_holder/proc/get_weather_datum(desired_type) return allowed_weather_types[desired_type] -/datum/weather_holder/sif - temperature = T0C - allowed_weather_types = list( - WEATHER_CLEAR = new /datum/weather/sif/clear(), - WEATHER_OVERCAST = new /datum/weather/sif/overcast(), - WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(), - WEATHER_SNOW = new /datum/weather/sif/snow(), - WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(), - WEATHER_RAIN = new /datum/weather/sif/rain(), - WEATHER_STORM = new /datum/weather/sif/storm(), - WEATHER_HAIL = new /datum/weather/sif/hail(), - WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon() - ) - planetary_wall_type = /turf/unsimulated/wall/planetary/sif - roundstart_weather_chances = list( - WEATHER_CLEAR = 30, - WEATHER_OVERCAST = 30, - WEATHER_LIGHT_SNOW = 20, - WEATHER_SNOW = 5, - WEATHER_BLIZZARD = 5, - WEATHER_RAIN = 5, - WEATHER_STORM = 2.5, - WEATHER_HAIL = 2.5 - ) /datum/weather var/name = "weather base" @@ -117,169 +64,3 @@ /datum/weather/proc/process_effects() return - -/datum/weather/sif - name = "sif base" - temp_high = 243.15 // -20c - temp_low = 233.15 // -30c - -/datum/weather/sif/clear - name = "clear" - transition_chances = list( - WEATHER_CLEAR = 60, - WEATHER_OVERCAST = 40 - ) - -/datum/weather/sif/overcast - name = "overcast" - light_modifier = 0.8 - transition_chances = list( - WEATHER_CLEAR = 25, - WEATHER_OVERCAST = 50, - WEATHER_LIGHT_SNOW = 10, - WEATHER_SNOW = 5, - WEATHER_RAIN = 5, - WEATHER_HAIL = 5 - ) - -/datum/weather/sif/light_snow - name = "light snow" - icon_state = "snowfall_light" - temp_high = 238.15 // -25c - temp_low = 228.15 // -35c - light_modifier = 0.7 - transition_chances = list( - WEATHER_OVERCAST = 20, - WEATHER_LIGHT_SNOW = 50, - WEATHER_SNOW = 25, - WEATHER_HAIL = 5 - ) - -/datum/weather/sif/snow - name = "moderate snow" - icon_state = "snowfall_med" - temp_high = 233.15 // -30c - temp_low = 223.15 // -40c - light_modifier = 0.5 - transition_chances = list( - WEATHER_LIGHT_SNOW = 20, - WEATHER_SNOW = 50, - WEATHER_BLIZZARD = 20, - WEATHER_HAIL = 5, - WEATHER_OVERCAST = 5 - ) - -/datum/weather/sif/snow/process_effects() - for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) - for(var/dir_checked in cardinal) - var/turf/simulated/floor/T = get_step(S, dir_checked) - if(istype(T)) - if(istype(T, /turf/simulated/floor/outdoors) && prob(33)) - T.chill() - -/datum/weather/sif/blizzard - name = "blizzard" - icon_state = "snowfall_heavy" - temp_high = 223.15 // -40c - temp_low = 203.15 // -60c - light_modifier = 0.3 - transition_chances = list( - WEATHER_SNOW = 45, - WEATHER_BLIZZARD = 40, - WEATHER_HAIL = 10, - WEATHER_OVERCAST = 5 - ) - -/datum/weather/sif/blizzard/process_effects() - for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) - for(var/dir_checked in cardinal) - var/turf/simulated/floor/T = get_step(S, dir_checked) - if(istype(T)) - if(istype(T, /turf/simulated/floor/outdoors) && prob(50)) - T.chill() - -/datum/weather/sif/rain - name = "rain" - icon_state = "rain" - light_modifier = 0.5 - transition_chances = list( - WEATHER_OVERCAST = 25, - WEATHER_LIGHT_SNOW = 10, - WEATHER_RAIN = 50, - WEATHER_STORM = 10, - WEATHER_HAIL = 5 - ) - -/datum/weather/sif/rain/process_effects() - for(var/mob/living/L in living_mob_list) - if(L.z in holder.our_planet.expected_z_levels) - var/turf/T = get_turf(L) - if(!T.outdoors) - return // They're indoors, so no need to rain on them. - - L.adjust_fire_stacks(-5) - to_chat(L, "Rain falls on you.") - -/datum/weather/sif/storm - name = "storm" - icon_state = "storm" - temp_high = 233.15 // -30c - temp_low = 213.15 // -50c - light_modifier = 0.3 - transition_chances = list( - WEATHER_RAIN = 45, - WEATHER_STORM = 40, - WEATHER_HAIL = 10, - WEATHER_OVERCAST = 5 - ) - -/datum/weather/sif/rain/process_effects() - for(var/mob/living/L in living_mob_list) - if(L.z in holder.our_planet.expected_z_levels) - var/turf/T = get_turf(L) - if(!T.outdoors) - return // They're indoors, so no need to rain on them. - - L.adjust_fire_stacks(-10) - to_chat(L, "Rain falls on you, drenching you in water.") - -/datum/weather/sif/hail - name = "hail" - icon_state = "hail" - temp_high = 233.15 // -30c - temp_low = 213.15 // -50c - light_modifier = 0.3 - transition_chances = list( - WEATHER_RAIN = 45, - WEATHER_STORM = 10, - WEATHER_HAIL = 40, - WEATHER_OVERCAST = 5 - ) - -/datum/weather/sif/hail/process_effects() - for(var/mob/living/L in living_mob_list) - if(L.z in holder.our_planet.expected_z_levels) - var/turf/T = get_turf(L) - if(!T.outdoors) - return // They're indoors, so no need to pelt them with ice. - - var/target_zone = pick(BP_ALL) - var/amount_blocked = L.run_armor_check(target_zone, "melee") - var/amount_soaked = L.get_armor_soak(target_zone, "melee") - - if(amount_blocked >= 100) - return // No need to apply damage. - - if(amount_soaked >= 10) - return // No need to apply damage. - - L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail") - to_chat(L, "The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!") - -/datum/weather/sif/blood_moon - name = "blood moon" - light_modifier = 0.5 - light_color = "#FF0000" - transition_chances = list( - WEATHER_BLOODMOON = 100 - ) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 671d57e04ef..27bf4c0ab7c 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -48,7 +48,7 @@ var/list/possible_cable_coil_colours = list( anchored =1 var/datum/powernet/powernet name = "power cable" - desc = "A flexible superconducting cable for heavy-duty power transfer" + desc = "A flexible superconducting cable for heavy-duty power transfer." icon = 'icons/obj/power_cond_white.dmi' icon_state = "0-1" var/d1 = 0 @@ -116,9 +116,9 @@ var/list/possible_cable_coil_colours = list( user.examinate(src) // following code taken from attackby (multitool) if(powernet && (powernet.avail > 0)) - user << "[powernet.avail]W in power network." + to_chat(user, "[powernet.avail]W in power network.") else - user << "The cable is not powered." + to_chat(user, "The cable is not powered.") return /////////////////////////////////// @@ -159,12 +159,12 @@ var/list/possible_cable_coil_colours = list( return if(istype(W, /obj/item/weapon/wirecutters)) - if(d1 == 12 || d2 == 12) - user << "You must cut this cable from above." + if(d1 == UP || d2 == UP) + to_chat(user, "You must cut this cable from above.") return if(breaker_box) - user << "\red This cable is connected to nearby breaker box. Use breaker box to interact with it." + to_chat(user, "This cable is connected to nearby breaker box. Use breaker box to interact with it.") return if (shock(user, 50)) @@ -178,11 +178,11 @@ var/list/possible_cable_coil_colours = list( for(var/mob/O in viewers(src, null)) O.show_message("[user] cuts the cable.", 1) - if(d1 == 11 || d2 == 11) + if(d1 == DOWN || d2 == DOWN) var/turf/turf = GetBelow(src) if(turf) for(var/obj/structure/cable/c in turf) - if(c.d1 == 12 || c.d2 == 12) + if(c.d1 == UP || c.d2 == UP) qdel(c) investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires") @@ -194,17 +194,17 @@ var/list/possible_cable_coil_colours = list( else if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = W if (coil.get_amount() < 1) - user << "Not enough cable" + to_chat(user, "Not enough cable") return coil.cable_join(src, user) else if(istype(W, /obj/item/device/multitool)) if(powernet && (powernet.avail > 0)) // is it powered? - user << "[powernet.avail]W in power network." + to_chat(user, "[powernet.avail]W in power network.") else - user << "The cable is not powered." + to_chat(user, "The cable is not powered.") shock(user, 5, 0.2) @@ -300,12 +300,12 @@ obj/structure/cable/proc/cableColor(var/colorC) // merge with the powernets of power objects in the given direction /obj/structure/cable/proc/mergeConnectedNetworks(var/direction) - var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf + var/fdir = direction ? reverse_dir[direction] : 0 //flip the direction, to match with the source position on its turf if(!(d1 == direction || d2 == direction)) //if the cable is not pointed in this direction, do nothing return - var/turf/TB = get_step(src, direction) + var/turf/TB = get_zstep(src, direction) for(var/obj/structure/cable/C in TB) @@ -376,25 +376,15 @@ obj/structure/cable/proc/cableColor(var/colorC) . = list() // this will be a list of all connected power objects var/turf/T - // Handle up/down cables - if(d1 == 11 || d2 == 11) - T = GetBelow(src) - if(T) - . += power_list(T, src, 12, 1) - if(d1 == 12 || d1 == 12) - T = GetAbove(src) - if(T) - . += power_list(T, src, 11, 1) - // Handle standard cables in adjacent turfs for(var/cable_dir in list(d1, d2)) - if(cable_dir == 11 || cable_dir == 12 || cable_dir == 0) + if(cable_dir == 0) continue var/reverse = reverse_dir[cable_dir] - T = get_step(src, cable_dir) + T = get_zstep(src, cable_dir) if(T) for(var/obj/structure/cable/C in T) - if((C.d1 && C.d1 == reverse) || (C.d2 && C.d2 == reverse)) + if(C.d1 == reverse || C.d2 == reverse) . += C if(cable_dir & (cable_dir - 1)) // Diagonal, check for /\/\/\ style cables along cardinal directions for(var/pair in list(NORTH|SOUTH, EAST|WEST)) @@ -402,7 +392,7 @@ obj/structure/cable/proc/cableColor(var/colorC) if(T) var/req_dir = cable_dir ^ pair for(var/obj/structure/cable/C in T) - if((C.d1 && C.d1 == req_dir) || (C.d2 && C.d2 == req_dir)) + if(C.d1 == req_dir || C.d2 == req_dir) . += C // Handle cables on the same turf as us @@ -566,7 +556,7 @@ obj/structure/cable/proc/cableColor(var/colorC) final_color = possible_cable_coil_colours["Red"] selected_color = "red" color = final_color - user << "You change \the [src]'s color to [lowertext(selected_color)]." + to_chat(user, "You change \the [src]'s color to [lowertext(selected_color)].") /obj/item/stack/cable_coil/proc/update_wclass() if(amount == 1) @@ -579,11 +569,11 @@ obj/structure/cable/proc/cableColor(var/colorC) return if(get_amount() == 1) - user << "A short piece of power cable." + to_chat(user, "A short piece of power cable.") else if(get_amount() == 2) - user << "A piece of power cable." + to_chat(user, "A piece of power cable.") else - user << "A coil of power cable. There are [get_amount()] lengths of cable in the coil." + to_chat(user, "A coil of power cable. There are [get_amount()] lengths of cable in the coil.") /obj/item/stack/cable_coil/verb/make_restraint() @@ -594,14 +584,14 @@ obj/structure/cable/proc/cableColor(var/colorC) if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned) if(!istype(usr.loc,/turf)) return if(src.amount <= 14) - usr << "\red You need at least 15 lengths to make restraints!" + to_chat(usr, "You need at least 15 lengths to make restraints!") return var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc) B.color = color - usr << "You wind some cable together to make some restraints." + to_chat(usr, "You wind some cable together to make some restraints.") src.use(15) else - usr << "\blue You cannot do that." + to_chat(usr, "You cannot do that.") ..() /obj/item/stack/cable_coil/cyborg/verb/set_colour() diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index fe51b4152e1..d6ae824fd1e 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -3,7 +3,6 @@ /obj/machinery/computer/gravity_control_computer name = "Gravity Generator Control" desc = "A computer to control a local gravity generator. Qualified personnel only." - icon = 'icons/obj/computer.dmi' icon_state = "airtunnel0e" anchored = 1 density = 1 diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 7697fdf6a45..13213c2e7e3 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -209,16 +209,8 @@ // if unmarked==1, only return those with no powernet /proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0) . = list() - var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0) -///// Z-Level Stuff - var/Zdir - if(d==11) - Zdir = 11 - else if (d==12) - Zdir = 12 - else - Zdir = 999 -///// Z-Level Stuff + + var/reverse = d ? reverse_dir[d] : 0 for(var/AM in T) if(AM == source) continue //we don't want to return source @@ -234,11 +226,7 @@ var/obj/structure/cable/C = AM if(!unmarked || !C.powernet) -///// Z-Level Stuff - if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir) -///// Z-Level Stuff - . += C - else if(C.d1 == d || C.d2 == d) + if(C.d1 == d || C.d2 == d || C.d1 == reverse || C.d2 == reverse ) . += C return . diff --git a/code/modules/power/sensors/sensor_monitoring.dm b/code/modules/power/sensors/sensor_monitoring.dm index 597ced19db1..21aecc59ea1 100644 --- a/code/modules/power/sensors/sensor_monitoring.dm +++ b/code/modules/power/sensors/sensor_monitoring.dm @@ -6,7 +6,6 @@ /obj/machinery/computer/power_monitor name = "Power Monitoring Console" desc = "Computer designed to remotely monitor power levels around the station" - icon = 'icons/obj/computer.dmi' icon_keyboard = "power_key" icon_screen = "power:0" light_color = "#ffcc33" diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 8786930e2f8..88c4ca34ac2 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -28,7 +28,6 @@ /obj/machinery/computer/turbine_computer name = "Gas turbine control computer" desc = "A computer to remotely control a gas turbine" - icon = 'icons/obj/computer.dmi' icon_keyboard = "tech_key" icon_screen = "turbinecomp" circuit = /obj/item/weapon/circuitboard/turbine_control diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 75d574ed632..9cb7292baf8 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -182,7 +182,11 @@ if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot) handle_suicide(user) else if(user.a_intent == I_HURT) //point blank shooting - Fire(A, user, pointblank=1) + if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A && A != user) + PreFire(A,user) //They're using the new gun system, locate what they're aiming at. + return + else + Fire(A, user, pointblank=1) else return ..() //Pistolwhippin' @@ -326,6 +330,8 @@ user.setMoveCooldown(move_delay) next_fire_time = world.time + fire_delay + accuracy = initial(accuracy) //Reset the gun's accuracy + if(muzzle_flash) set_light(0) @@ -396,6 +402,8 @@ //update timing next_fire_time = world.time + fire_delay + accuracy = initial(accuracy) //Reset the gun's accuracy + if(muzzle_flash) set_light(0) @@ -425,21 +433,21 @@ /obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0) if(silenced) playsound(user, fire_sound, 10, 1) + to_chat(user, "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]") + for(var/mob/living/L in oview(2,user)) + if(L.stat) + continue + if(L.blinded) + to_chat(L, "You hear a [fire_sound_text]!") + continue + to_chat(L, "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]") else playsound(user, fire_sound, 50, 1) - - if(reflex) - user.visible_message( - "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""] by reflex!", - "You fire \the [src] by reflex!", - "You hear a [fire_sound_text]!" - ) - else - user.visible_message( - "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""]!", - "You fire \the [src]!", - "You hear a [fire_sound_text]!" - ) + user.visible_message( + "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]", + "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]", + "You hear a [fire_sound_text]!" + ) if(muzzle_flash) set_light(muzzle_flash) @@ -482,11 +490,11 @@ // Certain statuses make it harder to aim, blindness especially. Same chances as melee, however guns accuracy uses multiples of 15. if(user.eye_blind) - accuracy -= 5 + P.accuracy -= 5 if(user.eye_blurry) - accuracy -= 2 + P.accuracy -= 2 if(user.confused) - accuracy -= 3 + P.accuracy -= 3 //accuracy bonus from aiming if (aim_targets && (target in aim_targets)) diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 6fd294f9284..604c936172b 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -28,6 +28,7 @@ name = "practice laser carbine" desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice." projectile_type = /obj/item/projectile/beam/practice + charge_cost = 48 cell_type = /obj/item/weapon/cell/device diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index faafd2e8c95..8fbfc0e6579 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -21,7 +21,7 @@ item_state = null w_class = ITEMSIZE_NORMAL force = 5 - slot_flags = SLOT_BELT + slot_flags = SLOT_BELT|SLOT_HOLSTER charge_cost = 480 projectile_type = /obj/item/projectile/ion diff --git a/code/modules/projectiles/guns/projectile/boltaction.dm b/code/modules/projectiles/guns/projectile/boltaction.dm index f96dfd22eae..e07c45294cd 100644 --- a/code/modules/projectiles/guns/projectile/boltaction.dm +++ b/code/modules/projectiles/guns/projectile/boltaction.dm @@ -49,4 +49,19 @@ desc = "The firepower of a Mosin, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds." user << "You shorten the barrel and stock of \the [src]!" else - ..() \ No newline at end of file + ..() + + +//Lever actions are the same thing, but bigger. +/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever + name = "lever-action rifle" + desc = "A reproduction of an almost ancient weapon design from the 19th century. This one uses a lever-action to move new rounds into the chamber. Uses 5.56mm rounds." + item_state = "leveraction" + icon_state = "leveraction" + fire_sound = 'sound/weapons/rifleshot.ogg' + max_shells = 5 + caliber = "a556" + origin_tech = list(TECH_COMBAT = 1)// Old as shit rifle doesn't have very good tech. + ammo_type = /obj/item/ammo_casing/a556 + load_method = SINGLE_CASING|SPEEDLOADER + action_sound = 'sound/weapons/riflebolt.ogg' \ No newline at end of file diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 750164a2602..f5a7460cc32 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -173,7 +173,7 @@ return //roll to-hit - miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.evasion), 0) + miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.get_evasion()), 0) var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss var/result = PROJECTILE_FORCE_MISS diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 54a2d301c7f..033b4065102 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -29,8 +29,8 @@ flash_strength *= H.species.flash_mod if(flash_strength > 0) - H.confused = max(H.confused, flash_strength + 5) - H.eye_blind = max(H.eye_blind, flash_strength) + H.Confuse(flash_strength + 5) + H.Blind(flash_strength) H.eye_blurry = max(H.eye_blurry, flash_strength + 5) H.adjustHalLoss(22 * (flash_strength / 5)) // Five flashes to stun. Bit weaker than melee flashes due to being ranged. @@ -146,9 +146,9 @@ var/ear_safety = 0 ear_safety = M.get_ear_protection() if(ear_safety == 1) - M.confused += 150 + M.Confuse(150) else if (ear_safety > 1) - M.confused += 30 + M.Confuse(30) else if (!ear_safety) M.Stun(10) M.Weaken(2) diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index b507afc3167..dd81d713fe3 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -150,7 +150,7 @@ on_hit(var/atom/target, var/blocked = 0) if(ishuman(target)) var/mob/living/carbon/human/M = target - M.confused += rand(5,8) + M.Confuse(rand(5,8)) /obj/item/projectile/chameleon name = "bullet" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index 091842663d2..d0be0469c10 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -95,7 +95,9 @@ if(alien == IS_SKRELL) strength_mod *= 5 if(alien == IS_TAJARA) - strength_mod *= 1.75 + strength_mod *= 1.25 + if(alien == IS_UNATHI) + strength_mod *= 0.75 if(alien == IS_DIONA) strength_mod = 0 @@ -106,7 +108,7 @@ if(dose * strength_mod >= strength * 2) // Slurring M.slurring = max(M.slurring, 30) if(dose * strength_mod >= strength * 3) // Confusion - walking in random directions - M.confused = max(M.confused, 20) + M.Confuse(20) if(dose * strength_mod >= strength * 4) // Blurry vision M.eye_blurry = max(M.eye_blurry, 10) if(dose * strength_mod >= strength * 5) // Drowsyness - periodically falling asleep diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 95f661d7a54..a5469149307 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -376,7 +376,7 @@ else if(eyes_covered) M << "Your [safe_thing] protect you from most of the pepperspray!" M.eye_blurry = max(M.eye_blurry, effective_strength * 3) - M.eye_blind = max(M.eye_blind, effective_strength) + M.Blind(effective_strength) M.Stun(5) M.Weaken(5) return @@ -387,7 +387,7 @@ else // Oh dear :D M << "You're sprayed directly in the eyes with pepperspray!" M.eye_blurry = max(M.eye_blurry, effective_strength * 5) - M.eye_blind = max(M.eye_blind, effective_strength * 2) + M.Blind(effective_strength * 2) M.Stun(5) M.Weaken(5) return @@ -1166,7 +1166,7 @@ if(M.dizziness) M.dizziness = max(0, M.dizziness - 15) if(M.confused) - M.confused = max(0, M.confused - 5) + M.Confuse(-5) /datum/reagent/drink/dry_ramen name = "Dry Ramen" @@ -1799,6 +1799,7 @@ reagent_state = LIQUID color = "#7F00FF" strength = 10 + druggy = 15 glass_name = "Pan-Galactic Gargle Blaster" glass_desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy." @@ -2232,3 +2233,26 @@ glass_name = "special blend whiskey" glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything." +/datum/reagent/ethanol/unathiliquor + name = "Redeemer's Brew" + id = "unathiliquor" + description = "This barely qualifies as a drink, and could give jetfuel a run for its money. Also known to cause feelings of euphoria and numbness." + taste_description = "spiced numbness" + color = "#242424" + strength = 5 + + glass_name = "unathi liquor" + glass_desc = "This barely qualifies as a drink, and may cause euphoria and numbness. Imbimber beware!" + +/datum/reagent/ethanol/unathiliquor/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) + ..() + if(alien == IS_DIONA) + return + + var/drug_strength = 10 + if(alien == IS_SKRELL) + drug_strength = drug_strength * 0.8 + + M.druggy = max(M.druggy, drug_strength) + if(prob(10) && isturf(M.loc) && !istype(M.loc, /turf/space) && M.canmove && !M.restrained()) + step(M, pick(cardinal)) \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index e0307e07cc3..ef6d8bb4287 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -258,7 +258,7 @@ /datum/reagent/oxycodone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) M.add_chemical_effect(CE_PAINKILLER, 200) M.eye_blurry += 10 - M.confused += 5 + M.Confuse(5) /datum/reagent/oxycodone/overdose(var/mob/living/carbon/M, var/alien) ..() @@ -319,7 +319,7 @@ /datum/reagent/imidazoline/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) M.eye_blurry = max(M.eye_blurry - 5, 0) - M.eye_blind = max(M.eye_blind - 5, 0) + M.AdjustBlinded(-5) if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES] @@ -349,7 +349,7 @@ continue if(I.damage > 0) //Peridaxon heals only non-robotic organs I.damage = max(I.damage - removed, 0) - H.confused += 5 + H.Confuse(5) if(I.damage <= 5 && I.organ_tag == O_EYES) H.eye_blurry += 10 //Eyes need to reset, or something H.sdisabilities &= ~BLIND @@ -441,7 +441,7 @@ M.dizziness = 0 M.drowsyness = 0 M.stuttering = 0 - M.confused = 0 + M.SetConfused(0) if(M.ingested) for(var/datum/reagent/R in M.ingested.reagent_list) if(istype(R, /datum/reagent/ethanol)) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm index 4f8e17cb1e6..0a7c78f9527 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm @@ -133,7 +133,7 @@ M.disabilities = 0 M.sdisabilities = 0 M.eye_blurry = 0 - M.eye_blind = 0 + M.SetBlinded(0) M.SetWeakened(0) M.SetStunned(0) M.SetParalysis(0) @@ -141,7 +141,7 @@ M.dizziness = 0 M.drowsyness = 0 M.stuttering = 0 - M.confused = 0 + M.SetConfused(0) M.sleeping = 0 M.jitteriness = 0 diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index 6e34257e4a4..12540c2d049 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -403,7 +403,7 @@ effective_dose *= 2 if(effective_dose == metabolism) - M.confused += 2 + M.Confuse(2) M.drowsyness += 2 else if(effective_dose < 2 * threshold) M.Weaken(30) @@ -429,6 +429,7 @@ glass_name = "beer" glass_desc = "A freezing pint of beer" + /* Drugs */ /datum/reagent/space_drugs @@ -490,7 +491,7 @@ if(alien == IS_SKRELL) drug_strength = drug_strength * 0.8 M.make_dizzy(drug_strength) - M.confused = max(M.confused, drug_strength * 5) + M.Confuse(drug_strength * 5) /datum/reagent/impedrezene name = "Impedrezene" diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 41ad4cb5c6c..e20ee9459f7 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -384,7 +384,7 @@ name = "Stimm" id = "stimm" result = "stimm" - required_reagents = list("sugar" = 1, "fuel" = 1) + required_reagents = list("left4zed" = 1, "fuel" = 1) catalysts = list("fuel" = 5) result_amount = 2 diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index ce377c87091..16a1cb3b265 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -121,7 +121,7 @@ recharge_time = 3 volume = 60 possible_transfer_amounts = list(5, 10, 20, 30) - reagent_ids = list("beer", "kahlua", "whiskey", "specialwhiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice") + reagent_ids = list("ale", "beer", "berryjuice", "coffee", "cognac", "cola", "dr_gibb", "egg", "gin", "hot_coco", "ice", "icetea", "kahlua", "lemonjuice", "lemon_lime", "limejuice", "mead", "milk", "mint", "orangejuice", "rum", "sodawater", "soymilk", "space_up", "spacemountainwind", "specialwhiskey", "sugar", "tea", "tequilla", "tomatojuice", "tonic", "vermouth", "vodka", "water", "watermelonjuice", "whiskey", "wine") /obj/item/weapon/reagent_containers/borghypo/service/attack(var/mob/M, var/mob/user) return diff --git a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm index 3300eb91d6e..2dcdd126057 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm @@ -407,6 +407,16 @@ ..() reagents.add_reagent("pwine", 100) +/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew + name = "Redeemer's Brew" + desc = "Just opening the top of this bottle makes you feel a bit tipsy. Not for the faint of heart." + icon_state = "redeemersbrew" + center_of_mass = list("x"=16, "y"=3) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew/New() + ..() + reagents.add_reagent("unathiliquor", 100) + //////////////////////////JUICES AND STUFF /////////////////////// /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index ed27e1a259b..bd670cc8bce 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -243,6 +243,12 @@ user.drop_from_inventory(src) qdel(src) return + else if(istype(D, /obj/item/weapon/wirecutters)) + to_chat(user, "You cut a big hole in \the [src] with \the [D]. It's kinda useless as a bucket now.") + user.put_in_hands(new /obj/item/clothing/head/helmet/bucket) + user.drop_from_inventory(src) + qdel(src) + return else if(istype(D, /obj/item/weapon/mop)) if(reagents.total_volume < 1) user << "\The [src] is empty!" diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm index f7bc1d1c803..48721314294 100644 --- a/code/modules/shieldgen/emergency_shield.dm +++ b/code/modules/shieldgen/emergency_shield.dm @@ -290,7 +290,7 @@ else if(istype(W, /obj/item/stack/cable_coil) && malfunction && is_open) var/obj/item/stack/cable_coil/coil = W user << "You begin to replace the wires." - //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + //if(do_after(user, min(60, round( ((getMaxHealth()/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage if(do_after(user, 30)) if (coil.use(1)) health = max_health diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index b6857a3f823..980053bd5d9 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/shuttle_control name = "shuttle control console" - icon = 'icons/obj/computer.dmi' icon_keyboard = "atmos_key" icon_screen = "shuttle" circuit = null diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm index a28f03e8feb..515453f6a35 100644 --- a/code/modules/spells/spellbook.dm +++ b/code/modules/spells/spellbook.dm @@ -322,7 +322,7 @@ /obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob) ..() user <<"You go blind!" - user.eye_blind = 10 + user.Blind(10) /obj/item/weapon/spellbook/oneuse/mindswap spell = /spell/targeted/mind_transfer diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm index 498d363408e..d9d581e0504 100644 --- a/code/modules/spells/targeted/targeted.dm +++ b/code/modules/spells/targeted/targeted.dm @@ -138,8 +138,8 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp if(amt_weakened || amt_paralysis || amt_stunned) if(target.buckled) target.buckled = null - target.eye_blind += amt_eye_blind + target.Blind(amt_eye_blind) target.eye_blurry += amt_eye_blurry target.dizziness += amt_dizziness - target.confused += amt_confused + target.Confuse(amt_confused) target.stuttering += amt_stuttering \ No newline at end of file diff --git a/code/modules/turbolift/turbolift.dm b/code/modules/turbolift/turbolift.dm index 7d2f3c11a83..90273250cb5 100644 --- a/code/modules/turbolift/turbolift.dm +++ b/code/modules/turbolift/turbolift.dm @@ -108,7 +108,7 @@ current_floor = next_floor control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.") - return 1 + return (next_floor.delay_time || move_delay || 30) /datum/turbolift/proc/queue_move_to(var/datum/turbolift_floor/floor) if(!floor || !(floor in floors) || (floor in queued_floors)) diff --git a/code/modules/turbolift/turbolift_areas.dm b/code/modules/turbolift/turbolift_areas.dm index dbf568aec2e..f9d69cc16f7 100644 --- a/code/modules/turbolift/turbolift_areas.dm +++ b/code/modules/turbolift/turbolift_areas.dm @@ -9,3 +9,4 @@ var/lift_floor_name = null var/lift_announce_str = "Ding!" var/arrival_sound = 'sound/machines/ding.ogg' + var/delay_time diff --git a/code/modules/turbolift/turbolift_console.dm b/code/modules/turbolift/turbolift_console.dm index 4cbee6a7737..f6619516816 100644 --- a/code/modules/turbolift/turbolift_console.dm +++ b/code/modules/turbolift/turbolift_console.dm @@ -123,7 +123,7 @@ dat += "Emergency Stop" dat += "
" - var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 230, 260) + var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 250, 320) popup.set_content(jointext(dat, null)) popup.open() return diff --git a/code/modules/turbolift/turbolift_floor.dm b/code/modules/turbolift/turbolift_floor.dm index 7761f092843..46e4dfa0f48 100644 --- a/code/modules/turbolift/turbolift_floor.dm +++ b/code/modules/turbolift/turbolift_floor.dm @@ -5,6 +5,7 @@ var/name var/announce_str var/arrival_sound + var/delay_time var/list/doors = list() var/obj/structure/lift/button/ext_panel @@ -20,6 +21,7 @@ name = A.lift_floor_name ? A.lift_floor_name : A.name announce_str = A.lift_announce_str arrival_sound = A.arrival_sound + delay_time = A.delay_time //called when a lift has queued this floor as a destination /datum/turbolift_floor/proc/pending_move(var/datum/turbolift/lift) diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm index 2e2498f88db..8930bf34d62 100644 --- a/code/modules/turbolift/turbolift_map.dm +++ b/code/modules/turbolift/turbolift_map.dm @@ -221,7 +221,7 @@ var/turf/T = locate(int_panel_x, int_panel_y, uz) lift.control_panel_interior = new(T, lift) lift.control_panel_interior.set_dir(udir) - lift.current_floor = lift.floors[uz] + lift.current_floor = lift.floors[1] lift.open_doors() diff --git a/code/modules/turbolift/turbolift_process.dm b/code/modules/turbolift/turbolift_process.dm index 83ce1b9faf0..124049d42e4 100644 --- a/code/modules/turbolift/turbolift_process.dm +++ b/code/modules/turbolift/turbolift_process.dm @@ -20,16 +20,17 @@ var/datum/controller/process/turbolift/turbolift_controller continue spawn(0) lift.busy = 1 - if(!lift.do_move()) + var/floor_delay + if(!(floor_delay = lift.do_move())) moving_lifts[liftref] = null moving_lifts -= liftref if(lift.target_floor) lift.target_floor.ext_panel.reset() lift.target_floor = null else - lift_is_moving(lift) + lift_is_moving(lift,floor_delay) lift.busy = 0 SCHECK -/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift) - moving_lifts["\ref[lift]"] = world.time + lift.move_delay +/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift,var/floor_delay) + moving_lifts["\ref[lift]"] = world.time + floor_delay diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index 5c2db9f3deb..1ece0248335 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -44,10 +44,15 @@ var/list/ventcrawl_machinery = list( /mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item) if(carried_item == ability_master) return 1 + + var/list/allowed = list() for(var/type in can_enter_vent_with) - if(istype(carried_item, can_enter_vent_with)) - return get_inventory_slot(carried_item) == 0 - return 0 + var/list/types = typesof(type) + allowed += types + + if(carried_item.type in allowed) + if(get_inventory_slot(carried_item) == 0) + return 1 /mob/living/carbon/is_allowed_vent_crawl_item(var/obj/item/carried_item) if(carried_item in internal_organs) diff --git a/code/modules/virus2/curer.dm b/code/modules/virus2/curer.dm index d6c5189f191..c297643e2a9 100644 --- a/code/modules/virus2/curer.dm +++ b/code/modules/virus2/curer.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/curer name = "cure research machine" - icon = 'icons/obj/computer.dmi' icon_keyboard = "med_key" icon_screen = "dna" circuit = /obj/item/weapon/circuitboard/curefab diff --git a/code/modules/virus2/diseasesplicer.dm b/code/modules/virus2/diseasesplicer.dm index 8d88639db3c..298dc49f27e 100644 --- a/code/modules/virus2/diseasesplicer.dm +++ b/code/modules/virus2/diseasesplicer.dm @@ -1,6 +1,5 @@ /obj/machinery/computer/diseasesplicer name = "disease splicer" - icon = 'icons/obj/computer.dmi' icon_keyboard = "med_key" icon_screen = "crew" diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index 5243bae35f6..310f2231593 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -264,7 +264,7 @@ stage = 3 activate(var/mob/living/carbon/mob,var/multiplier) mob << "You have trouble telling right and left apart all of a sudden." - mob.confused += 10 + mob.Confuse(10) /datum/disease2/effect/mutation name = "DNA Degradation" diff --git a/code/modules/xenobio2/machinery/injector_computer.dm b/code/modules/xenobio2/machinery/injector_computer.dm index 2f0144d37b3..6189a385e22 100644 --- a/code/modules/xenobio2/machinery/injector_computer.dm +++ b/code/modules/xenobio2/machinery/injector_computer.dm @@ -76,7 +76,7 @@ if(injector.occupant) data["occupantHealth"] = injector.occupant.health - data["occupantHealthMax"] = injector.occupant.maxHealth + data["occupantHealthMax"] = injector.occupant.getMaxHealth() else data["occupantHealth"] = null data["occupantHealthMax"] = null diff --git a/config/example/game_options.txt b/config/example/game_options.txt index 035431b8bad..9e122db4238 100644 --- a/config/example/game_options.txt +++ b/config/example/game_options.txt @@ -57,6 +57,8 @@ ALIEN_DELAY 0 METROID_DELAY 0 ANIMAL_DELAY 0 +## Volume of footstep sound effects. Range: 1-100, Set to 0 to disable footstep sounds. +FOOTSTEP_VOLUME 60 ### Miscellaneous ### diff --git a/html/changelog.html b/html/changelog.html index 79d28487748..b3ff3223e11 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,88 @@ -->
+

25 April 2017

+

Anewbe updated:

+
    +
  • Cultist armor now has better protection from strange energies.
  • +
  • Adds the ion pistol to the uplink.
  • +
  • The ion pistol can now be holstered.
  • +
  • Sprites on the smoking pipes should be fixed.
  • +
+

Atermonera updated:

+
    +
  • Brain type (Organic, cyborg, posi, or drone) is now displayed in all records.
  • +
+

Belsima updated:

+
    +
  • Changes relaymove() code in bodybags.
  • +
  • Above tweak used to allow exiting bodybag while in closed morgue tray.
  • +
+

Leshana updated:

+
    +
  • Implements footstep sound system and adds sounds to various floor types including plating, tiles, wood, and carpet.
  • +
+

LorenLuke updated:

+
    +
  • Allows people who are bucked to give/receive items.
  • +
  • Can click-drag people onto chairs/beds from 1 tile away to buckle them.
  • +
  • Allows you to place tape masks/restraints back on the roll (roll is still infinite).
  • +
  • Fixes ventcrawling for spiderbots/implants/etc.
  • +
+

Neerti updated:

+
    +
  • Drones will now spawn with an EIO-mandated ID card alongside their NT ID.
  • +
  • Fabricate Clothing for Changelings costs one point instead of two, and is fabricated twice as fast.
  • +
  • Dead changelings can no longer hear deadchat or freely ghost.
  • +
  • Shrieks now share a 10 second cooldown.
  • +
  • Lings cannot transform or shriek inside containers such as closets and pipes.
  • +
  • Regen. Stasis timer adjusted to be between 2 to 4 minutes.
  • +
  • Visible Camo. should end if the user is stunned.
  • +
  • Visible Camo. now blocks AI tracking when active.
  • +
  • Recursive Visible Camo. no longer gives true invis.
  • +
  • Recursive Visible Camo. will allow the changeling to run while cloaked instead.
  • +
  • Ling chemical meter on HUD now has a blinking exclaimation mark if below 20 chemicals, to warn that they cannot revive if they should die while still below 20.
  • +
+

Yoshax updated:

+
    +
  • Tape color is different now. Security tape is red rather than yellow, Engineering tape remains yellow and Atmos tape is a lighter cyan rather than blue.
  • +
+ +

19 April 2017

+

Anewbe updated:

+
    +
  • Unathi ribcages now reach down to their lower torso.
  • +
  • Unathi no longer have appendices or kidneys, the function of the kidneys is now a function of their liver.
  • +
  • Unathi are more slightly more difficult to damage.
  • +
  • Unathi now process medicine 15% slower. Additionally, it's harder for them to get drunk.
  • +
  • Unathi age range is now 32 to 260.
  • +
  • Unathi are not as slowed by heavy items.
  • +
+

Atermonera updated:

+
    +
  • Translators no longer try to translate null languages.
  • +
+

LorenLuke updated:

+
    +
  • Allows Blast doors to be attacked and broken like regular airlocks.
  • +
  • Changelings can bank up to a maximum of 3 respecs at one time.
  • +
  • Changelings begin with 2 respecs.
  • +
  • Firing a silenced weapon gives a message in text to the user.
  • +
+

MagmaRam updated:

+
    +
  • Added instructions on how to use the changelog updating scripts.
  • +
  • Updated in-game EVA manual.
  • +
+

Neerti updated:

+
    +
  • Adds makeshift armor for the head and chest regions. How protective they are depends on the material used to craft it. The helmet is made by using wirecutters on a bucket, then using a stack of material. The chestpiece is made by crafting two armor plate, using wires on one of them, then hiting one with the other.
  • +
+

Yoshax updated:

+
    +
  • Water such as the pool will no longer apply fire stacks when you enter, meaning you will no longer be flammable from swimming.
  • +
+

16 April 2017

Anewbe updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index a708517abef..92c00ef9134 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -3423,3 +3423,72 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - tweak: Scrubbers now scrub Phoron by default. - tweak: Scrubbers now have the first dangerzone at anything more than 0 Phoron. - bugfix: No longer will you attack Alarms with your ID when trying to unlock them. +2017-04-19: + Anewbe: + - rscadd: Unathi ribcages now reach down to their lower torso. + - rscadd: Unathi no longer have appendices or kidneys, the function of the kidneys + is now a function of their liver. + - rscadd: Unathi are more slightly more difficult to damage. + - rscadd: Unathi now process medicine 15% slower. Additionally, it's harder for + them to get drunk. + - rscadd: Unathi age range is now 32 to 260. + - rscadd: Unathi are not as slowed by heavy items. + Atermonera: + - bugfix: Translators no longer try to translate null languages. + LorenLuke: + - rscadd: Allows Blast doors to be attacked and broken like regular airlocks. + - tweak: Changelings can bank up to a maximum of 3 respecs at one time. + - tweak: Changelings begin with 2 respecs. + - tweak: Firing a silenced weapon gives a message in text to the user. + MagmaRam: + - rscadd: Added instructions on how to use the changelog updating scripts. + - tweak: Updated in-game EVA manual. + Neerti: + - rscadd: Adds makeshift armor for the head and chest regions. How protective they + are depends on the material used to craft it. The helmet is made by using wirecutters + on a bucket, then using a stack of material. The chestpiece is made by crafting + two armor plate, using wires on one of them, then hiting one with the other. + Yoshax: + - bugfix: Water such as the pool will no longer apply fire stacks when you enter, + meaning you will no longer be flammable from swimming. +2017-04-25: + Anewbe: + - rscadd: Cultist armor now has better protection from strange energies. + - rscadd: Adds the ion pistol to the uplink. + - tweak: The ion pistol can now be holstered. + - bugfix: Sprites on the smoking pipes should be fixed. + Atermonera: + - rscadd: Brain type (Organic, cyborg, posi, or drone) is now displayed in all records. + Belsima: + - tweak: Changes relaymove() code in bodybags. + - bugfix: Above tweak used to allow exiting bodybag while in closed morgue tray. + Leshana: + - rscadd: Implements footstep sound system and adds sounds to various floor types + including plating, tiles, wood, and carpet. + LorenLuke: + - bugfix: Allows people who are bucked to give/receive items. + - tweak: Can click-drag people onto chairs/beds from 1 tile away to buckle them. + - tweak: Allows you to place tape masks/restraints back on the roll (roll is still + infinite). + - bugfix: Fixes ventcrawling for spiderbots/implants/etc. + Neerti: + - rscadd: Drones will now spawn with an EIO-mandated ID card alongside their NT + ID. + - tweak: Fabricate Clothing for Changelings costs one point instead of two, and + is fabricated twice as fast. + - tweak: Dead changelings can no longer hear deadchat or freely ghost. + - tweak: Shrieks now share a 10 second cooldown. + - tweak: Lings cannot transform or shriek inside containers such as closets and + pipes. + - tweak: Regen. Stasis timer adjusted to be between 2 to 4 minutes. + - tweak: Visible Camo. should end if the user is stunned. + - rscadd: Visible Camo. now blocks AI tracking when active. + - rscdel: Recursive Visible Camo. no longer gives true invis. + - rscadd: Recursive Visible Camo. will allow the changeling to run while cloaked + instead. + - rscadd: Ling chemical meter on HUD now has a blinking exclaimation mark if below + 20 chemicals, to warn that they cannot revive if they should die while still + below 20. + Yoshax: + - tweak: Tape color is different now. Security tape is red rather than yellow, Engineering + tape remains yellow and Atmos tape is a lighter cyan rather than blue. diff --git a/html/changelogs/MagmaRam - evabook.yml b/html/changelogs/Anewbe - Thermals.yml similarity index 95% rename from html/changelogs/MagmaRam - evabook.yml rename to html/changelogs/Anewbe - Thermals.yml index f94057e6a40..d67f97bba8b 100644 --- a/html/changelogs/MagmaRam - evabook.yml +++ b/html/changelogs/Anewbe - Thermals.yml @@ -22,7 +22,7 @@ ################################# # Your name. -author: MagmaRam +author: Anewbe # Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. delete-after: True @@ -33,4 +33,4 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - tweak: "Updated in-game EVA manual." + - rscadd: "Thermals now let you see in the dark." diff --git a/html/changelogs/Arokha - Sleepers.yml b/html/changelogs/Arokha - Sleepers.yml new file mode 100644 index 00000000000..717b60f12fb --- /dev/null +++ b/html/changelogs/Arokha - Sleepers.yml @@ -0,0 +1,39 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Arokha + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Sleepers now have a 'stasis' level setting, that will ignore varying numbers of life() ticks on the patient." + - tweak: "Stasis bags and Ody sleepers now use a fixed level of this new stasis system (ignore 2/3 life ticks)." + - tweak: "You can escape from being asleep in a sleeper, similar to escaping from a cryotube." + - rscadd: "You can now use grabs on sleepers to insert patients, same as scanners." diff --git a/html/changelogs/MagmaRam - changelog_instructions.yml b/html/changelogs/LorenLuke - Changeling-Fix.yml similarity index 93% rename from html/changelogs/MagmaRam - changelog_instructions.yml rename to html/changelogs/LorenLuke - Changeling-Fix.yml index 82235bc8f6a..b6f0a759759 100644 --- a/html/changelogs/MagmaRam - changelog_instructions.yml +++ b/html/changelogs/LorenLuke - Changeling-Fix.yml @@ -22,7 +22,7 @@ ################################# # Your name. -author: MagmaRam +author: LorenLuke # Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. delete-after: True @@ -33,4 +33,4 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - rscadd: "Added instructions on how to use the changelog updating scripts." + - Bugfix: "Unfucks the screen bug on roundstart changelings." diff --git a/html/changelogs/LorenLuke - Changeling-Medhud.yml b/html/changelogs/LorenLuke - Changeling-Medhud.yml new file mode 100644 index 00000000000..e183cbce290 --- /dev/null +++ b/html/changelogs/LorenLuke - Changeling-Medhud.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Changeling now display 'alive' status on Medhuds properly." diff --git a/html/changelogs/LorenLuke - ChangelingSting.yml b/html/changelogs/LorenLuke - ChangelingSting.yml new file mode 100644 index 00000000000..fab527a62f6 --- /dev/null +++ b/html/changelogs/LorenLuke - ChangelingSting.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Refactors changeling ranged stings not passing over tables. Can now pass over tables, any machinery (except doors), machine frames, and past closet subtypes." diff --git a/html/changelogs/LorenLuke - Communicator-Video.yml b/html/changelogs/LorenLuke - Communicator-Video.yml new file mode 100644 index 00000000000..1c7d69c85da --- /dev/null +++ b/html/changelogs/LorenLuke - Communicator-Video.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "You can now view an active video call by using the communicator in hand." diff --git a/html/changelogs/LorenLuke - GunAim.yml b/html/changelogs/LorenLuke - GunAim.yml new file mode 100644 index 00000000000..58720590383 --- /dev/null +++ b/html/changelogs/LorenLuke - GunAim.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Guns on harm intent in aim mode will target, rather than shoot pointblank on first click." diff --git a/html/changelogs/LorenLuke - Handcuffs.yml b/html/changelogs/LorenLuke - Handcuffs.yml new file mode 100644 index 00000000000..a0774083cf2 --- /dev/null +++ b/html/changelogs/LorenLuke - Handcuffs.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "You can now put handcuffs on yourself." diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index a69e893b6fc..c13a604dba1 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 66574573449..1f4bd4a68f2 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 7407aeefb54..44f920fe30c 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi b/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi new file mode 100644 index 00000000000..70f3b98db24 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi differ diff --git a/icons/mob/human_races/r_lizard.dmi b/icons/mob/human_races/r_lizard.dmi index 5fb2c58be46..97e6f04bdc1 100644 Binary files a/icons/mob/human_races/r_lizard.dmi and b/icons/mob/human_races/r_lizard.dmi differ diff --git a/icons/mob/items/lefthand_guns.dmi b/icons/mob/items/lefthand_guns.dmi index ff49dc5577c..7b2b705c940 100644 Binary files a/icons/mob/items/lefthand_guns.dmi and b/icons/mob/items/lefthand_guns.dmi differ diff --git a/icons/mob/items/righthand_guns.dmi b/icons/mob/items/righthand_guns.dmi index 44521ed36e3..7c05fbd61d1 100644 Binary files a/icons/mob/items/righthand_guns.dmi and b/icons/mob/items/righthand_guns.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 00f14c373ea..02ffbf4e658 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/modifier_effects.dmi b/icons/mob/modifier_effects.dmi new file mode 100644 index 00000000000..ecb575c673b Binary files /dev/null and b/icons/mob/modifier_effects.dmi differ diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi index 9a326ac8a40..809046036da 100644 Binary files a/icons/mob/screen1.dmi and b/icons/mob/screen1.dmi differ diff --git a/icons/mob/species/tajaran/helmet.dmi b/icons/mob/species/tajaran/helmet.dmi index 87a3d3f58f3..ff89b2dcdd9 100644 Binary files a/icons/mob/species/tajaran/helmet.dmi and b/icons/mob/species/tajaran/helmet.dmi differ diff --git a/icons/mob/species/tajaran/mask.dmi b/icons/mob/species/tajaran/mask.dmi index cf3be6425fe..d7028d66a6d 100644 Binary files a/icons/mob/species/tajaran/mask.dmi and b/icons/mob/species/tajaran/mask.dmi differ diff --git a/icons/mob/species/unathi/helmet.dmi b/icons/mob/species/unathi/helmet.dmi index 1af66a7d089..618d3be5734 100644 Binary files a/icons/mob/species/unathi/helmet.dmi and b/icons/mob/species/unathi/helmet.dmi differ diff --git a/icons/mob/species/unathi/mask.dmi b/icons/mob/species/unathi/mask.dmi index cf3be6425fe..25cc585aed2 100644 Binary files a/icons/mob/species/unathi/mask.dmi and b/icons/mob/species/unathi/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 5d7180da7cf..b2eb9c72fe8 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index e1a2c1c2ae4..390fdb88ea8 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index ff4ea400ede..0e863674733 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 9337d5127c0..ef18c7bf49c 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index b6b28fdfbe4..fd3ff5cecaa 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index b1750efa362..c1183a4e939 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index c70873ccc7f..330915356a7 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi index d9e2dfef958..ba02b5a3246 100644 Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index dc3456ba672..778ec461bb0 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index b2ff3108ea6..39ed73fc3df 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index 5671731aab6..9bb3378c8ef 100755 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ diff --git a/icons/policetape.dmi b/icons/policetape.dmi index bc469f2eabc..5dde02f1b52 100644 Binary files a/icons/policetape.dmi and b/icons/policetape.dmi differ diff --git a/nano/templates/adv_med.tmpl b/nano/templates/adv_med.tmpl index 2dbd997cbd5..71e02e25095 100644 --- a/nano/templates/adv_med.tmpl +++ b/nano/templates/adv_med.tmpl @@ -94,7 +94,7 @@ Used In File(s): \code\game\machinery\adv_med.dm
{{:data.occupant.blood.percent}}%
-

Reagents

+

Blood Reagents

{{if data.occupant.reagents}} {{for data.occupant.reagents}} @@ -105,7 +105,20 @@ Used In File(s): \code\game\machinery\adv_med.dm {{/for}}
{{else}} -
No reagents detected.
+
No blood reagents detected.
+ {{/if}} +

Stomach Reagents

+ {{if data.occupant.ingested}} + + {{for data.occupant.ingested}} + + + + + {{/for}} +
{{:value.name}}:{{:value.amount}}
+ {{else}} +
No stomach reagents detected.
{{/if}}

External Organs

diff --git a/nano/templates/holodeck.tmpl b/nano/templates/holodeck.tmpl index 71d4ad56056..a91d5a60e51 100644 --- a/nano/templates/holodeck.tmpl +++ b/nano/templates/holodeck.tmpl @@ -5,7 +5,7 @@

Current Loaded Programs:

{{for data.supportedPrograms}} -
{{:helper.link(value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+
{{:helper.link(value, data.currentProgram == value ? 'check' : 'close', {'program' : value}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.
{{if data.isSilicon}} @@ -22,7 +22,7 @@ {{if data.safetyDisabled}} {{for data.restrictedPrograms}} -
{{:helper.link('Begin ' + value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+
{{:helper.link('Begin ' + value, data.currentProgram == value ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Ensure the holodeck is empty before testing.
Safety Protocols are DISABLED
diff --git a/nano/templates/pai_medrecords.tmpl b/nano/templates/pai_medrecords.tmpl index 89926d3915b..24e00e949f1 100644 --- a/nano/templates/pai_medrecords.tmpl +++ b/nano/templates/pai_medrecords.tmpl @@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+
Entity Classification
+
{{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pai_secrecords.tmpl b/nano/templates/pai_secrecords.tmpl index 51cb45dee2e..5ba1e4d90dc 100644 --- a/nano/templates/pai_secrecords.tmpl +++ b/nano/templates/pai_secrecords.tmpl @@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+
Entity Classification
+
{{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 6cd3004654e..77f026a3495 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -568,6 +568,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm
{{if data.records.general_exists == 1}} Name: {{:data.records.general.name}}
+ Entity Class: {{:data.records.general.brain_type}}
Sex: {{:data.records.general.sex}}
Species: {{:data.records.general.species}}
Age: {{:data.records.general.age}}
diff --git a/nano/templates/sleeper.tmpl b/nano/templates/sleeper.tmpl index 49fb0ae8d75..7ee370e890f 100644 --- a/nano/templates/sleeper.tmpl +++ b/nano/templates/sleeper.tmpl @@ -88,4 +88,12 @@
{{/if}} +
+
+ Stasis Level: +
+
+ {{:helper.link(data.stasis, null, {'change_stasis' : 1})}} +
+
{{/if}} diff --git a/polaris.dme b/polaris.dme index 28d9de7f22a..1df561601b3 100644 --- a/polaris.dme +++ b/polaris.dme @@ -32,6 +32,7 @@ #include "code\__defines\math_physics.dm" #include "code\__defines\misc.dm" #include "code\__defines\mobs.dm" +#include "code\__defines\planets.dm" #include "code\__defines\process_scheduler.dm" #include "code\__defines\research.dm" #include "code\__defines\species_languages.dm" @@ -470,8 +471,6 @@ #include "code\game\gamemodes\technomancer\spells\aura\frost_aura.dm" #include "code\game\gamemodes\technomancer\spells\aura\shock_aura.dm" #include "code\game\gamemodes\technomancer\spells\aura\unstable_aura.dm" -#include "code\game\gamemodes\technomancer\spells\insert\corona.dm" -#include "code\game\gamemodes\technomancer\spells\insert\haste.dm" #include "code\game\gamemodes\technomancer\spells\insert\insert.dm" #include "code\game\gamemodes\technomancer\spells\insert\mend_burns.dm" #include "code\game\gamemodes\technomancer\spells\insert\mend_metal.dm" @@ -479,7 +478,10 @@ #include "code\game\gamemodes\technomancer\spells\insert\mend_wires.dm" #include "code\game\gamemodes\technomancer\spells\insert\mend_wounds.dm" #include "code\game\gamemodes\technomancer\spells\insert\purify.dm" -#include "code\game\gamemodes\technomancer\spells\insert\repel_missiles.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\corona.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\haste.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\modifier.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\repel_missiles.dm" #include "code\game\gamemodes\technomancer\spells\projectile\beam.dm" #include "code\game\gamemodes\technomancer\spells\projectile\chain_lightning.dm" #include "code\game\gamemodes\technomancer\spells\projectile\force_missile.dm" @@ -898,6 +900,7 @@ #include "code\game\objects\items\weapons\material\foam.dm" #include "code\game\objects\items\weapons\material\kitchen.dm" #include "code\game\objects\items\weapons\material\knives.dm" +#include "code\game\objects\items\weapons\material\material_armor.dm" #include "code\game\objects\items\weapons\material\material_weapons.dm" #include "code\game\objects\items\weapons\material\misc.dm" #include "code\game\objects\items\weapons\material\shards.dm" @@ -1506,6 +1509,7 @@ #include "code\modules\mob\mob_helpers.dm" #include "code\modules\mob\mob_movement.dm" #include "code\modules\mob\mob_transformation_simple.dm" +#include "code\modules\mob\modifiers.dm" #include "code\modules\mob\say.dm" #include "code\modules\mob\transform_procs.dm" #include "code\modules\mob\typing_indicator.dm" @@ -1792,6 +1796,7 @@ #include "code\modules\organs\subtypes\machine.dm" #include "code\modules\organs\subtypes\seromi.dm" #include "code\modules\organs\subtypes\standard.dm" +#include "code\modules\organs\subtypes\unathi.dm" #include "code\modules\organs\subtypes\unbreakable.dm" #include "code\modules\organs\subtypes\vox.dm" #include "code\modules\overmap\_defines.dm" diff --git a/sound/effects/footstep/carpet1.ogg b/sound/effects/footstep/carpet1.ogg new file mode 100644 index 00000000000..2735a9bf3dc Binary files /dev/null and b/sound/effects/footstep/carpet1.ogg differ diff --git a/sound/effects/footstep/carpet2.ogg b/sound/effects/footstep/carpet2.ogg new file mode 100644 index 00000000000..07e5f2320aa Binary files /dev/null and b/sound/effects/footstep/carpet2.ogg differ diff --git a/sound/effects/footstep/carpet3.ogg b/sound/effects/footstep/carpet3.ogg new file mode 100644 index 00000000000..edb0193f6e2 Binary files /dev/null and b/sound/effects/footstep/carpet3.ogg differ diff --git a/sound/effects/footstep/carpet4.ogg b/sound/effects/footstep/carpet4.ogg new file mode 100644 index 00000000000..c9598e2b736 Binary files /dev/null and b/sound/effects/footstep/carpet4.ogg differ diff --git a/sound/effects/footstep/carpet5.ogg b/sound/effects/footstep/carpet5.ogg new file mode 100644 index 00000000000..076818323ae Binary files /dev/null and b/sound/effects/footstep/carpet5.ogg differ diff --git a/sound/effects/footstep/floor1.ogg b/sound/effects/footstep/floor1.ogg new file mode 100644 index 00000000000..1e3e1558399 Binary files /dev/null and b/sound/effects/footstep/floor1.ogg differ diff --git a/sound/effects/footstep/floor2.ogg b/sound/effects/footstep/floor2.ogg new file mode 100644 index 00000000000..cce5a25d829 Binary files /dev/null and b/sound/effects/footstep/floor2.ogg differ diff --git a/sound/effects/footstep/floor3.ogg b/sound/effects/footstep/floor3.ogg new file mode 100644 index 00000000000..16ab67f729c Binary files /dev/null and b/sound/effects/footstep/floor3.ogg differ diff --git a/sound/effects/footstep/floor4.ogg b/sound/effects/footstep/floor4.ogg new file mode 100644 index 00000000000..9ef15430ff8 Binary files /dev/null and b/sound/effects/footstep/floor4.ogg differ diff --git a/sound/effects/footstep/floor5.ogg b/sound/effects/footstep/floor5.ogg new file mode 100644 index 00000000000..0f6a66057de Binary files /dev/null and b/sound/effects/footstep/floor5.ogg differ diff --git a/sound/effects/footstep/hull1.ogg b/sound/effects/footstep/hull1.ogg new file mode 100644 index 00000000000..615df6c5502 Binary files /dev/null and b/sound/effects/footstep/hull1.ogg differ diff --git a/sound/effects/footstep/hull2.ogg b/sound/effects/footstep/hull2.ogg new file mode 100644 index 00000000000..3aecb743f70 Binary files /dev/null and b/sound/effects/footstep/hull2.ogg differ diff --git a/sound/effects/footstep/hull3.ogg b/sound/effects/footstep/hull3.ogg new file mode 100644 index 00000000000..03339131f63 Binary files /dev/null and b/sound/effects/footstep/hull3.ogg differ diff --git a/sound/effects/footstep/hull4.ogg b/sound/effects/footstep/hull4.ogg new file mode 100644 index 00000000000..2fba89d3185 Binary files /dev/null and b/sound/effects/footstep/hull4.ogg differ diff --git a/sound/effects/footstep/hull5.ogg b/sound/effects/footstep/hull5.ogg new file mode 100644 index 00000000000..10c5912b97a Binary files /dev/null and b/sound/effects/footstep/hull5.ogg differ diff --git a/sound/effects/footstep/plating1.ogg b/sound/effects/footstep/plating1.ogg new file mode 100644 index 00000000000..0df770e6638 Binary files /dev/null and b/sound/effects/footstep/plating1.ogg differ diff --git a/sound/effects/footstep/plating2.ogg b/sound/effects/footstep/plating2.ogg new file mode 100644 index 00000000000..314b9133d25 Binary files /dev/null and b/sound/effects/footstep/plating2.ogg differ diff --git a/sound/effects/footstep/plating3.ogg b/sound/effects/footstep/plating3.ogg new file mode 100644 index 00000000000..5c571d77eb6 Binary files /dev/null and b/sound/effects/footstep/plating3.ogg differ diff --git a/sound/effects/footstep/plating4.ogg b/sound/effects/footstep/plating4.ogg new file mode 100644 index 00000000000..5953262764b Binary files /dev/null and b/sound/effects/footstep/plating4.ogg differ diff --git a/sound/effects/footstep/plating5.ogg b/sound/effects/footstep/plating5.ogg new file mode 100644 index 00000000000..4676a637a6d Binary files /dev/null and b/sound/effects/footstep/plating5.ogg differ diff --git a/sound/effects/footstep/wood1.ogg b/sound/effects/footstep/wood1.ogg new file mode 100644 index 00000000000..c76fc423fc2 Binary files /dev/null and b/sound/effects/footstep/wood1.ogg differ diff --git a/sound/effects/footstep/wood2.ogg b/sound/effects/footstep/wood2.ogg new file mode 100644 index 00000000000..71dc1aa9679 Binary files /dev/null and b/sound/effects/footstep/wood2.ogg differ diff --git a/sound/effects/footstep/wood3.ogg b/sound/effects/footstep/wood3.ogg new file mode 100644 index 00000000000..bf86889006e Binary files /dev/null and b/sound/effects/footstep/wood3.ogg differ diff --git a/sound/effects/footstep/wood4.ogg b/sound/effects/footstep/wood4.ogg new file mode 100644 index 00000000000..44734425ce6 Binary files /dev/null and b/sound/effects/footstep/wood4.ogg differ diff --git a/sound/effects/footstep/wood5.ogg b/sound/effects/footstep/wood5.ogg new file mode 100644 index 00000000000..5ad4fa81e77 Binary files /dev/null and b/sound/effects/footstep/wood5.ogg differ