Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Апгрейд ксенобиологии. Порт slime management console + небольшой ремап #4554

Merged
merged 9 commits into from
Feb 15, 2020
7 changes: 7 additions & 0 deletions code/__DEFINES/components.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@
// /atom/movable signals
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)


#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob)
#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob)
#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob)
#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob)
#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob)
4 changes: 4 additions & 0 deletions code/__DEFINES/maps.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
#define ZTRAITS_SPACE list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_SPACE_RUINS = TRUE)
#define ZTRAITS_ASTEROID list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_MINING = TRUE)

#define CAMERA_LOCK_STATION 1
#define CAMERA_LOCK_MINING 2
#define CAMERA_LOCK_CENTCOM 4

#define DL_NAME "name"
#define DL_TRAITS "traits"
#define DECLARE_LEVEL(NAME, TRAITS) list(DL_NAME = NAME, DL_TRAITS = TRAITS)
Expand Down
232 changes: 232 additions & 0 deletions code/game/machinery/camera/camera_advanced.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/obj/machinery/computer/camera_advanced
name = "advanced camera console"
desc = "Used to access the various cameras on the station."
icon_state = "cameras"

circuit = /obj/item/weapon/circuitboard/camera_advanced
light_color = "#a91515"

var/lock_override = NONE
var/list/z_lock = list() // Lock use to these z levels. Do not! set this directly, use lock_override flags

var/mob/camera/Eye/remote/eyeobj
var/mob/living/current_user = null

var/list/networks = list("SS13")

var/list/actions = list()
var/datum/action/camera_off/off_action = new
var/datum/action/camera_jump/jump_action = new

/obj/machinery/computer/camera_advanced/atom_init()
. = ..()
actions += off_action
actions += jump_action
if(lock_override)
if(lock_override & CAMERA_LOCK_STATION)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_STATION)
if(lock_override & CAMERA_LOCK_MINING)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_MINING)
if(lock_override & CAMERA_LOCK_CENTCOM)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_CENTCOM)

/obj/machinery/computer/camera_advanced/Destroy()
if(current_user)
current_user.unset_machine()
current_user = null
QDEL_NULL(eyeobj)
QDEL_NULL(off_action)
QDEL_NULL(jump_action)
actions.Cut()
return ..()

/obj/machinery/computer/camera_advanced/proc/CreateEye()
eyeobj = new()
eyeobj.origin = src

/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user)
if(off_action)
off_action.target = user
off_action.Grant(user)


if(jump_action)
jump_action.target = user
jump_action.Grant(user)


/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user)
if(!user)
Zap-zapper marked this conversation as resolved.
Show resolved Hide resolved
CRASH("Attempted to call remove_eye_control() proc with null user")
for(var/V in actions)
var/datum/action/A = V
A.Remove(user)
for(var/V in eyeobj.visibleCameraChunks)
var/datum/camerachunk/C = V
C.remove(eyeobj)
if(user.client)
user.reset_view(null)
if(eyeobj.user_camera_icon && user.client)
user.client.images -= eyeobj.user_image
eyeobj.master = null
user.remote_control = null

current_user = null
user.unset_machine()

/obj/machinery/computer/camera_advanced/check_eye(mob/user)
if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || user.eye_blind || user.incapacitated() )
user.unset_machine()
return FALSE
return TRUE

/obj/machinery/computer/camera_advanced/on_unset_machine(mob/M)
if(M == current_user)
remove_eye_control(M)
..()

/obj/machinery/computer/camera_advanced/interact(mob/user)
user.machine = src
var/mob/living/L = user
if(!eyeobj)
CreateEye()

if(!eyeobj.eye_initialized)
var/camera_location
var/turf/myturf = get_turf(src)
if(z_lock.len && !(myturf.z in z_lock))
to_chat(user, "<span class='warning'>ERROR: system unable to access local camera network.</span>")
else
camera_location = myturf

if(camera_location)
eyeobj.eye_initialized = TRUE
give_eye_control(L)
eyeobj.setLoc(camera_location)
else
user.unset_machine()
else
give_eye_control(L)
eyeobj.setLoc(eyeobj.loc)


/obj/machinery/computer/camera_advanced/attack_hand(mob/user)
if(!is_operational())
return
if(current_user)
to_chat(user, "<span class='warning'>The console is already in use!</span>")
return
..()

/obj/machinery/computer/camera_advanced/attack_robot(mob/user)
return attack_hand(user)

/obj/machinery/computer/camera_advanced/attack_ai(mob/user)
return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise.

