Merge pull request #1229 from ArchieBeepBoop/iconupdates

Ports: Icon state updates Part 1
This commit is contained in:
QuoteFox
2021-06-06 19:51:08 +01:00
committed by GitHub
65 changed files with 9619 additions and 9452 deletions
+9 -13
View File
@@ -46,8 +46,7 @@
/obj/item/defibrillator/update_icon()
update_power()
update_overlays()
update_charge()
return ..()
/obj/item/defibrillator/proc/update_power()
if(!QDELETED(cell))
@@ -58,23 +57,20 @@
else
powered = FALSE
/obj/item/defibrillator/proc/update_overlays()
cut_overlays()
/obj/item/defibrillator/update_overlays()
. = ..()
if(!on)
add_overlay("[initial(icon_state)]-paddles")
. += "[initial(icon_state)]-paddles"
if(powered)
add_overlay("[initial(icon_state)]-powered")
if(!cell)
add_overlay("[initial(icon_state)]-nocell")
if(!safety)
add_overlay("[initial(icon_state)]-emagged")
/obj/item/defibrillator/proc/update_charge()
if(powered) //so it doesn't show charge if it's unpowered
. += "[initial(icon_state)]-powered"
if(!QDELETED(cell))
var/ratio = cell.charge / cell.maxcharge
ratio = CEILING(ratio*4, 1) * 25
add_overlay("[initial(icon_state)]-charge[ratio]")
if(!cell)
. += "[initial(icon_state)]-nocell"
if(!safety)
. += "[initial(icon_state)]-emagged"
/obj/item/defibrillator/CheckParts(list/parts_list)
..()
+237 -237
View File
@@ -1,237 +1,237 @@
/obj/item/transfer_valve
icon = 'icons/obj/assemblies.dmi'
name = "tank transfer valve"
icon_state = "valve_1"
item_state = "ttv"
lefthand_file = 'icons/mob/inhands/weapons/bombs_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/bombs_righthand.dmi'
desc = "Regulates the transfer of air between two tanks."
w_class = WEIGHT_CLASS_BULKY
var/obj/item/tank/tank_one
var/obj/item/tank/tank_two
var/obj/item/assembly/attached_device
var/mob/attacher = null
var/valve_open = FALSE
var/toggle = 1
/obj/item/transfer_valve/IsAssemblyHolder()
return TRUE
/obj/item/transfer_valve/attackby(obj/item/item, mob/user, params)
if(istype(item, /obj/item/tank))
if(tank_one && tank_two)
to_chat(user, "<span class='warning'>There are already two tanks attached, remove one first!</span>")
return
if(!tank_one)
if(!user.transferItemToLoc(item, src))
return
tank_one = item
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
else if(!tank_two)
if(!user.transferItemToLoc(item, src))
return
tank_two = item
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
update_icon()
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/assembly/A = item
if(A.secured)
to_chat(user, "<span class='notice'>The device is secured.</span>")
return
if(attached_device)
to_chat(user, "<span class='warning'>There is already a device attached to the valve, remove it first!</span>")
return
if(!user.transferItemToLoc(item, src))
return
attached_device = A
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
A.holder = src
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
GLOB.bombers += "[key_name(user)] attached a [item] to a transfer valve."
message_admins("[ADMIN_LOOKUPFLW(user)] attached a [item] to a transfer valve.")
log_game("[key_name(user)] attached a [item] to a transfer valve.")
attacher = user
return
//Attached device memes
/obj/item/transfer_valve/Move()
. = ..()
if(attached_device)
attached_device.holder_movement()
/obj/item/transfer_valve/dropped()
. = ..()
if(attached_device)
attached_device.dropped()
/obj/item/transfer_valve/on_found(mob/finder)
if(attached_device)
attached_device.on_found(finder)
/obj/item/transfer_valve/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(attached_device)
attached_device.Crossed(AM)
/obj/item/transfer_valve/attack_hand()//Triggers mousetraps
. = ..()
if(.)
return
if(attached_device)
attached_device.attack_hand()
//These keep attached devices synced up, for example a TTV with a mouse trap being found in a bag so it's triggered, or moving the TTV with an infrared beam sensor to update the beam's direction.
/obj/item/transfer_valve/attack_self(mob/user)
user.set_machine(src)
var/dat = {"<B> Valve properties: </B>
<BR> <B> Attachment one:</B> [tank_one] [tank_one ? "<A href='?src=[REF(src)];tankone=1'>Remove</A>" : ""]
<BR> <B> Attachment two:</B> [tank_two] [tank_two ? "<A href='?src=[REF(src)];tanktwo=1'>Remove</A>" : ""]
<BR> <B> Valve attachment:</B> [attached_device ? "<A href='?src=[REF(src)];device=1'>[attached_device]</A>" : "None"] [attached_device ? "<A href='?src=[REF(src)];rem_device=1'>Remove</A>" : ""]
<BR> <B> Valve status: </B> [ valve_open ? "<A href='?src=[REF(src)];open=1'>Closed</A> <B>Open</B>" : "<B>Closed</B> <A href='?src=[REF(src)];open=1'>Open</A>"]"}
var/datum/browser/popup = new(user, "trans_valve", name)
popup.set_content(dat)
popup.open()
return
/obj/item/transfer_valve/Topic(href, href_list)
..()
if(!usr.canUseTopic(src))
return
if(tank_one && href_list["tankone"])
split_gases()
valve_open = FALSE
tank_one.forceMove(drop_location())
tank_one = null
update_icon()
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = FALSE
tank_two.forceMove(drop_location())
tank_two = null
update_icon()
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.on_detach()
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
attack_self(usr)
add_fingerprint(usr)
/obj/item/transfer_valve/proc/process_activation(obj/item/D)
if(toggle)
toggle = FALSE
toggle_valve()
addtimer(CALLBACK(src, .proc/toggle_off), 5) //To stop a signal being spammed from a proxy sensor constantly going off or whatever
/obj/item/transfer_valve/proc/toggle_off()
toggle = TRUE
/obj/item/transfer_valve/update_icon()
cut_overlays()
underlays = null
if(!tank_one && !tank_two && !attached_device)
icon_state = "valve_1"
return
icon_state = "valve"
if(tank_one)
add_overlay("[tank_one.icon_state]")
if(tank_two)
var/icon/J = new(icon, icon_state = "[tank_two.icon_state]")
J.Shift(WEST, 13)
underlays += J
if(attached_device)
add_overlay("device")
if(istype(attached_device, /obj/item/assembly/infra))
var/obj/item/assembly/infra/sensor = attached_device
if(sensor.on && sensor.visible)
add_overlay("proxy_beam")
/obj/item/transfer_valve/proc/merge_gases(datum/gas_mixture/target, change_volume = TRUE)
var/target_self = FALSE
if(!target || (target == tank_one.air_contents))
target = tank_two.air_contents
if(target == tank_two.air_contents)
target_self = TRUE
if(change_volume)
if(!target_self)
target.volume += tank_two.volume
target.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
target.merge(temp)
if(!target_self)
temp = tank_two.air_contents.remove_ratio(1)
target.merge(temp)
/obj/item/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does).
*/
/obj/item/transfer_valve/proc/toggle_valve()
if(!valve_open && tank_one && tank_two)
valve_open = TRUE
var/turf/bombturf = get_turf(src)
var/attachment
if(attached_device)
if(istype(attached_device, /obj/item/assembly/signaler))
attachment = "<A HREF='?_src_=holder;[HrefToken()];secrets=list_signalers'>[attached_device]</A>"
else
attachment = attached_device
var/admin_attachment_message
var/attachment_message
if(attachment)
admin_attachment_message = " with [attachment] attached by [attacher ? ADMIN_LOOKUPFLW(attacher) : "Unknown"]"
attachment_message = " with [attachment] attached by [attacher ? key_name_admin(attacher) : "Unknown"]"
var/mob/bomber = get_mob_by_key(fingerprintslast)
var/admin_bomber_message
var/bomber_message
if(bomber)
admin_bomber_message = " - Last touched by: [ADMIN_LOOKUPFLW(bomber)]"
bomber_message = " - Last touched by: [key_name_admin(bomber)]"
var/admin_bomb_message = "Bomb valve opened in [ADMIN_VERBOSEJMP(bombturf)][admin_attachment_message][admin_bomber_message]"
GLOB.bombers += admin_bomb_message
message_admins(admin_bomb_message, 0, 1)
log_game("Bomb valve opened in [AREACOORD(bombturf)][attachment_message][bomber_message]")
merge_gases()
for(var/i in 1 to 6)
addtimer(CALLBACK(src, .proc/update_icon), 20 + (i - 1) * 10)
else if(valve_open && tank_one && tank_two)
split_gases()
valve_open = FALSE
update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/obj/item/transfer_valve/proc/c_state()
return
/obj/item/transfer_valve
icon = 'icons/obj/assemblies.dmi'
name = "tank transfer valve"
icon_state = "valve_1"
item_state = "ttv"
lefthand_file = 'icons/mob/inhands/weapons/bombs_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/bombs_righthand.dmi'
desc = "Regulates the transfer of air between two tanks."
w_class = WEIGHT_CLASS_BULKY
var/obj/item/tank/tank_one
var/obj/item/tank/tank_two
var/obj/item/assembly/attached_device
var/mob/attacher = null
var/valve_open = FALSE
var/toggle = 1
/obj/item/transfer_valve/IsAssemblyHolder()
return TRUE
/obj/item/transfer_valve/attackby(obj/item/item, mob/user, params)
if(istype(item, /obj/item/tank))
if(tank_one && tank_two)
to_chat(user, "<span class='warning'>There are already two tanks attached, remove one first!</span>")
return
if(!tank_one)
if(!user.transferItemToLoc(item, src))
return
tank_one = item
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
else if(!tank_two)
if(!user.transferItemToLoc(item, src))
return
tank_two = item
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
update_icon()
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/assembly/A = item
if(A.secured)
to_chat(user, "<span class='notice'>The device is secured.</span>")
return
if(attached_device)
to_chat(user, "<span class='warning'>There is already a device attached to the valve, remove it first!</span>")
return
if(!user.transferItemToLoc(item, src))
return
attached_device = A
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
A.holder = src
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
GLOB.bombers += "[key_name(user)] attached a [item] to a transfer valve."
message_admins("[ADMIN_LOOKUPFLW(user)] attached a [item] to a transfer valve.")
log_game("[key_name(user)] attached a [item] to a transfer valve.")
attacher = user
return
//Attached device memes
/obj/item/transfer_valve/Move()
. = ..()
if(attached_device)
attached_device.holder_movement()
/obj/item/transfer_valve/dropped()
. = ..()
if(attached_device)
attached_device.dropped()
/obj/item/transfer_valve/on_found(mob/finder)
if(attached_device)
attached_device.on_found(finder)
/obj/item/transfer_valve/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(attached_device)
attached_device.Crossed(AM)
/obj/item/transfer_valve/attack_hand()//Triggers mousetraps
. = ..()
if(.)
return
if(attached_device)
attached_device.attack_hand()
//These keep attached devices synced up, for example a TTV with a mouse trap being found in a bag so it's triggered, or moving the TTV with an infrared beam sensor to update the beam's direction.
/obj/item/transfer_valve/attack_self(mob/user)
user.set_machine(src)
var/dat = {"<B> Valve properties: </B>
<BR> <B> Attachment one:</B> [tank_one] [tank_one ? "<A href='?src=[REF(src)];tankone=1'>Remove</A>" : ""]
<BR> <B> Attachment two:</B> [tank_two] [tank_two ? "<A href='?src=[REF(src)];tanktwo=1'>Remove</A>" : ""]
<BR> <B> Valve attachment:</B> [attached_device ? "<A href='?src=[REF(src)];device=1'>[attached_device]</A>" : "None"] [attached_device ? "<A href='?src=[REF(src)];rem_device=1'>Remove</A>" : ""]
<BR> <B> Valve status: </B> [ valve_open ? "<A href='?src=[REF(src)];open=1'>Closed</A> <B>Open</B>" : "<B>Closed</B> <A href='?src=[REF(src)];open=1'>Open</A>"]"}
var/datum/browser/popup = new(user, "trans_valve", name)
popup.set_content(dat)
popup.open()
return
/obj/item/transfer_valve/Topic(href, href_list)
..()
if(!usr.canUseTopic(src))
return
if(tank_one && href_list["tankone"])
split_gases()
valve_open = FALSE
tank_one.forceMove(drop_location())
tank_one = null
update_icon()
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = FALSE
tank_two.forceMove(drop_location())
tank_two = null
update_icon()
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.on_detach()
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
attack_self(usr)
add_fingerprint(usr)
/obj/item/transfer_valve/proc/process_activation(obj/item/D)
if(toggle)
toggle = FALSE
toggle_valve()
addtimer(CALLBACK(src, .proc/toggle_off), 5) //To stop a signal being spammed from a proxy sensor constantly going off or whatever
/obj/item/transfer_valve/proc/toggle_off()
toggle = TRUE
/obj/item/transfer_valve/update_icon()
cut_overlays()
underlays = null
if(!tank_one && !tank_two && !attached_device)
icon_state = "valve_1"
return
icon_state = "valve"
if(tank_one)
add_overlay("[tank_one.icon_state]")
if(tank_two)
var/icon/J = new(icon, icon_state = "[tank_two.icon_state]")
J.Shift(WEST, 13)
underlays += J
if(attached_device)
add_overlay("device")
if(istype(attached_device, /obj/item/assembly/infra))
var/obj/item/assembly/infra/sensor = attached_device
if(sensor.on && sensor.visible)
add_overlay("proxy_beam")
/obj/item/transfer_valve/proc/merge_gases(datum/gas_mixture/target, change_volume = TRUE)
var/target_self = FALSE
if(!target || (target == tank_one.air_contents))
target = tank_two.air_contents
if(target == tank_two.air_contents)
target_self = TRUE
if(change_volume)
if(!target_self)
target.volume += tank_two.volume
target.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
target.merge(temp)
if(!target_self)
temp = tank_two.air_contents.remove_ratio(1)
target.merge(temp)
/obj/item/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does).
*/
/obj/item/transfer_valve/proc/toggle_valve()
if(!valve_open && tank_one && tank_two)
valve_open = TRUE
var/turf/bombturf = get_turf(src)
var/attachment
if(attached_device)
if(istype(attached_device, /obj/item/assembly/signaler))
attachment = "<A HREF='?_src_=holder;[HrefToken()];secrets=list_signalers'>[attached_device]</A>"
else
attachment = attached_device
var/admin_attachment_message
var/attachment_message
if(attachment)
admin_attachment_message = " with [attachment] attached by [attacher ? ADMIN_LOOKUPFLW(attacher) : "Unknown"]"
attachment_message = " with [attachment] attached by [attacher ? key_name_admin(attacher) : "Unknown"]"
var/mob/bomber = get_mob_by_key(fingerprintslast)
var/admin_bomber_message
var/bomber_message
if(bomber)
admin_bomber_message = " - Last touched by: [ADMIN_LOOKUPFLW(bomber)]"
bomber_message = " - Last touched by: [key_name_admin(bomber)]"
var/admin_bomb_message = "Bomb valve opened in [ADMIN_VERBOSEJMP(bombturf)][admin_attachment_message][admin_bomber_message]"
GLOB.bombers += admin_bomb_message
message_admins(admin_bomb_message, 0, 1)
log_game("Bomb valve opened in [AREACOORD(bombturf)][attachment_message][bomber_message]")
merge_gases()
for(var/i in 1 to 6)
addtimer(CALLBACK(src, /atom/.proc/update_icon), 20 + (i - 1) * 10)
else if(valve_open && tank_one && tank_two)
split_gases()
valve_open = FALSE
update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/obj/item/transfer_valve/proc/c_state()
return
+3 -4
View File
@@ -213,7 +213,7 @@
loadedWeightClass -= I.w_class
else if (A == tank)
tank = null
update_icons()
update_icon()
/obj/item/pneumatic_cannon/ghetto //Obtainable by improvised methods; more gas per use, less capacity, but smaller
name = "improvised pneumatic cannon"
@@ -239,14 +239,13 @@
return
to_chat(user, "<span class='notice'>You hook \the [thetank] up to \the [src].</span>")
tank = thetank
update_icons()
update_icon()
/obj/item/pneumatic_cannon/proc/update_icons()
/obj/item/pneumatic_cannon/update_icon()
cut_overlays()
if(!tank)
return
add_overlay(tank.icon_state)
update_icon()
/obj/item/pneumatic_cannon/proc/fill_with_type(type, amount)
if(!ispath(type, /obj) && !ispath(type, /mob))
+413 -413
View File
@@ -1,413 +1,413 @@
//The robot bodyparts have been moved to code/module/surgery/bodyparts/robot_bodyparts.dm
/obj/item/robot_suit
name = "cyborg endoskeleton"
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
icon = 'icons/mob/augmentation/augments.dmi'
icon_state = "robo_suit"
var/obj/item/bodypart/l_arm/robot/l_arm = null
var/obj/item/bodypart/r_arm/robot/r_arm = null
var/obj/item/bodypart/l_leg/robot/l_leg = null
var/obj/item/bodypart/r_leg/robot/r_leg = null
var/obj/item/bodypart/chest/robot/chest = null
var/obj/item/bodypart/head/robot/head = null
var/created_name = ""
var/mob/living/silicon/ai/forced_ai
var/locomotion = 1
var/lawsync = 1
var/aisync = 1
var/panel_locked = TRUE
/obj/item/robot_suit/New()
..()
updateicon()
/obj/item/robot_suit/prebuilt/New()
l_arm = new(src)
r_arm = new(src)
l_leg = new(src)
r_leg = new(src)
head = new(src)
head.flash1 = new(head)
head.flash2 = new(head)
chest = new(src)
chest.wired = TRUE
chest.cell = new /obj/item/stock_parts/cell/high/plus(chest)
..()
/obj/item/robot_suit/proc/updateicon()
cut_overlays()
if(l_arm)
add_overlay("[l_arm.icon_state]+o")
if(r_arm)
add_overlay("[r_arm.icon_state]+o")
if(chest)
add_overlay("[chest.icon_state]+o")
if(l_leg)
add_overlay("[l_leg.icon_state]+o")
if(r_leg)
add_overlay("[r_leg.icon_state]+o")
if(head)
add_overlay("[head.icon_state]+o")
/obj/item/robot_suit/proc/check_completion()
if(src.l_arm && src.r_arm)
if(src.l_leg && src.r_leg)
if(src.chest && src.head)
SSblackbox.record_feedback("amount", "cyborg_frames_built", 1)
return 1
return 0
/obj/item/robot_suit/wrench_act(mob/living/user, obj/item/I) //Deconstucts empty borg shell. Flashes remain unbroken because they haven't been used yet
var/turf/T = get_turf(src)
if(l_leg || r_leg || chest || l_arm || r_arm || head)
if(I.use_tool(src, user, 5, volume=50))
if(l_leg)
l_leg.forceMove(T)
l_leg = null
if(r_leg)
r_leg.forceMove(T)
r_leg = null
if(chest)
if (chest.cell) //Sanity check.
chest.cell.forceMove(T)
chest.cell = null
chest.forceMove(T)
new /obj/item/stack/cable_coil(T, 1)
chest.wired = FALSE
chest = null
if(l_arm)
l_arm.forceMove(T)
l_arm = null
if(r_arm)
r_arm.forceMove(T)
r_arm = null
if(head)
head.forceMove(T)
head.flash1.forceMove(T)
head.flash1 = null
head.flash2.forceMove(T)
head.flash2 = null
head = null
to_chat(user, "<span class='notice'>You disassemble the cyborg shell.</span>")
else
to_chat(user, "<span class='notice'>There is nothing to remove from the endoskeleton.</span>")
updateicon()
/obj/item/robot_suit/proc/put_in_hand_or_drop(mob/living/user, obj/item/I) //normal put_in_hands() drops the item ontop of the player, this drops it at the suit's loc
if(!user.put_in_hands(I))
I.forceMove(drop_location())
return FALSE
return TRUE
/obj/item/robot_suit/screwdriver_act(mob/living/user, obj/item/I) //Swaps the power cell if you're holding a new one in your other hand.
. = ..()
if(.)
return TRUE
if(!chest) //can't remove a cell if there's no chest to remove it from.
to_chat(user, "<span class='notice'>[src] has no attached torso.</span>")
return
var/obj/item/stock_parts/cell/temp_cell = user.is_holding_item_of_type(/obj/item/stock_parts/cell)
var/swap_failed
if(!temp_cell) //if we're not holding a cell
swap_failed = TRUE
else if(!user.transferItemToLoc(temp_cell, chest))
swap_failed = TRUE
to_chat(user, "<span class='warning'>[temp_cell] is stuck to your hand, you can't put it in [src]!</span>")
if(chest.cell) //drop the chest's current cell no matter what.
put_in_hand_or_drop(user, chest.cell)
if(swap_failed) //we didn't transfer any new items.
if(chest.cell) //old cell ejected, nothing inserted.
to_chat(user, "<span class='notice'>You remove [chest.cell] from [src].</span>")
chest.cell = null
else
to_chat(user, "<span class='notice'>The power cell slot in [src]'s torso is empty.</span>")
return
to_chat(user, "<span class='notice'>You [chest.cell ? "replace [src]'s [chest.cell.name] with [temp_cell]" : "insert [temp_cell] into [src]"].</span>")
chest.cell = temp_cell
return TRUE
/obj/item/robot_suit/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = W
if(!l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
if (M.use(1))
var/obj/item/bot_assembly/ed209/B = new
B.forceMove(drop_location())
to_chat(user, "<span class='notice'>You arm the robot frame.</span>")
var/holding_this = user.get_inactive_held_item()==src
qdel(src)
if (holding_this)
user.put_in_inactive_hand(B)
else
to_chat(user, "<span class='warning'>You need one sheet of metal to start building ED-209!</span>")
return
else if(istype(W, /obj/item/bodypart/l_leg/robot))
if(src.l_leg)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.l_leg = W
src.updateicon()
else if(istype(W, /obj/item/bodypart/r_leg/robot))
if(src.r_leg)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.r_leg = W
src.updateicon()
else if(istype(W, /obj/item/bodypart/l_arm/robot))
if(src.l_arm)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.l_arm = W
src.updateicon()
else if(istype(W, /obj/item/bodypart/r_arm/robot))
if(src.r_arm)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)//in case it is a dismembered robotic limb
W.cut_overlays()
src.r_arm = W
src.updateicon()
else if(istype(W, /obj/item/bodypart/chest/robot))
var/obj/item/bodypart/chest/robot/CH = W
if(src.chest)
return
if(CH.wired && CH.cell)
if(!user.transferItemToLoc(CH, src))
return
CH.icon_state = initial(CH.icon_state) //in case it is a dismembered robotic limb
CH.cut_overlays()
src.chest = CH
src.updateicon()
else if(!CH.wired)
to_chat(user, "<span class='warning'>You need to attach wires to it first!</span>")
else
to_chat(user, "<span class='warning'>You need to attach a cell to it first!</span>")
else if(istype(W, /obj/item/bodypart/head/robot))
var/obj/item/bodypart/head/robot/HD = W
for(var/X in HD.contents)
if(istype(X, /obj/item/organ))
to_chat(user, "<span class='warning'>There are organs inside [HD]!</span>")
return
if(src.head)
return
if(HD.flash2 && HD.flash1)
if(!user.transferItemToLoc(HD, src))
return
HD.icon_state = initial(HD.icon_state)//in case it is a dismembered robotic limb
HD.cut_overlays()
src.head = HD
src.updateicon()
else
to_chat(user, "<span class='warning'>You need to attach a flash to it first!</span>")
else if (istype(W, /obj/item/multitool))
if(check_completion())
Interact(user)
else
to_chat(user, "<span class='warning'>The endoskeleton must be assembled before debugging can begin!</span>")
else if(istype(W, /obj/item/mmi))
var/obj/item/mmi/M = W
if(check_completion())
if(!chest.cell)
to_chat(user, "<span class='warning'>The endoskeleton still needs a power cell!</span>")
return
if(!isturf(loc))
to_chat(user, "<span class='warning'>You can't put [M] in, the frame has to be standing on the ground to be perfectly precise!</span>")
return
if(!M.brainmob)
to_chat(user, "<span class='warning'>Sticking an empty [M.name] into the frame would sort of defeat the purpose!</span>")
return
var/mob/living/brain/BM = M.brainmob
if(!BM.key || !BM.mind)
to_chat(user, "<span class='warning'>The MMI indicates that their mind is completely unresponsive; there's no point!</span>")
return
if(!BM.client) //braindead
to_chat(user, "<span class='warning'>The MMI indicates that their mind is currently inactive; it might change!</span>")
return
if(BM.stat == DEAD || (M.brain && M.brain.organ_flags & ORGAN_FAILING))
to_chat(user, "<span class='warning'>Sticking a dead brain into the frame would sort of defeat the purpose!</span>")
return
if(jobban_isbanned(BM, "Cyborg") || QDELETED(src) || QDELETED(BM) || QDELETED(user) || QDELETED(M) || !Adjacent(user))
if(!QDELETED(M))
to_chat(user, "<span class='warning'>This [M.name] does not seem to fit!</span>")
return
if(!user.temporarilyRemoveItemFromInventory(W))
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc))
if(!O)
return
if(M.laws && M.laws.id != DEFAULT_AI_LAWID)
aisync = 0
lawsync = 0
O.laws = M.laws
M.laws.associate(O)
O.invisibility = 0
//Transfer debug settings to new mob
O.custom_name = created_name
O.locked = panel_locked
if(!aisync)
lawsync = 0
O.set_connected_ai(null)
else
O.notify_ai(NEW_BORG)
if(forced_ai)
O.set_connected_ai(forced_ai)
if(!lawsync)
O.lawupdate = 0
if(M.laws.id == DEFAULT_AI_LAWID)
O.make_laws()
SSticker.mode.remove_antag_for_borging(BM.mind)
if(!istype(M.laws, /datum/ai_laws/ratvar))
remove_servant_of_ratvar(BM, TRUE)
BM.mind.transfer_to(O)
if(O.mind && O.mind.special_role)
O.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
to_chat(O, "<span class='userdanger'>You have been robotized!</span>")
to_chat(O, "<span class='danger'>You must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.</span>")
O.job = "Cyborg"
O.cell = chest.cell
chest.cell.forceMove(O)
chest.cell = null
W.forceMove(O)//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
if(O.mmi) //we delete the mmi created by robot/New()
qdel(O.mmi)
O.mmi = W //and give the real mmi to the borg.
O.updatename()
SSblackbox.record_feedback("amount", "cyborg_birth", 1)
forceMove(O)
O.robot_suit = src
if(!locomotion)
O.lockcharge = 1
O.update_canmove()
to_chat(O, "<span class='warning'>Error: Servo motors unresponsive.</span>")
else
to_chat(user, "<span class='warning'>The MMI must go in after everything else!</span>")
else if(istype(W, /obj/item/borg/upgrade/ai))
var/obj/item/borg/upgrade/ai/M = W
if(check_completion())
if(!isturf(loc))
to_chat(user, "<span class='warning'>You cannot install[M], the frame has to be standing on the ground to be perfectly precise!</span>")
return
if(!user.temporarilyRemoveItemFromInventory(M))
to_chat(user, "<span class='warning'>[M] is stuck to your hand!</span>")
return
qdel(M)
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot/shell(get_turf(src))
if(!aisync)
lawsync = FALSE
O.set_connected_ai(null)
else
if(forced_ai)
O.set_connected_ai(forced_ai)
O.notify_ai(AI_SHELL)
if(!lawsync)
O.lawupdate = FALSE
O.make_laws()
O.cell = chest.cell
chest.cell.forceMove(O)
chest.cell = null
O.locked = panel_locked
O.job = "Cyborg"
forceMove(O)
O.robot_suit = src
if(!locomotion)
O.lockcharge = TRUE
O.update_canmove()
else if(istype(W, /obj/item/pen))
to_chat(user, "<span class='warning'>You need to use a multitool to name [src]!</span>")
else
return ..()
/obj/item/robot_suit/proc/Interact(mob/user)
var/t1 = "Designation: <A href='?src=[REF(src)];Name=1'>[(created_name ? "[created_name]" : "Default Cyborg")]</a><br>\n"
t1 += "Master AI: <A href='?src=[REF(src)];Master=1'>[(forced_ai ? "[forced_ai.name]" : "Automatic")]</a><br><br>\n"
t1 += "LawSync Port: <A href='?src=[REF(src)];Law=1'>[(lawsync ? "Open" : "Closed")]</a><br>\n"
t1 += "AI Connection Port: <A href='?src=[REF(src)];AI=1'>[(aisync ? "Open" : "Closed")]</a><br>\n"
t1 += "Servo Motor Functions: <A href='?src=[REF(src)];Loco=1'>[(locomotion ? "Unlocked" : "Locked")]</a><br>\n"
t1 += "Panel Lock: <A href='?src=[REF(src)];Panel=1'>[(panel_locked ? "Engaged" : "Disengaged")]</a><br>\n"
var/datum/browser/popup = new(user, "robotdebug", "Cyborg Boot Debug", 310, 220)
popup.set_content(t1)
popup.open()
/obj/item/robot_suit/Topic(href, href_list)
if(usr.incapacitated() || !Adjacent(usr))
return
var/mob/living/living_user = usr
var/obj/item/item_in_hand = living_user.get_active_held_item()
if(!istype(item_in_hand, /obj/item/multitool))
to_chat(living_user, "<span class='warning'>You need a multitool!</span>")
return
if(href_list["Name"])
var/new_name = reject_bad_name(input(usr, "Enter new designation. Set to blank to reset to default.", "Cyborg Debug", src.created_name), TRUE)
if(!in_range(src, usr) && src.loc != usr)
return
if(new_name)
created_name = new_name
else
created_name = ""
else if(href_list["Master"])
forced_ai = select_active_ai(usr)
if(!forced_ai)
to_chat(usr, "<span class='error'>No active AIs detected.</span>")
else if(href_list["Law"])
lawsync = !lawsync
else if(href_list["AI"])
aisync = !aisync
else if(href_list["Loco"])
locomotion = !locomotion
else if(href_list["Panel"])
panel_locked = !panel_locked
add_fingerprint(usr)
Interact(usr)
//The robot bodyparts have been moved to code/module/surgery/bodyparts/robot_bodyparts.dm
/obj/item/robot_suit
name = "cyborg endoskeleton"
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
icon = 'icons/mob/augmentation/augments.dmi'
icon_state = "robo_suit"
var/obj/item/bodypart/l_arm/robot/l_arm = null
var/obj/item/bodypart/r_arm/robot/r_arm = null
var/obj/item/bodypart/l_leg/robot/l_leg = null
var/obj/item/bodypart/r_leg/robot/r_leg = null
var/obj/item/bodypart/chest/robot/chest = null
var/obj/item/bodypart/head/robot/head = null
var/created_name = ""
var/mob/living/silicon/ai/forced_ai
var/locomotion = 1
var/lawsync = 1
var/aisync = 1
var/panel_locked = TRUE
/obj/item/robot_suit/New()
..()
update_icon()
/obj/item/robot_suit/prebuilt/New()
l_arm = new(src)
r_arm = new(src)
l_leg = new(src)
r_leg = new(src)
head = new(src)
head.flash1 = new(head)
head.flash2 = new(head)
chest = new(src)
chest.wired = TRUE
chest.cell = new /obj/item/stock_parts/cell/high/plus(chest)
..()
/obj/item/robot_suit/update_icon()
cut_overlays()
if(l_arm)
add_overlay("[l_arm.icon_state]+o")
if(r_arm)
add_overlay("[r_arm.icon_state]+o")
if(chest)
add_overlay("[chest.icon_state]+o")
if(l_leg)
add_overlay("[l_leg.icon_state]+o")
if(r_leg)
add_overlay("[r_leg.icon_state]+o")
if(head)
add_overlay("[head.icon_state]+o")
/obj/item/robot_suit/proc/check_completion()
if(src.l_arm && src.r_arm)
if(src.l_leg && src.r_leg)
if(src.chest && src.head)
SSblackbox.record_feedback("amount", "cyborg_frames_built", 1)
return 1
return 0
/obj/item/robot_suit/wrench_act(mob/living/user, obj/item/I) //Deconstucts empty borg shell. Flashes remain unbroken because they haven't been used yet
var/turf/T = get_turf(src)
if(l_leg || r_leg || chest || l_arm || r_arm || head)
if(I.use_tool(src, user, 5, volume=50))
if(l_leg)
l_leg.forceMove(T)
l_leg = null
if(r_leg)
r_leg.forceMove(T)
r_leg = null
if(chest)
if (chest.cell) //Sanity check.
chest.cell.forceMove(T)
chest.cell = null
chest.forceMove(T)
new /obj/item/stack/cable_coil(T, 1)
chest.wired = FALSE
chest = null
if(l_arm)
l_arm.forceMove(T)
l_arm = null
if(r_arm)
r_arm.forceMove(T)
r_arm = null
if(head)
head.forceMove(T)
head.flash1.forceMove(T)
head.flash1 = null
head.flash2.forceMove(T)
head.flash2 = null
head = null
to_chat(user, "<span class='notice'>You disassemble the cyborg shell.</span>")
else
to_chat(user, "<span class='notice'>There is nothing to remove from the endoskeleton.</span>")
update_icon()
/obj/item/robot_suit/proc/put_in_hand_or_drop(mob/living/user, obj/item/I) //normal put_in_hands() drops the item ontop of the player, this drops it at the suit's loc
if(!user.put_in_hands(I))
I.forceMove(drop_location())
return FALSE
return TRUE
/obj/item/robot_suit/screwdriver_act(mob/living/user, obj/item/I) //Swaps the power cell if you're holding a new one in your other hand.
. = ..()
if(.)
return TRUE
if(!chest) //can't remove a cell if there's no chest to remove it from.
to_chat(user, "<span class='notice'>[src] has no attached torso.</span>")
return
var/obj/item/stock_parts/cell/temp_cell = user.is_holding_item_of_type(/obj/item/stock_parts/cell)
var/swap_failed
if(!temp_cell) //if we're not holding a cell
swap_failed = TRUE
else if(!user.transferItemToLoc(temp_cell, chest))
swap_failed = TRUE
to_chat(user, "<span class='warning'>[temp_cell] is stuck to your hand, you can't put it in [src]!</span>")
if(chest.cell) //drop the chest's current cell no matter what.
put_in_hand_or_drop(user, chest.cell)
if(swap_failed) //we didn't transfer any new items.
if(chest.cell) //old cell ejected, nothing inserted.
to_chat(user, "<span class='notice'>You remove [chest.cell] from [src].</span>")
chest.cell = null
else
to_chat(user, "<span class='notice'>The power cell slot in [src]'s torso is empty.</span>")
return
to_chat(user, "<span class='notice'>You [chest.cell ? "replace [src]'s [chest.cell.name] with [temp_cell]" : "insert [temp_cell] into [src]"].</span>")
chest.cell = temp_cell
return TRUE
/obj/item/robot_suit/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = W
if(!l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
if (M.use(1))
var/obj/item/bot_assembly/ed209/B = new
B.forceMove(drop_location())
to_chat(user, "<span class='notice'>You arm the robot frame.</span>")
var/holding_this = user.get_inactive_held_item()==src
qdel(src)
if (holding_this)
user.put_in_inactive_hand(B)
else
to_chat(user, "<span class='warning'>You need one sheet of metal to start building ED-209!</span>")
return
else if(istype(W, /obj/item/bodypart/l_leg/robot))
if(src.l_leg)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.l_leg = W
update_icon()
else if(istype(W, /obj/item/bodypart/r_leg/robot))
if(src.r_leg)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.r_leg = W
update_icon()
else if(istype(W, /obj/item/bodypart/l_arm/robot))
if(src.l_arm)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)
W.cut_overlays()
src.l_arm = W
update_icon()
else if(istype(W, /obj/item/bodypart/r_arm/robot))
if(src.r_arm)
return
if(!user.transferItemToLoc(W, src))
return
W.icon_state = initial(W.icon_state)//in case it is a dismembered robotic limb
W.cut_overlays()
src.r_arm = W
update_icon()
else if(istype(W, /obj/item/bodypart/chest/robot))
var/obj/item/bodypart/chest/robot/CH = W
if(src.chest)
return
if(CH.wired && CH.cell)
if(!user.transferItemToLoc(CH, src))
return
CH.icon_state = initial(CH.icon_state) //in case it is a dismembered robotic limb
CH.cut_overlays()
src.chest = CH
update_icon()
else if(!CH.wired)
to_chat(user, "<span class='warning'>You need to attach wires to it first!</span>")
else
to_chat(user, "<span class='warning'>You need to attach a cell to it first!</span>")
else if(istype(W, /obj/item/bodypart/head/robot))
var/obj/item/bodypart/head/robot/HD = W
for(var/X in HD.contents)
if(istype(X, /obj/item/organ))
to_chat(user, "<span class='warning'>There are organs inside [HD]!</span>")
return
if(src.head)
return
if(HD.flash2 && HD.flash1)
if(!user.transferItemToLoc(HD, src))
return
HD.icon_state = initial(HD.icon_state)//in case it is a dismembered robotic limb
HD.cut_overlays()
src.head = HD
update_icon()
else
to_chat(user, "<span class='warning'>You need to attach a flash to it first!</span>")
else if (istype(W, /obj/item/multitool))
if(check_completion())
Interact(user)
else
to_chat(user, "<span class='warning'>The endoskeleton must be assembled before debugging can begin!</span>")
else if(istype(W, /obj/item/mmi))
var/obj/item/mmi/M = W
if(check_completion())
if(!chest.cell)
to_chat(user, "<span class='warning'>The endoskeleton still needs a power cell!</span>")
return
if(!isturf(loc))
to_chat(user, "<span class='warning'>You can't put [M] in, the frame has to be standing on the ground to be perfectly precise!</span>")
return
if(!M.brainmob)
to_chat(user, "<span class='warning'>Sticking an empty [M.name] into the frame would sort of defeat the purpose!</span>")
return
var/mob/living/brain/BM = M.brainmob
if(!BM.key || !BM.mind)
to_chat(user, "<span class='warning'>The MMI indicates that their mind is completely unresponsive; there's no point!</span>")
return
if(!BM.client) //braindead
to_chat(user, "<span class='warning'>The MMI indicates that their mind is currently inactive; it might change!</span>")
return
if(BM.stat == DEAD || (M.brain && M.brain.organ_flags & ORGAN_FAILING))
to_chat(user, "<span class='warning'>Sticking a dead brain into the frame would sort of defeat the purpose!</span>")
return
if(jobban_isbanned(BM, "Cyborg") || QDELETED(src) || QDELETED(BM) || QDELETED(user) || QDELETED(M) || !Adjacent(user))
if(!QDELETED(M))
to_chat(user, "<span class='warning'>This [M.name] does not seem to fit!</span>")
return
if(!user.temporarilyRemoveItemFromInventory(W))
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc))
if(!O)
return
if(M.laws && M.laws.id != DEFAULT_AI_LAWID)
aisync = 0
lawsync = 0
O.laws = M.laws
M.laws.associate(O)
O.invisibility = 0
//Transfer debug settings to new mob
O.custom_name = created_name
O.locked = panel_locked
if(!aisync)
lawsync = 0
O.set_connected_ai(null)
else
O.notify_ai(NEW_BORG)
if(forced_ai)
O.set_connected_ai(forced_ai)
if(!lawsync)
O.lawupdate = 0
if(M.laws.id == DEFAULT_AI_LAWID)
O.make_laws()
SSticker.mode.remove_antag_for_borging(BM.mind)
if(!istype(M.laws, /datum/ai_laws/ratvar))
remove_servant_of_ratvar(BM, TRUE)
BM.mind.transfer_to(O)
if(O.mind && O.mind.special_role)
O.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
to_chat(O, "<span class='userdanger'>You have been robotized!</span>")
to_chat(O, "<span class='danger'>You must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.</span>")
O.job = "Cyborg"
O.cell = chest.cell
chest.cell.forceMove(O)
chest.cell = null
W.forceMove(O)//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
if(O.mmi) //we delete the mmi created by robot/New()
qdel(O.mmi)
O.mmi = W //and give the real mmi to the borg.
O.updatename()
SSblackbox.record_feedback("amount", "cyborg_birth", 1)
forceMove(O)
O.robot_suit = src
if(!locomotion)
O.lockcharge = 1
O.update_canmove()
to_chat(O, "<span class='warning'>Error: Servo motors unresponsive.</span>")
else
to_chat(user, "<span class='warning'>The MMI must go in after everything else!</span>")
else if(istype(W, /obj/item/borg/upgrade/ai))
var/obj/item/borg/upgrade/ai/M = W
if(check_completion())
if(!isturf(loc))
to_chat(user, "<span class='warning'>You cannot install[M], the frame has to be standing on the ground to be perfectly precise!</span>")
return
if(!user.temporarilyRemoveItemFromInventory(M))
to_chat(user, "<span class='warning'>[M] is stuck to your hand!</span>")
return
qdel(M)
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot/shell(get_turf(src))
if(!aisync)
lawsync = FALSE
O.set_connected_ai(null)
else
if(forced_ai)
O.set_connected_ai(forced_ai)
O.notify_ai(AI_SHELL)
if(!lawsync)
O.lawupdate = FALSE
O.make_laws()
O.cell = chest.cell
chest.cell.forceMove(O)
chest.cell = null
O.locked = panel_locked
O.job = "Cyborg"
forceMove(O)
O.robot_suit = src
if(!locomotion)
O.lockcharge = TRUE
O.update_canmove()
else if(istype(W, /obj/item/pen))
to_chat(user, "<span class='warning'>You need to use a multitool to name [src]!</span>")
else
return ..()
/obj/item/robot_suit/proc/Interact(mob/user)
var/t1 = "Designation: <A href='?src=[REF(src)];Name=1'>[(created_name ? "[created_name]" : "Default Cyborg")]</a><br>\n"
t1 += "Master AI: <A href='?src=[REF(src)];Master=1'>[(forced_ai ? "[forced_ai.name]" : "Automatic")]</a><br><br>\n"
t1 += "LawSync Port: <A href='?src=[REF(src)];Law=1'>[(lawsync ? "Open" : "Closed")]</a><br>\n"
t1 += "AI Connection Port: <A href='?src=[REF(src)];AI=1'>[(aisync ? "Open" : "Closed")]</a><br>\n"
t1 += "Servo Motor Functions: <A href='?src=[REF(src)];Loco=1'>[(locomotion ? "Unlocked" : "Locked")]</a><br>\n"
t1 += "Panel Lock: <A href='?src=[REF(src)];Panel=1'>[(panel_locked ? "Engaged" : "Disengaged")]</a><br>\n"
var/datum/browser/popup = new(user, "robotdebug", "Cyborg Boot Debug", 310, 220)
popup.set_content(t1)
popup.open()
/obj/item/robot_suit/Topic(href, href_list)
if(usr.incapacitated() || !Adjacent(usr))
return
var/mob/living/living_user = usr
var/obj/item/item_in_hand = living_user.get_active_held_item()
if(!istype(item_in_hand, /obj/item/multitool))
to_chat(living_user, "<span class='warning'>You need a multitool!</span>")
return
if(href_list["Name"])
var/new_name = reject_bad_name(input(usr, "Enter new designation. Set to blank to reset to default.", "Cyborg Debug", src.created_name), TRUE)
if(!in_range(src, usr) && src.loc != usr)
return
if(new_name)
created_name = new_name
else
created_name = ""
else if(href_list["Master"])
forced_ai = select_active_ai(usr)
if(!forced_ai)
to_chat(usr, "<span class='error'>No active AIs detected.</span>")
else if(href_list["Law"])
lawsync = !lawsync
else if(href_list["AI"])
aisync = !aisync
else if(href_list["Loco"])
locomotion = !locomotion
else if(href_list["Panel"])
panel_locked = !panel_locked
add_fingerprint(usr)
Interact(usr)