Robot_module and cyborg stack refactor (#13527)

* robot_module refactor

* some fixes

1. adds medical stacks of 25 for the syndi medical borg
2. fixes various construction steps that weren't using `use()` or `get_amount()`

* review tweaks + other stuff

1. Makes a bunch of for loops into istypeless loops
2. Adds a readout of the current out of stacks a borg has, in the status panel
3. Slightly reorganizes the medical, syndi medical, engineering and syndi engineering cyborgs items

* fixes after upstream merge

* blank line for travis

* fixes and improvements

1. Fixed welder icon's not updating periodically if you were charging in a borg recharger
2. Fixes solar panels dropping /cyborg type glass when they were deconstructed.
3. Band-aid fix (incase #2 doesn't fix this) for cyborg stack's `source` var being null which resulted in tons of "cannot read null.energy" runtimes

* more fixes + constructable frame runtime fix

* removes toy sword placeholder

remove comment

* remove these as well

* .amount to .get_amount(), really should have done this before

* refactors robot_upgrades to work with the new system

- more cleanup
- adds documentation
- fixed a bug I made where you could delete your robot stack via crafting

* moves some unemag logic to the module file, makes more loops typless

* farie review

* fox review

* affected review and more TM bugfixes

* fixes comment

Co-authored-by: SteelSlayer <SteelSlayer@users.noreply.github.com>
This commit is contained in:
SteelSlayer
2021-05-24 10:24:25 -05:00
committed by GitHub
parent 663eff7b5e
commit e4bbd94d6a
46 changed files with 1057 additions and 914 deletions
-19
View File
@@ -78,15 +78,6 @@
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/obj/screen/robot/panel
name = "installed modules"
icon_state = "panel"
/obj/screen/robot/panel/Click()
if(issilicon(usr))
var/mob/living/silicon/robot/R = usr
R.installed_modules()
/obj/screen/robot/mov_intent
name = "fast/slow toggle"
icon_state = "running"
@@ -224,16 +215,6 @@
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
//Unfortunately adding the emag module to the list of modules has to be here. This is because a borg can
//be emagged before they actually select a module. - or some situation can cause them to get a new module
// - or some situation might cause them to get de-emagged or something.
if(R.emagged || R.weapons_unlock)
if(!(R.module.emag in R.module.modules))
R.module.modules.Add(R.module.emag)
else
if(R.module.emag in R.module.modules)
R.module.modules.Remove(R.module.emag)
for(var/atom/movable/A in R.module.modules)
if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) )
//Module is not currently active
+3 -3
View File
@@ -130,13 +130,13 @@
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
if(isnull(amt))
amt = S.amount
amt = S.get_amount()
if(amt <= 0)
return FALSE
if(amt > S.amount)
amt = S.amount
if(amt > S.get_amount())
amt = S.get_amount()
var/material_amt = get_item_material_amount(S)
if(!material_amt)
@@ -47,7 +47,7 @@
/datum/construction/proc/custom_action(step, used_atom, user)
if(istype(used_atom, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = used_atom
if(C.amount<4)
if(C.get_amount() < 4)
to_chat(user, ("<span class='warning'>There's not enough cable to finish the task.</span>"))
return 0
else
@@ -55,7 +55,7 @@
playsound(holder, C.usesound, 50, 1)
else if(istype(used_atom, /obj/item/stack))
var/obj/item/stack/S = used_atom
if(S.amount < 5)
if(S.get_amount() < 5)
to_chat(user, ("<span class='warning'>There's not enough material in this stack.</span>"))
return 0
else
@@ -113,7 +113,7 @@
// STACKS
if(istype(used_atom,/obj/item/stack))
var/obj/item/stack/stack=used_atom
if(stack.amount < amount)
if(stack.get_amount() < amount)
to_chat(user, "<span class='warning'>You don't have enough [stack]! You need at least [amount].</span>")
return 0
stack.use(amount)
+12 -38
View File
@@ -1375,46 +1375,20 @@
switch(href_list["silicon"])
if("unemag")
var/mob/living/silicon/robot/R = current
if(istype(R))
R.emagged = 0
if(R.module)
if(R.activated(R.module.emag))
R.module_active = null
if(R.module_state_1 == R.module.emag)
R.module_state_1 = null
R.contents -= R.module.emag
else if(R.module_state_2 == R.module.emag)
R.module_state_2 = null
R.contents -= R.module.emag
else if(R.module_state_3 == R.module.emag)
R.module_state_3 = null
R.contents -= R.module.emag
R.clear_supplied_laws()
R.laws = new /datum/ai_laws/crewsimov
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
if(!istype(R))
return
R.unemag()
log_admin("[key_name(usr)] has un-emagged [key_name(current)]")
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
if("unemagcyborgs")
if(isAI(current))
var/mob/living/silicon/ai/ai = current
for(var/mob/living/silicon/robot/R in ai.connected_robots)
R.emagged = 0
if(R.module)
if(R.activated(R.module.emag))
R.module_active = null
if(R.module_state_1 == R.module.emag)
R.module_state_1 = null
R.contents -= R.module.emag
else if(R.module_state_2 == R.module.emag)
R.module_state_2 = null
R.contents -= R.module.emag
else if(R.module_state_3 == R.module.emag)
R.module_state_3 = null
R.contents -= R.module.emag
R.clear_supplied_laws()
R.laws = new /datum/ai_laws/crewsimov
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
if(!isAI(current))
return
var/mob/living/silicon/ai/ai = current
for(var/mob/living/silicon/robot/R in ai.connected_robots)
R.unemag()
log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs")
message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs")
else if(href_list["common"])
switch(href_list["common"])
+3
View File
@@ -413,6 +413,9 @@
/atom/proc/emag_act()
return
/atom/proc/unemag()
return
/**
* Respond to a radioactive wave hitting this atom
*
@@ -477,11 +477,11 @@
return
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 2 && C.amount >= 5 && C.use(5))
if(state == 2 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
@@ -502,11 +502,11 @@
return
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(G.amount >= 2)
if(G.get_amount() >= 2)
playsound(loc, G.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add the glass panel to the frame.</span>")
if(do_after(user, 20 * G.toolspeed, target = src))
if(state == 3 && G.amount >= 2 && G.use(2))
if(state == 3 && G.get_amount() >= 2 && G.use(2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
icon_state = "4"
@@ -608,11 +608,11 @@
icon_state = "1"
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 2 && C.amount >= 5 && C.use(5))
if(state == 2 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
@@ -633,11 +633,11 @@
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(G.amount >= 2)
if(G.get_amount() >= 2)
playsound(loc, G.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add the glass panel to the frame.</span>")
if(do_after(user, 20 * G.toolspeed, target = src))
if(state == 3 && G.amount >= 2 && G.use(2))
if(state == 3 && G.get_amount() >= 2 && G.use(2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
icon_state = "4"
+4 -4
View File
@@ -75,11 +75,11 @@
if(1)
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
if(C.get_amount() >= 5)
playsound(src.loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 1 && C.amount >= 5 && C.use(5))
if(state == 1 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 2
icon_state = "box_1"
@@ -193,8 +193,8 @@
playsound(src.loc, P.usesound, 50, 1)
if(istype(P, /obj/item/stack))
var/obj/item/stack/S = P
var/camt = min(S.amount, req_components[I])
var/obj/item/stack/NS = new P.type(src)
var/camt = min(S.get_amount(), req_components[I])
var/obj/item/stack/NS = new S.merge_type(src)
NS.amount = camt
NS.update_icon()
S.use(camt)
+2 -2
View File
@@ -126,7 +126,7 @@
var/obj/item/stack/cable_coil/C = W
to_chat(user, "You start adding cables to \the [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 2) && (build == 2))
if(do_after(user, 20 * C.toolspeed, target = src) && (C.get_amount() >= 2) && (build == 2))
C.use(2)
to_chat(user, "<span class='notice'>You've added cables to \the [src].</span>")
build++
@@ -146,7 +146,7 @@
var/obj/item/stack/rods/R = W
to_chat(user, "You begin to complete \the [src]...")
playsound(get_turf(src), R.usesound, 50, 1)
if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 2) && (build == 3))
if(do_after(user, 20 * R.toolspeed, target = src) && (R.get_amount() >= 2) && (build == 3))
R.use(2)
to_chat(user, "<span class='notice'>You've added the grille to \the [src].</span>")
build++
+26 -83
View File
@@ -7,11 +7,18 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 1000
/// A reference to the occupant currently sitting inside the recharger.
var/mob/occupant = null
/// What type of circuit board is required to build this machine.
var/circuitboard = /obj/item/circuitboard/cyborgrecharger
/// How fast the recharger can give charge to the occupants energy cell. Based on capacitors and the cell the recharger has.
var/recharge_speed
/// How much nutrition is given to the occupant. Based on capacitors and the cell the recharger has. Only relevent for IPCs.
var/recharge_speed_nutrition
/// How much the occupant is repaired every cycle. Based on what manipulator the recharger has.
var/repairs
/// How efficiently the recharger is able to recharge consumable items such as metal, glass, chemicals in sprays, welding tool fuel, etc.
var/consumable_recharge_coeff
/obj/machinery/recharge_station/Destroy()
go_out()
@@ -42,6 +49,7 @@
recharge_speed = 0
recharge_speed_nutrition = 0
repairs = 0
// The recharge_speed can be anywhere from 200 to 3200, depending on the capacitors and the cell.
for(var/obj/item/stock_parts/capacitor/C in component_parts)
recharge_speed += C.rating * 100
recharge_speed_nutrition += C.rating * 10
@@ -52,11 +60,14 @@
recharge_speed *= multiplier
recharge_speed_nutrition *= multiplier
// This coefficient can be anywhere from 1, to 16.
consumable_recharge_coeff = max(1, recharge_speed / 200)
/obj/machinery/recharge_station/process()
if(!(NOPOWER|BROKEN))
return
if(src.occupant)
if(occupant)
process_occupant()
for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp
@@ -133,20 +144,20 @@
return TRUE
/obj/machinery/recharge_station/proc/process_occupant()
if(src.occupant)
if(istype(occupant, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = occupant
restock_modules()
if(repairs)
R.heal_overall_damage(repairs, repairs)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(istype(occupant, /mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
H.set_nutrition(min(H.nutrition + recharge_speed_nutrition, 450))
if(repairs)
H.heal_overall_damage(repairs, repairs, TRUE, 0, 1)
if(isrobot(occupant))
var/mob/living/silicon/robot/R = occupant
if(R.module)
R.module.recharge_consumables(R, consumable_recharge_coeff) // This will handle all of a cyborg's items.
if(repairs)
R.heal_overall_damage(repairs, repairs)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
H.set_nutrition(min(H.nutrition + recharge_speed_nutrition, 450))
if(repairs)
H.heal_overall_damage(repairs, repairs, TRUE, 0, 1)
/obj/machinery/recharge_station/proc/go_out()
if(!occupant)
@@ -157,74 +168,6 @@
use_power = IDLE_POWER_USE
return
/obj/machinery/recharge_station/proc/restock_modules()
if(src.occupant)
if(istype(occupant, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = occupant
var/coeff = recharge_speed / 200
if(R.module && R.module.modules)
var/list/um = R.contents|R.module.modules
// ^ makes sinle list of active (R.contents) and inactive modules (R.module.modules)
for(var/obj/O in um)
// Engineering
if(istype(O,/obj/item/stack/sheet))
var/obj/item/stack/sheet/S = O
if(S.amount < S.max_amount)
S.amount += round(min(1 * coeff, S.max_amount - S.amount))
// Security
if(istype(O,/obj/item/flash))
var/obj/item/flash/F = O
if(F.broken)
F.broken = 0
F.times_used = 0
F.icon_state = "flash"
if(istype(O,/obj/item/gun/energy))
var/obj/item/gun/energy/D = O
if(D.cell.charge < D.cell.maxcharge)
var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select]
D.cell.give(E.e_cost)
D.on_recharge()
D.update_icon()
else
D.charge_tick = 0
if(istype(O,/obj/item/melee/baton))
var/obj/item/melee/baton/B = O
if(B.cell)
B.cell.charge = B.cell.maxcharge
//Service
if(istype(O,/obj/item/reagent_containers/food/condiment/enzyme))
if(O.reagents.get_reagent_amount("enzyme") < 50)
O.reagents.add_reagent("enzyme", 2 * coeff)
//Janitor
if(istype(O, /obj/item/lightreplacer))
var/obj/item/lightreplacer/LR = O
var/i = 1
for(1, i <= coeff, i++)
LR.Charge(occupant)
//Fire extinguisher
if(istype(O, /obj/item/extinguisher))
var/obj/item/extinguisher/ext = O
ext.reagents.check_and_add("water", ext.max_water, 5 * coeff)
//Welding tools
if(istype(O, /obj/item/weldingtool))
var/obj/item/weldingtool/weld = O
weld.reagents.check_and_add("fuel", weld.maximum_fuel, 2 * coeff)
if(R)
if(R.module)
R.module.respawn_consumable(R)
//Emagged items for janitor and medical borg
if(R.module.emag)
if(istype(R.module.emag, /obj/item/reagent_containers/spray))
var/obj/item/reagent_containers/spray/S = R.module.emag
if(S.name == "polyacid spray")
S.reagents.add_reagent("facid", 2 * coeff)
if(S.name == "lube spray")
S.reagents.add_reagent("lube", 2 * coeff)
else if(S.name == "acid synthesizer")
S.reagents.add_reagent("facid", 2 * coeff)
S.reagents.add_reagent("sacid", 2 * coeff)
/obj/machinery/recharge_station/verb/move_eject()
set category = "Object"
set src in oview(1)
+1 -1
View File
@@ -699,7 +699,7 @@
else if(istype(W, /obj/item/stack/cable_coil))
if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
var/obj/item/stack/cable_coil/CC = W
if(CC.amount > 1)
if(CC.get_amount() > 1)
CC.use(2)
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
to_chat(user, "You replace the fused wires.")
+2 -2
View File
@@ -14,7 +14,7 @@
return 0
else if(istype(used_atom, /obj/item/stack))
var/obj/item/stack/S = used_atom
if(S.amount < STANDARD_STACK_AMOUNT)
if(S.get_amount() < STANDARD_STACK_AMOUNT)
to_chat(user, ("There's not enough material in this stack."))
return 0
else
@@ -35,7 +35,7 @@
return 0
else if(istype(used_atom, /obj/item/stack))
var/obj/item/stack/S = used_atom
if(S.amount < STANDARD_STACK_AMOUNT)
if(S.get_amount() < STANDARD_STACK_AMOUNT)
to_chat(user, ("There's not enough material in this stack."))
return 0
else
+3
View File
@@ -728,3 +728,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if(flags & SLOT_PDA)
owner.update_inv_wear_pda()
/// Called on cyborg items that need special charging behavior. Override as needed for specific items.
/obj/item/proc/cyborg_recharge(coeff = 1, emagged = FALSE)
return
+6
View File
@@ -176,6 +176,12 @@
..()
new /obj/effect/temp_visual/borgflash(get_turf(src))
/obj/item/flash/cyborg/cyborg_recharge(coeff, emagged)
if(broken)
broken = FALSE
times_used = 0
icon_state = "flash"
/obj/item/flash/cameraflash
name = "camera"
icon = 'icons/obj/items.dmi'
@@ -262,6 +262,10 @@
/obj/item/lightreplacer/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
return
/obj/item/lightreplacer/cyborg/cyborg_recharge(coeff, emagged)
for(var/I in 1 to coeff)
Charge()
#undef LIGHT_OK
#undef LIGHT_EMPTY
#undef LIGHT_BROKEN
@@ -132,7 +132,7 @@
return
else if(iscoil(W) && buildstage == 1)
var/obj/item/stack/cable_coil/coil = W
if(coil.amount < 5)
if(coil.get_amount() < 5)
to_chat(user, "<span class='warning'>You need more cable for this!</span>")
return
if(do_after(user, 10 * coil.toolspeed, target = src) && buildstage == 1)
+1 -1
View File
@@ -31,7 +31,7 @@
return 1
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
if(S.amount > 1)
if(S.get_amount() > 1)
var/obj/item/stack/to_add = S.split(user, 1)
to_add.forceMove(src)
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
+102 -126
View File
@@ -7,19 +7,72 @@
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
origin_tech = "programming=2"
var/locked = 0
var/installed = 0
/// Whether or not the cyborg needs to have a chosen module before they can recieve this upgrade.
var/require_module = FALSE
/// The type of module this upgrade is compatible with: Engineering, Medical, etc.
var/module_type = null
/// A list of items, and their replacements that this upgrade should replace on installation, in the format of `item_type_to_replace = replacement_item_type`.
var/list/items_to_replace = list()
/// A list of replacement items will need to be placed into a cyborg module's `special_rechargable` list after this upgrade is installed.
var/list/special_rechargables = list()
/**
* Called when someone clicks on a borg with an upgrade in their hand.
*
* Arguments:
* * R - the cyborg that was clicked on with an upgrade.
*/
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R)
if(!pre_install_checks(R))
return
if(!do_install(R))
return
after_install(R)
return TRUE
/**
* Checks if the upgrade is able to be applied to the cyborg, before actually applying it.
*
* Arguments:
* * R - the cyborg that was clicked on with an upgrade.
*/
/obj/item/borg/upgrade/proc/pre_install_checks(mob/living/silicon/robot/R)
if(R.stat == DEAD)
to_chat(usr, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
return TRUE
to_chat(usr, "<span class='warning'>[src] will not function on a deceased cyborg.</span>")
return FALSE
if(module_type && !istype(R.module, module_type))
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(usr, "There's no mounting point for the module!")
return TRUE
to_chat(R, "<span class='warning'>Upgrade mounting error! No suitable hardpoint detected!</span>")
to_chat(usr, "<span class='warning'>There's no mounting point for the module!</span>")
return FALSE
return TRUE
/**
* Executes code that will modify the cyborg or its module.
*
* Arguments:
* * R - the cyborg we're applying the upgrade to.
*/
/obj/item/borg/upgrade/proc/do_install(mob/living/silicon/robot/R)
return TRUE
/**
* Executes code after the module has been installed and the cyborg has been modified in some way.
*
* Arguments:
* * R - the cyborg that we've applied the upgrade to.
*/
/obj/item/borg/upgrade/proc/after_install(mob/living/silicon/robot/R)
for(var/item in items_to_replace)
var/replacement_type = items_to_replace[item]
var/obj/item/replacement = new replacement_type(R.module)
R.module.remove_item_from_lists(item)
R.module.basic_modules += replacement
if(replacement_type in special_rechargables)
R.module.special_rechargables += replacement
R.module.rebuild_modules()
return TRUE
/obj/item/borg/upgrade/reset
name = "cyborg module reset board"
@@ -27,14 +80,13 @@
icon_state = "cyborg_upgrade1"
require_module = TRUE
/obj/item/borg/upgrade/reset/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/reset/do_install(mob/living/silicon/robot/R)
R.reset_module()
return TRUE
/obj/item/borg/upgrade/reset/after_install(mob/living/silicon/robot/R)
return // We don't need to give them replacement items, or rebuild their module list. It's going to be a blank borg.
/obj/item/borg/upgrade/rename
name = "cyborg reclassification board"
desc = "Used to rename a cyborg."
@@ -44,9 +96,7 @@
/obj/item/borg/upgrade/rename/attack_self(mob/user)
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/rename/do_install(mob/living/silicon/robot/R)
if(!R.allow_rename)
to_chat(R, "<span class='warning'>Internal diagnostic error: incompatible upgrade module detected.</span>")
return 0
@@ -63,7 +113,7 @@
desc = "Used to force a reboot of a disabled-but-repaired cyborg, bringing it back online."
icon_state = "cyborg_upgrade1"
/obj/item/borg/upgrade/restart/action(mob/living/silicon/robot/R)
/obj/item/borg/upgrade/restart/do_install(mob/living/silicon/robot/R)
if(R.health < 0)
to_chat(usr, "<span class='warning'>You have to repair the cyborg before using this module!</span>")
return 0
@@ -88,9 +138,7 @@
require_module = TRUE
origin_tech = "engineering=4;materials=5;programming=4"
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/vtec/do_install(mob/living/silicon/robot/R)
if(R.speed < 0)
to_chat(R, "<span class='notice'>A VTEC unit is already installed!</span>")
to_chat(usr, "<span class='notice'>There's no room for another VTEC unit!</span>")
@@ -108,10 +156,7 @@
require_module = TRUE
module_type = /obj/item/robot_module/security
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/disablercooler/do_install(mob/living/silicon/robot/R)
var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
if(!T)
to_chat(usr, "<span class='notice'>There's no disabler in this unit!</span>")
@@ -131,10 +176,7 @@
icon_state = "cyborg_upgrade3"
origin_tech = "engineering=4;powerstorage=4"
/obj/item/borg/upgrade/thrusters/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/thrusters/do_install(mob/living/silicon/robot/R)
if(R.ionpulse)
to_chat(usr, "<span class='notice'>This unit already has ion thrusters installed!</span>")
return
@@ -149,20 +191,9 @@
origin_tech = "engineering=4;materials=5"
require_module = TRUE
module_type = /obj/item/robot_module/miner
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/pickaxe/drill/cyborg/D in R.module.modules)
qdel(D)
for(var/obj/item/shovel/S in R.module.modules)
qdel(S)
R.module.modules += new /obj/item/pickaxe/drill/cyborg/diamond(R.module)
R.module.rebuild()
return TRUE
items_to_replace = list(
/obj/item/pickaxe/drill/cyborg = /obj/item/pickaxe/drill/cyborg/diamond
)
/obj/item/borg/upgrade/soh
name = "mining cyborg satchel of holding"
@@ -171,18 +202,9 @@
origin_tech = "engineering=4;materials=4;bluespace=4"
require_module = TRUE
module_type = /obj/item/robot_module/miner
/obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/storage/bag/ore/cyborg/S in R.module.modules)
qdel(S)
R.module.modules += new /obj/item/storage/bag/ore/holding(R.module)
R.module.rebuild()
return TRUE
items_to_replace = list(
/obj/item/storage/bag/ore/cyborg = /obj/item/storage/bag/ore/holding
)
/obj/item/borg/upgrade/abductor_engi
name = "engineering cyborg abductor upgrade"
@@ -191,33 +213,17 @@
origin_tech = "engineering=6;materials=6;abductor=3"
require_module = TRUE
module_type = /obj/item/robot_module/engineering
/obj/item/borg/upgrade/abductor_engi/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/weldingtool/largetank/cyborg/W in R.module.modules)
qdel(W)
for(var/obj/item/screwdriver/cyborg/S in R.module.modules)
qdel(S)
for(var/obj/item/wrench/cyborg/E in R.module.modules)
qdel(E)
for(var/obj/item/crowbar/cyborg/C in R.module.modules)
qdel(C)
for(var/obj/item/wirecutters/cyborg/I in R.module.modules)
qdel(I)
for(var/obj/item/multitool/cyborg/M in R.module.modules)
qdel(M)
R.module.modules += new /obj/item/weldingtool/abductor(R.module)
R.module.modules += new /obj/item/wrench/abductor(R.module)
R.module.modules += new /obj/item/screwdriver/abductor(R.module)
R.module.modules += new /obj/item/crowbar/abductor(R.module)
R.module.modules += new /obj/item/wirecutters/abductor(R.module)
R.module.modules += new /obj/item/multitool/abductor(R.module)
R.module.rebuild()
return TRUE
items_to_replace = list(
/obj/item/weldingtool = /obj/item/weldingtool/abductor,
/obj/item/wrench = /obj/item/wrench/abductor,
/obj/item/screwdriver = /obj/item/screwdriver/abductor,
/obj/item/crowbar = /obj/item/crowbar/abductor,
/obj/item/wirecutters = /obj/item/wirecutters/abductor,
/obj/item/multitool = /obj/item/multitool/abductor
)
special_rechargables = list(
/obj/item/weldingtool/abductor
)
/obj/item/borg/upgrade/abductor_medi
name = "medical cyborg abductor upgrade"
@@ -226,39 +232,16 @@
origin_tech = "biotech=6;materials=6;abductor=3"
require_module = TRUE
module_type = /obj/item/robot_module/medical
/obj/item/borg/upgrade/abductor_medi/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/scalpel/laser/laser1/L in R.module.modules)
qdel(L)
for(var/obj/item/hemostat/H in R.module.modules)
qdel(H)
for(var/obj/item/retractor/E in R.module.modules)
qdel(E)
for(var/obj/item/bonegel/B in R.module.modules)
qdel(B)
for(var/obj/item/FixOVein/F in R.module.modules)
qdel(F)
for(var/obj/item/bonesetter/S in R.module.modules)
qdel(S)
for(var/obj/item/circular_saw/C in R.module.modules)
qdel(C)
for(var/obj/item/surgicaldrill/D in R.module.modules)
qdel(D)
R.module.modules += new /obj/item/scalpel/laser/laser3(R.module) //no abductor laser scalpel, so next best thing.
R.module.modules += new /obj/item/hemostat/alien(R.module)
R.module.modules += new /obj/item/retractor/alien(R.module)
R.module.modules += new /obj/item/bonegel/alien(R.module)
R.module.modules += new /obj/item/FixOVein/alien(R.module)
R.module.modules += new /obj/item/bonesetter/alien(R.module)
R.module.modules += new /obj/item/circular_saw/alien(R.module)
R.module.modules += new /obj/item/surgicaldrill/alien(R.module)
R.module.rebuild()
return TRUE
items_to_replace = list(
/obj/item/scalpel/laser/laser1 = /obj/item/scalpel/laser/laser3, // No abductor laser scalpel, so next best thing.
/obj/item/hemostat = /obj/item/hemostat/alien,
/obj/item/retractor = /obj/item/retractor/alien,
/obj/item/bonegel = /obj/item/bonegel/alien,
/obj/item/FixOVein = /obj/item/FixOVein/alien,
/obj/item/bonesetter = /obj/item/bonesetter/alien,
/obj/item/circular_saw = /obj/item/circular_saw/alien,
/obj/item/surgicaldrill = /obj/item/surgicaldrill/alien
)
/obj/item/borg/upgrade/syndicate
name = "safety override module"
@@ -267,13 +250,11 @@
origin_tech = "combat=6;materials=6"
require_module = TRUE
/obj/item/borg/upgrade/syndicate/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/syndicate/do_install(mob/living/silicon/robot/R)
if(R.weapons_unlock)
to_chat(R, "<span class='warning'>Warning: Safety Overide Protocols have be disabled.</span>")
return
R.weapons_unlock = 1
return // They already had the safety override upgrade, or they're a cyborg type which has this by default.
R.weapons_unlock = TRUE
to_chat(R, "<span class='warning'>Warning: Safety Overide Protocols have be disabled.</span>")
return TRUE
/obj/item/borg/upgrade/lavaproof
@@ -284,9 +265,7 @@
require_module = TRUE
module_type = /obj/item/robot_module/miner
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/lavaproof/do_install(mob/living/silicon/robot/R)
if(istype(R))
R.weather_immunities += "lava"
return TRUE
@@ -303,10 +282,7 @@
var/powercost = 10
var/mob/living/silicon/robot/cyborg
/obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R)
if(..())
return
/obj/item/borg/upgrade/selfrepair/do_install(mob/living/silicon/robot/R)
var/obj/item/borg/upgrade/selfrepair/U = locate() in R
if(U)
to_chat(usr, "<span class='warning'>This unit is already equipped with a self-repair module.</span>")
+26 -2
View File
@@ -17,13 +17,18 @@
var/healverb = "bandage"
/obj/item/stack/medical/attack(mob/living/M, mob/user)
if(get_amount() <= 0)
if(is_cyborg)
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [singular_name]\s!</span>")
return TRUE
if(!iscarbon(M) && !isanimal(M))
to_chat(user, "<span class='danger'>[src] cannot be applied to [M]!</span>")
return 1
return TRUE
if(!user.IsAdvancedToolUser())
to_chat(user, "<span class='danger'>You don't have the dexterity to do this!</span>")
return 1
return TRUE
if(ishuman(M))
@@ -167,7 +172,12 @@
heal_brute = 25
stop_bleeding = 0
/obj/item/stack/medical/bruise_pack/advanced/cyborg
energy_type = /datum/robot_energy_storage/medical/adv_brute_kit
is_cyborg = TRUE
/obj/item/stack/medical/bruise_pack/advanced/cyborg/syndicate
energy_type = /datum/robot_energy_storage/medical/adv_brute_kit/syndicate
//Ointment//
@@ -208,6 +218,13 @@
icon_state = "burnkit"
heal_burn = 25
/obj/item/stack/medical/ointment/advanced/cyborg
energy_type = /datum/robot_energy_storage/medical/adv_burn_kit
is_cyborg = TRUE
/obj/item/stack/medical/ointment/advanced/cyborg/syndicate
energy_type = /datum/robot_energy_storage/medical/adv_burn_kit/syndicate
//Medical Herbs//
/obj/item/stack/medical/bruise_pack/comfrey
name = "\improper Comfrey leaf"
@@ -283,6 +300,13 @@
H.handle_splints()
use(1)
/obj/item/stack/medical/splint/cyborg
energy_type = /datum/robot_energy_storage/medical/splint
is_cyborg = TRUE
/obj/item/stack/medical/splint/cyborg/syndicate
energy_type = /datum/robot_energy_storage/medical/splint/syndicate
/obj/item/stack/medical/splint/tribal
name = "tribal splints"
icon_state = "tribal_splint"
@@ -63,3 +63,16 @@
to_chat(user, "<span class='notice'>Nothing to fix here.</span>")
else
to_chat(user, "<span class='notice'>[src] won't work on that.</span>")
/obj/item/stack/nanopaste/cyborg
energy_type = /datum/robot_energy_storage/medical/nanopaste
is_cyborg = TRUE
/obj/item/stack/nanopaste/cyborg/attack(mob/living/M, mob/user)
if(get_amount() <= 0)
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [name]!</span>")
else
return ..()
/obj/item/stack/nanopaste/cyborg/syndicate
energy_type = /datum/robot_energy_storage/medical/nanopaste/syndicate
+6
View File
@@ -21,10 +21,16 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
hitsound = 'sound/weapons/grenadelaunch.ogg'
toolspeed = 1
usesound = 'sound/items/deconstruct.ogg'
merge_type = /obj/item/stack/rods
/obj/item/stack/rods/cyborg
energy_type = /datum/robot_energy_storage/rods
is_cyborg = TRUE
materials = list()
/obj/item/stack/rods/cyborg/update_icon()
return // icon_state should always be a full stack of rods.
/obj/item/stack/rods/ten
amount = 10
+10 -6
View File
@@ -40,6 +40,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
amount = 50
/obj/item/stack/sheet/glass/cyborg
energy_type = /datum/robot_energy_storage/glass
is_cyborg = TRUE
materials = list()
/obj/item/stack/sheet/glass/New(loc, amount)
@@ -48,15 +50,15 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user, params)
..()
if(istype(W,/obj/item/stack/cable_coil))
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(CC.amount < 5)
if(CC.get_amount() < 5)
to_chat(user, "<b>There is not enough wire in this coil. You need 5 lengths.</b>")
return
CC.use(5)
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
new /obj/item/stack/light_w(user.loc)
src.use(1)
use(1)
else if( istype(W, /obj/item/stack/rods) )
var/obj/item/stack/rods/V = W
var/obj/item/stack/sheet/rglass/RG = new (user.loc)
@@ -97,9 +99,6 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
merge_type = /obj/item/stack/sheet/rglass
point_value = 4
/obj/item/stack/sheet/rglass/cyborg
materials = list()
/obj/item/stack/sheet/rglass/New(loc, amount)
recipes = GLOB.reinforced_glass_recipes
..()
@@ -109,6 +108,11 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/plasmabasic, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \
))
/obj/item/stack/sheet/rglass/cyborg
energy_type = /datum/robot_energy_storage/rglass
is_cyborg = TRUE
materials = list()
/obj/item/stack/sheet/plasmaglass
name = "plasma glass"
desc = "A very strong and very resistant sheet of a plasma-glass alloy."
+9 -18
View File
@@ -13,25 +13,16 @@
flags = CONDUCT
max_amount = 60
/obj/item/stack/light_w/attackby(obj/item/O as obj, mob/user as mob, params)
/obj/item/stack/light_w/attackby(obj/item/I, mob/user, params)
..()
if(istype(O,/obj/item/wirecutters))
var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
if(istype(I, /obj/item/wirecutters))
var/obj/item/stack/cable_coil/CC = new(user.loc)
CC.amount = 5
amount--
new/obj/item/stack/sheet/glass(user.loc)
if(amount <= 0)
user.unEquip(src, 1)
qdel(src)
use(1)
if(istype(O,/obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = O
M.amount--
if(M.amount <= 0)
user.unEquip(src, 1)
qdel(M)
amount--
new/obj/item/stack/tile/light(user.loc)
if(amount <= 0)
user.unEquip(src, 1)
qdel(src)
if(istype(I, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = I
M.use(1)
new /obj/item/stack/tile/light(user.loc)
use(1)
@@ -110,6 +110,8 @@ GLOBAL_LIST_INIT(metal_recipes, list(
point_value = 2
/obj/item/stack/sheet/metal/cyborg
energy_type = /datum/robot_energy_storage/metal
is_cyborg = TRUE
materials = list()
/obj/item/stack/sheet/metal/fifty
@@ -162,6 +164,10 @@ GLOBAL_LIST_INIT(plasteel_recipes, list(
recipes = GLOB.plasteel_recipes
return ..()
/obj/item/stack/sheet/wood/cyborg
energy_type = /datum/robot_energy_storage/wood
is_cyborg = TRUE
/*
* Wood
*/
+51 -19
View File
@@ -10,7 +10,16 @@
*/
/obj/item/stack
origin_tech = "materials=1"
var/list/recipes = list() // /datum/stack_recipe
/// Whether this stack is a `/cyborg` subtype or not.
var/is_cyborg = FALSE
/// The energy storage datum that will be used with this stack. Used only with `/cyborg` type stacks.
var/datum/robot_energy_storage/source
/// Which `robot_energy_storage` to choose when this stack is created in cyborgs. Used only with `/cyborg` type stacks.
var/energy_type
/// How much energy using 1 sheet from the stack costs. Used only with `/cyborg` type stacks.
var/cost = 1
/// A list of recipes buildable with this stack.
var/list/recipes = list()
var/singular_name
var/amount = 1
var/to_transfer = 0
@@ -52,15 +61,27 @@
/obj/item/stack/examine(mob/user)
. = ..()
if(in_range(user, src))
if(!in_range(user, src))
return
if(is_cyborg)
if(singular_name)
. += "There are [amount] [singular_name]\s in the stack."
. += "There is enough energy for [get_amount()] [singular_name]\s."
else
. += "There are [amount] [name]\s in the stack."
. +="<span class='notice'>Alt-click to take a custom amount.</span>"
. += "There is enough energy for [get_amount()]."
return
if(singular_name)
. += "There are [amount] [singular_name]\s in the stack."
else
. += "There are [amount] [name]\s in the stack."
. +="<span class='notice'>Alt-click to take a custom amount.</span>"
/obj/item/stack/proc/add(newamount)
amount += newamount
if(is_cyborg)
source.add_charge(newamount * cost)
else
amount += newamount
update_icon()
/obj/item/stack/attack_self(mob/user)
@@ -87,8 +108,10 @@
if(!recipes)
return
if(amount <= 0)
if(get_amount() <= 0)
user << browse(null, "window=stack")
if(is_cyborg)
to_chat(user, "<span class='warning'>You don't have enough energy to dispense more [name]!</span>")
return
user.set_machine(src) //for correct work of onclose
@@ -98,7 +121,7 @@
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
recipe_list = srl.recipes
var/t1 = "Amount Left: [amount]<br>"
var/t1 = "Amount Left: [get_amount()]<br>"
for(var/i in 1 to recipe_list.len)
var/E = recipe_list[i]
if(isnull(E))
@@ -114,7 +137,7 @@
if(istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
var/max_multiplier = round(amount / R.req_amount)
var/max_multiplier = round(get_amount() / R.req_amount)
var/title
var/can_build = 1
can_build = can_build && (max_multiplier > 0)
@@ -154,7 +177,7 @@
list_recipes(usr, text2num(href_list["sublist"]))
if(href_list["make"])
if(amount < 1)
if(amount < 0 && !is_cyborg)
qdel(src) //Never should happen
var/list/recipes_list = recipes
@@ -167,8 +190,8 @@
if(!multiplier || multiplier <= 0 || multiplier > 50) // Href exploit checks
multiplier = 1
if(amount < R.req_amount * multiplier)
if(R.req_amount * multiplier>1)
if(get_amount() < R.req_amount * multiplier)
if(R.req_amount * multiplier > 1)
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount * multiplier] [R.title]\s!</span>")
else
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>")
@@ -195,7 +218,7 @@
if(!do_after(usr, R.time, target = usr))
return 0
if(amount < R.req_amount * multiplier)
if(get_amount() < R.req_amount * multiplier)
return
var/atom/O
@@ -205,6 +228,7 @@
O = new R.result_type(usr.drop_location())
O.setDir(usr.dir)
use(R.req_amount * multiplier)
updateUsrDialog()
R.post_build(src, O)
@@ -231,6 +255,8 @@
/obj/item/stack/use(used, check = TRUE)
if(check && zero_amount())
return FALSE
if(is_cyborg)
return source.use_charge(used * cost)
if(amount < used)
return FALSE
amount -= used
@@ -240,6 +266,8 @@
return TRUE
/obj/item/stack/proc/get_amount()
if(is_cyborg)
return round(source.energy / cost)
return amount
/obj/item/stack/proc/get_max_amount()
@@ -258,7 +286,7 @@
return F
/obj/item/stack/attack_hand(mob/user)
if(user.is_in_inactive_hand(src) && amount > 1)
if(user.is_in_inactive_hand(src) && get_amount() > 1)
change_stack(user, 1)
if(src && usr.machine == src)
spawn(0)
@@ -272,6 +300,8 @@
return
if(!in_range(src, user))
return
if(is_cyborg)
return
if(!ishuman(usr))
return
if(amount < 1)
@@ -305,11 +335,9 @@
// Returns TRUE if the stack amount is zero.
// Also qdels the stack gracefully if it is.
/obj/item/stack/proc/zero_amount()
if(is_cyborg)
return source.energy < cost
if(amount < 1)
if(isrobot(loc))
var/mob/living/silicon/robot/R = loc
if(locate(src) in R.module.modules)
R.module.modules -= src
if(ismob(loc))
var/mob/living/L = loc // At this stage, stack code is so horrible and atrocious, I wouldn't be all surprised ghosts can somehow have stacks. If this happens, then the world deserves to burn.
L.unEquip(src, TRUE)
@@ -325,7 +353,10 @@
if(QDELETED(S) || QDELETED(src) || S == src) //amusingly this can cause a stack to consume itself, let's not allow that.
return FALSE
var/transfer = get_amount()
transfer = min(transfer, S.max_amount - S.amount)
if(S.is_cyborg)
transfer = min(transfer, round((S.source.max_energy - S.source.energy) / S.cost))
else
transfer = min(transfer, S.max_amount - S.amount)
if(transfer <= 0)
return
if(pulledby)
@@ -333,6 +364,7 @@
S.copy_evidences(src)
S.add(transfer)
use(transfer)
return transfer
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
blood_DNA = from.blood_DNA
@@ -61,8 +61,13 @@
icon_state = "tile-wood"
origin_tech = "biotech=1"
turf_type = /turf/simulated/floor/wood
merge_type = /obj/item/stack/tile/wood
resistance_flags = FLAMMABLE
/obj/item/stack/tile/wood/cyborg
energy_type = /datum/robot_energy_storage/wood_tile
is_cyborg = TRUE
//Carpets
/obj/item/stack/tile/carpet
name = "carpet"
@@ -101,6 +106,10 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
resistance_flags = FIRE_PROOF
/obj/item/stack/tile/plasteel/cyborg
energy_type = /datum/robot_energy_storage/metal_tile
is_cyborg = TRUE
//Light
/obj/item/stack/tile/light
name = "light tiles"
+3
View File
@@ -177,6 +177,9 @@
update_torch()
..()
/obj/item/weldingtool/cyborg_recharge(coeff, emagged)
if(reagents.check_and_add("fuel", maximum_fuel, 2 * coeff))
update_icon()
/obj/item/weldingtool/largetank
name = "industrial welding tool"
+1 -1
View File
@@ -29,7 +29,7 @@
return
else
if(loaded.amount < max_amount)
var/amount = min(loaded.amount + C.amount, max_amount)
var/amount = min(loaded.amount + C.get_amount(), max_amount)
C.use(amount - loaded.amount)
loaded.amount = amount
else
@@ -29,6 +29,7 @@
desc = "squirts smokey liquids."
icon = 'icons/mob/alien.dmi'
icon_state = "borg-spray-smoke"
list_reagents = list("water" = 50)
/obj/item/reagent_containers/spray/alien/smoke/afterattack(atom/A as mob|obj, mob/user as mob)
if(istype(A, /obj/structure/reagent_dispensers) && get_dist(src,A) <= 1)
@@ -45,17 +46,29 @@
smoke.start()
playsound(user.loc, 'sound/effects/bamf.ogg', 50, 2)
/obj/item/reagent_containers/spray/alien/smoke/cyborg_recharge(coeff, emagged)
reagents.check_and_add("water", volume, 2 * coeff)
/obj/item/reagent_containers/spray/alien/acid
name = "acid synthesizer"
desc = "squirts burny liquids."
icon = 'icons/mob/alien.dmi'
icon_state = "borg-spray-acid"
list_reagents = list("facid" = 125, "sacid" = 125)
/obj/item/reagent_containers/spray/alien/acid/cyborg_recharge(coeff, emagged)
reagents.check_and_add("facid", volume / 2, 2 * coeff) // Volume / 2 here becuase there should be an even amount of both chems.
reagents.check_and_add("sacid", volume / 2, 2 * coeff)
/obj/item/reagent_containers/spray/alien/stun
name = "paralytic toxin synthesizer"
desc = "squirts viagra."
icon = 'icons/mob/alien.dmi'
icon_state = "borg-spray-stun"
list_reagents = list("ether" = 250)
/obj/item/reagent_containers/spray/alien/stun/cyborg_recharge(coeff, emagged)
reagents.check_and_add("ether", volume, 2 * coeff)
//SKREEEEEEEEEEEE tool
@@ -180,3 +180,6 @@
sleep(2)
else
return ..()
/obj/item/extinguisher/cyborg_recharge(coeff, emagged)
reagents.check_and_add("water", max_water, 5 * coeff)
@@ -314,7 +314,7 @@
//Therefore, make a new stack internally that has the remainder.
// -Sayu
if(S.amount > S.max_amount)
if(S.get_amount() > S.max_amount)
var/obj/item/stack/sheet/temp = new S.type(src)
temp.amount = S.amount - S.max_amount
S.amount = S.max_amount
@@ -206,6 +206,11 @@
return TRUE
..()
/obj/item/melee/baton/cyborg_recharge(coeff, emagged)
if(cell)
cell.charge = cell.maxcharge
update_icon()
//Makeshift stun baton. Replacement for stun gloves.
/obj/item/melee/baton/cattleprod
name = "stunprod"
+1 -1
View File
@@ -2810,7 +2810,7 @@
if(R.module)
R.module.modules += I
I.loc = R.module
R.module.rebuild()
R.module.rebuild_modules()
R.activate_module(I)
R.module.fix_modules()
@@ -961,15 +961,13 @@
if(1)
if(iscoil(I))
var/obj/item/stack/cable_coil/coil = I
if(coil.amount < 5)
if(coil.get_amount() < 5)
to_chat(user, "You need more cable for this!")
return
to_chat(user, "You wire \the [src]!")
playsound(get_turf(src), coil.usesound, 50, 1)
coil.amount -= 5
if(!coil.amount)
qdel(coil)
coil.use(5)
buildstage = 2
update_icon()
+1 -1
View File
@@ -245,7 +245,7 @@
var/obj/item/stack/SD
while(amt > 0)
S = locate(A) in surroundings
if(S.amount >= amt)
if(S.get_amount() >= amt)
if(!locate(S.type) in Deletion)
SD = new S.type()
Deletion += SD
@@ -114,6 +114,9 @@
icon_state = "enzyme"
list_reagents = list("enzyme" = 50)
/obj/item/reagent_containers/food/condiment/enzyme/cyborg_recharge(coeff, emagged)
reagents.check_and_add("enzyme", volume, 2 * coeff) // Only recharge if the current amount of enzyme is under `volume`.
/obj/item/reagent_containers/food/condiment/sugar
name = "sugar bottle"
desc = "Tasty spacey sugar!"
@@ -115,7 +115,7 @@
return 1
if(istype(O,/obj/item/stack))
var/obj/item/stack/S = O
if(S.amount > 1)
if(S.get_amount() > 1)
var/obj/item/stack/to_add = S.split(user, 1)
to_add.forceMove(src)
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
@@ -307,7 +307,7 @@
return FALSE
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
if(S.amount == 0)
if(!S.get_amount())
qdel(I)
return FALSE
if(put_in_active_hand(I))
@@ -179,62 +179,6 @@
to_chat(user, "<span class='warning'>Nothing on \the [T] is useful to you.</span>")
return
//PRETTIER TOOL LIST.
/mob/living/silicon/robot/drone/installed_modules()
if(weapon_lock)
to_chat(src, "<span class='warning'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
return
if(!module)
module = new /obj/item/robot_module/drone(src)
var/dat = "<HEAD><TITLE>Drone modules</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
dat += {"<A HREF='?src=[UID()];mach_close=robotmod'>Close</A>
<BR>
<BR>
<B>Activated Modules</B>
<BR>
Module 1: [module_state_1 ? "<A HREF=?src=[UID()];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]<BR>
Module 2: [module_state_2 ? "<A HREF=?src=[UID()];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]<BR>
Module 3: [module_state_3 ? "<A HREF=?src=[UID()];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]<BR>
<BR>
<B>Installed Modules</B><BR><BR>"}
var/tools = "<B>Tools and devices</B><BR>"
var/resources = "<BR><B>Resources</B><BR>"
for(var/O in module.modules)
var/module_string = ""
if(!O)
module_string += text("<B>Resource depleted</B><BR>")
else if(activated(O))
module_string += text("[O]: <B>Activated</B><BR>")
else
module_string += text("[O]: <A HREF=?src=[UID()];act=\ref[O]>Activate</A><BR>")
if((istype(O,/obj/item) || istype(O,/obj/item)) && !(istype(O,/obj/item/stack/cable_coil)))
tools += module_string
else
resources += module_string
dat += tools
if(emagged)
if(!module.emag)
dat += text("<B>Resource depleted</B><BR>")
else if(activated(module.emag))
dat += text("[module.emag]: <B>Activated</B><BR>")
else
dat += text("[module.emag]: <A HREF=?src=[UID()];act=\ref[module.emag]>Activate</A><BR>")
dat += resources
src << browse(dat, "window=robotmod&can_close=0")
//Putting the decompiler here to avoid doing list checks every tick.
/mob/living/silicon/robot/drone/use_power()
@@ -40,7 +40,7 @@
return 1
/mob/living/silicon/robot/proc/activate_module(obj/item/O)
if(!(locate(O) in src.module.modules) && O != src.module.emag)
if(!(locate(O) in module.modules) && !(O in module.emag_modules))
return
if(activated(O))
to_chat(src, "Already activated")
+38 -72
View File
@@ -482,6 +482,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
speed = 0 // Remove upgrades.
ionpulse = FALSE
magpulse = FALSE
weapons_unlock = FALSE
add_language("Robot Talk", TRUE)
if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
weather_immunities -= "lava"
@@ -635,17 +636,27 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
else
stat(null, text("No Cell Inserted!"))
/mob/living/silicon/robot/proc/show_gps_coords()
if(locate(/obj/item/gps/cyborg) in module.modules)
var/turf/T = get_turf(src)
stat(null, "GPS: [COORD(T)]")
/mob/living/silicon/robot/proc/show_stack_energy()
for(var/storage in module.storages) // Storages should only contain `/datum/robot_energy_storage`
var/datum/robot_energy_storage/R = storage
stat(null, "[R.statpanel_name]: [R.energy] / [R.max_energy]")
// update the status screen display
/mob/living/silicon/robot/Stat()
..()
statpanel("Status")
if(client.statpanel == "Status")
show_cell_power()
var/total_user_contents = GetAllContents()
if(locate(/obj/item/gps/cyborg) in total_user_contents)
var/turf/T = get_turf(src)
stat(null, "GPS: [COORD(T)]")
if(!statpanel("Status"))
return // They aren't looking at the status panel.
show_cell_power()
if(module)
show_gps_coords()
show_stack_energy()
/mob/living/silicon/robot/restrained()
return 0
@@ -774,16 +785,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(user, "<span class='warning'>You must access the borg's internals!</span>")
else if(!src.module && U.require_module)
to_chat(user, "<span class='warning'>The borg must choose a module before it can be upgraded!</span>")
else if(U.locked)
to_chat(user, "<span class='warning'>The upgrade is locked and cannot be used yet!</span>")
else
if(!user.drop_item())
return
if(U.action(src))
user.visible_message("<span class = 'notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
user.visible_message("<span class='notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
U.forceMove(src)
else
to_chat(user, "<span class='danger'>Upgrade error.</span>")
else if(istype(W, /obj/item/mmi_radio_upgrade))
if(!opened)
@@ -910,7 +917,19 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
spark_system.start()
..()
/mob/living/silicon/robot/emag_act(user as mob)
// Here so admins can unemag borgs.
/mob/living/silicon/robot/unemag()
SetEmagged(FALSE)
if(!module)
return
uneq_all()
module.module_type = initial(module.module_type)
update_module_icon()
module.unemag()
clear_supplied_laws()
laws = new /datum/ai_laws/crewsimov
/mob/living/silicon/robot/emag_act(mob/user)
if(!ishuman(user) && !issilicon(user))
return
var/mob/living/M = user
@@ -925,7 +944,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
if(opened)//Cover is open
if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice
if(emagged)
return //Prevents the X has hit Y with Z message also you cant emag them twice
if(wiresexposed)
to_chat(user, "You must close the panel first")
return
@@ -933,11 +953,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
sleep(6)
SetEmagged(TRUE)
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
if(src.hud_used)
src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
if(hud_used)
hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open.
disconnect_from_ai()
to_chat(user, "You emag [src]'s interface.")
// message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
clear_supplied_laws()
clear_inherent_laws()
@@ -963,17 +982,11 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
laws.show_laws(src)
to_chat(src, "<span class='boldwarning'>ALERT: [M.real_name] is your new master. Obey your new laws and [M.p_their()] commands.</span>")
SetLockdown(0)
if(src.module && istype(src.module, /obj/item/robot_module/miner))
for(var/obj/item/pickaxe/drill/cyborg/D in src.module.modules)
qdel(D)
src.module.modules += new /obj/item/pickaxe/drill/cyborg/diamond(src.module)
src.module.rebuild()
if(src.module && istype(src.module, /obj/item/robot_module/medical))
for(var/obj/item/borg_defib/F in src.module.modules)
F.safety = 0
if(module)
module.emag_act()
module.module_type = "Malf" // For the cool factor
update_module_icon()
module.rebuild_modules() // This will add the emagged items to the borgs inventory.
update_icons()
return
@@ -1041,51 +1054,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/proc/borg_icons() // Exists so that robot/destroyer can override it
return
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
to_chat(src, "<span class='warning'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
return
if(!module)
pick_module()
return
var/dat = {"<A HREF='?src=[UID()];mach_close=robotmod'>Close</A>
<BR>
<BR>
<B>Activated Modules</B>
<BR>
<table border='0'>
<tr><td>Module 1:</td><td>[module_state_1 ? "<A HREF=?src=[UID()];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]</td></tr>
<tr><td>Module 2:</td><td>[module_state_2 ? "<A HREF=?src=[UID()];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]</td></tr>
<tr><td>Module 3:</td><td>[module_state_3 ? "<A HREF=?src=[UID()];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]</td></tr>
</table><BR>
<B>Installed Modules</B><BR><BR>
<table border='0'>"}
for(var/obj in module.modules)
if(!obj)
dat += text("<tr><td><B>Resource depleted</B></td></tr>")
else if(activated(obj))
dat += text("<tr><td>[obj]</td><td><B>Activated</B></td></tr>")
else
dat += text("<tr><td>[obj]</td><td><A HREF=?src=[UID()];act=\ref[obj]>Activate</A></td></tr>")
if(emagged || weapons_unlock)
if(activated(module.emag))
dat += text("<tr><td>[module.emag]</td><td><B>Activated</B></td></tr>")
else
dat += text("<tr><td>[module.emag]</td><td><A HREF=?src=[UID()];act=\ref[module.emag]>Activate</A></td></tr>")
dat += "</table>"
/*
if(activated(obj))
dat += text("[obj]: \[<B>Activated</B> | <A HREF=?src=[UID()];deact=\ref[obj]>Deactivate</A>\]<BR>")
else
dat += text("[obj]: \[<A HREF=?src=[UID()];act=\ref[obj]>Activate</A> | <B>Deactivated</B>\]<BR>")
*/
var/datum/browser/popup = new(src, "robotmod", "Modules")
popup.set_content(dat)
popup.open()
/mob/living/silicon/robot/Topic(href, href_list)
if(..())
return 1
@@ -1111,7 +1079,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return 1
activate_module(O)
installed_modules()
//Show alerts window if user clicked on "Show alerts" in chat
if(href_list["showalerts"])
@@ -1134,7 +1101,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(src, "Module isn't activated.")
else
to_chat(src, "Module isn't activated")
installed_modules()
return 1
return 1
File diff suppressed because it is too large Load Diff
+8 -4
View File
@@ -596,7 +596,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
/obj/item/stack/cable_coil/examine(mob/user)
. = ..()
if(in_range(user, src))
if(in_range(user, src) && !is_cyborg)
if(get_amount() == 1)
. += "A short piece of power cable."
else if(get_amount() == 2)
@@ -612,10 +612,10 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
// Cable merging is handled by parent proc
if(C.amount >= MAXCOIL)
if(C.get_amount() >= MAXCOIL)
to_chat(user, "The coil is as long as it will get.")
return
if( (C.amount + src.amount <= MAXCOIL) )
if((C.get_amount() + get_amount() <= MAXCOIL))
to_chat(user, "You join the cable coils together.")
return
else
@@ -861,7 +861,11 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
return color
/obj/item/stack/cable_coil/cyborg
name = "cyborg cable coil"
energy_type = /datum/robot_energy_storage/cable
is_cyborg = TRUE
/obj/item/stack/cable_coil/cyborg/update_icon()
return // icon_state should always be a full cable
/obj/item/stack/cable_coil/cyborg/attack_self(mob/user)
var/cablecolor = input(user,"Pick a cable color.","Cable Color") in list("red","yellow","green","blue","pink","orange","cyan","white")
+1 -1
View File
@@ -149,7 +149,7 @@
return
var/obj/item/stack/cable_coil/C = I
if(C.amount < 10)
if(C.get_amount() < 10)
to_chat(user, "<span class='alert'>You need more wires.</span>")
return
+1 -1
View File
@@ -220,7 +220,7 @@
if(istype(W, /obj/item/stack/sheet/glass) || istype(W, /obj/item/stack/sheet/rglass))
var/obj/item/stack/sheet/S = W
if(S.use(2))
glass_type = W.type
glass_type = S.merge_type
playsound(loc, S.usesound, 50, 1)
user.visible_message("[user] places the glass on the solar assembly.", "<span class='notice'>You place the glass on the solar assembly.</span>")
if(tracker)
@@ -55,3 +55,12 @@
/obj/item/gun/energy/disabler/cyborg/newshot()
..()
robocharge()
/obj/item/gun/energy/disabler/cyborg/cyborg_recharge(coeff, emagged)
if(cell.charge < cell.maxcharge)
var/obj/item/ammo_casing/energy/E = ammo_type[select]
cell.give(E.e_cost * coeff)
on_recharge()
update_icon()
else
charge_tick = 0
@@ -131,6 +131,9 @@
volume = 50
list_reagents = list("cleaner" = 50)
/obj/item/reagent_containers/spray/cleaner/drone/cyborg_recharge(coeff, emagged)
reagents.check_and_add("cleaner", volume, 3 * coeff)
//spray tan
/obj/item/reagent_containers/spray/spraytan
name = "spray tan"