diff --git a/baystation12.dme b/baystation12.dme
index ed845c859c..9ef6c90239 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -14,7 +14,6 @@
#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/ShieldGen"
#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Supermatter"
#define FILE_DIR "code/WorkInProgress/Susan"
-#define FILE_DIR "code/WorkInProgress/Uristqwerty"
#define FILE_DIR "html"
#define FILE_DIR "icons"
#define FILE_DIR "icons/48x48"
@@ -606,6 +605,7 @@
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\target_stake.dm"
+#include "code\game\objects\structures\transit_tubes.dm"
#include "code\game\objects\structures\watercloset.dm"
#include "code\game\objects\structures\windoor_assembly.dm"
#include "code\game\objects\structures\window.dm"
@@ -1291,7 +1291,6 @@
#include "code\WorkInProgress\Ported\policetape.dm"
#include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm"
#include "code\WorkInProgress\Susan\susan_desert_turfs.dm"
-#include "code\WorkInProgress\Uristqwerty\transit_tubes.dm"
#include "code\WorkInProgress\virus2\analyser.dm"
#include "code\WorkInProgress\virus2\antibodies.dm"
#include "code\WorkInProgress\virus2\base.dm"
diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/core_gen.dm b/code/WorkInProgress/Cael_Aislinn/Rust/core_gen.dm
index 52ab6d043a..438894ca86 100644
--- a/code/WorkInProgress/Cael_Aislinn/Rust/core_gen.dm
+++ b/code/WorkInProgress/Cael_Aislinn/Rust/core_gen.dm
@@ -62,6 +62,7 @@ max volume of plasma storeable by the field = the total volume of a number of ti
active_power_usage = 500 //multiplied by field strength
var/cached_power_avail = 0
directwired = 1
+ anchored = 0
var/state = 0
var/locked = 1
diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_injector.dm b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_injector.dm
index 64e9f46535..6d18b71f4c 100644
--- a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_injector.dm
+++ b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_injector.dm
@@ -3,17 +3,19 @@
name = "Fuel Injector"
icon = 'code/WorkInProgress/Cael_Aislinn/Rust/rust.dmi'
icon_state = "injector0"
+
density = 1
- var/state = 2
+ anchored = 0
+ var/state = 0
var/locked = 0
+ req_access = list(access_engine)
+
var/obj/item/weapon/fuel_assembly/cur_assembly
var/fuel_usage = 0.0001 //percentage of available fuel to use per cycle
var/id_tag = "One"
var/injecting = 0
var/trying_to_swap_fuel = 0
- //
- req_access = list(access_engine)
- //
+
use_power = 1
idle_power_usage = 10
active_power_usage = 500
diff --git a/code/WorkInProgress/Uristqwerty/transit_tube.dmi b/code/WorkInProgress/Uristqwerty/transit_tube.dmi
deleted file mode 100644
index e708700180..0000000000
Binary files a/code/WorkInProgress/Uristqwerty/transit_tube.dmi and /dev/null differ
diff --git a/code/WorkInProgress/Uristqwerty/transit_tubes.dm b/code/WorkInProgress/Uristqwerty/transit_tubes.dm
deleted file mode 100644
index 96fffda15a..0000000000
--- a/code/WorkInProgress/Uristqwerty/transit_tubes.dm
+++ /dev/null
@@ -1,405 +0,0 @@
-
-// Basic transit tubes. Straight pieces, curved sections,
-// and basic splits/joins (no routing logic).
-// Mappers: you can use "Generate Instances from Icon-states"
-// to get the different pieces.
-/obj/structure/transit_tube
- icon = 'transit_tube.dmi'
- icon_state = "E-W"
- density = 1
- layer = 3.1
- anchored = 1.0
- var/list/tube_dirs = null
- var/exit_delay = 2
- var/enter_delay = 1
-
-
-// A place where tube pods stop, and people can get in or out.
-// Mappers: use "Generate Instances from Directions" for this
-// one.
-/obj/structure/transit_tube/station
- icon = 'transit_tube_station.dmi'
- icon_state = "closed"
- exit_delay = 2
- enter_delay = 3
- var/pod_moving = 0
- var/automatic_launch_time = 100
-
- var/const/OPEN_DURATION = 6
- var/const/CLOSE_DURATION = 6
-
-
-
-/obj/structure/transit_tube_pod
- icon = 'transit_tube_pod.dmi'
- icon_state = "pod"
- animate_movement = FORWARD_STEPS
- var/moving = 0
- var/datum/gas_mixture/air_contents
-
-
-
-/obj/structure/transit_tube/station/New(loc)
- ..(loc)
-
- spawn(automatic_launch_time)
- launch_pod()
-
-
-/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj)
- if(!pod_moving && icon_state == "open" && istype(AM, /mob))
- for(var/obj/structure/transit_tube_pod/pod in loc)
- if(!pod.moving && pod.dir in directions())
- AM.loc = pod
- return
-
-
-
-/obj/structure/transit_tube/station/attack_hand(mob/user as mob)
- if(!pod_moving)
- for(var/obj/structure/transit_tube_pod/pod in loc)
- if(!pod.moving && pod.dir in directions())
- if(icon_state == "closed")
- open_animation()
-
- else if(icon_state == "open")
- close_animation()
-
-
-
-/obj/structure/transit_tube/station/proc/open_animation()
- if(icon_state == "closed")
- icon_state = "opening"
- spawn(OPEN_DURATION)
- if(icon_state == "opening")
- icon_state = "open"
-
-
-
-/obj/structure/transit_tube/station/proc/close_animation()
- if(icon_state == "open")
- icon_state = "closing"
- spawn(CLOSE_DURATION)
- if(icon_state == "closing")
- icon_state = "closed"
-
-
-
-/obj/structure/transit_tube/station/proc/launch_pod()
- for(var/obj/structure/transit_tube_pod/pod in loc)
- if(!pod.moving && pod.dir in directions())
- spawn(5)
- pod_moving = 1
- close_animation()
- sleep(CLOSE_DURATION + 2)
- if(icon_state == "closed" && pod)
- pod.follow_tube()
-
- pod_moving = 0
-
- return
-
-
-
-/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir)
- return 0
-
-
-
-/obj/structure/transit_tube/station/should_stop_pod(pod, from_dir)
- return 1
-
-
-
-/obj/structure/transit_tube/proc/pod_stopped(pod, from_dir)
- return 0
-
-
-
-/obj/structure/transit_tube/station/pod_stopped(obj/structure/transit_tube_pod/pod, from_dir)
- pod_moving = 1
- spawn(5)
- open_animation()
- sleep(OPEN_DURATION + 2)
- pod_moving = 0
- pod.mix_air()
-
- if(automatic_launch_time)
- var/const/wait_step = 5
- var/i = 0
- while(i < automatic_launch_time)
- sleep(wait_step)
- i += wait_step
-
- if(pod_moving || icon_state != "open")
- return
-
- launch_pod()
-
-
-
-// Returns a /list of directions this tube section can
-// connect to.
-/obj/structure/transit_tube/proc/directions()
- return tube_dirs
-
-
-
-/obj/structure/transit_tube/proc/has_entrance(from_dir)
- from_dir = turn(from_dir, 180)
-
- for(var/direction in directions())
- if(direction == from_dir)
- return 1
-
- return 0
-
-
-
-/obj/structure/transit_tube/proc/has_exit(in_dir)
- for(var/direction in directions())
- if(direction == in_dir)
- return 1
-
- return 0
-
-
-
-// Searches for an exit direction within 45 degrees of the
-// specified dir. Returns that direction, or 0 if none match.
-/obj/structure/transit_tube/proc/get_exit(in_dir)
- var/near_dir = 0
- var/in_dir_cw = turn(in_dir, -45)
- var/in_dir_ccw = turn(in_dir, 45)
-
- for(var/direction in directions())
- if(direction == in_dir)
- return direction
-
- else if(direction == in_dir_cw)
- near_dir = direction
-
- else if(direction == in_dir_ccw)
- near_dir = direction
-
- return near_dir
-
-
-
-/obj/structure/transit_tube/proc/exit_delay(pod, to_dir)
- return exit_delay
-
-/obj/structure/transit_tube/proc/enter_delay(pod, to_dir)
- return enter_delay
-
-
-
-/obj/structure/transit_tube_pod/proc/follow_tube()
- if(moving)
- return
-
- moving = 1
-
- spawn()
- var/obj/structure/transit_tube/current_tube = null
- var/next_dir
- var/next_loc
-
- for(var/obj/structure/transit_tube/tube in loc)
- if(tube.has_exit(dir))
- current_tube = tube
- break
-
- while(current_tube)
- next_dir = current_tube.get_exit(dir)
-
- if(!next_dir)
- break
-
- sleep(current_tube.exit_delay(src, dir))
- next_loc = get_step(loc, next_dir)
-
- current_tube = null
- for(var/obj/structure/transit_tube/tube in next_loc)
- if(tube.has_entrance(next_dir))
- current_tube = tube
- break
-
- if(current_tube == null)
- dir = next_dir
- step(src, dir)
- break
-
- sleep(current_tube.enter_delay(src, next_dir))
- dir = next_dir
- loc = next_loc
-
- if(current_tube && current_tube.should_stop_pod(src, next_dir))
- current_tube.pod_stopped(src, dir)
- break
-
- moving = 0
-
-
-
-// HUGE HACK: Because the pod isn't a mecha, travelling through tubes over space
-// won't protect people from space.
-// This avoids editing an additional file, so that adding
-// tubes to a SS13 codebase is a simple as dropping this code file and the
-// required icon files somewhere where BYOND can find them.
-/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
- if(!istype(loc, /obj/structure/transit_tube_pod))
- return ..(environment)
-
-
-
-/obj/structure/transit_tube_pod/return_air()
- var/datum/gas_mixture/GM = new()
- GM.oxygen = MOLES_O2STANDARD * 2
- GM.nitrogen = MOLES_N2STANDARD
- GM.temperature = T20C
- return GM
-
-// For now, copying what I found in an unused FEA file (and almost identical in a
-// used ZAS file). Means that assume_air and remove_air don't actually alter the
-// air contents.
-/obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver)
- return 0
-
-/obj/structure/transit_tube_pod/remove_air(amount)
- var/oxygen = MOLES_O2STANDARD
- var/carbon_dioxide = 0
- var/nitrogen = MOLES_N2STANDARD
- var/toxins = 0
-
- var/datum/gas_mixture/GM = new()
-
- var/sum = oxygen + carbon_dioxide + nitrogen + toxins
- if(sum>0)
- GM.oxygen = (oxygen/sum)*amount
- GM.carbon_dioxide = (carbon_dioxide/sum)*amount
- GM.nitrogen = (nitrogen/sum)*amount
- GM.toxins = (toxins/sum)*amount
-
- GM.temperature = T20C
- GM.update_values() //Needed in ZAS to prevent suffocation. Not present in FEA. Comment/uncomment as nessecary.
-
- return GM
-
-
-
-// Called when a pod arrives at, and before a pod departs from a station,
-// giving it a chance to mix its internal air supply with the turf it is
-// currently on.
-/obj/structure/transit_tube_pod/proc/mix_air()
- //Needs to be implemented at some point
-
-
-
-// When the player moves, check if the pos is currently stopped at a station.
-// if it is, check the direction. If the direction matches the direction of
-// the station, try to exit. If the direction matches one of the station's
-// tube directions, launch the pod in that direction.
-/obj/structure/transit_tube_pod/relaymove(mob/mob, direction)
- if(!moving && istype(mob, /mob) && mob.client)
- for(var/obj/structure/transit_tube/station/station in loc)
- if(!station.pod_moving && (dir in station.directions()))
- if(direction == station.dir)
- if(station.icon_state == "open")
- mob.loc = loc
- mob.client.Move(get_step(loc, direction), direction)
-
- else
- station.open_animation()
-
- else if(direction in station.directions())
- dir = direction
- station.launch_pod()
-
-
-
-/obj/structure/transit_tube/New(loc)
- ..(loc)
-
- if(tube_dirs == null)
- init_dirs()
-
-
-
-// Parse the icon_state into a list of directions.
-// This means that mappers can use Dream Maker's built in
-// "Generate Instances from Icon-states" option to get all
-// variations. Additionally, as a separate proc, sub-types
-// can handle it more intelligently.
-/obj/structure/transit_tube/proc/init_dirs()
- tube_dirs = parse_dirs(icon_state)
-
- if(copytext(icon_state, 1, 3) == "D-")
- density = 0
-
-
-
-// Tube station directions are simply 90 to either side of
-// the exit.
-/obj/structure/transit_tube/station/init_dirs()
- tube_dirs = list(turn(dir, 90), turn(dir, -90))
-
-
-
-// Uses a list() to cache return values. Since they should
-// never be edited directly, all tubes with a certain
-// icon_state can just reference the same list. In theory,
-// reduces memory usage, and improves CPU cache usage.
-// In reality, I don't know if that is quite how BYOND works,
-// but it is probably safer to assume the existence of, and
-// rely on, a sufficiently smart compiler/optimizer.
-/obj/structure/transit_tube/proc/parse_dirs(text)
- var/global/list/direction_table = list()
-
- if(text in direction_table)
- return direction_table[text]
-
- var/list/split_text = stringsplit(text, "-")
-
- // If the first token is D, the icon_state represents
- // a purely decorative tube, and doesn't actually
- // connect to anything.
- if(split_text[1] == "D")
- direction_table[text] = list()
- return null
-
- var/list/directions = list()
-
- for(var/text_part in split_text)
- var/direction = text2dir_extended(text_part)
-
- if(direction > 0)
- directions += direction
-
- direction_table[text] = directions
- return directions
-
-
-
-// A copy of text2dir, extended to accept one and two letter
-// directions, and to clearly return 0 otherwise.
-/obj/structure/transit_tube/proc/text2dir_extended(direction)
- switch(uppertext(direction))
- if("NORTH", "N")
- return 1
- if("SOUTH", "S")
- return 2
- if("EAST", "E")
- return 4
- if("WEST", "W")
- return 8
- if("NORTHEAST", "NE")
- return 5
- if("NORTHWEST", "NW")
- return 9
- if("SOUTHEAST", "SE")
- return 6
- if("SOUTHWEST", "SW")
- return 10
- else
- return 0
\ No newline at end of file
diff --git a/code/game/machinery/bees.dm b/code/game/machinery/bees.dm
index 68b2838e70..27a317a91a 100644
--- a/code/game/machinery/bees.dm
+++ b/code/game/machinery/bees.dm
@@ -1,5 +1,5 @@
-/obj/effect/bee
+/mob/living/simple_animal/bee
name = "bees"
icon = 'icons/obj/apiary_bees_etc.dmi'
icon_state = "bees1"
@@ -11,162 +11,154 @@
var/mob/target_mob
var/obj/machinery/apiary/parent
pass_flags = PASSGRILLE|PASSTABLE
+ turns_per_move = 6
+ var/obj/machinery/hydroponics/my_hydrotray
-/obj/effect/bee/New(loc, var/obj/machinery/apiary/new_parent)
+/mob/living/simple_animal/bee/New(loc, var/obj/machinery/apiary/new_parent)
..()
- processing_objects.Add(src)
parent = new_parent
+ verbs -= /atom/movable/verb/pull
-/obj/effect/bee/Del()
- processing_objects.Remove(src)
+/mob/living/simple_animal/bee/Del()
if(parent)
parent.owned_bee_swarms.Remove(src)
..()
-/obj/effect/bee/process()
+/mob/living/simple_animal/bee/Life()
+ ..()
- //if we're strong enough, sting some people
- var/overrun = strength - 5 + feral / 2
- if(prob(max( overrun * 10 + feral * 10, 0)))
- var/mob/living/carbon/human/M = locate() in src.loc
- if(M)
- var/sting_prob = 100
- var/obj/item/clothing/worn_suit = M.wear_suit
- var/obj/item/clothing/worn_helmet = M.head
- if(worn_suit)
- sting_prob -= worn_suit.armor["bio"]
- if(worn_helmet)
- sting_prob -= worn_helmet.armor["bio"]
+ if(stat == CONSCIOUS)
+ //if we're strong enough, sting some people
+ var/overrun = strength - 5 + feral / 2
+ if(prob(max( overrun * 10 + feral * 10, 0)))
+ var/mob/living/carbon/human/M = pick(range(1,src))
+ if(M)
+ var/sting_prob = 100
+ var/obj/item/clothing/worn_suit = M.wear_suit
+ var/obj/item/clothing/worn_helmet = M.head
+ if(worn_suit)
+ sting_prob -= worn_suit.armor["bio"]
+ if(worn_helmet)
+ sting_prob -= worn_helmet.armor["bio"]
- if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) )
- M.apply_damage(overrun / 2 + mut / 2, BRUTE)
- M.apply_damage(overrun / 2 + toxic / 2, TOX)
- M << "\red You have been stung!"
- M.flash_pain()
+ if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) )
+ M.apply_damage(overrun / 2 + mut / 2, BRUTE)
+ M.apply_damage(overrun / 2 + toxic / 2, TOX)
+ M << "\red You have been stung!"
+ M.flash_pain()
- //if we're chasing someone, get a little bit angry
- if(target_mob && prob(10))
- feral++
+ //if we're chasing someone, get a little bit angry
+ if(target_mob && prob(10))
+ feral++
- //calm down a little bit
- var/move_prob = 40
- if(feral > 0)
- if(prob(feral * 10))
- feral -= 1
- else
- //if feral is less than 0, we're becalmed by smoke or steam
- if(feral < 0)
- feral += 1
-
- if(target_mob)
- target_mob = null
- target_turf = null
- if(strength > 5)
- //calm down and spread out a little
- var/obj/effect/bee/B = new(get_turf(pick(orange(src,1))))
- B.strength = rand(1,5)
- src.strength -= B.strength
- if(src.strength <= 5)
- src.icon_state = "bees[src.strength]"
- B.icon_state = "bees[B.strength]"
- if(src.parent)
- B.parent = src.parent
- src.parent.owned_bee_swarms.Add(B)
-
- //make some noise
- if(prob(0.5))
- src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]")
-
- //smoke, water and steam calms us down
- var/calming = 0
- var/list/calmers = list(/obj/effect/effect/chem_smoke, /obj/effect/effect/water, /obj/effect/effect/foam, /obj/effect/effect/steam, /obj/effect/mist)
-
- for(var/this_type in calmers)
- var/obj/effect/check_effect = locate() in src.loc
- if(check_effect.type == this_type)
- calming = 1
- break
-
- if(calming)
+ //calm down a little bit
if(feral > 0)
- src.visible_message("\blue The bees calm down!")
- feral = -10
- target_mob = null
- target_turf = null
-
- for(var/obj/effect/bee/B in src.loc)
- if(B == src)
- continue
-
- if(feral > 0)
- src.strength += B.strength
- del(B)
- src.icon_state = "bees[src.strength]"
- if(strength > 5)
- icon_state = "bees_swarm"
- else if(prob(10))
- //make the other swarm of bees stronger, then move away
- var/total_bees = B.strength + src.strength
- if(total_bees < 10)
- B.strength = min(5, total_bees)
- src.strength = total_bees - B.strength
-
- B.icon_state = "bees[B.strength]"
- if(src.strength <= 0)
- del(src)
- return
- src.icon_state = "bees[B.strength]"
- var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
- density = 1
- if(T.Enter(src, get_turf(src)))
- src.loc = T
- density = 0
- break
-
- if(target_mob)
- if(target_mob in view(src,7))
- target_turf = get_turf(target_mob)
+ if(prob(feral * 10))
+ feral -= 1
else
- for(var/mob/living/carbon/M in view(src,7))
- target_mob = M
+ //if feral is less than 0, we're becalmed by smoke or steam
+ if(feral < 0)
+ feral += 1
+
+ if(target_mob)
+ target_mob = null
+ target_turf = null
+ if(strength > 5)
+ //calm down and spread out a little
+ var/mob/living/simple_animal/bee/B = new(get_turf(pick(orange(src,1))))
+ B.strength = rand(1,5)
+ src.strength -= B.strength
+ if(src.strength <= 5)
+ src.icon_state = "bees[src.strength]"
+ B.icon_state = "bees[B.strength]"
+ if(src.parent)
+ B.parent = src.parent
+ src.parent.owned_bee_swarms.Add(B)
+
+ //make some noise
+ if(prob(0.5))
+ src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]")
+
+ //smoke, water and steam calms us down
+ var/calming = 0
+ var/list/calmers = list(/obj/effect/effect/chem_smoke, \
+ /obj/effect/effect/water, \
+ /obj/effect/effect/foam, \
+ /obj/effect/effect/steam, \
+ /obj/effect/mist)
+
+ for(var/this_type in calmers)
+ var/mob/living/simple_animal/check_effect = locate() in src.loc
+ if(check_effect.type == this_type)
+ calming = 1
break
- if(target_turf)
- var/turf/next_turf = get_step(src.loc, get_dir(src,target_turf))
+ if(calming)
+ if(feral > 0)
+ src.visible_message("\blue The bees calm down!")
+ feral = -10
+ target_mob = null
+ target_turf = null
+ wander = 1
+
+ for(var/mob/living/simple_animal/bee/B in src.loc)
+ if(B == src)
+ continue
+
+ if(feral > 0)
+ src.strength += B.strength
+ del(B)
+ src.icon_state = "bees[src.strength]"
+ if(strength > 5)
+ icon_state = "bees_swarm"
+ else if(prob(10))
+ //make the other swarm of bees stronger, then move away
+ var/total_bees = B.strength + src.strength
+ if(total_bees < 10)
+ B.strength = min(5, total_bees)
+ src.strength = total_bees - B.strength
+
+ B.icon_state = "bees[B.strength]"
+ if(src.strength <= 0)
+ del(src)
+ return
+ src.icon_state = "bees[B.strength]"
+ var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
+ density = 1
+ if(T.Enter(src, get_turf(src)))
+ src.loc = T
+ density = 0
+ break
+
+ if(target_mob)
+ if(target_mob in view(src,7))
+ target_turf = get_turf(target_mob)
+ wander = 0
+ else
+ for(var/mob/living/carbon/M in view(src,7))
+ target_mob = M
+ break
+
+ if(target_turf)
+ Move(get_step(src, get_dir(src,target_turf)))
- //hacky, but w/e
- var/old_density = -1
- if(target_mob && get_dist(src, target_mob) <= 1)
- old_density = target_mob.density
- target_mob.density = 0
- density = 1
- if(next_turf.Enter(src, get_turf(src)))
- src.loc = next_turf
- density = 0
if(src.loc == target_turf)
target_turf = null
- if(target_mob && old_density != -1)
- target_mob.density = old_density
+ wander = 1
else
//find some flowers, harvest
//angry bee swarms don't hang around
if(feral > 0)
- move_prob = 60
+ turns_per_move = rand(1,3)
else if(feral < 0)
- move_prob = 0
- else
- var/obj/machinery/hydroponics/H = locate() in src.loc
- if(H)
- if(H.planted && !H.dead && H.myseed)
- move_prob = 1
-
- //chance to wander around
- if(prob(move_prob))
- var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
- density = 1
- if(T.Enter(src, get_turf(src)))
- src.loc = T
- density = 0
+ turns_since_move = 0
+ else if(!my_hydrotray || my_hydrotray.loc != src.loc || !my_hydrotray.planted || my_hydrotray.dead || !my_hydrotray.myseed)
+ var/obj/machinery/hydroponics/my_hydrotray = locate() in src.loc
+ if(my_hydrotray)
+ if(my_hydrotray.planted && !my_hydrotray.dead && my_hydrotray.myseed)
+ turns_per_move = rand(20,50)
+ else
+ my_hydrotray = null
pixel_x = rand(-12,12)
pixel_y = rand(-12,12)
diff --git a/code/game/machinery/bees_apiary.dm b/code/game/machinery/bees_apiary.dm
index 9bd9a45bfb..982feec1f2 100644
--- a/code/game/machinery/bees_apiary.dm
+++ b/code/game/machinery/bees_apiary.dm
@@ -22,6 +22,7 @@
var/bees_in_hive = 0
var/list/owned_bee_swarms = list()
+ var/hydrotray_type = /obj/machinery/hydroponics
//overwrite this after it's created if the apiary needs a custom machinery sprite
/obj/machinery/apiary/New()
@@ -69,7 +70,7 @@
else
user << "\blue You begin to dislodge the dead apiary from the tray."
if(do_after(user, 50))
- new /obj/machinery/hydroponics(src.loc)
+ new hydrotray_type(src.loc)
new /obj/item/apiary(src.loc)
user << "\red You dislodge the apiary from the tray."
del(src)
@@ -112,11 +113,11 @@
if(swarming > 0)
swarming -= 1
if(swarming <= 0)
- for(var/obj/effect/bee/B in src.loc)
+ for(var/mob/living/simple_animal/bee/B in src.loc)
bees_in_hive += B.strength
del(B)
else if(bees_in_hive < 10)
- for(var/obj/effect/bee/B in src.loc)
+ for(var/mob/living/simple_animal/bee/B in src.loc)
bees_in_hive += B.strength
del(B)
@@ -144,7 +145,7 @@
health += max(nutrilevel - 1, round(-health / 2))
bees_in_hive += max(nutrilevel - 1, round(-bees_in_hive / 2))
if(owned_bee_swarms.len)
- var/obj/effect/bee/B = pick(owned_bee_swarms)
+ var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms)
B.target_turf = get_turf(src)
//clear out some toxins
@@ -161,7 +162,7 @@
//make some new bees
if(bees_in_hive >= 10 && prob(bees_in_hive * 10))
- var/obj/effect/bee/B = new(get_turf(src), src)
+ var/mob/living/simple_animal/bee/B = new(get_turf(src), src)
owned_bee_swarms.Add(B)
B.mut = mut
B.toxic = toxic
@@ -193,7 +194,7 @@
/obj/machinery/apiary/proc/die()
if(owned_bee_swarms.len)
- var/obj/effect/bee/B = pick(owned_bee_swarms)
+ var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms)
B.target_turf = get_turf(src)
B.strength -= 1
if(B.strength <= 0)
@@ -204,7 +205,7 @@
health = 0
/obj/machinery/apiary/proc/angry_swarm(var/mob/M)
- for(var/obj/effect/bee/B in owned_bee_swarms)
+ for(var/mob/living/simple_animal/bee/B in owned_bee_swarms)
B.feral = 50
B.target_mob = M
@@ -215,7 +216,7 @@
if(bees_in_hive >= 5)
spawn_strength = 6
- var/obj/effect/bee/B = new(get_turf(src), src)
+ var/mob/living/simple_animal/bee/B = new(get_turf(src), src)
B.target_mob = M
B.strength = spawn_strength
B.feral = 5
diff --git a/code/game/machinery/bees_items.dm b/code/game/machinery/bees_items.dm
index cbfc2b3bd7..01ed5bfa40 100644
--- a/code/game/machinery/bees_items.dm
+++ b/code/game/machinery/bees_items.dm
@@ -17,7 +17,7 @@
/obj/item/weapon/bee_net/attack_self(mob/user as mob)
var/turf/T = get_step(get_turf(user), user.dir)
- for(var/obj/effect/bee/B in T)
+ for(var/mob/living/simple_animal/bee/B in T)
if(B.feral < 0)
caught_bees += B.strength
del(B)
@@ -38,7 +38,7 @@
while(caught_bees > 0)
//release a few super massive swarms
while(caught_bees > 5)
- var/obj/effect/bee/B = new(src.loc)
+ var/mob/living/simple_animal/bee/B = new(src.loc)
B.feral = 5
B.target_mob = M
B.strength = 6
@@ -46,7 +46,7 @@
caught_bees -= 6
//what's left over
- var/obj/effect/bee/B = new(src.loc)
+ var/mob/living/simple_animal/bee/B = new(src.loc)
B.strength = caught_bees
B.icon_state = "bees[B.strength]"
B.feral = 5
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 939b87aa7f..f24d0ce2b8 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -117,7 +117,7 @@
laws.add_inherent_law(M.newFreeFormLaw)
usr << "Added a freeform law."
- if(istype(P, /obj/item/device/mmi) || istype(P, /obj/item/device/posibrain))
+ if(istype(P, /obj/item/device/mmi) || istype(P, /obj/item/device/mmi/posibrain))
if(!P:brainmob)
user << "\red Sticking an empty [P] into the frame would sort of defeat the purpose."
return
diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm
index 265e3aec36..5d187b337c 100644
--- a/code/game/machinery/hydroponics.dm
+++ b/code/game/machinery/hydroponics.dm
@@ -779,6 +779,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob)
var/obj/machinery/apiary/A = new(src.loc)
A.icon = src.icon
A.icon_state = src.icon_state
+ A.hydrotray_type = src.type
del(src)
return
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 225318a9b8..d70512148c 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -651,7 +651,7 @@
/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain))
+ if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain))
if(mmi_move_inside(W,user))
user << "[src]-MMI interface initialized successfuly"
else
@@ -1136,7 +1136,7 @@
src.occupant.client.perspective = MOB_PERSPECTIVE
*/
src.occupant << browse(null, "window=exosuit")
- if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/posibrain))
+ if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/mmi/posibrain))
var/obj/item/device/mmi/mmi = mob_container
if(mmi.brainmob)
occupant.loc = mmi
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 68f57112cb..522ff35af1 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -114,7 +114,8 @@
/obj/effect/spider/spiderling/proc/die()
visible_message("[src] dies!")
- icon_state = "greenshatter"
+ new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
+ del(src)
/obj/effect/spider/spiderling/healthcheck()
if(health <= 0)
@@ -189,6 +190,12 @@
new spawn_type(src.loc)
del(src)
+/obj/effect/decal/cleanable/spiderling_remains
+ name = "spiderling remains"
+ desc = "Green squishy mess."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "greenshatter"
+
/obj/effect/spider/cocoon
name = "cocoon"
desc = "Something wrapped in silky spider web"
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 3b5da8c3a1..cc6a5b52f5 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -210,10 +210,12 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
if (!connection)
return
- Broadcast_Message(connection, new /mob/living/silicon/ai(src,null,null,1),
+ var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(src, null, null, 1)
+ Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src,
message, from, "Automated Announcement", from, "synthesized voice",
- 4, 0, 1)
+ 4, 0, list(1), 1459)
+ del(A)
return
/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 6d8a77549f..f86f38cc83 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -126,9 +126,11 @@ MASS SPECTROMETER
if(M.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal"
user.show_message("[OX] | [TX] | [BU] | [BR]")
- if (istype(M, /mob/living/carbon/human))
- if(M:virus2 || M:reagents.total_volume > 0)
+ if (istype(M, /mob/living/carbon))
+ if(M:reagents.total_volume > 0)
user.show_message(text("\red Warning: Unknown substance detected in subject's blood."))
+ if(M:virus2)
+ user.show_message(text("\red Warning: Unknown pathogen detected in subject's blood."))
if (M.getCloneLoss())
user.show_message("\red Subject appears to have been imperfectly cloned.")
for(var/datum/disease/D in M.viruses)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 62dfb126bf..b410785563 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -161,7 +161,7 @@
else
user << "\blue You need to attach a flash to it first!"
- if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain))
+ if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain))
var/obj/item/device/mmi/M = W
if(check_completion())
if(!istype(loc,/turf))
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 38662ddcf5..48c13eb849 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -46,7 +46,7 @@
for(var/obj/effect/dummy/chameleon/AD in src)
AD.loc = src.loc
- for(var/obj/item/I in src)
+ for(var/obj/I in src)
I.loc = src.loc
for(var/mob/M in src)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 05d8b4241b..0026aa5316 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -175,15 +175,29 @@
redlight = "largemetalr"
greenlight = "largemetalg"
-/obj/structure/closet/crate/secure/large_reinforced
- name = "large crate"
+/obj/structure/closet/crate/secure/large/close()
+ //we can hold up to one large item
+ var/found = 0
+ for(var/obj/structure/S in src.loc)
+ if(S == src)
+ continue
+ if(!S.anchored)
+ found = 1
+ S.loc = src
+ break
+ if(!found)
+ for(var/obj/machinery/M in src.loc)
+ if(!M.anchored)
+ M.loc = src
+ break
+ ..()
+
+//fluff variant
+/obj/structure/closet/crate/secure/large/reinforced
desc = "A hefty, reinforced metal crate with an electronic locking system."
- icon = 'icons/obj/storage.dmi'
icon_state = "largermetal"
icon_opened = "largermetalopen"
icon_closed = "largermetal"
- redlight = "largemetalr"
- greenlight = "largemetalg"
/obj/structure/closet/crate/secure
desc = "A secure crate."
@@ -206,6 +220,23 @@
icon_opened = "largemetalopen"
icon_closed = "largemetal"
+/obj/structure/closet/crate/large/close()
+ //we can hold up to one large item
+ var/found = 0
+ for(var/obj/structure/S in src.loc)
+ if(S == src)
+ continue
+ if(!S.anchored)
+ found = 1
+ S.loc = src
+ break
+ if(!found)
+ for(var/obj/machinery/M in src.loc)
+ if(!M.anchored)
+ M.loc = src
+ break
+ ..()
+
/obj/structure/closet/crate/hydroponics
name = "Hydroponics crate"
desc = "All you need to destroy those pesky weeds and pests."
diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm
new file mode 100644
index 0000000000..5e85802b1f
--- /dev/null
+++ b/code/game/objects/structures/transit_tubes.dm
@@ -0,0 +1,621 @@
+
+// Basic transit tubes. Straight pieces, curved sections,
+// and basic splits/joins (no routing logic).
+// Mappers: you can use "Generate Instances from Icon-states"
+// to get the different pieces.
+/obj/structure/transit_tube
+ icon = 'icons/obj/pipes/transit_tube.dmi'
+ icon_state = "E-W"
+ density = 1
+ layer = 3.1
+ anchored = 1.0
+ var/list/tube_dirs = null
+ var/exit_delay = 2
+ var/enter_delay = 1
+
+ // alldirs in global.dm is the same list of directions, but since
+ // the specific order matters to get a usable icon_state, it is
+ // copied here so that, in the unlikely case that alldirs is changed,
+ // this continues to work.
+ var/global/list/tube_dir_list = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
+
+
+// A place where tube pods stop, and people can get in or out.
+// Mappers: use "Generate Instances from Directions" for this
+// one.
+/obj/structure/transit_tube/station
+ icon = 'icons/obj/pipes/transit_tube_station.dmi'
+ icon_state = "closed"
+ exit_delay = 2
+ enter_delay = 3
+ var/pod_moving = 0
+ var/automatic_launch_time = 100
+
+ var/const/OPEN_DURATION = 6
+ var/const/CLOSE_DURATION = 6
+
+
+
+/obj/structure/transit_tube_pod
+ icon = 'icons/obj/pipes/transit_tube_pod.dmi'
+ icon_state = "pod"
+ animate_movement = FORWARD_STEPS
+ anchored = 1.0
+ density = 1
+ var/moving = 0
+ var/datum/gas_mixture/air_contents = new()
+
+
+
+/obj/structure/transit_tube_pod/Del()
+ for(var/atom/movable/AM in contents)
+ AM.loc = loc
+
+ ..()
+
+
+
+// When destroyed by explosions, properly handle contents.
+obj/structure/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ for(var/atom/movable/AM in contents)
+ AM.loc = loc
+ AM.ex_act(severity++)
+
+ del(src)
+ return
+ if(2.0)
+ if(prob(50))
+ for(var/atom/movable/AM in contents)
+ AM.loc = loc
+ AM.ex_act(severity++)
+
+ del(src)
+ return
+ if(3.0)
+ return
+
+
+
+/obj/structure/transit_tube_pod/New(loc)
+ ..(loc)
+
+ air_contents.oxygen = MOLES_O2STANDARD * 2
+ air_contents.nitrogen = MOLES_N2STANDARD
+ air_contents.temperature = T20C
+
+ // Give auto tubes time to align before trying to start moving
+ spawn(5)
+ follow_tube()
+
+
+
+/obj/structure/transit_tube/New(loc)
+ ..(loc)
+
+ if(tube_dirs == null)
+ init_dirs()
+
+
+
+/obj/structure/transit_tube/station/New(loc)
+ ..(loc)
+
+
+
+/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj)
+ if(!pod_moving && icon_state == "open" && istype(AM, /mob))
+ for(var/obj/structure/transit_tube_pod/pod in loc)
+ if(!pod.moving && pod.dir in directions())
+ AM.loc = pod
+ return
+
+
+
+/obj/structure/transit_tube/station/attack_hand(mob/user as mob)
+ if(!pod_moving)
+ for(var/obj/structure/transit_tube_pod/pod in loc)
+ if(!pod.moving && pod.dir in directions())
+ if(icon_state == "closed")
+ open_animation()
+
+ else if(icon_state == "open")
+ close_animation()
+
+
+
+/obj/structure/transit_tube/station/proc/open_animation()
+ if(icon_state == "closed")
+ icon_state = "opening"
+ spawn(OPEN_DURATION)
+ if(icon_state == "opening")
+ icon_state = "open"
+
+
+
+/obj/structure/transit_tube/station/proc/close_animation()
+ if(icon_state == "open")
+ icon_state = "closing"
+ spawn(CLOSE_DURATION)
+ if(icon_state == "closing")
+ icon_state = "closed"
+
+
+
+/obj/structure/transit_tube/station/proc/launch_pod()
+ for(var/obj/structure/transit_tube_pod/pod in loc)
+ if(!pod.moving && pod.dir in directions())
+ spawn(5)
+ pod_moving = 1
+ close_animation()
+ sleep(CLOSE_DURATION + 2)
+ if(icon_state == "closed" && pod)
+ pod.follow_tube()
+
+ pod_moving = 0
+
+ return
+
+
+
+// Called to check if a pod should stop upon entering this tube.
+/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir)
+ return 0
+
+
+
+/obj/structure/transit_tube/station/should_stop_pod(pod, from_dir)
+ return 1
+
+
+
+// Called when a pod stops in this tube section.
+/obj/structure/transit_tube/proc/pod_stopped(pod, from_dir)
+ return
+
+
+
+/obj/structure/transit_tube/station/pod_stopped(obj/structure/transit_tube_pod/pod, from_dir)
+ pod_moving = 1
+ spawn(5)
+ open_animation()
+ sleep(OPEN_DURATION + 2)
+ pod_moving = 0
+ pod.mix_air()
+
+ if(automatic_launch_time)
+ var/const/wait_step = 5
+ var/i = 0
+ while(i < automatic_launch_time)
+ sleep(wait_step)
+ i += wait_step
+
+ if(pod_moving || icon_state != "open")
+ return
+
+ launch_pod()
+
+
+
+// Returns a /list of directions this tube section can connect to.
+// Tubes that have some sort of logic or changing direction might
+// override it with additional logic.
+/obj/structure/transit_tube/proc/directions()
+ return tube_dirs
+
+
+
+/obj/structure/transit_tube/proc/has_entrance(from_dir)
+ from_dir = turn(from_dir, 180)
+
+ for(var/direction in directions())
+ if(direction == from_dir)
+ return 1
+
+ return 0
+
+
+
+/obj/structure/transit_tube/proc/has_exit(in_dir)
+ for(var/direction in directions())
+ if(direction == in_dir)
+ return 1
+
+ return 0
+
+
+
+// Searches for an exit direction within 45 degrees of the
+// specified dir. Returns that direction, or 0 if none match.
+/obj/structure/transit_tube/proc/get_exit(in_dir)
+ var/near_dir = 0
+ var/in_dir_cw = turn(in_dir, -45)
+ var/in_dir_ccw = turn(in_dir, 45)
+
+ for(var/direction in directions())
+ if(direction == in_dir)
+ return direction
+
+ else if(direction == in_dir_cw)
+ near_dir = direction
+
+ else if(direction == in_dir_ccw)
+ near_dir = direction
+
+ return near_dir
+
+
+
+// Return how many BYOND ticks to wait before entering/exiting
+// the tube section. Default action is to return the value of
+// a var, which wouldn't need a proc, but it makes it possible
+// for later tube types to interact in more interesting ways
+// such as being very fast in one direction, but slow in others
+/obj/structure/transit_tube/proc/exit_delay(pod, to_dir)
+ return exit_delay
+
+/obj/structure/transit_tube/proc/enter_delay(pod, to_dir)
+ return enter_delay
+
+
+
+/obj/structure/transit_tube_pod/proc/follow_tube()
+ if(moving)
+ return
+
+ moving = 1
+
+ spawn()
+ var/obj/structure/transit_tube/current_tube = null
+ var/next_dir
+ var/next_loc
+ var/last_delay = 0
+ var/exit_delay
+
+ for(var/obj/structure/transit_tube/tube in loc)
+ if(tube.has_exit(dir))
+ current_tube = tube
+ break
+
+ while(current_tube)
+ next_dir = current_tube.get_exit(dir)
+
+ if(!next_dir)
+ break
+
+ exit_delay = current_tube.exit_delay(src, dir)
+ last_delay += exit_delay
+
+ sleep(exit_delay)
+
+ next_loc = get_step(loc, next_dir)
+
+ current_tube = null
+ for(var/obj/structure/transit_tube/tube in next_loc)
+ if(tube.has_entrance(next_dir))
+ current_tube = tube
+ break
+
+ if(current_tube == null)
+ dir = next_dir
+ Move(get_step(loc, dir)) // Allow collisions when leaving the tubes.
+ break
+
+ last_delay = current_tube.enter_delay(src, next_dir)
+ sleep(last_delay)
+ dir = next_dir
+ loc = next_loc // When moving from one tube to another, skip collision and such.
+ density = current_tube.density
+
+ if(current_tube && current_tube.should_stop_pod(src, next_dir))
+ current_tube.pod_stopped(src, dir)
+ break
+
+ density = 1
+
+ // If the pod is no longer in a tube, move in a line until stopped or slowed to a halt.
+ // /turf/inertial_drift appears to only work on mobs, and re-implementing some of the
+ // logic allows a gradual slowdown and eventual stop when passing over non-space turfs.
+ if(!current_tube && last_delay <= 10)
+ do
+ sleep(last_delay)
+
+ if(!istype(loc, /turf/space))
+ last_delay++
+
+ if(last_delay > 10)
+ break
+
+ while(isturf(loc) && Move(get_step(loc, dir)))
+
+ moving = 0
+
+
+// Should I return a copy here? If the caller edits or del()s the returned
+// datum, there might be problems if I don't...
+/obj/structure/transit_tube_pod/return_air()
+ var/datum/gas_mixture/GM = new()
+ GM.oxygen = air_contents.oxygen
+ GM.carbon_dioxide = air_contents.carbon_dioxide
+ GM.nitrogen = air_contents.nitrogen
+ GM.toxins = air_contents.toxins
+ GM.temperature = air_contents.temperature
+ return GM
+
+// For now, copying what I found in an unused FEA file (and almost identical in a
+// used ZAS file). Means that assume_air and remove_air don't actually alter the
+// air contents.
+/obj/structure/transit_tube_pod/assume_air(datum/gas_mixture/giver)
+ return air_contents.merge(giver)
+
+/obj/structure/transit_tube_pod/remove_air(amount)
+ return air_contents.remove(amount)
+
+
+
+// Called when a pod arrives at, and before a pod departs from a station,
+// giving it a chance to mix its internal air supply with the turf it is
+// currently on.
+/obj/structure/transit_tube_pod/proc/mix_air()
+ var/datum/gas_mixture/environment = loc.return_air()
+ var/env_pressure = environment.return_pressure()
+ var/int_pressure = air_contents.return_pressure()
+ var/total_pressure = env_pressure + int_pressure
+
+ if(total_pressure == 0)
+ return
+
+ // Math here: Completely made up, not based on realistic equasions.
+ // Goal is to balance towards equal pressure, but ensure some gas
+ // transfer in both directions regardless.
+ // Feel free to rip this out and replace it with something better,
+ // I don't really know muhch about how gas transfer rates work in
+ // SS13.
+ var/transfer_in = max(0.1, 0.5 * (env_pressure - int_pressure) / total_pressure)
+ var/transfer_out = max(0.1, 0.3 * (int_pressure - env_pressure) / total_pressure)
+
+ var/datum/gas_mixture/from_env = loc.remove_air(environment.total_moles() * transfer_in)
+ var/datum/gas_mixture/from_int = air_contents.remove(air_contents.total_moles() * transfer_out)
+
+ loc.assume_air(from_int)
+ air_contents.merge(from_env)
+
+
+
+// When the player moves, check if the pos is currently stopped at a station.
+// if it is, check the direction. If the direction matches the direction of
+// the station, try to exit. If the direction matches one of the station's
+// tube directions, launch the pod in that direction.
+/obj/structure/transit_tube_pod/relaymove(mob/mob, direction)
+ if(istype(mob, /mob) && mob.client)
+ // If the pod is not in a tube at all, you can get out at any time.
+ if(!(locate(/obj/structure/transit_tube) in loc))
+ mob.loc = loc
+ mob.client.Move(get_step(loc, direction), direction)
+
+ //if(moving && istype(loc, /turf/space))
+ // Todo: If you get out of a moving pod in space, you should move as well.
+ // Same direction as pod? Direcion you moved? Halfway between?
+
+ if(!moving)
+ for(var/obj/structure/transit_tube/station/station in loc)
+ if(dir in station.directions())
+ if(!station.pod_moving)
+ if(direction == station.dir)
+ if(station.icon_state == "open")
+ mob.loc = loc
+ mob.client.Move(get_step(loc, direction), direction)
+
+ else
+ station.open_animation()
+
+ else if(direction in station.directions())
+ dir = direction
+ station.launch_pod()
+ return
+
+ for(var/obj/structure/transit_tube/tube in loc)
+ if(dir in tube.directions())
+ if(tube.has_exit(direction))
+ dir = direction
+ return
+
+
+
+// Parse the icon_state into a list of directions.
+// This means that mappers can use Dream Maker's built in
+// "Generate Instances from Icon-states" option to get all
+// variations. Additionally, as a separate proc, sub-types
+// can handle it more intelligently.
+/obj/structure/transit_tube/proc/init_dirs()
+ if(icon_state == "auto")
+ // Additional delay, for map loading.
+ spawn(1)
+ init_dirs_automatic()
+
+ else
+ tube_dirs = parse_dirs(icon_state)
+
+ if(copytext(icon_state, 1, 3) == "D-" || findtextEx(icon_state, "Pass"))
+ density = 0
+
+
+
+// Tube station directions are simply 90 to either side of
+// the exit.
+/obj/structure/transit_tube/station/init_dirs()
+ tube_dirs = list(turn(dir, 90), turn(dir, -90))
+
+
+
+// Initialize dirs by searching for tubes that do/might connect
+// on nearby turfs. Create corner pieces if nessecary.
+// Pick two directions, preferring tubes that already connect
+// to loc, or other auto tubes if there aren't enough connections.
+/obj/structure/transit_tube/proc/init_dirs_automatic()
+ var/list/connected = list()
+ var/list/connected_auto = list()
+
+ for(var/direction in tube_dir_list)
+ var/location = get_step(loc, direction)
+ for(var/obj/structure/transit_tube/tube in location)
+ if(tube.directions() == null && tube.icon_state == "auto")
+ connected_auto += direction
+ break
+
+ else if(turn(direction, 180) in tube.directions())
+ connected += direction
+ break
+
+ connected += connected_auto
+
+ tube_dirs = select_automatic_dirs(connected)
+
+ if(length(tube_dirs) == 2 && tube_dir_list.Find(tube_dirs[1]) > tube_dir_list.Find(tube_dirs[2]))
+ tube_dirs.Swap(1, 2)
+
+ generate_automatic_corners(tube_dirs)
+ select_automatic_icon_state(tube_dirs)
+
+
+
+// Given a list of directions, look a pair that forms a 180 or
+// 135 degree angle, and return a list containing the pair.
+// If none exist, return list(connected[1], turn(connected[1], 180)
+/obj/structure/transit_tube/proc/select_automatic_dirs(connected)
+ if(length(connected) < 1)
+ return list()
+
+ for(var/i = 1, i <= length(connected), i++)
+ for(var/j = i + 1, j <= length(connected), j++)
+ var/d1 = connected[i]
+ var/d2 = connected[j]
+
+ if(d1 == turn(d2, 135) || d1 == turn(d2, 180) || d1 == turn(d2, 225))
+ return list(d1, d2)
+
+ return list(connected[1], turn(connected[1], 180))
+
+
+
+/obj/structure/transit_tube/proc/select_automatic_icon_state(directions)
+ if(length(directions) == 2)
+ icon_state = "[dir2text_short(directions[1])]-[dir2text_short(directions[2])]"
+
+
+
+// Look for diagonal directions, generate the decorative corners in each.
+/obj/structure/transit_tube/proc/generate_automatic_corners(directions)
+ for(var/direction in directions)
+ if(direction == 5 || direction == 6 || direction == 9 || direction == 10)
+ if(direction & NORTH)
+ create_automatic_decorative_corner(get_step(loc, NORTH), direction ^ 3)
+
+ else
+ create_automatic_decorative_corner(get_step(loc, SOUTH), direction ^ 3)
+
+ if(direction & EAST)
+ create_automatic_decorative_corner(get_step(loc, EAST), direction ^ 12)
+
+ else
+ create_automatic_decorative_corner(get_step(loc, WEST), direction ^ 12)
+
+
+
+// Generate a corner, if one doesn't exist for the direction on the turf.
+/obj/structure/transit_tube/proc/create_automatic_decorative_corner(location, direction)
+ var/state = "D-[dir2text_short(direction)]"
+
+ for(var/obj/structure/transit_tube/tube in location)
+ if(tube.icon_state == state)
+ return
+
+ var/obj/structure/transit_tube/tube = new(location)
+ tube.icon_state = state
+ tube.init_dirs()
+
+
+
+// Uses a list() to cache return values. Since they should
+// never be edited directly, all tubes with a certain
+// icon_state can just reference the same list. In theory,
+// reduces memory usage, and improves CPU cache usage.
+// In reality, I don't know if that is quite how BYOND works,
+// but it is probably safer to assume the existence of, and
+// rely on, a sufficiently smart compiler/optimizer.
+/obj/structure/transit_tube/proc/parse_dirs(text)
+ var/global/list/direction_table = list()
+
+ if(text in direction_table)
+ return direction_table[text]
+
+ var/list/split_text = stringsplit(text, "-")
+
+ // If the first token is D, the icon_state represents
+ // a purely decorative tube, and doesn't actually
+ // connect to anything.
+ if(split_text[1] == "D")
+ direction_table[text] = list()
+ return null
+
+ var/list/directions = list()
+
+ for(var/text_part in split_text)
+ var/direction = text2dir_extended(text_part)
+
+ if(direction > 0)
+ directions += direction
+
+ direction_table[text] = directions
+ return directions
+
+
+
+// A copy of text2dir, extended to accept one and two letter
+// directions, and to clearly return 0 otherwise.
+/obj/structure/transit_tube/proc/text2dir_extended(direction)
+ switch(uppertext(direction))
+ if("NORTH", "N")
+ return 1
+ if("SOUTH", "S")
+ return 2
+ if("EAST", "E")
+ return 4
+ if("WEST", "W")
+ return 8
+ if("NORTHEAST", "NE")
+ return 5
+ if("NORTHWEST", "NW")
+ return 9
+ if("SOUTHEAST", "SE")
+ return 6
+ if("SOUTHWEST", "SW")
+ return 10
+ else
+ return 0
+
+
+
+// A copy of dir2text, which returns the short one or two letter
+// directions used in tube icon states.
+/obj/structure/transit_tube/proc/dir2text_short(direction)
+ switch(direction)
+ if(1)
+ return "N"
+ if(2)
+ return "S"
+ if(4)
+ return "E"
+ if(8)
+ return "W"
+ if(5)
+ return "NE"
+ if(6)
+ return "SE"
+ if(9)
+ return "NW"
+ if(10)
+ return "SW"
+ else
+ return
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 30fe52b562..94c1d350dd 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -350,6 +350,8 @@ commented out in r5061, I left it because of the shroom thingies
excavate_find(5, src.finds[1])
else if(prob(50))
src.finds.Remove(src.finds[1])
+ if(prob(50))
+ artifact_debris()
if(do_after(user,P.digspeed))
user << "\blue You finish [P.drill_verb] the rock."
@@ -387,9 +389,8 @@ commented out in r5061, I left it because of the shroom thingies
B = new(src)
if(artifact_find)
B.artifact_find = artifact_find
- else if(src.excavation_level + P.excavation_amount >= 100)
- spawn(0)
- artifact_debris()
+ else if(artifact_find && src.excavation_level + P.excavation_amount >= 100)
+ artifact_debris(1)
gets_drilled(B ? 0 : 1)
return
@@ -477,13 +478,8 @@ commented out in r5061, I left it because of the shroom thingies
for (var/i=0;i[pick("[display_name] crumbles away into dust","[display_name] breaks apart","[display_name] collapses onto itself")].")
+ src.visible_message("\red[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].")
del(X)
src.finds.Remove(F)
-/turf/simulated/mineral/proc/artifact_debris()
+/turf/simulated/mineral/proc/artifact_debris(var/severity = 0)
//cael's patented random limited drop componentized loot system!
+ severity = max(min(severity,1),0)
var/materials = 0
var/list/viable_materials = list(1,2,4,8,16,32,64,128,256)
- var/num_materials = rand(1,5)
+ var/num_materials = rand(1,3 + severity*2)
for(var/i=0, i 406)
for(var/datum/disease/D in viruses)
D.cure()
+ if(virus2) virus2.cure(src)
if(!virus2)
for(var/obj/effect/decal/cleanable/blood/B in view(1,src))
if(B.virus2 && get_infection_chance())
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 375d175f21..e8d8525e7a 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -126,7 +126,7 @@ Please contact me on #coderbus IRC. ~Carn x
var/list/overlays_lying[TOTAL_LAYERS]
var/list/overlays_standing[TOTAL_LAYERS]
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
-
+ var/race_icon
//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING
//this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers
@@ -234,24 +234,8 @@ proc/get_damage_icon_part(damage_state, body_part)
var/g = "m"
if(gender == FEMALE) g = "f"
- var/icon/icobase
- if(skeleton)
- icobase = 'icons/mob/human_races/r_skeleton.dmi'
- else if(dna)
- switch(dna.mutantrace)
- if("tajaran")
- icobase = 'icons/mob/human_races/r_tajaran.dmi'
- if("lizard")
- icobase = 'icons/mob/human_races/r_lizard.dmi'
- if("skrell")
- icobase = 'icons/mob/human_races/r_skrell.dmi'
- else
- icobase = 'icons/mob/human_races/r_human.dmi'
- else
- icobase = 'icons/mob/human_races/r_human.dmi'
-
if(!skeleton)
- stand_icon = new /icon(icobase, "torso_[g][fat?"_fat":""]")
+ stand_icon = new /icon(race_icon, "torso_[g][fat?"_fat":""]")
if(husk)
stand_icon.ColorTone(husk_color_mod)
else if(hulk)
@@ -261,7 +245,7 @@ proc/get_damage_icon_part(damage_state, body_part)
else if(plant)
stand_icon.ColorTone(plant_color_mod)
else
- stand_icon = new /icon(icobase, "torso")
+ stand_icon = new /icon(race_icon, "torso")
var/datum/organ/external/head = get_organ("head")
var/has_head = 0
@@ -273,16 +257,16 @@ proc/get_damage_icon_part(damage_state, body_part)
var/icon/temp
if(istype(part, /datum/organ/external/groin))
if(skeleton)
- temp = new /icon(icobase, "groin")
+ temp = new /icon(race_icon, "groin")
else
- temp = new /icon(icobase, "groin_[g]")
+ temp = new /icon(race_icon, "groin_[g]")
else if(istype(part, /datum/organ/external/head))
if(skeleton)
- temp = new /icon(icobase, "head")
+ temp = new /icon(race_icon, "head")
else
- temp = new /icon(icobase, "head_[g]")
+ temp = new /icon(race_icon, "head_[g]")
else
- temp = new /icon(icobase, "[part.icon_name]")
+ temp = new /icon(race_icon, "[part.icon_name]")
if(part.status & ORGAN_ROBOT)
temp.GrayScale()
if(part.status & ORGAN_DEAD)
@@ -327,7 +311,7 @@ proc/get_damage_icon_part(damage_state, body_part)
if(husk)
var/icon/mask = new(stand_icon)
- var/icon/husk_over = new(icobase,"overlay_husk")
+ var/icon/husk_over = new(race_icon,"overlay_husk")
mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0)
husk_over.Blend(mask, ICON_ADD)
stand_icon.Blend(husk_over, ICON_OVERLAY)
@@ -451,14 +435,30 @@ proc/get_damage_icon_part(damage_state, body_part)
// var/g = "m"
// if (gender == FEMALE) g = "f"
//BS12 EDIT
+ var/skeleton = (SKELETON in src.mutations)
+ if(skeleton)
+ race_icon = 'icons/mob/human_races/r_skeleton.dmi'
+ else if(dna)
+ switch(dna.mutantrace)
+ if("tajaran")
+ race_icon = 'icons/mob/human_races/r_tajaran.dmi'
+ if("lizard")
+ race_icon = 'icons/mob/human_races/r_lizard.dmi'
+ if("skrell")
+ race_icon = 'icons/mob/human_races/r_skrell.dmi'
+ else
+ race_icon = 'icons/mob/human_races/r_human.dmi'
+ else
+ icon = 'icons/mob/human_races/r_human.dmi'
+
if(dna)
switch(dna.mutantrace)
- if("lizard","golem","slime","shadow","adamantine")
+ if("golem","slime","shadow","adamantine")
overlays_lying[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/genetics.dmi', "icon_state" = "[dna.mutantrace][fat]_[gender]_l")
overlays_standing[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/genetics.dmi', "icon_state" = "[dna.mutantrace][fat]_[gender]_s")
- if("lizard","tajaran","skrell")
- overlays_lying[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.mutantrace]_[gender]_l")
- overlays_standing[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.mutantrace]_[gender]_s")
+ // if("lizard","tajaran","skrell")
+ // overlays_lying[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.mutantrace]_[gender]_l")
+ // overlays_standing[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.mutantrace]_[gender]_s")
if("plant")
if(stat == DEAD) //TODO
overlays_lying[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/genetics.dmi', "icon_state" = "[dna.mutantrace]_d")
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index 14fdc2eb1f..45e57a3da7 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -42,6 +42,9 @@
//Disabilities
handle_disabilities()
+ //Virus updates, duh
+ handle_virus_updates()
+
//Apparently, the person who wrote this code designed it so that
//blinded get reset each cycle and then get activated later in the
//code. Very ugly. I dont care. Moving this stuff here so its easy
@@ -147,6 +150,28 @@
emote("gasp")
updatehealth()
+ proc/handle_virus_updates()//copypaste from mob/carbon/human/life.dm
+ if(bodytemperature > 406)
+ for(var/datum/disease/D in viruses)
+ D.cure()
+ if(!virus2)
+ for(var/obj/effect/decal/cleanable/blood/B in view(1,src))
+ if(B.virus2 && get_infection_chance())
+ infect_virus2(src,B.virus2)
+ for(var/obj/effect/decal/cleanable/mucus/M in view(1,src))
+ if(M.virus2 && get_infection_chance())
+ infect_virus2(src,M.virus2)
+ else
+ if(isnull(virus2)) // Trying to figure out a runtime error that keeps repeating
+ CRASH("virus2 nulled before calling activate()")
+ else
+ virus2.activate(src)
+
+ // activate may have deleted the virus
+ if(!virus2) return
+
+ // check if we're immune
+ if(virus2.antigen & src.antibodies) virus2.dead = 1
proc/breathe()
if(reagents)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index b82f7b1d98..5415ba9900 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -194,7 +194,7 @@
/mob/living/silicon/robot/proc/updatename(var/prefix as text)
- if(istype(mmi, /obj/item/device/posibrain))
+ if(istype(mmi, /obj/item/device/mmi/posibrain))
braintype = "Android"
else
braintype = "Cyborg"
diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
index 3958dc5e26..719c9764ce 100644
--- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
@@ -43,7 +43,7 @@
/mob/living/simple_animal/spiderbot/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O, /obj/item/device/mmi) || istype(O, /obj/item/device/posibrain))
+ if(istype(O, /obj/item/device/mmi) || istype(O, /obj/item/device/mmi/posibrain))
var/obj/item/device/mmi/B = O
if(src.mmi) //There's already a brain in it.
user << "\red There's already a brain in [src]!"
@@ -284,14 +284,14 @@
return 0
if(istype(held_item, /obj/item/weapon/grenade))
- visible_message("\red [src] launches the [held_item]!", "\red You launch the [held_item]!", "You hear a skittering noise and a thump!")
+ visible_message("\red [src] launches \the [held_item]!", "\red You launch \the [held_item]!", "You hear a skittering noise and a thump!")
var/obj/item/weapon/grenade/G = held_item
G.loc = src.loc
G.prime()
held_item = null
return 1
- visible_message("\blue [src] drops the [held_item]!", "\blue You drop the [held_item]!", "You hear a skittering noise and a soft thump.")
+ visible_message("\blue [src] drops \the [held_item]!", "\blue You drop \the [held_item]!", "You hear a skittering noise and a soft thump.")
held_item.loc = src.loc
held_item = null
@@ -308,7 +308,7 @@
return -1
if(held_item)
- src << "\red You are already holding the [held_item]"
+ src << "\red You are already holding \the [held_item]"
return 1
var/list/items = list()
@@ -318,16 +318,14 @@
var/obj/selection = input("Select an item.", "Pickup") in items
- items.Cut()
if(selection)
for(var/obj/item/I in view(1, src))
if(selection == I)
held_item = selection
selection.loc = src
- visible_message("\blue [src] scoops up the [held_item]!", "\blue You grab the [held_item]!", "You hear a skittering noise and a clink.")
+ visible_message("\blue [src] scoops up \the [held_item]!", "\blue You grab \the [held_item]!", "You hear a skittering noise and a clink.")
return held_item
- else
- src << "\red \The [selection] is too far away."
+ src << "\red \The [selection] is too far away."
src << "\red There is nothing of interest to take."
return 0
@@ -335,4 +333,4 @@
/mob/living/simple_animal/spiderbot/examine()
..()
if(src.held_item)
- usr << "It is carrying \a [src.held_item] \icon[src.held_item]."
\ No newline at end of file
+ usr << "It is carrying \a [src.held_item] \icon[src.held_item]."
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 131711916b..bc25116ae5 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -224,9 +224,11 @@
return "[emote], \"[text]\""
return "says, \"[text]\"";
-/mob/living/simple_animal/emote(var/act)
+/mob/living/simple_animal/emote(var/act, var/type, var/desc)
if(act)
if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P
+ if(act == "me") //Allow me-emotes.
+ act = desc
if( findtext(act,".",lentext(act)) == 0 && findtext(act,"!",lentext(act)) == 0 && findtext(act,"?",lentext(act)) == 0 )
act = addtext(act,".") //Makes sure all emotes end with a period.
for (var/mob/O in viewers(src, null))
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 7402019ad4..1e8dd38692 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -129,7 +129,10 @@
return
if(client.prefs.species != "Human")
- if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist)
+
+ var/S = client.prefs.species
+ if(S == "Unathi") S = "Soghun"
+ if(!is_alien_whitelisted(src, S) && config.usealienwhitelist)
src << alert("You are currently not whitelisted to play [client.prefs.species].")
return 0
@@ -144,7 +147,9 @@
usr << "\blue There is an administrative lock on entering the game!"
return
- if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist)
+ var/S = client.prefs.species
+ if(S == "Unathi") S = "Soghun"
+ if(!is_alien_whitelisted(src, S) && config.usealienwhitelist)
src << alert("You are currently not whitelisted to play [client.prefs.species].")
return 0
@@ -286,13 +291,9 @@
proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank)
if (ticker.current_state == GAME_STATE_PLAYING)
var/obj/item/device/radio/intercom/a = new /obj/item/device/radio/intercom(null)// BS12 EDIT Arrivals Announcement Computer, rather than the AI.
-
- //unlikely for this to be an issue, but just in case
- if(istype(character.wear_id, /obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/I = character.wear_id
- a.autosay("\"[character.real_name],[I.assignment ? " [I.assignment]," : "" ] has arrived on the station.\"", "Arrivals Announcement Computer")
- else
- a.autosay("\"[character.real_name], visitor, has arrived on the station.\"", "Arrivals Announcement Computer")
+ if(character.mind.role_alt_title)
+ rank = character.mind.role_alt_title
+ a.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] has arrived on the station.", "Arrivals Announcement Computer")
del(a)
proc/LateChoices()
@@ -331,15 +332,15 @@
new_character.lastarea = get_area(loc)
if(client.prefs.species == "Tajaran") //This is like the worst, but it works, so meh. - Erthilo
- if(is_alien_whitelisted(src, "Tajaran") || !config.usealienwhitelist)
+ if(is_alien_whitelisted(src, "Tajaran"|| !config.usealienwhitelist))
new_character.dna.mutantrace = "tajaran"
new_character.tajaran_talk_understand = 1
if(client.prefs.species == "Unathi")
- if(is_alien_whitelisted(src, "Soghun") || !config.usealienwhitelist)
+ if(is_alien_whitelisted(src, "Soghun"|| !config.usealienwhitelist))
new_character.dna.mutantrace = "lizard"
new_character.soghun_talk_understand = 1
if(client.prefs.species == "Skrell")
- if(is_alien_whitelisted(src, "Skrell") || !config.usealienwhitelist)
+ if(is_alien_whitelisted(src, "Skrell"|| !config.usealienwhitelist))
new_character.dna.mutantrace = "skrell"
new_character.skrell_talk_understand = 1
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index 5c18258954..45a6de87f7 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -135,37 +135,34 @@ datum/preferences
var/g = "m"
if(gender == FEMALE) g = "f"
- if(species == "Tajaran")
- preview_icon = new /icon('icons/effects/species.dmi', "tajaran_[g]_s")
- preview_icon.Blend(new /icon('icons/effects/species.dmi', "tajtail_s"), ICON_OVERLAY)
- else if(species == "Unathi")
- preview_icon = new /icon('icons/effects/species.dmi', "lizard_[g]_s")
- preview_icon.Blend(new /icon('icons/effects/species.dmi', "sogtail_s"), ICON_OVERLAY)
- else if(species == "Skrell")
- preview_icon = new /icon('icons/effects/species.dmi', "skrell_[g]_s")
- else
- preview_icon = new /icon('human.dmi', "torso_[g]_s")
- preview_icon.Blend(new /icon('human.dmi', "chest_[g]_s"), ICON_OVERLAY)
+ var/icon/icobase
+ switch(species)
+ if("Tajaran")
+ icobase = 'icons/mob/human_races/r_tajaran.dmi'
+ if("Unathi")
+ icobase = 'icons/mob/human_races/r_lizard.dmi'
+ if("Skrell")
+ icobase = 'icons/mob/human_races/r_skrell.dmi'
+ else
+ icobase = 'icons/mob/human_races/r_human.dmi'
+ preview_icon = new /icon(icobase, "torso_[g]")
+ preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY)
+ preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY)
- if(organ_data["head"] != "amputated")
- preview_icon.Blend(new /icon('human.dmi', "head_[g]_s"), ICON_OVERLAY)
+ for(var/name in list("l_arm","r_arm","l_leg","r_leg","l_foot","r_foot","l_hand","r_hand"))
+ // make sure the organ is added to the list so it's drawn
+ if(organ_data[name] == null)
+ organ_data[name] = null
- for(var/name in list("l_arm","r_arm","l_leg","r_leg","l_foot","r_foot","l_hand","r_hand"))
- // make sure the organ is added to the list so it's drawn
- if(organ_data[name] == null)
- organ_data[name] = null
+ for(var/name in organ_data)
+ if(organ_data[name] == "amputated") continue
- for(var/name in organ_data)
- if(organ_data[name] == "amputated") continue
+ var/icon/temp = new /icon(icobase, "[name]")
+ if(organ_data[name] == "cyborg")
+ temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
- var/icon/temp = new /icon('human.dmi', "[name]_s")
- if(organ_data[name] == "cyborg")
- temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
-
- preview_icon.Blend(temp, ICON_OVERLAY)
-
- preview_icon.Blend(new /icon('human.dmi', "groin_[g]_s"), ICON_OVERLAY)
+ preview_icon.Blend(temp, ICON_OVERLAY)
// Skin tone
if(species == "Human")
diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm
index 6764da2e28..51f17273e3 100644
--- a/code/modules/organs/blood.dm
+++ b/code/modules/organs/blood.dm
@@ -25,7 +25,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
for(var/datum/reagent/blood/B in vessel.reagent_list)
if(B.id == "blood")
B.data = list( "donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_type"=dna.b_type, \
- "resistances"=null,"trace_chem"=null, "virus2" = null, "antobodies" = null)
+ "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = null)
// Takes care blood loss and regeneration
/mob/living/carbon/human/proc/handle_blood()
@@ -165,7 +165,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
B.data["donor"] = src
if(src.virus2)
B.data["virus2"] = src.virus2.getcopy()
- B.data["antibodies"] |= src.antibodies
+ B.data["antibodies"] = src.antibodies
B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
if(src.resistances && src.resistances.len)
if(B.data["resistances"])
@@ -176,8 +176,8 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
var/list/temp_chem = list()
for(var/datum/reagent/R in src.reagents.reagent_list)
- temp_chem += R.name
- temp_chem[R.name] = R.volume
+ temp_chem += R.id
+ temp_chem[R.id] = R.volume
B.data["trace_chem"] = list2params(temp_chem)
return B
@@ -197,9 +197,16 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
reagents.add_reagent("toxin",amount * 0.5)
reagents.update_total()
else
- vessel.add_reagent("blood", amount)
+ vessel.add_reagent("blood", amount, injected.data)
vessel.update_total()
+ var/list/chems = list()
+ chems = params2list(injected.data["trace_chem"])
+ for(var/C in chems)
+ src.reagents.add_reagent(C, (text2num(chems[C]) / 560) * amount)//adds trace chemicals to owner's blood
+ //world << "added [(text2num(chems[C])/560) * amount] = [text2num(chems[C])]/560*[amount] units of [C] to [src]" //DEBUG
+ reagents.update_total()
+
container.reagents.remove_reagent("blood", amount)
//Gets human's own blood.
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 2bcd0cfa00..247c380eb2 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -340,6 +340,9 @@
P.pixel_y = rand(-7, 7)
P.icon_state = "pill"+pillsprite
reagents.trans_to(P,50)
+ if(src.loaded_pill_bottle)
+ P.loc = src.loaded_pill_bottle
+ src.updateUsrDialog()
else if (href_list["createbottle"])
if(!condi)
var/name = reject_bad_text(input(usr,"Name:","Name your bottle!",reagents.get_master_reagent_name()))
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index 08bd8ad3d4..26666f0ecb 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -103,7 +103,7 @@ datum
blood
- data = new/list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null)
+ data = new/list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null, "antibodies" = null)
name = "Blood"
id = "blood"
reagent_state = LIQUID
@@ -122,11 +122,14 @@ datum
M.contract_disease(D)
else //injected
M.contract_disease(D, 1, 0)
- if(self.data && self.data["virus2"])
+ if(self.data && self.data["virus2"] && istype(M, /mob/living/carbon))//infecting...
if(method == TOUCH)
infect_virus2(M,self.data["virus2"])
else
infect_virus2(M,self.data["virus2"],1)
+ if(self.data && self.data["antibodies"] && istype(M, /mob/living/carbon))//... and curing
+ var/mob/living/carbon/C = M
+ C.antibodies |= self.data["antibodies"]
@@ -1693,6 +1696,13 @@ datum
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ holywater
+ name = "Holy Water"
+ id = "holywater"
+ description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen."
+ reagent_state = LIQUID
+ color = "#535E66" // rgb: 83, 94, 102
+
nanites
name = "Nanomachines"
id = "nanites"
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index c20091e4c3..44fd0cf046 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -11,10 +11,12 @@
var/slices_num
//Placeholder for effect that trigger on eating that aren't tied to reagents.
-/obj/item/weapon/reagent_containers/food/snacks/proc/On_Consume()
+/obj/item/weapon/reagent_containers/food/snacks/proc/On_Consume(var/mob/M)
if(!usr) return
if(!reagents.total_volume)
- usr.visible_message("[usr] finishes eating [src].","You finish eating [src].")
+ if(M == usr)
+ usr << "You finish eating \the [src]."
+ usr.visible_message("[usr] finishes eating \the [src].")
usr.drop_from_inventory(src) //so icons update :[
if(trash)
@@ -90,7 +92,7 @@
else
reagents.trans_to(M, reagents.total_volume)
bitecount++
- On_Consume()
+ On_Consume(M)
return 1
return 0
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 45cf1331e9..d491448a18 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -207,15 +207,15 @@
if (target != user && target.getarmor(target_zone, "melee") > 5 && prob(50))
for(var/mob/O in viewers(world.view, user))
- O.show_message(text("\red [user] tries to stab [target] in the [hit_area] with [src.name], but the attack is deflected by armor!"), 1)
+ O.show_message(text("\red [user] tries to stab [target] in \the [hit_area] with [src.name], but the attack is deflected by armor!"), 1)
user.u_equip(src)
del(src)
return
for(var/mob/O in viewers(world.view, user))
- O.show_message(text("\red [user] stabs [target] in the [hit_area] with [src.name]!"), 1)
+ O.show_message(text("\red [user] stabs [target] in \the [hit_area] with [src.name]!"), 1)
- if(affecting.take_damage(7))
+ if(affecting.take_damage(3))
target:UpdateDamageIcon()
else
diff --git a/code/modules/reagents/syringe_gun.dm b/code/modules/reagents/syringe_gun.dm
index a724d91ecd..30b1e66658 100644
--- a/code/modules/reagents/syringe_gun.dm
+++ b/code/modules/reagents/syringe_gun.dm
@@ -22,16 +22,20 @@
usr << "\blue [syringes.len] / [max_syringes] syringes."
attackby(obj/item/I as obj, mob/user as mob)
-
if(istype(I, /obj/item/weapon/reagent_containers/syringe))
- if(syringes.len < max_syringes)
- user.drop_item()
- I.loc = src
- syringes += I
- user << "\blue You put the syringe in [src]."
- user << "\blue [syringes.len] / [max_syringes] syringes."
+ var/obj/item/weapon/reagent_containers/syringe/S = I
+ if(S.mode != 2)//SYRINGE_BROKEN in syringes.dm
+ if(syringes.len < max_syringes)
+ user.drop_item()
+ I.loc = src
+ syringes += I
+ user << "\blue You put the syringe in [src]."
+ user << "\blue [syringes.len] / [max_syringes] syringes."
+ else
+ usr << "\red [src] cannot hold more syringes."
else
- usr << "\red [src] cannot hold more syringes."
+ usr << "\red This syringe is broken!"
+
afterattack(obj/target, mob/user , flag)
if(!isturf(target.loc) || target == user) return
diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
index a21b8181f7..838c26a87c 100644
--- a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
+++ b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm
@@ -33,19 +33,19 @@
return 0
//these three procs overriden to play different sounds
-/obj/mecha/mechturn(direction)
+/obj/mecha/working/hoverpod/mechturn(direction)
dir = direction
//playsound(src,'sound/machines/hiss.ogg',40,1)
return 1
-/obj/mecha/mechstep(direction)
+/obj/mecha/working/hoverpod/mechstep(direction)
var/result = step(src,direction)
if(result)
playsound(src,'sound/machines/hiss.ogg',40,1)
return result
-/obj/mecha/mechsteprand()
+/obj/mecha/working/hoverpod/mechsteprand()
var/result = step_rand(src)
if(result)
playsound(src,'sound/machines/hiss.ogg',40,1)
diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm b/code/modules/research/xenoarchaeology/machinery/analysis_base.dm
index 2f29eb6a1d..5319102be9 100644
--- a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm
+++ b/code/modules/research/xenoarchaeology/machinery/analysis_base.dm
@@ -12,7 +12,7 @@
var/target_scan_ticks = 60
var/report_num = 0
var/scan_process = 0
- var/heat_accumulation_rate = 1
+ var/heat_accumulation_rate = 0.25
var/temperature = 273 //measured in kelvin, if this exceeds 1200, the machine is damaged and requires repairs
//if this exceeds 600 and safety is enabled it will shutdown
//temp greater than 600 also requires a safety prompt to initiate scanning
diff --git a/code/modules/research/xenoarchaeology/manuals.dm b/code/modules/research/xenoarchaeology/manuals.dm
index 84230853d7..ceaa3d036e 100644
--- a/code/modules/research/xenoarchaeology/manuals.dm
+++ b/code/modules/research/xenoarchaeology/manuals.dm
@@ -312,7 +312,7 @@
the the denser clumps of matter out of the refined sample. This is done by mixing 1 part lithium, 2 parts sodium, 1 part tungsten, 4 parts oxygen.
Mix separator with sample - The resulting mixture is very close to the final product, but make sure to extract any leftover reagents and
the chemical waste byproduct.
- Bring sample to boil - Using a standard bunsen burner, bring the mixture to a boil to vaporise the remaining unwanted matter. Remember
+ Bring sample to boil - Using a standard bunsen burner, bring the mixture containing at least 5u of DST to a boil to vaporise the remaining unwanted matter. Remember
to again clear out any waste byproducts.
Contents
@@ -411,3 +411,65 @@