diff --git a/.travis.yml b/.travis.yml index 432d409314..2ccfc69801 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 92dd6f5d51..4a4c29dcfb 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 8115790c50..cd0c9955c1 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 eb572aa0e2..0a8598d21f 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 09f5e81ca0..f85ac5e7d4 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 1dc6436355..ef00eed334 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 0000000000..e8f526382e --- /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 1531a67d5b..b59857c8f6 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 1038b6a2e4..463a7da26d 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 71eff4a392..3602a52481 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 88e69696bf..b41dd9c57b 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 b3b556d7bd..7b446b4d2d 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 6039dd6612..57f2247255 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 ee361c9888..f0d3cc3341 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 d40fd4fa5a..274c0c0903 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 d6427f063f..0c7fd3f4ed 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 41a1779322..34b20a9f48 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 b511c9befd..fe9f99b032 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 e06f774a83..a28dd27036 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 a60faeb830..e54eb3c1cd 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 e8ed12a446..9c73a4e3d2 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 10cb5f9fbb..396e6faf34 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 3068f1eee5..c173ba55ac 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 e098c98f03..41b14478b3 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 fd15d94dae..a22130484c 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 fd72524e5a..a9b323465c 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 4052568a50..536aef26ce 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 5370a68200..b7a6c56957 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 3875a4b4fa..38d200cad5 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 f106d9167f..138cd156e3 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 dee603fc4a..765dbb51e6 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 eddf83292e..2eb628b8f6 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 7910ceaf7c..66f13e720f 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 2f0b9c57e7..c640e35392 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 2b8af49eb6..37e7f67fe0 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 236af69f5f..37a9945210 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 00e31cc932..167f6f41b9 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 5868bf4b59..cecb7b87c7 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 61f177eae5..027b61333e 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 2d43e67f24..b9418bfea9 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 e2f6b8a56c..098f9fd329 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 5c440d0dcd..8d1fb4c6ad 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 fa9985b1b6..453469619c 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 431e72a32f..3c65a9503f 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 87edf6a621..10f258bf58 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 12f04db48c..50a9bf5da7 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 555ff9f559..84b0b22931 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 0ecd700732..0000000000 --- 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 30422cef3f..0000000000 --- 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 38e4ef4720..0000000000 --- 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 0000000000..74a06855d9 --- /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 0000000000..7f7c1045b3 --- /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 0000000000..b0a5c93747 --- /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 0000000000..d267ecce88 --- /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 c56df4f26e..90a352c95f 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 eafb167dd4..be978e7ee4 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 7cf36ebabf..0e7e96104c 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 1e4398546c..e7bb56347e 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 9ca5c327fa..8bfb5760a2 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 f69f5f6b2a..f54d069b9d 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 bba12887a9..b1cf9bac08 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 83c6f81e30..546e6acd88 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 31c8fe7819..1aadf981c4 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 de81fbb0fa..cf657e1c10 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 9f1b7afb38..3826eb3c94 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 75ba732950..db932f8cd0 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 6eae870cfd..b51fa788ab 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 e8fe96ae6c..3d0235fab9 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 1c54fb0f4c..8c435f5845 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 ca56ce168d..4d29a56b89 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 54c94d8684..465884b2ca 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 1a67778fdf..bd9c66dbae 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 cb0f8a5552..0a337f4df8 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 d390a7f163..4bcc43bbec 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 d36f03b525..ba7193b69b 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 57a662db46..bb4228397d 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 a314bed273..6b77a274bf 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 d1ab11e706..5d0f707ae8 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 6441a5e72a..672a6a425b 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 6aeecfc8e5..e78cba3568 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 209e3bb228..3d899377cc 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 185de7f06d..cd38f9f1ce 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 ae48142b4d..a18edbc5fa 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 ffe30bf3fd..1e10e03f4f 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 a6da9bfa00..00a0654cc1 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 967c03252f..6aec830c89 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 7950200137..f456a95d73 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 1450fa94ce..4d77da4ae9 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 674e746c28..667adfc712 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 8bfe2dffca..42c8e4949b 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 b553f4416c..62d7e7b311 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 1bd7f9349a..74d9a4b8ed 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 243d301289..5d883784aa 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 90fb43724e..5de1ba1396 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 15f3310322..db4e890d60 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 10a847b469..d404b5cd44 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 76c4f9e768..ee2d2f2c57 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 1190d7f812..62941c24f0 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 cf55cbd706..db24be3c0a 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 b13b5e6ac2..87b635ce50 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 593b1d9237..9545504f84 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 0000000000..1041fb5d1f --- /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 5edd1c77b5..2d85bc0a66 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 bb0ebfdd0c..8008959460 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 a9f2a15dea..9b4cb3ca9b 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 b6fc2f4251..04e5aa909b 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 1080e1b8fb..8c4067187f 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 cd11af3400..e6abdcb366 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 bd28078782..42ee6af2e3 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 779f76fc93..2170ea3019 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 3a7c1afdf0..336a34b2fe 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 da69406157..75c7e68083 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 77eb419ed1..781ddeeb7f 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 c13b4606d3..3f2e0064f2 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 ce4ffa44c0..7d9159d04a 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 ec84ee4232..6e23d74bbb 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 affa55ce10..439e1f1b7f 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 ffea7b7fab..099aa43978 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 497b145190..e3d781df29 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 137cab1a01..4fb748f73a 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 978a5c13e6..5a311c5172 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 ff0f8ae077..e23c3c0c26 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 d08726371a..f090312320 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 d9dc2f2e54..5d734c9d95 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 e09c062ab0..d0f9a8165c 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 dcb5b4e499..f3a9efb6d2 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 eb18581551..ff0b95f365 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 9cb77f2a4b..4ae4361a21 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 c404f61581..7089c19d51 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 88b804f80a..5c49e1817c 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 87bb4cd182..1593297734 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 8220162be7..a875917441 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 c6134f9bd1..059c699e50 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 9e04e24db5..431faa241f 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 baa5738d4e..456fae889f 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 beb44bf535..759b1586eb 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 65bae751e0..4ee5145179 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 7b3256e06b..3480a83a4a 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 d0c26baf66..e3b69d31cd 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 c159522e97..a90a3f57a3 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 72766c0c48..322ee2f9e0 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 b1a19f4a40..72d779b621 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 fa8c6d9615..54d72e0718 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 11f6021c75..68fb129108 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 4610b4e00f..921b28d733 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 128dc17332..e531e5208f 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 07562ad190..4384151cbd 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 fdb0b012ef..3a451bff44 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 85942fcb4e..44e0d00280 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 8c61b68a3e..873934c0c7 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 a7764d3d1d..fd48b912a0 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 3f41f21ce5..bac50b1e62 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 14c8efbbad..6b07140211 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 ee0c867ffb..b4a47d2e47 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 1c4f4e841e..66abc50cab 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 fa3d19ebab..30ee7c64d6 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 86bbdebc15..61b13316b8 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 0a1817e6b2..636d6af792 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 7682f675b0..cb49001d3c 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 2ffec34288..98f8f81d9c 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 e6563a28a1..2738686c38 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 8a8650aa9b..f547cba9fc 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 5015e19940..e49236af94 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 a84a2889dc..1924bd5e78 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 7bbc4110dd..0f393a9417 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 3c0bfbdbad..5fdea4a0e6 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 933596ef5e..9e20d49a44 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 552319e6fe..0fa139c36f 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 9271167d40..2209c63008 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 ab55807be8..0b47ba7870 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 8a49ed8922..66e1278e22 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 e6b7f2979d..d8913e7b5b 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 1aef4eca81..80c0dbc505 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 349f27114b..8c12226e3d 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 9dacf9924c..a9464c595e 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 1b051e029f..58a81ca7a7 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 738e996967..40b1852528 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 3d1ae1bd02..06de6b4d14 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 1bb202d1a0..95b7e81a17 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 c24100476c..1cc1a85108 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 05087c4036..7b5e77f5c3 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 79f389821e..ae700d60b7 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 af20f04201..3ad6260813 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 714bde7096..f16af92a74 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 1901902c80..a63590acf8 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 f3cd084ffa..80f68b979d 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 4327840a47..ba5b24dbe7 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 476a8b6810..a553d4309c 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 0000000000..8e1f9e2f6f --- /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 e76c6516aa..0ed4e5364a 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 586b624260..122e1aa4cd 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 1cb5b9b4da..7c1fee0525 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 5727808276..18bb91a9e4 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 8389df7112..b6845d076f 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 0f5ea190f2..c6670d2a30 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 6514092dfc..1390c89b29 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 2a2b8305d3..4febf8f479 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 daa0a88f76..6b7459500b 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 63c6da6409..20390a3555 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 244c0b7971..cfc0910901 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 25db1953d6..69d14c1dd1 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 0000000000..212330577c --- /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 53a07f228b..4c308ca930 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 303d05f509..e35646ce7f 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 c98383a242..5e392be796 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 671d57e04e..27bf4c0ab7 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 fe51b4152e..d6ae824fd1 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 7697fdf6a4..13213c2e7e 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 597ced19db..21aecc59ea 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 8786930e2f..88c4ca34ac 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 75d574ed63..9cb7292baf 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 6fd294f928..604c936172 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 faafd2e8c9..8fbfc0e657 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 f96dfd22ea..e07c45294c 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 750164a260..f5a7460cc3 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 54a2d301c7..033b406510 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 b507afc316..dd81d713fe 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 091842663d..d0be0469c1 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 95f661d7a5..a546914930 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 e0307e07cc..ef6d8bb428 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 4f8e17cb1e..0a7c78f952 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 6e34257e4a..12540c2d04 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 41ad4cb5c6..e20ee9459f 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 ce377c8709..16a1cb3b26 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 3300eb91d6..2dcdd12605 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 ed27e1a259..bd670cc8bc 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 f7bc1d1c80..4872131429 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 b6857a3f82..980053bd5d 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 a28f03e8fe..515453f6a3 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 498d363408..d9d581e050 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 7d2f3c11a8..90273250cb 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 dbf568aec2..f9d69cc16f 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 4cbee6a773..f661951681 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 7761f09284..46e4dfa0f4 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 2e2498f88d..8930bf34d6 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 83ce1b9faf..124049d42e 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 5c2db9f3de..1ece024833 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 d6c5189f19..c297643e2a 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 8d88639db3..298dc49f27 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 5243bae35f..310f223159 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 2f0144d37b..6189a385e2 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 035431b8ba..9e122db423 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 79d2848774..b3ff3223e1 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 a708517abe..92c00ef913 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 f94057e6a4..d67f97bba8 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 0000000000..717b60f12f --- /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 82235bc8f6..b6f0a75975 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 0000000000..e183cbce29 --- /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 0000000000..fab527a62f --- /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 0000000000..1c7d69c85d --- /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 0000000000..5872059038 --- /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 0000000000..a0774083cf --- /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 a69e893b6f..c13a604dba 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 6657457344..1f4bd4a68f 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 7407aeefb5..44f920fe30 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 0000000000..70f3b98db2 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 5fb2c58be4..97e6f04bdc 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 ff49dc5577..7b2b705c94 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 44521ed36e..7c05fbd61d 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 00f14c373e..02ffbf4e65 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 0000000000..ecb575c673 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 9a326ac8a4..809046036d 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 87a3d3f58f..ff89b2dcdd 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 cf3be6425f..d7028d66a6 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 1af66a7d08..618d3be573 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 cf3be6425f..25cc585aed 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 5d7180da7c..b2eb9c72fe 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 e1a2c1c2ae..390fdb88ea 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 ff4ea400ed..0e86367473 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 9337d5127c..ef18c7bf49 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 b6b28fdfbe..fd3ff5ceca 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 b1750efa36..c1183a4e93 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 c70873ccc7..330915356a 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 d9e2dfef95..ba02b5a324 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 dc3456ba67..778ec461bb 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 b2ff3108ea..39ed73fc3d 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 5671731aab..9bb3378c8e 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 bc469f2eab..5dde02f1b5 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 2dbd997cbd..71e02e2509 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 71d4ad5605..a91d5a60e5 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 89926d3915..24e00e949f 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 51cb45dee2..5ba1e4d90d 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 6cd3004654..77f026a349 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 49fb0ae8d7..7ee370e890 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 28d9de7f22..1df561601b 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 0000000000..2735a9bf3d 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 0000000000..07e5f2320a 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 0000000000..edb0193f6e 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 0000000000..c9598e2b73 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 0000000000..076818323a 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 0000000000..1e3e155839 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 0000000000..cce5a25d82 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 0000000000..16ab67f729 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 0000000000..9ef15430ff 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 0000000000..0f6a66057d 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 0000000000..615df6c550 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 0000000000..3aecb743f7 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 0000000000..03339131f6 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 0000000000..2fba89d318 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 0000000000..10c5912b97 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 0000000000..0df770e663 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 0000000000..314b9133d2 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 0000000000..5c571d77eb 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 0000000000..5953262764 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 0000000000..4676a637a6 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 0000000000..c76fc423fc 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 0000000000..71dc1aa967 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 0000000000..bf86889006 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 0000000000..44734425ce 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 0000000000..5ad4fa81e7 Binary files /dev/null and b/sound/effects/footstep/wood5.ogg differ