/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user)
GrantActions(user)
current_user = user
eyeobj.master = user
eyeobj.name = "Camera Eye ([user.name])"
user.remote_control = eyeobj
user.reset_view(eyeobj)
eyeobj.setLoc(eyeobj.loc)
if(eyeobj.user_camera_icon && user.client)
user.client.images += eyeobj.user_image

/mob/camera/Eye/remote
name = "Inactive Camera Eye"
var/obj/machinery/computer/camera_advanced/origin
var/sprint = 10
var/cooldown = 0
var/acceleration = FALSE
var/eye_initialized = FALSE
var/user_camera_icon = null //How icon appears to user. If you want eye to be invisible to anyone but user, use this instead of "icon" variable.
var/image/user_image = null
var/allowed_area_type = null

/mob/camera/Eye/remote/atom_init()
if(!user_image && user_camera_icon)
user_image = image(icon = user_camera_icon,loc = src,icon_state = icon_state,layer = LIGHTING_LAYER+1)
. = ..()

/mob/camera/Eye/remote/Destroy()
if(origin && master)
origin.remove_eye_control(master)
Zap-zapper marked this conversation as resolved.
Show resolved Hide resolved
origin = null
master = null
return ..()

/mob/camera/Eye/remote/relaymove(mob/user,direct)
var/initial = initial(sprint)
var/max_sprint = 50

if(cooldown && cooldown < world.timeofday) // 3 seconds
sprint = initial

for(var/i = 0; i < max(sprint, initial); i += 20)
var/turf/movement = get_step(src, direct)
if(movement)
setLoc(movement)

cooldown = world.timeofday + 5
if(acceleration)
sprint = min(sprint + 0.5, max_sprint)
else
sprint = initial

/mob/camera/Eye/remote/setLoc(turf/T)
if (allowed_area_type != null && !istype(get_area(T), allowed_area_type))
return
..()

/datum/action/camera_off
name = "End Camera View"
button_icon = 'icons/mob/actions.dmi'
button_icon_state = "camera_off"
action_type = AB_INNATE

/datum/action/camera_off/Activate()
if(!target || !isliving(target))
return
var/mob/living/C = target
var/mob/camera/Eye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin
console.remove_eye_control(target)

/datum/action/camera_jump
name = "Jump To Camera"
button_icon = 'icons/mob/actions.dmi'
button_icon_state = "camera_jump"
action_type = AB_INNATE

/datum/action/camera_jump/Activate()
if(!target || !isliving(target))
return

var/mob/living/C = target
var/mob/camera/Eye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin

var/list/L = list()

for (var/obj/machinery/camera/cam in cameranet.cameras)
if(origin.z_lock.len && !(cam.z in origin.z_lock))
continue
L.Add(cam)

camera_sort(L)

var/list/T = list()

for (var/obj/machinery/camera/netcam in L)
if (length(netcam.network & origin.networks))
if (remote_eye.allowed_area_type != null && !istype(get_area(netcam), remote_eye.allowed_area_type))
continue
T["[netcam.c_tag][netcam.can_use() ? null : " (Deactivated)"]"] = netcam

var/camera = input("Choose which camera you want to view", "Cameras") as null|anything in T
var/obj/machinery/camera/final = T[camera]
if(final)
remote_eye.setLoc(get_turf(final))
8 changes: 8 additions & 0 deletions code/game/machinery/computer/buildandrepair.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
name = "Circuit board (Message Monitor)"
build_path = /obj/machinery/computer/message_monitor
origin_tech = "programming=3"
/obj/item/weapon/circuitboard/camera_advanced
name = "circuit board (Advanced Camera Console)"
build_path = /obj/machinery/computer/camera_advanced
req_access = list(access_security)
/obj/item/weapon/circuitboard/camera_advanced/xenobio
name = "circuit board (Slime management console)"
build_path = /obj/machinery/computer/camera_advanced/xenobio
origin_tech = "biotech=3;bluespace=3"
/obj/item/weapon/circuitboard/security
name = "Circuit board (Security)"
build_path = /obj/machinery/computer/security
Expand Down
57 changes: 41 additions & 16 deletions code/game/machinery/kitchen/monkeyrecycler.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/obj/machinery/monkey_recycler
name = "Monkey Recycler"
desc = "A machine used for recycling dead monkeys into monkey cubes."
name = "Recycler"
desc = "A machine used for recycling dead monkeys into monkey cubes. Can also quickly extract cores from dead slimes"
icon = 'icons/obj/kitchen.dmi'
icon_state = "grinder"
layer = 2.9
Expand All @@ -12,6 +12,7 @@
var/grinded = 0
var/required_grind = 5
var/cube_production = 1
var/obj/machinery/computer/camera_advanced/xenobio/connected

