mirror of
https://github.com/KabKebab/GS13.git
synced 2026-07-10 15:36:56 +01:00
Merge pull request #1229 from ArchieBeepBoop/iconupdates
Ports: Icon state updates Part 1
This commit is contained in:
@@ -464,7 +464,7 @@
|
||||
status = rcd_status
|
||||
delay = rcd_delay
|
||||
if (status == RCD_DECONSTRUCT)
|
||||
addtimer(CALLBACK(src, .proc/update_icon), 11)
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 11)
|
||||
delay -= 11
|
||||
icon_state = "rcd_end_reverse"
|
||||
else
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
+252
-255
@@ -1,255 +1,252 @@
|
||||
|
||||
/obj
|
||||
var/crit_fail = FALSE
|
||||
animate_movement = 2
|
||||
speech_span = SPAN_ROBOT
|
||||
var/obj_flags = CAN_BE_HIT
|
||||
var/set_obj_flags // ONLY FOR MAPPING: Sets flags from a string list, handled in Initialize. Usage: set_obj_flags = "EMAGGED;!CAN_BE_HIT" to set EMAGGED and clear CAN_BE_HIT.
|
||||
|
||||
var/damtype = BRUTE
|
||||
var/force = 0
|
||||
|
||||
var/datum/armor/armor
|
||||
var/obj_integrity //defaults to max_integrity
|
||||
var/max_integrity = 500
|
||||
var/integrity_failure = 0 //0 if we have no special broken behavior
|
||||
|
||||
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
|
||||
|
||||
var/acid_level = 0 //how much acid is on that obj
|
||||
|
||||
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
|
||||
var/current_skin //the item reskin
|
||||
var/list/unique_reskin //List of options to reskin.
|
||||
var/always_reskinnable = FALSE
|
||||
|
||||
// Access levels, used in modules\jobs\access.dm
|
||||
var/list/req_access
|
||||
var/req_access_txt = "0"
|
||||
var/list/req_one_access
|
||||
var/req_one_access_txt = "0"
|
||||
|
||||
var/renamedByPlayer = FALSE //set when a player uses a pen on a renamable object
|
||||
|
||||
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of obj in openspace.
|
||||
|
||||
/obj/vv_edit_var(vname, vval)
|
||||
switch(vname)
|
||||
if("anchored")
|
||||
setAnchored(vval)
|
||||
return TRUE
|
||||
if("obj_flags")
|
||||
if ((obj_flags & DANGEROUS_POSSESSION) && !(vval & DANGEROUS_POSSESSION))
|
||||
return FALSE
|
||||
if("control_object")
|
||||
var/obj/O = vval
|
||||
if(istype(O) && (O.obj_flags & DANGEROUS_POSSESSION))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/Initialize()
|
||||
. = ..()
|
||||
if (islist(armor))
|
||||
armor = getArmor(arglist(armor))
|
||||
else if (!armor)
|
||||
armor = getArmor()
|
||||
else if (!istype(armor, /datum/armor))
|
||||
stack_trace("Invalid type [armor.type] found in .armor during /obj Initialize()")
|
||||
|
||||
if(obj_integrity == null)
|
||||
obj_integrity = max_integrity
|
||||
if (set_obj_flags)
|
||||
var/flagslist = splittext(set_obj_flags,";")
|
||||
var/list/string_to_objflag = GLOB.bitfields["obj_flags"]
|
||||
for (var/flag in flagslist)
|
||||
if(flag[1] == "!")
|
||||
flag = copytext(flag, length(flag[1]) + 1) // Get all but the initial !
|
||||
obj_flags &= ~string_to_objflag[flag]
|
||||
else
|
||||
obj_flags |= string_to_objflag[flag]
|
||||
if((obj_flags & ON_BLUEPRINTS) && isturf(loc))
|
||||
var/turf/T = loc
|
||||
T.add_blueprints_preround(src)
|
||||
|
||||
|
||||
/obj/Destroy(force=FALSE)
|
||||
if(!ismachinery(src))
|
||||
STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
|
||||
SStgui.close_uis(src)
|
||||
. = ..()
|
||||
|
||||
/obj/proc/setAnchored(anchorvalue)
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
|
||||
anchored = anchorvalue
|
||||
|
||||
/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
|
||||
. = ..()
|
||||
if(obj_flags & FROZEN)
|
||||
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/assume_air(datum/gas_mixture/giver)
|
||||
if(loc)
|
||||
return loc.assume_air(giver)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/remove_air(amount)
|
||||
if(loc)
|
||||
return loc.remove_air(amount)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/return_air()
|
||||
if(loc)
|
||||
return loc.return_air()
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request)
|
||||
//Return: (NONSTANDARD)
|
||||
// null if object handles breathing logic for lifeform
|
||||
// datum/air_group to tell lifeform to process using that breath return
|
||||
//DEFAULT: Take air from turf to give to have mob process
|
||||
|
||||
if(breath_request>0)
|
||||
var/datum/gas_mixture/environment = return_air()
|
||||
var/breath_percentage = BREATH_VOLUME / environment.return_volume()
|
||||
return remove_air(environment.total_moles() * breath_percentage)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/proc/updateUsrDialog()
|
||||
if((obj_flags & IN_USE) && !(obj_flags & USES_TGUI))
|
||||
var/is_in_use = FALSE
|
||||
var/list/nearby = viewers(1, src)
|
||||
for(var/mob/M in nearby)
|
||||
if ((M.client && M.machine == src))
|
||||
is_in_use = TRUE
|
||||
ui_interact(M)
|
||||
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr))
|
||||
if (!(usr in nearby))
|
||||
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
|
||||
is_in_use = TRUE
|
||||
ui_interact(usr)
|
||||
|
||||
// check for TK users
|
||||
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(!(usr in nearby))
|
||||
if(usr.client && usr.machine==src)
|
||||
if(H.dna.check_mutation(TK))
|
||||
is_in_use = TRUE
|
||||
ui_interact(usr)
|
||||
if (is_in_use)
|
||||
obj_flags |= IN_USE
|
||||
else
|
||||
obj_flags &= ~IN_USE
|
||||
|
||||
/obj/proc/updateDialog(update_viewers = TRUE,update_ais = TRUE)
|
||||
// Check that people are actually using the machine. If not, don't update anymore.
|
||||
if(obj_flags & IN_USE)
|
||||
var/is_in_use = FALSE
|
||||
if(update_viewers)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
is_in_use = TRUE
|
||||
src.interact(M)
|
||||
var/ai_in_use = FALSE
|
||||
if(update_ais)
|
||||
ai_in_use = AutoUpdateAI(src)
|
||||
|
||||
if(update_viewers && update_ais) //State change is sure only if we check both
|
||||
if(!ai_in_use && !is_in_use)
|
||||
obj_flags &= ~IN_USE
|
||||
|
||||
|
||||
/obj/attack_ghost(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/proc/container_resist(mob/living/user)
|
||||
return
|
||||
|
||||
/obj/proc/update_icon()
|
||||
return
|
||||
|
||||
/mob/proc/unset_machine()
|
||||
if(machine)
|
||||
machine.on_unset_machine(src)
|
||||
machine = null
|
||||
|
||||
//called when the user unsets the machine.
|
||||
/atom/movable/proc/on_unset_machine(mob/user)
|
||||
return
|
||||
|
||||
/mob/proc/set_machine(obj/O)
|
||||
if(src.machine)
|
||||
unset_machine()
|
||||
src.machine = O
|
||||
if(istype(O))
|
||||
O.obj_flags |= IN_USE
|
||||
|
||||
/obj/item/proc/updateSelfDialog()
|
||||
var/mob/M = src.loc
|
||||
if(istype(M) && M.client && M.machine == src)
|
||||
src.attack_self(M)
|
||||
|
||||
/obj/proc/hide(h)
|
||||
return
|
||||
|
||||
/obj/singularity_pull(S, current_size)
|
||||
..()
|
||||
if(!anchored || current_size >= STAGE_FIVE)
|
||||
step_towards(src,S)
|
||||
|
||||
/obj/get_dumping_location(datum/component/storage/source,mob/user)
|
||||
return get_turf(src)
|
||||
|
||||
/obj/proc/CanAStarPass()
|
||||
. = !density
|
||||
|
||||
/obj/proc/check_uplink_validity()
|
||||
return 1
|
||||
|
||||
/obj/proc/intercept_user_move(dir, mob, newLoc, oldLoc)
|
||||
return
|
||||
|
||||
/obj/vv_get_dropdown()
|
||||
. = ..()
|
||||
.["Delete all of type"] = "?_src_=vars;[HrefToken()];delall=[REF(src)]"
|
||||
.["Osay"] = "?_src_=vars;[HrefToken()];osay[REF(src)]"
|
||||
.["Modify armor values"] = "?_src_=vars;[HrefToken()];modarmor=[REF(src)]"
|
||||
|
||||
/obj/examine(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & UNIQUE_RENAME)
|
||||
. += "<span class='notice'>Use a pen on it to rename it or change its description.</span>"
|
||||
if(unique_reskin && (!current_skin || always_reskinnable))
|
||||
. += "<span class='notice'>Alt-click it to reskin it.</span>"
|
||||
|
||||
/obj/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(unique_reskin && (!current_skin || always_reskinnable) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
reskin_obj(user)
|
||||
return TRUE
|
||||
|
||||
/obj/proc/reskin_obj(mob/M)
|
||||
if(!LAZYLEN(unique_reskin))
|
||||
return
|
||||
var/dat = "<b>Reskin options for [name]:</b>\n"
|
||||
for(var/V in unique_reskin)
|
||||
var/output = icon2html(src, M, unique_reskin[V])
|
||||
dat += "[V]: <span class='reallybig'>[output]</span>\n"
|
||||
to_chat(M, dat)
|
||||
|
||||
var/choice = input(M, always_reskinnable ? "Choose the a reskin for [src]" : "Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin
|
||||
if(QDELETED(src) || !choice || (current_skin && !always_reskinnable) || M.incapacitated() || !in_range(M,src) || !unique_reskin[choice] || unique_reskin[choice] == current_skin)
|
||||
return
|
||||
current_skin = choice
|
||||
icon_state = unique_reskin[choice]
|
||||
to_chat(M, "[src] is now skinned as '[choice]'.")
|
||||
|
||||
/obj
|
||||
var/crit_fail = FALSE
|
||||
animate_movement = 2
|
||||
speech_span = SPAN_ROBOT
|
||||
var/obj_flags = CAN_BE_HIT
|
||||
var/set_obj_flags // ONLY FOR MAPPING: Sets flags from a string list, handled in Initialize. Usage: set_obj_flags = "EMAGGED;!CAN_BE_HIT" to set EMAGGED and clear CAN_BE_HIT.
|
||||
|
||||
var/damtype = BRUTE
|
||||
var/force = 0
|
||||
|
||||
var/datum/armor/armor
|
||||
var/obj_integrity //defaults to max_integrity
|
||||
var/max_integrity = 500
|
||||
var/integrity_failure = 0 //0 if we have no special broken behavior
|
||||
|
||||
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
|
||||
|
||||
var/acid_level = 0 //how much acid is on that obj
|
||||
|
||||
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
|
||||
var/current_skin //the item reskin
|
||||
var/list/unique_reskin //List of options to reskin.
|
||||
var/always_reskinnable = FALSE
|
||||
|
||||
// Access levels, used in modules\jobs\access.dm
|
||||
var/list/req_access
|
||||
var/req_access_txt = "0"
|
||||
var/list/req_one_access
|
||||
var/req_one_access_txt = "0"
|
||||
|
||||
var/renamedByPlayer = FALSE //set when a player uses a pen on a renamable object
|
||||
|
||||
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of obj in openspace.
|
||||
|
||||
/obj/vv_edit_var(vname, vval)
|
||||
switch(vname)
|
||||
if("anchored")
|
||||
setAnchored(vval)
|
||||
return TRUE
|
||||
if("obj_flags")
|
||||
if ((obj_flags & DANGEROUS_POSSESSION) && !(vval & DANGEROUS_POSSESSION))
|
||||
return FALSE
|
||||
if("control_object")
|
||||
var/obj/O = vval
|
||||
if(istype(O) && (O.obj_flags & DANGEROUS_POSSESSION))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/Initialize()
|
||||
. = ..()
|
||||
if (islist(armor))
|
||||
armor = getArmor(arglist(armor))
|
||||
else if (!armor)
|
||||
armor = getArmor()
|
||||
else if (!istype(armor, /datum/armor))
|
||||
stack_trace("Invalid type [armor.type] found in .armor during /obj Initialize()")
|
||||
|
||||
if(obj_integrity == null)
|
||||
obj_integrity = max_integrity
|
||||
if (set_obj_flags)
|
||||
var/flagslist = splittext(set_obj_flags,";")
|
||||
var/list/string_to_objflag = GLOB.bitfields["obj_flags"]
|
||||
for (var/flag in flagslist)
|
||||
if(flag[1] == "!")
|
||||
flag = copytext(flag, length(flag[1]) + 1) // Get all but the initial !
|
||||
obj_flags &= ~string_to_objflag[flag]
|
||||
else
|
||||
obj_flags |= string_to_objflag[flag]
|
||||
if((obj_flags & ON_BLUEPRINTS) && isturf(loc))
|
||||
var/turf/T = loc
|
||||
T.add_blueprints_preround(src)
|
||||
|
||||
|
||||
/obj/Destroy(force=FALSE)
|
||||
if(!ismachinery(src))
|
||||
STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
|
||||
SStgui.close_uis(src)
|
||||
. = ..()
|
||||
|
||||
/obj/proc/setAnchored(anchorvalue)
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
|
||||
anchored = anchorvalue
|
||||
|
||||
/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
|
||||
. = ..()
|
||||
if(obj_flags & FROZEN)
|
||||
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/assume_air(datum/gas_mixture/giver)
|
||||
if(loc)
|
||||
return loc.assume_air(giver)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/remove_air(amount)
|
||||
if(loc)
|
||||
return loc.remove_air(amount)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/return_air()
|
||||
if(loc)
|
||||
return loc.return_air()
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request)
|
||||
//Return: (NONSTANDARD)
|
||||
// null if object handles breathing logic for lifeform
|
||||
// datum/air_group to tell lifeform to process using that breath return
|
||||
//DEFAULT: Take air from turf to give to have mob process
|
||||
|
||||
if(breath_request>0)
|
||||
var/datum/gas_mixture/environment = return_air()
|
||||
var/breath_percentage = BREATH_VOLUME / environment.return_volume()
|
||||
return remove_air(environment.total_moles() * breath_percentage)
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/proc/updateUsrDialog()
|
||||
if((obj_flags & IN_USE) && !(obj_flags & USES_TGUI))
|
||||
var/is_in_use = FALSE
|
||||
var/list/nearby = viewers(1, src)
|
||||
for(var/mob/M in nearby)
|
||||
if ((M.client && M.machine == src))
|
||||
is_in_use = TRUE
|
||||
ui_interact(M)
|
||||
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr))
|
||||
if (!(usr in nearby))
|
||||
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
|
||||
is_in_use = TRUE
|
||||
ui_interact(usr)
|
||||
|
||||
// check for TK users
|
||||
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(!(usr in nearby))
|
||||
if(usr.client && usr.machine==src)
|
||||
if(H.dna.check_mutation(TK))
|
||||
is_in_use = TRUE
|
||||
ui_interact(usr)
|
||||
if (is_in_use)
|
||||
obj_flags |= IN_USE
|
||||
else
|
||||
obj_flags &= ~IN_USE
|
||||
|
||||
/obj/proc/updateDialog(update_viewers = TRUE,update_ais = TRUE)
|
||||
// Check that people are actually using the machine. If not, don't update anymore.
|
||||
if(obj_flags & IN_USE)
|
||||
var/is_in_use = FALSE
|
||||
if(update_viewers)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
is_in_use = TRUE
|
||||
src.interact(M)
|
||||
var/ai_in_use = FALSE
|
||||
if(update_ais)
|
||||
ai_in_use = AutoUpdateAI(src)
|
||||
|
||||
if(update_viewers && update_ais) //State change is sure only if we check both
|
||||
if(!ai_in_use && !is_in_use)
|
||||
obj_flags &= ~IN_USE
|
||||
|
||||
|
||||
/obj/attack_ghost(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/proc/container_resist(mob/living/user)
|
||||
return
|
||||
|
||||
/mob/proc/unset_machine()
|
||||
if(machine)
|
||||
machine.on_unset_machine(src)
|
||||
machine = null
|
||||
|
||||
//called when the user unsets the machine.
|
||||
/atom/movable/proc/on_unset_machine(mob/user)
|
||||
return
|
||||
|
||||
/mob/proc/set_machine(obj/O)
|
||||
if(src.machine)
|
||||
unset_machine()
|
||||
src.machine = O
|
||||
if(istype(O))
|
||||
O.obj_flags |= IN_USE
|
||||
|
||||
/obj/item/proc/updateSelfDialog()
|
||||
var/mob/M = src.loc
|
||||
if(istype(M) && M.client && M.machine == src)
|
||||
src.attack_self(M)
|
||||
|
||||
/obj/proc/hide(h)
|
||||
return
|
||||
|
||||
/obj/singularity_pull(S, current_size)
|
||||
..()
|
||||
if(!anchored || current_size >= STAGE_FIVE)
|
||||
step_towards(src,S)
|
||||
|
||||
/obj/get_dumping_location(datum/component/storage/source,mob/user)
|
||||
return get_turf(src)
|
||||
|
||||
/obj/proc/CanAStarPass()
|
||||
. = !density
|
||||
|
||||
/obj/proc/check_uplink_validity()
|
||||
return 1
|
||||
|
||||
/obj/proc/intercept_user_move(dir, mob, newLoc, oldLoc)
|
||||
return
|
||||
|
||||
/obj/vv_get_dropdown()
|
||||
. = ..()
|
||||
.["Delete all of type"] = "?_src_=vars;[HrefToken()];delall=[REF(src)]"
|
||||
.["Osay"] = "?_src_=vars;[HrefToken()];osay[REF(src)]"
|
||||
.["Modify armor values"] = "?_src_=vars;[HrefToken()];modarmor=[REF(src)]"
|
||||
|
||||
/obj/examine(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & UNIQUE_RENAME)
|
||||
. += "<span class='notice'>Use a pen on it to rename it or change its description.</span>"
|
||||
if(unique_reskin && (!current_skin || always_reskinnable))
|
||||
. += "<span class='notice'>Alt-click it to reskin it.</span>"
|
||||
|
||||
/obj/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(unique_reskin && (!current_skin || always_reskinnable) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
reskin_obj(user)
|
||||
return TRUE
|
||||
|
||||
/obj/proc/reskin_obj(mob/M)
|
||||
if(!LAZYLEN(unique_reskin))
|
||||
return
|
||||
var/dat = "<b>Reskin options for [name]:</b>\n"
|
||||
for(var/V in unique_reskin)
|
||||
var/output = icon2html(src, M, unique_reskin[V])
|
||||
dat += "[V]: <span class='reallybig'>[output]</span>\n"
|
||||
to_chat(M, dat)
|
||||
|
||||
var/choice = input(M, always_reskinnable ? "Choose the a reskin for [src]" : "Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin
|
||||
if(QDELETED(src) || !choice || (current_skin && !always_reskinnable) || M.incapacitated() || !in_range(M,src) || !unique_reskin[choice] || unique_reskin[choice] == current_skin)
|
||||
return
|
||||
current_skin = choice
|
||||
icon_state = unique_reskin[choice]
|
||||
to_chat(M, "[src] is now skinned as '[choice]'.")
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
last_process = world.time
|
||||
to_chat(user, "<span class='notice'>The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards.</span>")
|
||||
user.reagents.add_reagent(/datum/reagent/medicine/omnizine/godblood,20)
|
||||
update_icons()
|
||||
addtimer(CALLBACK(src, .proc/update_icons), time_between_uses)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), time_between_uses)
|
||||
|
||||
|
||||
/obj/structure/healingfountain/proc/update_icons()
|
||||
/obj/structure/healingfountain/update_icon()
|
||||
if(last_process + time_between_uses > world.time)
|
||||
icon_state = "fountain"
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user