/obj/machinery/monkey_recycler/atom_init()
. = ..()
Expand All @@ -21,18 +22,32 @@
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
RefreshParts()

/obj/machinery/monkey_recycler/proc/grind(var/M, mob/user)
user.drop_item()
qdel(M)
to_chat(user, "<span class='notice'>You stuff the monkey in the machine.</span>")
/obj/machinery/monkey_recycler/Destroy()
connected.connected_recycler = null
Zap-zapper marked this conversation as resolved.
Show resolved Hide resolved
connected = null
return ..()

/obj/machinery/monkey_recycler/proc/grind(atom/movable/P, mob/user)
playsound(src, 'sound/machines/juicer.ogg', VOL_EFFECTS_MASTER)
var/offset = prob(50) ? -2 : 2
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking
use_power(500)
src.grinded++
sleep(50)
var/atom/movable/M = P
M.forceMove(src) //To hide them from view
addtimer(CALLBACK(src, .proc/finish_processing,M,user), 50)


/obj/machinery/monkey_recycler/proc/finish_processing(atom/movable/M, mob/user)
if(ismonkey(M))
src.grinded++
to_chat(user, "<span class='notice'>The machine now has [grinded/required_grind] monkeys worth of material stored.</span>")
else if(isslime(M))
var/mob/living/carbon/slime/S = M
var/C = S.cores
for(var/i in 1 to (C+cube_production-1)) //Can extract many cores if upgraded
new S.coretype(loc)
qdel(M)
pixel_x = initial(pixel_x)
to_chat(user, "<span class='notice'>The machine now has [grinded] monkeys worth of material stored.</span>")

/obj/machinery/monkey_recycler/RefreshParts()
var/req_grind = 5
Expand All @@ -43,7 +58,7 @@
cubes_made = M.rating
cube_production = cubes_made
required_grind = req_grind
desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces [cubes_made] cube(s) for every [required_grind] monkey(s) inserted."
desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces [cubes_made] cube(s) for every [required_grind] monkey(s) inserted. Can also quickly extract cores from dead slimes."

/obj/machinery/monkey_recycler/attackby(obj/item/O, mob/user, params)
if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O))
Expand All @@ -68,20 +83,30 @@
for (var/mob/living/M in O.contents)
G = M
if (G.stat == CONSCIOUS)
to_chat(user, "<span class='warning'>The monkey is struggling far too much to put it in the recycler.</span>")
to_chat(user, "<span class='warning'>The subject is struggling far too much to put it in the recycler.</span>")
else
user.drop_item()
to_chat(user, "<span class='notice'>You stuff the subject in the machine.</span>")
grind(O, user)
if (istype(O, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = O
var/grabbed = G.affecting
if(ismonkey(grabbed))
var/mob/living/carbon/monkey/target = grabbed
if(ismonkey(grabbed) || isslime(grabbed))
var/mob/living/carbon/target = grabbed
if(target.stat == CONSCIOUS)
to_chat(user, "<span class='warning'>The monkey is struggling far too much to put it in the recycler.</span>")
to_chat(user, "<span class='warning'>The subject is struggling far too much to put it in the recycler.</span>")
else
user.drop_item()
to_chat(user, "<span class='notice'>You stuff the subject in the machine.</span>")
grind(target, user)
else
to_chat(user, "<span class='warning'>The machine only accepts monkeys!</span>")
to_chat(user, "<span class='warning'>The machine only accepts monkeys and slimes!</span>")

if(panel_open)
if(ismultitool(O))
var/obj/item/device/multitool/M = O
M.buffer = src
to_chat(user, "<span class='notice'>You save the data in the [O.name]'s buffer.</span>")
return

/obj/machinery/monkey_recycler/attack_hand(mob/user)
Expand All @@ -96,4 +121,4 @@
new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(loc)
to_chat(user, "<span class='notice'>The machine's display flashes that it has [grinded] monkeys worth of material left.</span>")
else
to_chat(user, "<span class='danger'>The machine needs at least [required_grind] monkey(s) worth of material to produce a monkey cube. It only has [grinded].</span>")
to_chat(user, "<span class='danger'>The machine needs at least [required_grind] monkey(s) worth of material to produce a monkey cube. It only has [grinded].</span>")