Porting flying robots from Bay. [IDB IGNORE] (#8885)
* Semiport of Allow_Spacemove from Bay. * Porting flying robots from Bay. * Converting platforms to an alt title of Robot. * Converting existing modules to new proc flow. * Cleaning up jetpack code for robots. * Making flyers and platforms buildable. * Debugging/refining robots port. * Reverting some unneeded spacemove changes. * Refining/debugging bots. * Removing Bay subtypes, adding flying subtypes of existing modules. * Icon rework for flying robots. * Working commit for flying borgs PR.
@@ -351,6 +351,11 @@
|
||||
#define SA_ROBOTIC 3
|
||||
#define SA_HUMANOID 4
|
||||
|
||||
// Robot module categorization
|
||||
#define ROBOT_MODULE_TYPE_GROUNDED "grounded"
|
||||
#define ROBOT_MODULE_TYPE_FLYING "flying"
|
||||
#define ROBOT_MODULE_TYPE_PLATFORM "platform"
|
||||
|
||||
// More refined version of SA_* ""intelligence"" separators.
|
||||
// Now includes bitflags, so to target two classes you just do 'MOB_CLASS_ANIMAL|MOB_CLASS_HUMANOID'
|
||||
#define MOB_CLASS_NONE 0 // Default value, and used to invert for _ALL.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
SUBSYSTEM_DEF(robots)
|
||||
name = "Robots"
|
||||
init_order = INIT_ORDER_MISC_EARLY
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/modules_by_category = list()
|
||||
var/list/crisis_modules_by_category = list()
|
||||
var/list/upgrade_modules_by_category = list()
|
||||
var/list/all_module_names = list()
|
||||
|
||||
var/list/mob_types_by_title = list(
|
||||
"cyborg, flying" = /mob/living/silicon/robot/flying,
|
||||
"robot, flying" = /mob/living/silicon/robot/flying,
|
||||
"drone, flying" = /mob/living/silicon/robot/flying,
|
||||
"drone, platform" = /mob/living/silicon/robot/platform
|
||||
)
|
||||
|
||||
var/list/mmi_types_by_title = list(
|
||||
"robot" = /obj/item/mmi/digital/posibrain,
|
||||
"robot, flying" = /obj/item/mmi/digital/posibrain,
|
||||
"drone" = /obj/item/mmi/digital/robot,
|
||||
"drone, flying" = /obj/item/mmi/digital/robot,
|
||||
"drone, platform" = /obj/item/mmi/digital/robot
|
||||
)
|
||||
|
||||
/datum/controller/subsystem/robots/Initialize(start_uptime)
|
||||
|
||||
for(var/module_type in subtypesof(/obj/item/robot_module))
|
||||
var/obj/item/robot_module/module = module_type
|
||||
if(initial(module.unavailable_by_default))
|
||||
continue
|
||||
var/module_category = initial(module.module_category)
|
||||
var/module_name = initial(module.display_name)
|
||||
if(module_name && module_category)
|
||||
if(initial(module.upgrade_locked))
|
||||
LAZYINITLIST(upgrade_modules_by_category[module_category])
|
||||
LAZYSET(upgrade_modules_by_category[module_category], module_name, module)
|
||||
else if(initial(module.crisis_locked))
|
||||
LAZYINITLIST(crisis_modules_by_category[module_category])
|
||||
LAZYSET(crisis_modules_by_category[module_category], module_name, module)
|
||||
else
|
||||
LAZYINITLIST(modules_by_category[module_category])
|
||||
LAZYSET(modules_by_category[module_category], module_name, module)
|
||||
all_module_names |= module_name
|
||||
all_module_names = sortTim(all_module_names, /proc/cmp_text_asc)
|
||||
|
||||
/datum/controller/subsystem/robots/proc/get_available_modules(module_category, crisis_mode, include_override)
|
||||
. = list()
|
||||
if(modules_by_category[module_category])
|
||||
. += modules_by_category[module_category]
|
||||
if(crisis_mode && crisis_modules_by_category[module_category])
|
||||
. |= crisis_modules_by_category[module_category]
|
||||
if(include_override && upgrade_modules_by_category[module_category])
|
||||
var/list/modules = upgrade_modules_by_category[module_category]
|
||||
if(modules[include_override])
|
||||
.[include_override] = modules[include_override]
|
||||
|
||||
/datum/controller/subsystem/robots/proc/get_mmi_type_by_title(check_title)
|
||||
. = mmi_types_by_title[lowertext(trim(check_title))] || /obj/item/mmi
|
||||
|
||||
/datum/controller/subsystem/robots/proc/get_mob_type_by_title(check_title)
|
||||
. = mob_types_by_title[lowertext(trim(check_title))] || /mob/living/silicon/robot
|
||||
@@ -205,6 +205,5 @@
|
||||
|
||||
/datum/job/proc/handle_nonhuman_mob(var/mob/living/carbon/human/player, var/alt_title)
|
||||
if(mob_type & JOB_SILICON_ROBOT)
|
||||
return player.Robotize()
|
||||
if(mob_type & JOB_SILICON_AI)
|
||||
return player
|
||||
return player.Robotize(SSrobots.get_mob_type_by_title(alt_title || title))
|
||||
return player
|
||||
|
||||
@@ -57,9 +57,17 @@
|
||||
assignable = FALSE
|
||||
mob_type = JOB_SILICON_ROBOT
|
||||
outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg
|
||||
substitute_announce_title = "Stationbound Synthetic"
|
||||
job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \
|
||||
to follow its Laws."
|
||||
alt_titles = list("Robot" = /datum/alt_title/robot, "Drone" = /datum/alt_title/drone)
|
||||
alt_titles = list(
|
||||
"Cyborg, Flying",
|
||||
"Robot" = /datum/alt_title/robot,
|
||||
"Robot, Flying" = /datum/alt_title/robot,
|
||||
"Drone" = /datum/alt_title/drone,
|
||||
"Drone, Flying" = /datum/alt_title/drone,
|
||||
"Drone, Platform" = /datum/alt_title/drone
|
||||
)
|
||||
|
||||
// Cyborg Alt Titles
|
||||
/datum/alt_title/robot
|
||||
|
||||
@@ -71,55 +71,54 @@ Please wait until completion...</TT><BR>
|
||||
if(!operating)
|
||||
var/part_type = text2num(href_list["make"])
|
||||
|
||||
var/build_type = ""
|
||||
var/build_type
|
||||
var/build_time = 200
|
||||
var/build_cost = 25000
|
||||
|
||||
switch (part_type)
|
||||
if(1)
|
||||
build_type = "/obj/item/robot_parts/l_arm"
|
||||
build_type = /obj/item/robot_parts/l_arm
|
||||
build_time = 200
|
||||
build_cost = 25000
|
||||
|
||||
if(2)
|
||||
build_type = "/obj/item/robot_parts/r_arm"
|
||||
build_type = /obj/item/robot_parts/r_arm
|
||||
build_time = 200
|
||||
build_cost = 25000
|
||||
|
||||
if(3)
|
||||
build_type = "/obj/item/robot_parts/l_leg"
|
||||
build_type = /obj/item/robot_parts/l_leg
|
||||
build_time = 200
|
||||
build_cost = 25000
|
||||
|
||||
if(4)
|
||||
build_type = "/obj/item/robot_parts/r_leg"
|
||||
build_type = /obj/item/robot_parts/r_leg
|
||||
build_time = 200
|
||||
build_cost = 25000
|
||||
|
||||
if(5)
|
||||
build_type = "/obj/item/robot_parts/chest"
|
||||
build_type = /obj/item/robot_parts/chest
|
||||
build_time = 350
|
||||
build_cost = 50000
|
||||
|
||||
if(6)
|
||||
build_type = "/obj/item/robot_parts/head"
|
||||
build_type = /obj/item/robot_parts/head
|
||||
build_time = 350
|
||||
build_cost = 50000
|
||||
|
||||
if(7)
|
||||
build_type = "/obj/item/robot_parts/robot_suit"
|
||||
build_type = /obj/item/robot_parts/frame
|
||||
build_time = 600
|
||||
build_cost = 75000
|
||||
|
||||
var/building = text2path(build_type)
|
||||
if(!isnull(building))
|
||||
if(!isnull(build_type))
|
||||
if(metal_amount >= build_cost)
|
||||
operating = 1
|
||||
update_use_power(USE_POWER_ACTIVE)
|
||||
|
||||
metal_amount = max(0, metal_amount - build_cost)
|
||||
|
||||
being_built = new building(src)
|
||||
being_built = new build_type(src) // TODO: pass in model info to new
|
||||
|
||||
add_overlay("fab-active")
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot
|
||||
name = "robot debris"
|
||||
desc = "It's a useless heap of junk... <i>or is it?</i>"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon = 'icons/mob/robot_gibs.dmi'
|
||||
icon_state = "gib1"
|
||||
basecolor = SYNTH_BLOOD_COLOUR
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/obj/effect/decal/remains/robot
|
||||
desc = "They look like the remains of something mechanical. They have a strange aura about them."
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon = 'icons/mob/robot_gibs.dmi'
|
||||
icon_state = "remainsrobot"
|
||||
|
||||
/obj/effect/decal/remains/mouse
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/obj/item/robot_parts/frame
|
||||
name = "standard robot frame"
|
||||
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
|
||||
icon_state = "robo_suit"
|
||||
var/list/parts = list()
|
||||
var/list/required_parts = list(
|
||||
BP_L_ARM = /obj/item/robot_parts/l_arm,
|
||||
BP_R_ARM = /obj/item/robot_parts/r_arm,
|
||||
BP_TORSO = /obj/item/robot_parts/chest,
|
||||
BP_L_LEG = /obj/item/robot_parts/l_leg,
|
||||
BP_R_LEG = /obj/item/robot_parts/r_leg,
|
||||
BP_HEAD = /obj/item/robot_parts/head
|
||||
)
|
||||
var/created_name = ""
|
||||
var/product = /mob/living/silicon/robot
|
||||
|
||||
/obj/item/robot_parts/frame/examine(mob/user)
|
||||
. = ..()
|
||||
if(check_completion())
|
||||
. += SPAN_NOTICE("It is ready to receive a controlling intelligence.")
|
||||
else
|
||||
for(var/part in required_parts)
|
||||
if(!parts[part])
|
||||
var/obj/item/part_type = part
|
||||
. += SPAN_WARNING("It is missing \a [initial(part_type.name)]")
|
||||
|
||||
/obj/item/robot_parts/frame/update_model_info(var/model)
|
||||
return FALSE
|
||||
|
||||
/obj/item/robot_parts/frame/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/robot_parts/frame/update_icon()
|
||||
cut_overlays()
|
||||
for(var/part in required_parts)
|
||||
if(parts[part])
|
||||
add_overlay("[part]+o")
|
||||
|
||||
/obj/item/robot_parts/frame/proc/check_completion()
|
||||
for(var/part in required_parts)
|
||||
if(!parts[part])
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/robot_parts/frame/attackby(obj/item/W, mob/user)
|
||||
|
||||
// Uninstall a robotic part.
|
||||
if(W.is_crowbar())
|
||||
if(!parts.len)
|
||||
to_chat(user, SPAN_WARNING("\The [src] has no parts to remove."))
|
||||
return
|
||||
var/removing = pick(parts)
|
||||
var/obj/item/robot_parts/part = parts[removing]
|
||||
part.forceMove(get_turf(src))
|
||||
user.put_in_hands(part)
|
||||
parts -= removing
|
||||
to_chat(user, SPAN_WARNING("You lever \the [part] off \the [src]."))
|
||||
update_icon()
|
||||
|
||||
// Install a robotic part.
|
||||
else if (istype(W, /obj/item/robot_parts))
|
||||
var/obj/item/robot_parts/part = W
|
||||
if(!required_parts[part.bp_tag] || !istype(W, required_parts[part.bp_tag]))
|
||||
to_chat(user, SPAN_WARNING("\The [src] is not compatible with \the [W]."))
|
||||
return
|
||||
if(parts[part.bp_tag])
|
||||
to_chat(user, SPAN_WARNING("\The [src] already has \a [W] installed."))
|
||||
return
|
||||
if(part.can_install(user) && user.unEquip(W, src))
|
||||
parts[part.bp_tag] = part
|
||||
part.forceMove(src)
|
||||
update_icon()
|
||||
|
||||
// Install an MMI/brain.
|
||||
else if(istype(W, /obj/item/mmi))
|
||||
|
||||
if(!istype(loc,/turf))
|
||||
to_chat(user, SPAN_WARNING("You can't put \the [W] in without the frame being on the ground."))
|
||||
return
|
||||
|
||||
if(!check_completion())
|
||||
to_chat(user, SPAN_WARNING("The frame is not ready for the central processor to be installed."))
|
||||
return
|
||||
|
||||
var/obj/item/mmi/M = W
|
||||
var/mob/living/carbon/brain/B = M.brainmob
|
||||
if(!B)
|
||||
to_chat(user, SPAN_WARNING("Sticking an empty [W.name] into the frame would sort of defeat the purpose."))
|
||||
return
|
||||
|
||||
if(jobban_isbanned(B, "Robot"))
|
||||
to_chat(user, SPAN_WARNING("\The [W] does not seem to fit."))
|
||||
return
|
||||
|
||||
if(B.stat == DEAD)
|
||||
to_chat(user, SPAN_WARNING("Sticking a dead [W.name] into the frame would sort of defeat the purpose."))
|
||||
return
|
||||
|
||||
var/ghost_can_reenter = 0
|
||||
if(B.mind)
|
||||
if(B.key)
|
||||
ghost_can_reenter = TRUE
|
||||
else
|
||||
for(var/mob/observer/dead/G in player_list)
|
||||
if(G.can_reenter_corpse && G.mind == B.mind)
|
||||
ghost_can_reenter = TRUE
|
||||
//Jamming a ghosted brain into a borg is likely detrimental, and may result in some problems.
|
||||
to_chat(user, SPAN_NOTICE("\The [W] is completely unresponsive, but it may be able to auto-resuscitate if you leave it be for awhile."))
|
||||
break
|
||||
|
||||
if(!ghost_can_reenter)
|
||||
to_chat(user, SPAN_WARNING("\The [W] is completely unresponsive; there's no point."))
|
||||
return
|
||||
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
var/mob/living/silicon/robot/O = new product(get_turf(loc))
|
||||
if(!O)
|
||||
return
|
||||
|
||||
O.mmi = W
|
||||
O.invisibility = 0
|
||||
O.custom_name = created_name
|
||||
O.updatename("Default")
|
||||
B.mind.transfer_to(O)
|
||||
if(O.mind && O.mind.assigned_role)
|
||||
O.job = O.mind.assigned_role
|
||||
else
|
||||
O.job = "Robot"
|
||||
|
||||
var/obj/item/robot_parts/chest/chest = parts[BP_TORSO]
|
||||
if (chest && chest.cell)
|
||||
chest.cell.forceMove(O)
|
||||
W.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
|
||||
|
||||
// Since we "magically" installed a cell, we also have to update the correct component.
|
||||
if(O.cell)
|
||||
var/datum/robot_component/cell_component = O.components["power cell"]
|
||||
cell_component.wrapped = O.cell
|
||||
cell_component.installed = 1
|
||||
callHook("borgify", list(O))
|
||||
O.Namepick()
|
||||
qdel(src)
|
||||
|
||||
else if(istype(W, /obj/item/pen))
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
|
||||
if(t && (in_range(src, user) || loc == user))
|
||||
created_name = t
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/robot_parts/frame/Destroy()
|
||||
parts.Cut()
|
||||
for(var/thing in contents)
|
||||
qdel(thing)
|
||||
. = ..()
|
||||
|
||||
/obj/item/robot_parts/frame/proc/dismantled_from(mob/living/silicon/robot/donor)
|
||||
for(var/thing in required_parts - list(BP_TORSO, BP_HEAD))
|
||||
var/part_type = required_parts[thing]
|
||||
parts[thing] = new part_type(src)
|
||||
var/obj/item/robot_parts/chest/chest = (locate() in donor.contents) || new
|
||||
if(chest)
|
||||
chest.forceMove(src)
|
||||
parts[BP_TORSO] = chest
|
||||
update_icon()
|
||||
|
||||
/obj/item/robot_parts/frame/SetDefaultName()
|
||||
name = initial(name)
|
||||
|
||||
/obj/item/robot_parts/frame/flyer
|
||||
name = "flying robot frame"
|
||||
icon = 'icons/obj/robot_parts_flying.dmi'
|
||||
product = /mob/living/silicon/robot/flying
|
||||
required_parts = list(
|
||||
BP_L_ARM = /obj/item/robot_parts/l_arm,
|
||||
BP_R_ARM = /obj/item/robot_parts/r_arm,
|
||||
BP_TORSO = /obj/item/robot_parts/chest,
|
||||
BP_HEAD = /obj/item/robot_parts/head
|
||||
)
|
||||
|
||||
/obj/item/robot_parts/frame/platform
|
||||
name = "large robot frame"
|
||||
icon = 'icons/obj/robot_parts_platform.dmi'
|
||||
product = /mob/living/silicon/robot/platform
|
||||
required_parts = list(
|
||||
BP_L_ARM = /obj/item/robot_parts/l_arm,
|
||||
BP_R_ARM = /obj/item/robot_parts/r_arm,
|
||||
BP_L_LEG = /obj/item/robot_parts/l_leg,
|
||||
BP_R_LEG = /obj/item/robot_parts/r_leg,
|
||||
BP_TORSO = /obj/item/robot_parts/chest,
|
||||
BP_HEAD = /obj/item/robot_parts/head
|
||||
)
|
||||
@@ -4,294 +4,222 @@
|
||||
item_state = "buildpipe"
|
||||
icon_state = "blank"
|
||||
slot_flags = SLOT_BELT
|
||||
dir = SOUTH
|
||||
var/list/part = null // Order of args is important for installing robolimbs.
|
||||
var/sabotaged = 0 //Emagging limbs can have repercussions when installed as prosthetics.
|
||||
var/model_info
|
||||
dir = SOUTH
|
||||
var/bp_tag = null // What part is this?
|
||||
|
||||
/obj/item/robot_parts/set_dir()
|
||||
return
|
||||
|
||||
/obj/item/robot_parts/proc/update_model_info(var/model)
|
||||
if(!model)
|
||||
return FALSE
|
||||
model_info = model
|
||||
var/datum/robolimb/R = all_robolimbs[model]
|
||||
if(R)
|
||||
name = "[R.company] [initial(name)]"
|
||||
desc = "[R.desc]"
|
||||
if(icon_state in icon_states(R.icon))
|
||||
icon = R.icon
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/robot_parts/Initialize(ml, model)
|
||||
. = ..(ml)
|
||||
if(!update_model_info(model))
|
||||
SetDefaultName()
|
||||
|
||||
/obj/item/robot_parts/proc/SetDefaultName()
|
||||
name = "robot [initial(name)]"
|
||||
|
||||
/obj/item/robot_parts/proc/can_install(mob/user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/robot_parts/l_arm
|
||||
name = "cyborg left arm"
|
||||
name = "left arm"
|
||||
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
|
||||
icon_state = "l_arm"
|
||||
part = list(BP_L_ARM, BP_L_HAND)
|
||||
model_info = 1
|
||||
bp_tag = BP_L_ARM
|
||||
|
||||
/obj/item/robot_parts/r_arm
|
||||
name = "cyborg right arm"
|
||||
name = "right arm"
|
||||
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
|
||||
icon_state = "r_arm"
|
||||
part = list(BP_R_ARM, BP_R_HAND)
|
||||
model_info = 1
|
||||
bp_tag = BP_R_ARM
|
||||
|
||||
/obj/item/robot_parts/l_leg
|
||||
name = "cyborg left leg"
|
||||
name = "left leg"
|
||||
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
|
||||
icon_state = "l_leg"
|
||||
part = list(BP_L_LEG, BP_L_FOOT)
|
||||
model_info = 1
|
||||
bp_tag = BP_L_LEG
|
||||
|
||||
/obj/item/robot_parts/r_leg
|
||||
name = "cyborg leg"
|
||||
name = "right leg"
|
||||
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
|
||||
icon_state = "r_leg"
|
||||
part = list(BP_R_LEG, BP_R_FOOT)
|
||||
model_info = 1
|
||||
|
||||
/obj/item/robot_parts/chest
|
||||
name = "cyborg chest"
|
||||
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
|
||||
icon_state = "chest"
|
||||
part = list(BP_GROIN,BP_TORSO)
|
||||
var/wires = 0.0
|
||||
var/obj/item/cell/cell = null
|
||||
bp_tag = BP_R_LEG
|
||||
|
||||
/obj/item/robot_parts/head
|
||||
name = "cyborg head"
|
||||
name = "head"
|
||||
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
|
||||
icon_state = "head"
|
||||
part = list(BP_HEAD)
|
||||
bp_tag = BP_HEAD
|
||||
var/obj/item/flash/flash1 = null
|
||||
var/obj/item/flash/flash2 = null
|
||||
|
||||
/obj/item/robot_parts/robot_suit
|
||||
name = "endoskeleton"
|
||||
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
|
||||
icon_state = "robo_suit"
|
||||
var/obj/item/robot_parts/l_arm/l_arm = null
|
||||
var/obj/item/robot_parts/r_arm/r_arm = null
|
||||
var/obj/item/robot_parts/l_leg/l_leg = null
|
||||
var/obj/item/robot_parts/r_leg/r_leg = null
|
||||
var/obj/item/robot_parts/chest/chest = null
|
||||
var/obj/item/robot_parts/head/head = null
|
||||
var/created_name = ""
|
||||
/obj/item/robot_parts/head/can_install(mob/user)
|
||||
var/success = TRUE
|
||||
if(!flash1 || !flash2)
|
||||
to_chat(user, SPAN_WARNING("You need to attach a flash to it first!"))
|
||||
success = FALSE
|
||||
return success && ..()
|
||||
|
||||
/obj/item/robot_parts/robot_suit/Initialize()
|
||||
. = ..()
|
||||
src.updateicon()
|
||||
/obj/item/robot_parts/chest
|
||||
name = "torso"
|
||||
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
|
||||
icon_state = "torso"
|
||||
part = list(BP_GROIN,BP_TORSO)
|
||||
bp_tag = BP_TORSO
|
||||
var/wires = 0.0
|
||||
var/obj/item/cell/cell = null
|
||||
|
||||
/obj/item/robot_parts/robot_suit/proc/updateicon()
|
||||
cut_overlays()
|
||||
if(src.l_arm)
|
||||
add_overlay("l_arm+o")
|
||||
if(src.r_arm)
|
||||
add_overlay("r_arm+o")
|
||||
if(src.chest)
|
||||
add_overlay("chest+o")
|
||||
if(src.l_leg)
|
||||
add_overlay("l_leg+o")
|
||||
if(src.r_leg)
|
||||
add_overlay("r_leg+o")
|
||||
if(src.head)
|
||||
add_overlay("head+o")
|
||||
/obj/item/robot_parts/chest/can_install(mob/user)
|
||||
var/success = TRUE
|
||||
if(!wires)
|
||||
to_chat(user, SPAN_WARNING("You need to attach wires to it first!"))
|
||||
success = FALSE
|
||||
if(!cell)
|
||||
to_chat(user, SPAN_WARNING("You need to attach a cell to it first!"))
|
||||
success = FALSE
|
||||
return success && ..()
|
||||
|
||||
/obj/item/robot_parts/robot_suit/proc/check_completion()
|
||||
if(src.l_arm && src.r_arm)
|
||||
if(src.l_leg && src.r_leg)
|
||||
if(src.chest && src.head)
|
||||
feedback_inc("cyborg_frames_built",1)
|
||||
return 1
|
||||
return 0
|
||||
/obj/item/robot_parts/chest/attackby(obj/item/W, mob/user)
|
||||
|
||||
/obj/item/robot_parts/robot_suit/attackby(obj/item/W as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/stack/material) && W.get_material_name() == MAT_STEEL && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
|
||||
var/obj/item/stack/material/M = W
|
||||
if (M.use(1))
|
||||
var/obj/item/secbot_assembly/ed209_assembly/B = new /obj/item/secbot_assembly/ed209_assembly
|
||||
B.loc = get_turf(src)
|
||||
to_chat(user, "<span class='notice'>You armed the robot frame.</span>")
|
||||
if (user.get_inactive_hand()==src)
|
||||
user.remove_from_mob(src)
|
||||
user.put_in_inactive_hand(B)
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one sheet of metal to arm the robot frame.</span>")
|
||||
if(istype(W, /obj/item/robot_parts/l_leg))
|
||||
if(src.l_leg) return
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.l_leg = W
|
||||
src.updateicon()
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/r_leg))
|
||||
if(src.r_leg) return
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.r_leg = W
|
||||
src.updateicon()
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/l_arm))
|
||||
if(src.l_arm) return
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.l_arm = W
|
||||
src.updateicon()
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/r_arm))
|
||||
if(src.r_arm) return
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.r_arm = W
|
||||
src.updateicon()
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/chest))
|
||||
if(src.chest) return
|
||||
if(W:wires && W:cell)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.chest = W
|
||||
src.updateicon()
|
||||
else if(!W:wires)
|
||||
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>")
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/head))
|
||||
if(src.head) return
|
||||
if(W:flash2 && W:flash1)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.head = W
|
||||
src.updateicon()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to attach a flash to it first!</span>")
|
||||
|
||||
if(istype(W, /obj/item/mmi))
|
||||
var/obj/item/mmi/M = W
|
||||
if(check_completion())
|
||||
if(!istype(loc,/turf))
|
||||
to_chat(user, "<span class='warning'>You can't put \the [W] in, the frame has to be standing on the ground to be perfectly precise.</span>")
|
||||
return
|
||||
if(!istype(W, /obj/item/mmi/inert))
|
||||
if(!M.brainmob)
|
||||
to_chat(user, "<span class='warning'>Sticking an empty [W] into the frame would sort of defeat the purpose.</span>")
|
||||
return
|
||||
if(!M.brainmob.key)
|
||||
var/ghost_can_reenter = 0
|
||||
if(M.brainmob.mind)
|
||||
for(var/mob/observer/dead/G in player_list)
|
||||
if(G.can_reenter_corpse && G.mind == M.brainmob.mind)
|
||||
ghost_can_reenter = 1 //May come in use again at another point.
|
||||
to_chat(user, "<span class='notice'>\The [W] is completely unresponsive; though it may be able to auto-resuscitate.</span>") //Jamming a ghosted brain into a borg is likely detrimental, and may result in some problems.
|
||||
return
|
||||
if(!ghost_can_reenter)
|
||||
to_chat(user, "<span class='notice'>\The [W] is completely unresponsive; there's no point.</span>")
|
||||
return
|
||||
|
||||
if(M.brainmob.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>Sticking a dead [W] into the frame would sort of defeat the purpose.</span>")
|
||||
return
|
||||
|
||||
if(jobban_isbanned(M.brainmob, "Cyborg"))
|
||||
to_chat(user, "<span class='warning'>This [W] does not seem to fit.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc), TRUE)
|
||||
if(!O) return
|
||||
|
||||
user.drop_item()
|
||||
|
||||
O.mmi = W
|
||||
O.post_mmi_setup()
|
||||
O.invisibility = 0
|
||||
O.custom_name = created_name
|
||||
O.updatename("Default")
|
||||
|
||||
if(M.brainmob)
|
||||
M.brainmob.mind.transfer_to(O)
|
||||
if(O.mind && O.mind.special_role)
|
||||
O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
|
||||
for(var/datum/language/L in M.brainmob.languages)
|
||||
O.add_language(L.name)
|
||||
O.job = "Cyborg"
|
||||
O.cell = chest.cell
|
||||
O.cell.loc = O
|
||||
W.loc = O//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
|
||||
|
||||
// Since we "magically" installed a cell, we also have to update the correct component.
|
||||
if(O.cell)
|
||||
var/datum/robot_component/cell_component = O.components["power cell"]
|
||||
cell_component.wrapped = O.cell
|
||||
cell_component.installed = 1
|
||||
|
||||
feedback_inc("cyborg_birth",1)
|
||||
callHook("borgify", list(O))
|
||||
O.Namepick()
|
||||
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The MMI must go in after everything else!</span>")
|
||||
|
||||
if (istype(W, /obj/item/pen))
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src, usr) && src.loc != usr)
|
||||
return
|
||||
|
||||
src.created_name = t
|
||||
|
||||
return
|
||||
|
||||
/obj/item/robot_parts/chest/attackby(obj/item/W as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/cell))
|
||||
if(src.cell)
|
||||
to_chat(user, "<span class='warning'>You have already inserted a cell!</span>")
|
||||
return
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
to_chat(user, SPAN_WARNING("You have already inserted a cell!"))
|
||||
return TRUE
|
||||
if(user.unEquip(W, src))
|
||||
src.cell = W
|
||||
to_chat(user, "<span class='notice'>You insert the cell!</span>")
|
||||
W.forceMove(src)
|
||||
to_chat(user, SPAN_NOTICE("You insert the cell!"))
|
||||
return TRUE
|
||||
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
if(src.wires)
|
||||
to_chat(user, "<span class='warning'>You have already inserted wire!</span>")
|
||||
return
|
||||
else
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
coil.use(1)
|
||||
to_chat(user, SPAN_WARNING("You have already inserted wire!"))
|
||||
return TRUE
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if(coil.use(1))
|
||||
src.wires = 1.0
|
||||
to_chat(user, "<span class='notice'>You insert the wire!</span>")
|
||||
return
|
||||
to_chat(user, SPAN_NOTICE("You insert the wire!"))
|
||||
return TRUE
|
||||
|
||||
/obj/item/robot_parts/head/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/robot_parts/head))
|
||||
var/obj/item/robot_parts/head/head_part = W
|
||||
// Attempt to create full-body prosthesis.
|
||||
var/success = TRUE
|
||||
success &= can_install(user)
|
||||
success &= head_part.can_install(user)
|
||||
if (success)
|
||||
|
||||
// Species selection.
|
||||
var/species = input(user, "Select a species for the prosthetic.") as null|anything in GetCyborgSpecies()
|
||||
if(!species)
|
||||
return TRUE
|
||||
var/name = sanitizeSafe(input(user,"Set a name for the new prosthetic."), MAX_NAME_LEN)
|
||||
if(!name)
|
||||
name = "prosthetic ([random_id("prosthetic_id", 1, 999)])"
|
||||
|
||||
// Create a new, nonliving human.
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(get_turf(loc))
|
||||
H.death(0, DEATHGASP_NO_MESSAGE)
|
||||
H.set_species(species)
|
||||
H.fully_replace_character_name(name)
|
||||
|
||||
// Remove all external organs other than chest and head..
|
||||
for (var/O in list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG))
|
||||
var/obj/item/organ/external/organ = H.organs_by_name[O]
|
||||
H.organs -= organ
|
||||
H.organs_by_name[organ.organ_tag] = null
|
||||
qdel(organ)
|
||||
|
||||
// Remove brain (we want to put one in).
|
||||
var/obj/item/organ/internal/brain = H.internal_organs_by_name[O_BRAIN]
|
||||
H.organs -= brain
|
||||
H.organs_by_name[brain.organ_tag] = null
|
||||
qdel(brain)
|
||||
|
||||
// Robotize remaining organs: Eyes, head, and chest.
|
||||
// Respect brand used.
|
||||
var/obj/item/organ/internal/eyes = H.internal_organs_by_name[O_EYES]
|
||||
eyes.robotize()
|
||||
|
||||
var/obj/item/organ/external/head = H.organs_by_name[BP_HEAD]
|
||||
var/head_company = head_part.model_info
|
||||
head.robotize(head_company)
|
||||
|
||||
var/obj/item/organ/external/chest = H.organs_by_name[BP_TORSO]
|
||||
var/chest_company = model_info
|
||||
chest.robotize(chest_company)
|
||||
|
||||
// Cleanup
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/robot_parts/chest/proc/GetCyborgSpecies()
|
||||
. = list()
|
||||
for(var/N in GLOB.playable_species)
|
||||
var/datum/species/S = GLOB.all_species[N]
|
||||
if(S.spawn_flags & SPECIES_NO_FBP_CONSTRUCTION)
|
||||
continue
|
||||
. += N
|
||||
|
||||
/obj/item/robot_parts/head/attackby(obj/item/W, mob/user)
|
||||
..()
|
||||
if(istype(W, /obj/item/flash))
|
||||
if(istype(user,/mob/living/silicon/robot))
|
||||
var/current_module = user.get_active_hand()
|
||||
if(current_module == W)
|
||||
to_chat(user, "<span class='warning'>How do you propose to do that?</span>")
|
||||
to_chat(user, SPAN_WARNING("How do you propose to do that?"))
|
||||
return
|
||||
else
|
||||
add_flashes(W,user)
|
||||
else
|
||||
add_flashes(W,user)
|
||||
return
|
||||
|
||||
/obj/item/robot_parts/head/proc/add_flashes(obj/item/W as obj, mob/user as mob) //Made into a separate proc to avoid copypasta
|
||||
/obj/item/robot_parts/head/proc/add_flashes(obj/item/W, mob/user) //Made into a seperate proc to avoid copypasta
|
||||
if(src.flash1 && src.flash2)
|
||||
to_chat(user, "<span class='notice'>You have already inserted the eyes!</span>")
|
||||
to_chat(user, SPAN_NOTICE("You have already inserted the eyes!"))
|
||||
return
|
||||
else if(src.flash1)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
if(!user.unEquip(W, src))
|
||||
return
|
||||
src.flash2 = W
|
||||
to_chat(user, "<span class='notice'>You insert the flash into the eye socket!</span>")
|
||||
W.forceMove(src)
|
||||
to_chat(user, SPAN_NOTICE("You insert the flash into the eye socket!"))
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
if(!user.unEquip(W, src))
|
||||
return
|
||||
src.flash1 = W
|
||||
to_chat(user, "<span class='notice'>You insert the flash into the eye socket!</span>")
|
||||
W.forceMove(src)
|
||||
to_chat(user, SPAN_NOTICE("You insert the flash into the eye socket!"))
|
||||
|
||||
|
||||
/obj/item/robot_parts/emag_act(var/remaining_charges, var/mob/user)
|
||||
/obj/item/robot_parts/emag_act(remaining_charges, mob/user)
|
||||
if(sabotaged)
|
||||
to_chat(user, "<span class='warning'>[src] is already sabotaged!</span>")
|
||||
to_chat(user, SPAN_WARNING("[src] is already sabotaged!"))
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You short out the safeties.</span>")
|
||||
to_chat(user, SPAN_WARNING("You short out the safeties."))
|
||||
sabotaged = 1
|
||||
return 1
|
||||
|
||||
@@ -133,22 +133,17 @@
|
||||
require_module = 1
|
||||
|
||||
/obj/item/borg/upgrade/jetpack/action(var/mob/living/silicon/robot/R)
|
||||
if(..()) return 0
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/tank/jetpack/carbondioxide/T = locate() in R.module
|
||||
if(!T)
|
||||
T = locate() in R.module.contents
|
||||
if(!T)
|
||||
T = locate() in R.module.modules
|
||||
if(!T)
|
||||
R.module.modules += new/obj/item/tank/jetpack/carbondioxide(R.module)
|
||||
for(var/obj/item/tank/jetpack/carbondioxide in R.module.modules)
|
||||
R.internals = src
|
||||
return 1
|
||||
if(T)
|
||||
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
|
||||
if(R.module.jetpack)
|
||||
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
|
||||
to_chat(usr, "There's no mounting point for the module!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
R.module.jetpack = new /obj/item/tank/jetpack/carbondioxide(R.module)
|
||||
R.internals = R.module.jetpack
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/advhealth
|
||||
name = "advanced health analyzer module"
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
update_state()
|
||||
|
||||
/obj/structure/door_assembly/attack_robot(mob/living/silicon/robot/user)
|
||||
if(Adjacent(user) && (user.module && (istype(user.module,/obj/item/robot_module/robot/engineering/general)) \
|
||||
if(Adjacent(user) && (user.module && (istype(user.module,/obj/item/robot_module/robot/engineering)) \
|
||||
|| istype(user.module,/obj/item/robot_module/drone))) //Only dron (and engiborg) needs this.
|
||||
rename_door(user)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/obj/structure/ghost_pod/manual/lost_drone/create_occupant(var/mob/M)
|
||||
density = FALSE
|
||||
var/mob/living/silicon/robot/lost/randomlaws/R = new(get_turf(src))
|
||||
var/mob/living/silicon/robot/flying/lost/randomlaws/R = new(get_turf(src))
|
||||
R.adjustBruteLoss(rand(5, 30))
|
||||
R.adjustFireLoss(rand(5, 10))
|
||||
if(M.mind)
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
update_state()
|
||||
|
||||
/obj/structure/windoor_assembly/attack_robot(mob/living/silicon/robot/user)
|
||||
if(Adjacent(user) && (user.module && (istype(user.module,/obj/item/robot_module/robot/engineering/general)) \
|
||||
if(Adjacent(user) && (user.module && (istype(user.module,/obj/item/robot_module/robot/engineering)) \
|
||||
|| istype(user.module,/obj/item/robot_module/drone))) //Only dron (and engiborg) needs this.
|
||||
rename_door(user)
|
||||
|
||||
|
||||
@@ -124,14 +124,6 @@ var/global/DBConnection/dbcon_old = new() // /tg/station database (Old database)
|
||||
// Added for Xenoarchaeology, might be useful for other stuff.
|
||||
var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
|
||||
|
||||
|
||||
// Used by robots and robot preferences.
|
||||
var/global/list/robot_module_types = list(
|
||||
"Standard", "Engineering", "Surgeon", "Crisis",
|
||||
"Miner", "Janitor", "Service", "Clerical", "Security",
|
||||
"Research"
|
||||
)
|
||||
|
||||
// Some scary sounds.
|
||||
var/global/static/list/scarySounds = list(
|
||||
'sound/weapons/thudswoosh.ogg',
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
//Flavour text for robots.
|
||||
S["flavour_texts_robot_Default"] >> pref.flavour_texts_robot["Default"]
|
||||
for(var/module in robot_module_types)
|
||||
for(var/module in SSrobots.all_module_names)
|
||||
S["flavour_texts_robot_[module]"] >> pref.flavour_texts_robot[module]
|
||||
|
||||
/datum/category_item/player_setup_item/general/flavor/save_character(var/savefile/S)
|
||||
@@ -30,7 +30,7 @@
|
||||
S["flavor_texts_feet"] << pref.flavor_texts["feet"]
|
||||
|
||||
S["flavour_texts_robot_Default"] << pref.flavour_texts_robot["Default"]
|
||||
for(var/module in robot_module_types)
|
||||
for(var/module in SSrobots.all_module_names)
|
||||
S["flavour_texts_robot_[module]"] << pref.flavour_texts_robot[module]
|
||||
|
||||
/datum/category_item/player_setup_item/general/flavor/sanitize_character()
|
||||
@@ -129,7 +129,7 @@
|
||||
HTML += "<a href='?src=\ref[src];flavour_text_robot=Default'>Default:</a> "
|
||||
HTML += TextPreview(pref.flavour_texts_robot["Default"])
|
||||
HTML += "<hr />"
|
||||
for(var/module in robot_module_types)
|
||||
for(var/module in SSrobots.all_module_names)
|
||||
HTML += "<a href='?src=\ref[src];flavour_text_robot=[module]'>[module]:</a> "
|
||||
HTML += TextPreview(pref.flavour_texts_robot[module])
|
||||
HTML += "<br>"
|
||||
|
||||
@@ -912,7 +912,7 @@
|
||||
return
|
||||
|
||||
if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0))
|
||||
if(!wearer.Process_Spacemove(0))
|
||||
if(!wearer.Process_Spacemove(FALSE))
|
||||
return 0
|
||||
|
||||
if(malfunctioning)
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
. += "<span class='deadsay'>It appears to be completely inactive.</span>"
|
||||
else
|
||||
. += "<span class='deadsay'>It appears to be completely inactive.</span>"
|
||||
|
||||
|
||||
/obj/item/mmi/digital/emp_act(severity)
|
||||
if(!src.brainmob)
|
||||
return
|
||||
@@ -351,4 +351,4 @@
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "mainboard"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_DATA = 3)
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_DATA = 3)
|
||||
|
||||
@@ -173,34 +173,12 @@
|
||||
for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules)
|
||||
return module.jets
|
||||
|
||||
/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0)
|
||||
//Can we act?
|
||||
if(restrained()) return 0
|
||||
|
||||
if(..()) //Can move due to other reasons, don't use jetpack fuel
|
||||
return 1
|
||||
|
||||
//Do we have a working jetpack?
|
||||
var/obj/item/tank/jetpack/thrust = get_jetpack()
|
||||
|
||||
if(thrust)
|
||||
if(((!check_drift) || (check_drift && thrust.stabilization_on)) && (!lying) && (thrust.do_thrust(0.01, src)))
|
||||
inertia_dir = 0
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/carbon/human/Process_Spaceslipping(var/prob_slip = 5)
|
||||
//If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such.
|
||||
|
||||
if(species.flags & NO_SLIP)
|
||||
return 0
|
||||
|
||||
var/obj/item/tank/jetpack/thrust = get_jetpack()
|
||||
if(thrust?.can_thrust(0.01))
|
||||
return 0
|
||||
|
||||
if(stat)
|
||||
prob_slip = 0 // Changing this to zero to make it line up with the comment, and also, make more sense.
|
||||
|
||||
@@ -209,13 +187,16 @@
|
||||
prob_slip = 0
|
||||
|
||||
//Check hands and mod slip
|
||||
if(!l_hand) prob_slip -= 2
|
||||
else if(l_hand.w_class <= 2) prob_slip -= 1
|
||||
if (!r_hand) prob_slip -= 2
|
||||
else if(r_hand.w_class <= 2) prob_slip -= 1
|
||||
if(!l_hand)
|
||||
prob_slip -= 2
|
||||
else if(l_hand.w_class <= 2)
|
||||
prob_slip -= 1
|
||||
if (!r_hand)
|
||||
prob_slip -= 2
|
||||
else if(r_hand.w_class <= 2)
|
||||
prob_slip -= 1
|
||||
|
||||
prob_slip = round(prob_slip)
|
||||
return(prob_slip)
|
||||
return round(prob_slip)
|
||||
|
||||
// Handle footstep sounds
|
||||
/mob/living/carbon/human/handle_footstep(var/turf/T)
|
||||
|
||||
@@ -249,7 +249,7 @@ default behaviour is:
|
||||
|
||||
/mob/living/proc/inertial_drift()
|
||||
if(x > 1 && x < (world.maxx) && y > 1 && y < (world.maxy))
|
||||
if(Process_Spacemove(1))
|
||||
if(Process_Spacemove(TRUE))
|
||||
inertia_dir = 0
|
||||
return
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@
|
||||
external_type = /obj/item/robot_parts/robot_component/armour_platform
|
||||
max_damage = 140
|
||||
|
||||
/datum/robot_component/armour/light
|
||||
name = "lightweight armour plating"
|
||||
external_type = /obj/item/robot_parts/robot_component/armour_light
|
||||
max_damage = 75
|
||||
|
||||
// ACTUATOR
|
||||
// Enables movement.
|
||||
// Uses no power when idle. Uses 200J for each tile the cyborg moves.
|
||||
@@ -181,13 +186,13 @@
|
||||
|
||||
// Initializes cyborg's components. Technically, adds default set of components to new borgs
|
||||
/mob/living/silicon/robot/proc/initialize_components()
|
||||
components["actuator"] = new/datum/robot_component/actuator(src)
|
||||
components["radio"] = new/datum/robot_component/radio(src)
|
||||
components["power cell"] = new/datum/robot_component/cell(src)
|
||||
components["diagnosis unit"] = new/datum/robot_component/diagnosis_unit(src)
|
||||
components["camera"] = new/datum/robot_component/camera(src)
|
||||
components["comms"] = new/datum/robot_component/binary_communication(src)
|
||||
components["armour"] = new/datum/robot_component/armour(src)
|
||||
components["actuator"] = new /datum/robot_component/actuator(src)
|
||||
components["radio"] = new /datum/robot_component/radio(src)
|
||||
components["power cell"] = new /datum/robot_component/cell(src)
|
||||
components["diagnosis unit"] = new /datum/robot_component/diagnosis_unit(src)
|
||||
components["camera"] = new /datum/robot_component/camera(src)
|
||||
components["comms"] = new /datum/robot_component/binary_communication(src)
|
||||
components["armour"] = new /datum/robot_component/armour(src)
|
||||
|
||||
// Checks if component is functioning
|
||||
/mob/living/silicon/robot/proc/is_component_functioning(module_name)
|
||||
@@ -258,6 +263,12 @@
|
||||
icon_state_broken = "armor_broken"
|
||||
color = COLOR_GRAY80
|
||||
|
||||
/obj/item/robot_parts/robot_component/armour_light
|
||||
name = "lightweight armour plating"
|
||||
desc = "A pair of flexible, light armor plates, used to protect the internals of robots equipped with anti-gravity frames."
|
||||
icon_state = "armor_l"
|
||||
icon_state_broken = "armor_l_broken"
|
||||
|
||||
/obj/item/robot_parts/robot_component/camera
|
||||
name = "camera"
|
||||
desc = "A modified camera module used as a visual receptor for robots and exosuits, also serving as a relay for wireless video feed."
|
||||
@@ -274,4 +285,4 @@
|
||||
name = "radio"
|
||||
desc = "A modular, multi-frequency radio used by robots and exosuits to enable communication systems. Comes with built-in subspace receivers."
|
||||
icon_state = "radio"
|
||||
icon_state_broken = "radio_broken"
|
||||
icon_state_broken = "radio_broken"
|
||||
|
||||
@@ -21,7 +21,6 @@ var/global/list/mob_hat_cache = list()
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "maintenance drone"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "repairbot"
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
@@ -153,7 +152,7 @@ var/global/list/mob_hat_cache = list()
|
||||
/mob/living/silicon/robot/drone/choose_icon()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
/mob/living/silicon/robot/drone/pick_module(override)
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/wear_hat(var/obj/item/new_hat)
|
||||
@@ -272,10 +271,6 @@ var/global/list/mob_hat_cache = list()
|
||||
return
|
||||
..()
|
||||
|
||||
//DRONE MOVEMENT.
|
||||
/mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip)
|
||||
return 0
|
||||
|
||||
//CONSOLE PROCS
|
||||
/mob/living/silicon/robot/drone/proc/law_resync()
|
||||
if(stat != DEAD)
|
||||
|
||||
@@ -129,6 +129,17 @@
|
||||
|
||||
)
|
||||
|
||||
/obj/item/gripper/cultivator
|
||||
name = "cultivator gripper"
|
||||
icon_state = "gripper"
|
||||
desc = "A simple grasping tool used to perform tasks in the xenobiology division, such as handling plant samples and disks."
|
||||
can_hold = list(
|
||||
/obj/item/reagent_containers/glass,
|
||||
/obj/item/seeds,
|
||||
/obj/item/slime_extract,
|
||||
/obj/item/disk/botany
|
||||
)
|
||||
|
||||
/obj/item/gripper/circuit
|
||||
name = "circuit assembly gripper"
|
||||
icon_state = "gripper-circ"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/mob/living/silicon/robot
|
||||
name = "Cyborg"
|
||||
real_name = "Cyborg"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon = 'icons/mob/robots/robots_grounded.dmi'
|
||||
icon_state = "robot"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
var/lights_on = 0 // Is our integrated light on?
|
||||
var/used_power_this_tick = 0
|
||||
var/power_efficiency = 1
|
||||
var/sight_mode = 0
|
||||
var/custom_name = ""
|
||||
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
|
||||
@@ -22,6 +23,8 @@
|
||||
var/crisis_override = 0
|
||||
var/integrated_light_power = 6
|
||||
var/datum/wires/robot/wires
|
||||
var/module_category = ROBOT_MODULE_TYPE_GROUNDED
|
||||
var/dismantle_type = /obj/item/robot_parts/frame
|
||||
|
||||
can_be_antagged = TRUE
|
||||
|
||||
@@ -75,7 +78,6 @@
|
||||
var/viewalerts = 0
|
||||
var/modtype = "Default"
|
||||
var/lower_mod = 0
|
||||
var/jetpack = 0
|
||||
var/datum/effect_system/ion_trail_follow/ion_trail = null
|
||||
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
|
||||
var/jeton = 0
|
||||
@@ -258,28 +260,42 @@
|
||||
updateicon()
|
||||
return module_sprites
|
||||
|
||||
/mob/living/silicon/robot/proc/pick_module()
|
||||
if(module)
|
||||
return
|
||||
var/list/modules = list()
|
||||
modules.Add(robot_module_types)
|
||||
if((crisis && security_level == SEC_LEVEL_RED) || crisis_override) //Leaving this in until it's balanced appropriately.
|
||||
to_chat(src, "<font color='red'>Crisis mode active. Combat module available.</font>")
|
||||
modules+="Combat"
|
||||
modtype = input("Please, select a module!", "Robot module", null, null) as null|anything in modules
|
||||
/mob/living/silicon/robot/proc/pick_module(override)
|
||||
|
||||
if(module)
|
||||
if(module && !override)
|
||||
return
|
||||
if(!(modtype in robot_modules))
|
||||
|
||||
var/is_crisis_mode = crisis_override || (security_level == SEC_LEVEL_RED)
|
||||
var/list/robot_modules = SSrobots.get_available_modules(module_category, is_crisis_mode, override)
|
||||
if(!length(robot_modules))
|
||||
to_chat(src, SPAN_WARNING("For some reason, no modules are available to you. Please report this on the issue tracker!"))
|
||||
return
|
||||
|
||||
if(!override)
|
||||
if(is_crisis_mode)
|
||||
to_chat(src, SPAN_WARNING("Crisis mode active. Additional modules available."))
|
||||
modtype = input("Please select a module!", "Robot module", null, null) as null|anything in robot_modules
|
||||
else
|
||||
if(module)
|
||||
QDEL_NULL(module)
|
||||
modtype = override
|
||||
|
||||
if(module || !modtype)
|
||||
return
|
||||
|
||||
var/module_type = robot_modules[modtype]
|
||||
if(!module_type)
|
||||
to_chat(src, SPAN_WARNING("You are unable to select a module."))
|
||||
return
|
||||
|
||||
new module_type(src)
|
||||
|
||||
hands.icon_state = lowertext(modtype)
|
||||
if(hands)
|
||||
hands.icon_state = lowertext(modtype)
|
||||
feedback_inc("cyborg_[lowertext(modtype)]",1)
|
||||
updatename()
|
||||
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
|
||||
if(module)
|
||||
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
|
||||
|
||||
/mob/living/silicon/robot/proc/update_braintype()
|
||||
if(istype(mmi, /obj/item/mmi/digital/posibrain))
|
||||
@@ -416,19 +432,11 @@
|
||||
// this function displays jetpack pressure in the stat panel
|
||||
/mob/living/silicon/robot/proc/show_jetpack_pressure()
|
||||
// if you have a jetpack, show the internal tank pressure
|
||||
var/obj/item/tank/jetpack/current_jetpack = installed_jetpack()
|
||||
var/obj/item/tank/jetpack/current_jetpack = get_jetpack()
|
||||
if (current_jetpack)
|
||||
stat("Internal Atmosphere Info", current_jetpack.name)
|
||||
stat("Tank Pressure", current_jetpack.air_contents.return_pressure())
|
||||
|
||||
|
||||
// this function returns the robots jetpack, if one is installed
|
||||
/mob/living/silicon/robot/proc/installed_jetpack()
|
||||
if(module)
|
||||
return (locate(/obj/item/tank/jetpack) in module.modules)
|
||||
return 0
|
||||
|
||||
|
||||
// this function displays the cyborgs current cell charge in the stat panel
|
||||
/mob/living/silicon/robot/proc/show_cell_power()
|
||||
if(cell)
|
||||
@@ -555,13 +563,8 @@
|
||||
to_chat(user, "<span class='filter_notice'>You jam the crowbar into the robot and begin levering [mmi].</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='filter_notice'>You damage some parts of the chassis, but eventually manage to rip out [mmi]!</span>")
|
||||
var/obj/item/robot_parts/robot_suit/C = new/obj/item/robot_parts/robot_suit(loc)
|
||||
C.l_leg = new/obj/item/robot_parts/l_leg(C)
|
||||
C.r_leg = new/obj/item/robot_parts/r_leg(C)
|
||||
C.l_arm = new/obj/item/robot_parts/l_arm(C)
|
||||
C.r_arm = new/obj/item/robot_parts/r_arm(C)
|
||||
C.updateicon()
|
||||
new/obj/item/robot_parts/chest(loc)
|
||||
var/obj/item/robot_parts/frame/C = new dismantle_type(loc)
|
||||
C.dismantled_from(src)
|
||||
qdel(src)
|
||||
else
|
||||
// Okay we're not removing the cell or an MMI, but maybe something else?
|
||||
@@ -1016,7 +1019,7 @@
|
||||
if(icontype == "Custom")
|
||||
icon = CUSTOM_ITEM_SYNTH
|
||||
else // This is to fix an issue where someone with a custom borg sprite chooses a non-custom sprite and turns invisible.
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon = initial(icon)
|
||||
icon_state = module_sprites[icontype]
|
||||
updateicon()
|
||||
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/obj/item/robot_module
|
||||
name = "robot module"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "std_module"
|
||||
w_class = ITEMSIZE_NO_CONTAINER
|
||||
item_state = "std_mod"
|
||||
|
||||
var/unavailable_by_default
|
||||
var/display_name
|
||||
var/hide_on_manifest = FALSE
|
||||
var/channels = list()
|
||||
var/networks = list()
|
||||
var/languages = list(
|
||||
LANGUAGE_SOL_COMMON = 1,
|
||||
LANGUAGE_SIVIAN= 0,
|
||||
LANGUAGE_TRADEBAND = 1,
|
||||
LANGUAGE_UNATHI = 0,
|
||||
LANGUAGE_SIIK = 0,
|
||||
LANGUAGE_AKHANI = 0,
|
||||
LANGUAGE_SKRELLIAN = 0,
|
||||
LANGUAGE_GUTTER = 0,
|
||||
LANGUAGE_SCHECHI = 0,
|
||||
LANGUAGE_SIGN = 0,
|
||||
LANGUAGE_TERMINUS = 1,
|
||||
LANGUAGE_ZADDAT = 0
|
||||
)
|
||||
var/sprites = list()
|
||||
var/can_be_pushed = 1
|
||||
var/no_slip = 0
|
||||
var/list/modules = list()
|
||||
var/list/datum/matter_synth/synths = list()
|
||||
var/obj/item/emag = null
|
||||
var/obj/item/borg/upgrade/advhealth = null
|
||||
var/list/subsystems = list()
|
||||
var/list/obj/item/borg/upgrade/supported_upgrades = list()
|
||||
|
||||
var/obj/item/tank/jetpack/jetpack
|
||||
|
||||
var/list/universal_equipment = list(
|
||||
/obj/item/flash/robot,
|
||||
/obj/item/tool/crowbar/cyborg,
|
||||
/obj/item/extinguisher,
|
||||
/obj/item/gps/robot
|
||||
)
|
||||
// Module categorization values.
|
||||
var/module_category = ROBOT_MODULE_TYPE_GROUNDED
|
||||
var/upgrade_locked = FALSE
|
||||
var/crisis_locked = FALSE
|
||||
|
||||
// Bookkeeping
|
||||
var/list/original_languages = list()
|
||||
var/list/added_networks = list()
|
||||
|
||||
/obj/item/robot_module/proc/hide_on_manifest()
|
||||
. = hide_on_manifest
|
||||
|
||||
/obj/item/robot_module/Initialize(var/ml)
|
||||
. = ..()
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(!istype(R))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
R.module = src
|
||||
|
||||
build_equipment(R)
|
||||
build_emag(R)
|
||||
build_synths(R)
|
||||
|
||||
finalize_equipment(R)
|
||||
finalize_emag(R)
|
||||
finalize_synths(R)
|
||||
|
||||
add_camera_networks(R)
|
||||
add_languages(R)
|
||||
add_subsystems(R)
|
||||
apply_status_flags(R)
|
||||
handle_shell(R)
|
||||
|
||||
if(R.radio)
|
||||
addtimer(CALLBACK(R.radio, /obj/item/radio/proc/recalculateChannels), 0)
|
||||
|
||||
R.set_module_sprites(sprites)
|
||||
addtimer(CALLBACK(R, /mob/living/silicon/robot/proc/choose_icon, R.module_sprites.len + 1, R.module_sprites), 0)
|
||||
|
||||
/obj/item/robot_module/proc/build_equipment()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
for(var/thing in (modules|universal_equipment))
|
||||
modules -= thing
|
||||
if(ispath(thing, /obj/item))
|
||||
modules += new thing(src)
|
||||
else if(isitem(thing))
|
||||
var/obj/item/I = thing
|
||||
I.forceMove(src)
|
||||
modules += I
|
||||
else
|
||||
log_debug("Invalid var type in [type] equipment creation - [thing]")
|
||||
if(ispath(jetpack))
|
||||
jetpack = new jetpack(src)
|
||||
|
||||
/obj/item/robot_module/proc/finalize_equipment()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
for(var/obj/item/I in modules)
|
||||
I.canremove = FALSE
|
||||
if(jetpack)
|
||||
if(istype(jetpack))
|
||||
jetpack.canremove = FALSE
|
||||
var/mob/living/silicon/robot/robit = loc
|
||||
if(istype(robit))
|
||||
jetpack.forceMove(robit)
|
||||
robit.internals = jetpack
|
||||
else
|
||||
log_debug("Invalid var type in [type] jetpack creation - [jetpack]")
|
||||
jetpack = null
|
||||
|
||||
/obj/item/robot_module/proc/build_emag()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(ispath(emag))
|
||||
emag = new emag(src)
|
||||
|
||||
/obj/item/robot_module/proc/finalize_emag()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(emag)
|
||||
if(istype(emag))
|
||||
emag.canremove = FALSE
|
||||
else
|
||||
log_debug("Invalid var type in [type] emag creation - [emag]")
|
||||
emag = null
|
||||
|
||||
/obj/item/robot_module/proc/build_synths()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
for(var/thing in synths)
|
||||
if(istype(thing, /datum/matter_synth))
|
||||
continue
|
||||
if(!ispath(thing, /datum/matter_synth))
|
||||
log_debug("Invalid var type in [type] synth creation - [thing]")
|
||||
continue
|
||||
if(isnull(synths[thing]))
|
||||
synths += new thing
|
||||
else
|
||||
synths += new thing(synths[thing])
|
||||
synths -= thing
|
||||
|
||||
/obj/item/robot_module/proc/finalize_synths()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return
|
||||
|
||||
/obj/item/robot_module/proc/Reset(var/mob/living/silicon/robot/R)
|
||||
remove_camera_networks(R)
|
||||
remove_languages(R)
|
||||
remove_subsystems(R)
|
||||
remove_status_flags(R)
|
||||
|
||||
if(R.radio)
|
||||
R.radio.recalculateChannels()
|
||||
R.choose_icon(0, R.set_module_sprites(list("Default" = "robot")))
|
||||
|
||||
// This can qdel before init if spawned outside a mob, so
|
||||
// Destroy() needs to be a bit nuanced to avoid runtimes.
|
||||
/obj/item/robot_module/Destroy()
|
||||
for(var/datum/thing in modules)
|
||||
qdel(thing)
|
||||
// Robot icons unit test needs the module types list.
|
||||
#ifndef UNIT_TEST
|
||||
modules = null
|
||||
#endif
|
||||
for(var/datum/thing in synths)
|
||||
qdel(thing)
|
||||
synths = null
|
||||
if(istype(emag))
|
||||
QDEL_NULL(emag)
|
||||
if(istype(jetpack))
|
||||
QDEL_NULL(jetpack)
|
||||
return ..()
|
||||
|
||||
/obj/item/robot_module/emp_act(severity)
|
||||
if(modules)
|
||||
for(var/obj/O in modules)
|
||||
O.emp_act(severity)
|
||||
if(emag)
|
||||
emag.emp_act(severity)
|
||||
if(synths)
|
||||
for(var/datum/matter_synth/S in synths)
|
||||
S.emp_act(severity)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate)
|
||||
if(!synths || !synths.len)
|
||||
return
|
||||
|
||||
for(var/datum/matter_synth/T in synths)
|
||||
T.add_charge(T.recharge_rate * rate)
|
||||
|
||||
/obj/item/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module
|
||||
var/list/temp_list = modules
|
||||
modules = list()
|
||||
for(var/obj/O in temp_list)
|
||||
if(O)
|
||||
modules += O
|
||||
|
||||
/obj/item/robot_module/proc/add_languages(var/mob/living/silicon/robot/R)
|
||||
// Stores the languages as they were before receiving the module, and whether they could be synthezized.
|
||||
for(var/datum/language/language_datum in R.languages)
|
||||
original_languages[language_datum] = (language_datum in R.speech_synthesizer_langs)
|
||||
|
||||
for(var/language in languages)
|
||||
R.add_language(language, languages[language])
|
||||
|
||||
/obj/item/robot_module/proc/remove_languages(var/mob/living/silicon/robot/R)
|
||||
// Clear all added languages, whether or not we originally had them.
|
||||
for(var/language in languages)
|
||||
R.remove_language(language)
|
||||
|
||||
// Then add back all the original languages, and the relevant synthezising ability
|
||||
for(var/original_language in original_languages)
|
||||
R.add_language(original_language, original_languages[original_language])
|
||||
original_languages.Cut()
|
||||
|
||||
/obj/item/robot_module/proc/add_camera_networks(var/mob/living/silicon/robot/R)
|
||||
if(R.camera && (NETWORK_ROBOTS in R.camera.network))
|
||||
for(var/network in networks)
|
||||
if(!(network in R.camera.network))
|
||||
R.camera.add_network(network)
|
||||
added_networks |= network
|
||||
|
||||
/obj/item/robot_module/proc/remove_camera_networks(var/mob/living/silicon/robot/R)
|
||||
if(R.camera)
|
||||
R.camera.remove_networks(added_networks)
|
||||
added_networks.Cut()
|
||||
|
||||
/obj/item/robot_module/proc/add_subsystems(var/mob/living/silicon/robot/R)
|
||||
R.verbs |= subsystems
|
||||
|
||||
/obj/item/robot_module/proc/remove_subsystems(var/mob/living/silicon/robot/R)
|
||||
R.verbs -= subsystems
|
||||
|
||||
/obj/item/robot_module/proc/apply_status_flags(var/mob/living/silicon/robot/R)
|
||||
if(!can_be_pushed)
|
||||
R.status_flags &= ~CANPUSH
|
||||
|
||||
/obj/item/robot_module/proc/remove_status_flags(var/mob/living/silicon/robot/R)
|
||||
if(!can_be_pushed)
|
||||
R.status_flags |= CANPUSH
|
||||
|
||||
/obj/item/robot_module/proc/handle_shell(var/mob/living/silicon/robot/R)
|
||||
if(R.braintype == BORG_BRAINTYPE_AI_SHELL)
|
||||
channels = list(
|
||||
"Medical" = 1,
|
||||
"Engineering" = 1,
|
||||
"Security" = 1,
|
||||
"Service" = 1,
|
||||
"Supply" = 1,
|
||||
"Science" = 1,
|
||||
"Command" = 1,
|
||||
"Explorer" = 1
|
||||
)
|
||||
@@ -3,86 +3,68 @@
|
||||
// The module that borgs on the surface have. Generally has a lot of useful tools in exchange for questionable loyalty to the crew.
|
||||
/obj/item/robot_module/robot/lost
|
||||
name = "lost robot module"
|
||||
display_name = "Unregistered"
|
||||
module_category = ROBOT_MODULE_TYPE_FLYING
|
||||
unavailable_by_default = TRUE
|
||||
hide_on_manifest = TRUE
|
||||
sprites = list(
|
||||
"Drone" = "drone-lost"
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/lost/Initialize(var/ml)
|
||||
"Drone" = "drone-lost"
|
||||
)
|
||||
modules = list(
|
||||
/obj/item/melee/baton/shocker/robot,
|
||||
/obj/item/handcuffs/cyborg,
|
||||
/obj/item/borg/combat/shield,
|
||||
/obj/item/healthanalyzer,
|
||||
/obj/item/reagent_containers/borghypo/lost,
|
||||
/obj/item/weldingtool/electric/mounted,
|
||||
/obj/item/tool/screwdriver/cyborg,
|
||||
/obj/item/tool/wrench/cyborg,
|
||||
/obj/item/tool/wirecutters/cyborg,
|
||||
/obj/item/multitool,
|
||||
/obj/item/robotanalyzer,
|
||||
/obj/item/stack/cable_coil/cyborg
|
||||
)
|
||||
emag = /obj/item/gun/energy/retro/mounted
|
||||
synths = list(
|
||||
/datum/matter_synth/wire
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/lost/finalize_synths()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
// Sec
|
||||
src.modules += new /obj/item/melee/baton/shocker/robot(src)
|
||||
src.modules += new /obj/item/handcuffs/cyborg(src)
|
||||
src.modules += new /obj/item/borg/combat/shield(src)
|
||||
|
||||
// Med
|
||||
src.modules += new /obj/item/healthanalyzer(src)
|
||||
src.modules += new /obj/item/reagent_containers/borghypo/lost(src)
|
||||
|
||||
// Engi
|
||||
src.modules += new /obj/item/weldingtool/electric/mounted(src)
|
||||
src.modules += new /obj/item/tool/screwdriver/cyborg(src)
|
||||
src.modules += new /obj/item/tool/wrench/cyborg(src)
|
||||
src.modules += new /obj/item/tool/wirecutters/cyborg(src)
|
||||
src.modules += new /obj/item/multitool(src)
|
||||
|
||||
// Sci
|
||||
src.modules += new /obj/item/robotanalyzer(src)
|
||||
|
||||
// Potato
|
||||
src.emag = new /obj/item/gun/energy/retro/mounted(src)
|
||||
|
||||
var/datum/matter_synth/wire = new /datum/matter_synth/wire()
|
||||
synths += wire
|
||||
|
||||
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
|
||||
var/datum/matter_synth/wire/wire = locate() in synths
|
||||
var/obj/item/stack/cable_coil/cyborg/C = locate() in modules
|
||||
C.synths = list(wire)
|
||||
src.modules += C
|
||||
|
||||
/obj/item/robot_module/robot/gravekeeper
|
||||
name = "gravekeeper robot module"
|
||||
display_name = "Gravekeeper"
|
||||
unavailable_by_default = TRUE
|
||||
hide_on_manifest = TRUE
|
||||
sprites = list(
|
||||
"Drone" = "drone-gravekeeper",
|
||||
"Sleek" = "sleek-gravekeeper"
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/gravekeeper/Initialize(var/ml)
|
||||
"Gravekeeper" = "sleek-gravekeeper"
|
||||
)
|
||||
modules = list(
|
||||
/obj/item/melee/baton/shocker/robot,
|
||||
/obj/item/borg/combat/shield,
|
||||
/obj/item/weldingtool/electric/mounted,
|
||||
/obj/item/tool/screwdriver/cyborg,
|
||||
/obj/item/tool/wrench/cyborg,
|
||||
/obj/item/material/minihoe,
|
||||
/obj/item/material/knife/machete/hatchet,
|
||||
/obj/item/analyzer/plant_analyzer,
|
||||
/obj/item/storage/bag/plants,
|
||||
/obj/item/robot_harvester,
|
||||
/obj/item/shovel,
|
||||
/obj/item/gripper/gravekeeper
|
||||
)
|
||||
emag = /obj/item/gun/energy/retro/mounted
|
||||
synths = list(
|
||||
/datum/matter_synth/wood = 25000
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/gravekeeper/finalize_synths()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
// For fending off animals and looters
|
||||
src.modules += new /obj/item/melee/baton/shocker/robot(src)
|
||||
src.modules += new /obj/item/borg/combat/shield(src)
|
||||
|
||||
// For repairing gravemarkers
|
||||
src.modules += new /obj/item/weldingtool/electric/mounted(src)
|
||||
src.modules += new /obj/item/tool/screwdriver/cyborg(src)
|
||||
src.modules += new /obj/item/tool/wrench/cyborg(src)
|
||||
|
||||
// For growing flowers
|
||||
src.modules += new /obj/item/material/minihoe(src)
|
||||
src.modules += new /obj/item/material/knife/machete/hatchet(src)
|
||||
src.modules += new /obj/item/analyzer/plant_analyzer(src)
|
||||
src.modules += new /obj/item/storage/bag/plants(src)
|
||||
src.modules += new /obj/item/robot_harvester(src)
|
||||
|
||||
// For digging and beautifying graves
|
||||
src.modules += new /obj/item/shovel(src)
|
||||
src.modules += new /obj/item/gripper/gravekeeper(src)
|
||||
|
||||
// For really persistent looters
|
||||
src.emag = new /obj/item/gun/energy/retro/mounted(src)
|
||||
|
||||
var/datum/matter_synth/wood = new /datum/matter_synth/wood(25000)
|
||||
synths += wood
|
||||
|
||||
var/obj/item/stack/material/cyborg/wood/W = new (src)
|
||||
var/datum/matter_synth/wood/wood = locate() in synths
|
||||
var/obj/item/stack/material/cyborg/wood/W = locate() in modules
|
||||
W.synths = list(wood)
|
||||
src.modules += W
|
||||
src.modules += W
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
/obj/item/robot_module/drone/swarm
|
||||
name = "swarm drone module"
|
||||
display_name = "Swarm Drone"
|
||||
unavailable_by_default = TRUE
|
||||
modules = list(
|
||||
/obj/item/rcd/electric/mounted/borg/swarm,
|
||||
/obj/item/flash/robot,
|
||||
/obj/item/handcuffs/cable/tape/cyborg,
|
||||
/obj/item/melee/baton/robot,
|
||||
/obj/item/gun/energy/taser/mounted/cyborg/swarm,
|
||||
/obj/item/matter_decompiler/swarm
|
||||
)
|
||||
var/id
|
||||
|
||||
/obj/item/robot_module/drone/swarm/Initialize(var/ml)
|
||||
|
||||
/obj/item/robot_module/drone/swarm/build_equipment()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
id = R.idcard
|
||||
src.modules += id
|
||||
src.modules += new /obj/item/rcd/electric/mounted/borg/swarm(src)
|
||||
src.modules += new /obj/item/flash/robot(src)
|
||||
src.modules += new /obj/item/handcuffs/cable/tape/cyborg(src)
|
||||
src.modules += new /obj/item/melee/baton/robot(src)
|
||||
src.modules += new /obj/item/gun/energy/taser/mounted/cyborg/swarm(src)
|
||||
src.modules += new /obj/item/matter_decompiler/swarm(src)
|
||||
if(istype(R) && R.idcard)
|
||||
id = R.idcard
|
||||
modules += id
|
||||
|
||||
/obj/item/robot_module/drone/swarm/ranged
|
||||
name = "swarm gunner module"
|
||||
|
||||
/obj/item/robot_module/drone/swarm/ranged/Initialize(var/ml)
|
||||
/obj/item/robot_module/drone/swarm/ranged/build_equipment()
|
||||
. = ..()
|
||||
if(. == INITIALIZE_HINT_NORMAL)
|
||||
modules += new /obj/item/gun/energy/xray/swarm(src)
|
||||
modules += new /obj/item/gun/energy/xray/swarm(src)
|
||||
|
||||
/obj/item/robot_module/drone/swarm/melee/Initialize(var/ml)
|
||||
/obj/item/robot_module/drone/swarm/melee/build_equipment()
|
||||
. = ..()
|
||||
if(. == INITIALIZE_HINT_NORMAL)
|
||||
modules += new /obj/item/melee/energy/sword/ionic_rapier/lance(src)
|
||||
modules += new /obj/item/melee/energy/sword/ionic_rapier/lance(src)
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
/obj/item/robot_module/robot/syndicate
|
||||
name = "illegal robot module"
|
||||
display_name = "Subverted"
|
||||
hide_on_manifest = TRUE
|
||||
unavailable_by_default = TRUE
|
||||
languages = list(
|
||||
LANGUAGE_SOL_COMMON = 1,
|
||||
LANGUAGE_SIVIAN = 0,
|
||||
@@ -21,42 +23,42 @@
|
||||
LANGUAGE_ZADDAT = 0
|
||||
)
|
||||
sprites = list(
|
||||
"Cerberus" = "syndie_bloodhound",
|
||||
"Cerberus - Treaded" = "syndie_treadhound",
|
||||
"Ares" = "squats",
|
||||
"Telemachus" = "toiletbotantag",
|
||||
"WTOperator" = "hosborg",
|
||||
"XI-GUS" = "spidersyndi",
|
||||
"XI-ALP" = "syndi-heavy"
|
||||
)
|
||||
"Cerberus" = "syndie_bloodhound",
|
||||
"Cerberus - Treaded" = "syndie_treadhound",
|
||||
"Ares" = "squats",
|
||||
"Telemachus" = "toiletbotantag",
|
||||
"XI-GUS" = "spidersyndi",
|
||||
"XI-ALP" = "syndi-heavy"
|
||||
)
|
||||
universal_equipment = list(
|
||||
/obj/item/flash/robot,
|
||||
/obj/item/tool/crowbar/cyborg,
|
||||
/obj/item/extinguisher,
|
||||
/obj/item/gps/robot,
|
||||
/obj/item/pinpointer/shuttle/merc,
|
||||
/obj/item/melee/energy/sword,
|
||||
)
|
||||
jetpack = /obj/item/tank/jetpack/carbondioxide
|
||||
synths = list(
|
||||
/datum/matter_synth/cloth = 40000
|
||||
)
|
||||
var/id
|
||||
|
||||
// All syndie modules get these, and the base borg items (flash, crowbar, etc).
|
||||
/obj/item/robot_module/robot/syndicate/Initialize()
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/finalize_synths()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
src.modules += new /obj/item/pinpointer/shuttle/merc(src)
|
||||
src.modules += new /obj/item/melee/energy/sword(src)
|
||||
|
||||
var/datum/matter_synth/cloth = new /datum/matter_synth/cloth(40000)
|
||||
synths += cloth
|
||||
|
||||
var/obj/item/stack/sandbags/cyborg/SB = new /obj/item/stack/sandbags/cyborg(src)
|
||||
var/datum/matter_synth/cloth/cloth = locate() in synths
|
||||
var/obj/item/stack/sandbags/cyborg/SB = locate() in modules
|
||||
SB.synths += list(cloth)
|
||||
|
||||
var/jetpack = new/obj/item/tank/jetpack/carbondioxide(src)
|
||||
src.modules += jetpack
|
||||
/obj/item/robot_module/robot/syndicate/finalize_equipment()
|
||||
. = ..()
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
R.internals = jetpack
|
||||
|
||||
id = R.idcard
|
||||
src.modules += id
|
||||
if(istype(R))
|
||||
id = R.idcard
|
||||
modules += id
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/Destroy()
|
||||
src.modules -= id
|
||||
id = null
|
||||
return ..()
|
||||
|
||||
@@ -69,17 +71,12 @@
|
||||
"Ares" = "squats",
|
||||
"XI-ALP" = "syndi-heavy"
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/protector/Initialize()
|
||||
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
src.modules += new /obj/item/shield_projector/rectangle/weak(src)
|
||||
src.modules += new /obj/item/gun/energy/dakkalaser(src)
|
||||
src.modules += new /obj/item/handcuffs/cyborg(src)
|
||||
src.modules += new /obj/item/melee/baton/robot(src)
|
||||
modules = list(
|
||||
/obj/item/shield_projector/rectangle/weak,
|
||||
/obj/item/gun/energy/dakkalaser,
|
||||
/obj/item/handcuffs/cyborg,
|
||||
/obj/item/melee/baton/robot
|
||||
)
|
||||
|
||||
// 95% engi-borg and 15% roboticist.
|
||||
/obj/item/robot_module/robot/syndicate/mechanist
|
||||
@@ -87,133 +84,114 @@
|
||||
sprites = list(
|
||||
"XI-GUS" = "spidersyndi",
|
||||
"WTOperator" = "sleekhos"
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/mechanist/Initialize()
|
||||
)
|
||||
modules = list(
|
||||
/obj/item/borg/sight/meson,
|
||||
/obj/item/weldingtool/electric/mounted/cyborg,
|
||||
/obj/item/tool/screwdriver/cyborg,
|
||||
/obj/item/tool/wrench/cyborg,
|
||||
/obj/item/tool/wirecutters/cyborg,
|
||||
/obj/item/multitool/ai_detector,
|
||||
/obj/item/pickaxe/plasmacutter,
|
||||
/obj/item/rcd/electric/mounted/borg/lesser,
|
||||
/obj/item/melee/energy/sword/ionic_rapier,
|
||||
/obj/item/robotanalyzer,
|
||||
/obj/item/shockpaddles/robot/jumper,
|
||||
/obj/item/gripper/no_use/organ/robotics,
|
||||
/obj/item/card/robot/syndi,
|
||||
/obj/item/card/emag,
|
||||
/obj/item/stack/nanopaste,
|
||||
/obj/item/stack/material/cyborg/steel,
|
||||
/obj/item/stack/material/cyborg/glass,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/cable_coil/cyborg,
|
||||
/obj/item/stack/material/cyborg/glass/reinforced
|
||||
)
|
||||
synths = list(
|
||||
/datum/matter_synth/nanite = 10000,
|
||||
/datum/matter_synth/metal = 40000,
|
||||
/datum/matter_synth/glass = 40000,
|
||||
/datum/matter_synth/wire
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/mechanist/finalize_synths()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
// General engineering/hacking.
|
||||
src.modules += new /obj/item/borg/sight/meson(src)
|
||||
src.modules += new /obj/item/weldingtool/electric/mounted/cyborg(src)
|
||||
src.modules += new /obj/item/tool/screwdriver/cyborg(src)
|
||||
src.modules += new /obj/item/tool/wrench/cyborg(src)
|
||||
src.modules += new /obj/item/tool/wirecutters/cyborg(src)
|
||||
src.modules += new /obj/item/multitool/ai_detector(src)
|
||||
src.modules += new /obj/item/pickaxe/plasmacutter(src)
|
||||
src.modules += new /obj/item/rcd/electric/mounted/borg/lesser(src) // Can't eat rwalls to prevent AI core cheese.
|
||||
src.modules += new /obj/item/melee/energy/sword/ionic_rapier(src)
|
||||
|
||||
// FBP repair.
|
||||
src.modules += new /obj/item/robotanalyzer(src)
|
||||
src.modules += new /obj/item/shockpaddles/robot/jumper(src)
|
||||
src.modules += new /obj/item/gripper/no_use/organ/robotics(src)
|
||||
|
||||
// Hacking other things.
|
||||
src.modules += new /obj/item/card/robot/syndi(src)
|
||||
src.modules += new /obj/item/card/emag(src)
|
||||
|
||||
// Materials.
|
||||
var/datum/matter_synth/nanite = new /datum/matter_synth/nanite(10000)
|
||||
synths += nanite
|
||||
var/datum/matter_synth/wire = new /datum/matter_synth/wire()
|
||||
synths += wire
|
||||
var/datum/matter_synth/metal = new /datum/matter_synth/metal(40000)
|
||||
synths += metal
|
||||
var/datum/matter_synth/glass = new /datum/matter_synth/glass(40000)
|
||||
synths += glass
|
||||
|
||||
var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src)
|
||||
var/datum/matter_synth/nanite/nanite = locate() in synths
|
||||
var/obj/item/stack/nanopaste/N = locate() in modules
|
||||
N.uses_charge = 1
|
||||
N.charge_costs = list(1000)
|
||||
N.synths = list(nanite)
|
||||
src.modules += N
|
||||
|
||||
var/obj/item/stack/material/cyborg/steel/M = new (src)
|
||||
var/datum/matter_synth/metal/metal = locate() in synths
|
||||
var/obj/item/stack/material/cyborg/steel/M = locate() in modules
|
||||
var/obj/item/stack/rods/cyborg/rods = locate() in modules
|
||||
M.synths = list(metal)
|
||||
src.modules += M
|
||||
|
||||
var/obj/item/stack/material/cyborg/glass/G = new (src)
|
||||
G.synths = list(glass)
|
||||
src.modules += G
|
||||
|
||||
var/obj/item/stack/rods/cyborg/rods = new /obj/item/stack/rods/cyborg(src)
|
||||
rods.synths = list(metal)
|
||||
src.modules += rods
|
||||
|
||||
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
|
||||
var/datum/matter_synth/glass/glass = locate() in synths
|
||||
var/obj/item/stack/material/cyborg/glass/G = locate() in modules
|
||||
G.synths = list(glass)
|
||||
|
||||
var/datum/matter_synth/wire/wire = locate() in synths
|
||||
var/obj/item/stack/cable_coil/cyborg/C = locate() in modules
|
||||
C.synths = list(wire)
|
||||
src.modules += C
|
||||
|
||||
var/obj/item/stack/material/cyborg/glass/reinforced/RG = new (src)
|
||||
var/obj/item/stack/material/cyborg/glass/reinforced/RG = locate() in modules
|
||||
RG.synths = list(metal, glass)
|
||||
src.modules += RG
|
||||
|
||||
|
||||
|
||||
|
||||
// Mediborg optimized for on-the-field healing, but can also do surgery if needed.
|
||||
/obj/item/robot_module/robot/syndicate/combat_medic
|
||||
name = "combat medic robot module"
|
||||
sprites = list(
|
||||
"Telemachus" = "toiletbotantag"
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/combat_medic/Initialize()
|
||||
)
|
||||
modules = list(
|
||||
/obj/item/borg/sight/hud/med,
|
||||
/obj/item/healthanalyzer/advanced,
|
||||
/obj/item/reagent_containers/borghypo/merc,
|
||||
/obj/item/autopsy_scanner,
|
||||
/obj/item/surgical/scalpel/cyborg,
|
||||
/obj/item/surgical/hemostat/cyborg,
|
||||
/obj/item/surgical/retractor/cyborg,
|
||||
/obj/item/surgical/cautery/cyborg,
|
||||
/obj/item/surgical/bonegel/cyborg,
|
||||
/obj/item/surgical/FixOVein/cyborg,
|
||||
/obj/item/surgical/bonesetter/cyborg,
|
||||
/obj/item/surgical/circular_saw/cyborg,
|
||||
/obj/item/surgical/surgicaldrill/cyborg,
|
||||
/obj/item/gripper/no_use/organ,
|
||||
/obj/item/gripper/medical,
|
||||
/obj/item/shockpaddles/robot/combat,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/item/reagent_containers/syringe,
|
||||
/obj/item/roller_holder,
|
||||
/obj/item/stack/medical/advanced/ointment,
|
||||
/obj/item/stack/medical/advanced/bruise_pack,
|
||||
/obj/item/stack/medical/splint
|
||||
)
|
||||
synths = list(
|
||||
/datum/matter_synth/medicine = 15000
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/combat_medic/finalize_synths()
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
src.modules += new /obj/item/borg/sight/hud/med(src)
|
||||
src.modules += new /obj/item/healthanalyzer/advanced(src)
|
||||
src.modules += new /obj/item/reagent_containers/borghypo/merc(src)
|
||||
|
||||
// Surgery things.
|
||||
src.modules += new /obj/item/autopsy_scanner(src)
|
||||
src.modules += new /obj/item/surgical/scalpel/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/hemostat/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/retractor/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/cautery/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/bonegel/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/FixOVein/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/bonesetter/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/circular_saw/cyborg(src)
|
||||
src.modules += new /obj/item/surgical/surgicaldrill/cyborg(src)
|
||||
src.modules += new /obj/item/gripper/no_use/organ(src)
|
||||
|
||||
// General healing.
|
||||
src.modules += new /obj/item/gripper/medical(src)
|
||||
src.modules += new /obj/item/shockpaddles/robot/combat(src)
|
||||
src.modules += new /obj/item/reagent_containers/dropper(src) // Allows borg to fix necrosis apparently
|
||||
src.modules += new /obj/item/reagent_containers/syringe(src)
|
||||
src.modules += new /obj/item/roller_holder(src)
|
||||
|
||||
// Materials.
|
||||
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(15000)
|
||||
synths += medicine
|
||||
|
||||
var/obj/item/stack/medical/advanced/ointment/O = new /obj/item/stack/medical/advanced/ointment(src)
|
||||
var/obj/item/stack/medical/advanced/bruise_pack/B = new /obj/item/stack/medical/advanced/bruise_pack(src)
|
||||
var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src)
|
||||
var/datum/matter_synth/medicine/medicine = locate() in synths
|
||||
var/obj/item/stack/medical/advanced/ointment/O = locate() in modules
|
||||
O.uses_charge = 1
|
||||
O.charge_costs = list(1000)
|
||||
O.synths = list(medicine)
|
||||
var/obj/item/stack/medical/advanced/bruise_pack/B = locate() in modules
|
||||
B.uses_charge = 1
|
||||
B.charge_costs = list(1000)
|
||||
B.synths = list(medicine)
|
||||
var/obj/item/stack/medical/splint/S = locate() in modules
|
||||
S.uses_charge = 1
|
||||
S.charge_costs = list(1000)
|
||||
S.synths = list(medicine)
|
||||
src.modules += O
|
||||
src.modules += B
|
||||
src.modules += S
|
||||
|
||||
/obj/item/robot_module/robot/syndicate/combat_medic/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
|
||||
var/obj/item/reagent_containers/syringe/S = locate() in src.modules
|
||||
var/obj/item/reagent_containers/syringe/S = locate() in modules
|
||||
if(S.mode == 2)
|
||||
S.reagents.clear_reagents()
|
||||
S.mode = initial(S.mode)
|
||||
|
||||
@@ -1,29 +1,11 @@
|
||||
/mob/living/silicon/robot/get_jetpack()
|
||||
if(module)
|
||||
for(var/obj/item/tank/jetpack/J in module.modules)
|
||||
return J
|
||||
return module?.jetpack
|
||||
|
||||
/mob/living/silicon/robot/Check_Shoegrip()
|
||||
return module && module.no_slip
|
||||
|
||||
/mob/living/silicon/robot/Process_Spaceslipping(var/prob_slip)
|
||||
var/obj/item/tank/jetpack/thrust = get_jetpack()
|
||||
if(thrust?.can_thrust(0.01))
|
||||
return 0
|
||||
if(module && module.no_slip)
|
||||
return 0
|
||||
..(prob_slip)
|
||||
|
||||
/mob/living/silicon/robot/Process_Spacemove(var/check_drift = 0)
|
||||
if(..())//Can move due to other reasons, don't use jetpack fuel
|
||||
return 1
|
||||
|
||||
var/obj/item/tank/jetpack/thrust = get_jetpack()
|
||||
if(thrust && (!check_drift || (check_drift && thrust.stabilization_on)) && thrust.do_thrust(0.01))
|
||||
inertia_dir = 0
|
||||
return 1
|
||||
|
||||
return 0
|
||||
return ..(module?.no_slip ? 0 : prob_slip)
|
||||
|
||||
//No longer needed, but I'll leave it here incase we plan to re-use it.
|
||||
/mob/living/silicon/robot/movement_delay()
|
||||
@@ -43,7 +25,7 @@
|
||||
return 0
|
||||
|
||||
var/datum/robot_component/actuator/A = get_component("actuator")
|
||||
if (cell_use_power(A.active_usage))
|
||||
if (cell_use_power(A.active_usage * power_efficiency))
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/mob/living/silicon/robot/flying
|
||||
desc = "A utility robot with an anti-gravity hover unit and a lightweight frame."
|
||||
icon = 'icons/mob/robots/robots_flying.dmi'
|
||||
icon_state = "drone-standard"
|
||||
module_category = ROBOT_MODULE_TYPE_FLYING
|
||||
dismantle_type = /obj/item/robot_parts/frame/flyer
|
||||
power_efficiency = 0.75
|
||||
|
||||
// They are not very heavy or strong.
|
||||
mob_size = MOB_SMALL
|
||||
mob_bump_flag = SIMPLE_ANIMAL
|
||||
mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
|
||||
/mob/living/silicon/robot/flying/initialize_components()
|
||||
components["actuator"] = new/datum/robot_component/actuator(src)
|
||||
components["radio"] = new/datum/robot_component/radio(src)
|
||||
components["power cell"] = new/datum/robot_component/cell(src)
|
||||
components["diagnosis unit"] = new/datum/robot_component/diagnosis_unit(src)
|
||||
components["camera"] = new /datum/robot_component/camera(src)
|
||||
components["comms"] = new/datum/robot_component/binary_communication(src)
|
||||
components["armour"] = new/datum/robot_component/armour/light(src)
|
||||
|
||||
/mob/living/silicon/robot/flying/Life()
|
||||
. = ..()
|
||||
if(incapacitated() || !is_component_functioning("actuator"))
|
||||
stop_hovering()
|
||||
else
|
||||
start_hovering()
|
||||
|
||||
/mob/living/silicon/robot/flying/proc/start_hovering()
|
||||
hovering = TRUE
|
||||
pass_flags |= PASSTABLE
|
||||
default_pixel_y = 0
|
||||
make_floating(10)
|
||||
|
||||
/mob/living/silicon/robot/flying/proc/stop_hovering()
|
||||
hovering = FALSE
|
||||
pass_flags &= ~PASSTABLE
|
||||
default_pixel_y = -8
|
||||
stop_floating()
|
||||
|
||||
/mob/living/silicon/robot/flying/death()
|
||||
. = ..()
|
||||
if(!QDELETED(src) && stat == DEAD)
|
||||
stop_hovering()
|
||||
|
||||
/mob/living/silicon/robot/flying/Allow_Spacemove(var/dense_object, check_drift = 0)
|
||||
return hovering || ..()
|
||||
|
||||
/mob/living/silicon/robot/flying/Process_Spaceslipping(var/prob_slip = 5)
|
||||
return ..(hovering ? 0 : prob_slip)
|
||||
|
||||
/mob/living/silicon/robot/flying/can_fall(anchor_bypass = FALSE, turf/location_override = loc)
|
||||
return !hovering && ..()
|
||||
|
||||
/mob/living/silicon/robot/flying/can_overcome_gravity()
|
||||
return hovering
|
||||
@@ -11,17 +11,12 @@
|
||||
|
||||
/mob/living/silicon/robot/gravekeeper/init()
|
||||
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
|
||||
mmi = new /obj/item/mmi/digital/robot(src)
|
||||
module = new /obj/item/robot_module/robot/gravekeeper(src)
|
||||
cut_overlays()
|
||||
init_id()
|
||||
|
||||
updatename("Gravekeeper")
|
||||
|
||||
if(!cell)
|
||||
cell = new /obj/item/cell/high(src) // 15k cell, as recharging stations are a lot more rare on the Surface.
|
||||
|
||||
laws = new /datum/ai_laws/gravekeeper()
|
||||
|
||||
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/silicon/robot/lost
|
||||
/mob/living/silicon/robot/flying/lost
|
||||
lawupdate = 0
|
||||
scrambledcodes = 1
|
||||
icon_state = "drone-lost"
|
||||
@@ -8,7 +8,7 @@
|
||||
idcard_type = /obj/item/card/id
|
||||
icon_selected = FALSE
|
||||
|
||||
/mob/living/silicon/robot/lost/init()
|
||||
/mob/living/silicon/robot/flying/lost/init()
|
||||
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
|
||||
mmi = new /obj/item/mmi/digital/robot(src)
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
playsound(src, 'sound/mecha/nominalsyndi.ogg', 75, 0)
|
||||
|
||||
/mob/living/silicon/robot/lost/speech_bubble_appearance()
|
||||
/mob/living/silicon/robot/flying/lost/speech_bubble_appearance()
|
||||
return "synthetic_evil"
|
||||
|
||||
/mob/living/silicon/robot/lost/randomlaws
|
||||
/mob/living/silicon/robot/flying/lost/randomlaws
|
||||
|
||||
/mob/living/silicon/robot/lost/randomlaws/init()
|
||||
/mob/living/silicon/robot/flying/lost/randomlaws/init()
|
||||
..()
|
||||
laws = give_random_lawset()
|
||||
|
||||
|
||||
@@ -1,28 +1,12 @@
|
||||
// Spawner landmarks are used because platforms that are mapped during
|
||||
// SSatoms init try to Initialize() twice. I have no idea why and I am
|
||||
// not paid enough to spend more time trying to debug it.
|
||||
/obj/effect/landmark/robot_platform
|
||||
name = "recon platform spawner"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x3"
|
||||
delete_me = TRUE
|
||||
var/platform_type
|
||||
|
||||
/obj/effect/landmark/robot_platform/Initialize()
|
||||
if(platform_type)
|
||||
new platform_type(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/platform
|
||||
name = "support platform"
|
||||
desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence."
|
||||
icon = 'icons/mob/robots_thinktank.dmi'
|
||||
icon = 'icons/mob/robots/robots_platform.dmi'
|
||||
icon_state = "tachi"
|
||||
color = "#68a2f2"
|
||||
|
||||
cell = /obj/item/cell/mech
|
||||
idcard_type = /obj/item/card/id/platform
|
||||
module = /obj/item/robot_module/robot/platform
|
||||
|
||||
lawupdate = FALSE
|
||||
modtype = "Standard"
|
||||
@@ -33,6 +17,10 @@
|
||||
mob_push_flags = HEAVY
|
||||
mob_size = MOB_LARGE
|
||||
|
||||
dismantle_type = /obj/item/robot_parts/frame/platform
|
||||
module_category = ROBOT_MODULE_TYPE_PLATFORM
|
||||
|
||||
var/mapped = FALSE
|
||||
var/has_had_player = FALSE
|
||||
var/const/platform_respawn_time = 3 MINUTES
|
||||
|
||||
@@ -42,19 +30,6 @@
|
||||
var/tmp/recharger_tick_cost = 80 KILOWATTS
|
||||
var/weakref/recharging
|
||||
|
||||
var/list/stored_atoms
|
||||
var/max_stored_atoms = 1
|
||||
var/static/list/can_store_types = list(
|
||||
/mob/living,
|
||||
/obj/item,
|
||||
/obj/structure,
|
||||
/obj/machinery
|
||||
)
|
||||
// Currently set to prevent tonks hauling a deliaminating SM into the middle of the station.
|
||||
var/static/list/cannot_store_types = list(
|
||||
/obj/machinery/power/supermatter
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/platform/Login()
|
||||
. = ..()
|
||||
has_had_player = TRUE
|
||||
@@ -66,9 +41,10 @@
|
||||
|
||||
/mob/living/silicon/robot/platform/Initialize(var/mapload)
|
||||
. = ..()
|
||||
if(!mmi)
|
||||
mmi = new /obj/item/mmi/digital/robot(src)
|
||||
SetName("inactive [initial(name)]")
|
||||
if(mapped)
|
||||
if(!mmi)
|
||||
mmi = new /obj/item/mmi/digital/robot(src)
|
||||
SetName("inactive [initial(name)]")
|
||||
updateicon()
|
||||
|
||||
// Copypasting from root proc to avoid calling ..() and accidentally creating duplicate armour etc.
|
||||
@@ -82,11 +58,13 @@
|
||||
components["armour"] = new /datum/robot_component/armour/platform(src)
|
||||
|
||||
/mob/living/silicon/robot/platform/Destroy()
|
||||
for(var/weakref/drop_ref in stored_atoms)
|
||||
var/atom/movable/drop_atom = drop_ref.resolve()
|
||||
if(istype(drop_atom) && !QDELETED(drop_atom) && drop_atom.loc == src)
|
||||
drop_atom.dropInto(loc)
|
||||
stored_atoms = null
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(istype(thinktank_module))
|
||||
for(var/weakref/drop_ref in thinktank_module.stored_atoms)
|
||||
var/atom/movable/drop_atom = drop_ref.resolve()
|
||||
if(istype(drop_atom) && !QDELETED(drop_atom) && drop_atom.loc == src)
|
||||
drop_atom.dropInto(loc)
|
||||
thinktank_module.stored_atoms = null
|
||||
if(recharging)
|
||||
var/obj/item/recharging_atom = recharging.resolve()
|
||||
if(istype(recharging_atom) && recharging_atom.loc == src)
|
||||
@@ -108,9 +86,10 @@
|
||||
else
|
||||
. += "Its recharging port is empty."
|
||||
|
||||
if(length(stored_atoms))
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(istype(thinktank_module) && length(thinktank_module.stored_atoms))
|
||||
var/list/atom_names = list()
|
||||
for(var/weakref/stored_ref in stored_atoms)
|
||||
for(var/weakref/stored_ref in thinktank_module.stored_atoms)
|
||||
var/atom/movable/AM = stored_ref.resolve()
|
||||
if(istype(AM))
|
||||
atom_names += "\a [AM]"
|
||||
@@ -127,9 +106,6 @@
|
||||
if(ispath(module, /obj/item/robot_module))
|
||||
module = new module(src)
|
||||
|
||||
/mob/living/silicon/robot/platform/module_reset()
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/robot/platform/use_power()
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -5,56 +5,74 @@
|
||||
|
||||
cut_overlays()
|
||||
underlays.Cut()
|
||||
|
||||
var/use_armor_color
|
||||
var/use_pupil_color
|
||||
var/use_base_color
|
||||
var/use_eye_color
|
||||
var/use_state
|
||||
var/list/use_decals
|
||||
var/obj/item/robot_module/robot/platform/tank_module = module
|
||||
if(!istype(tank_module))
|
||||
icon = initial(icon)
|
||||
icon_state = initial(icon_state)
|
||||
color = initial(color)
|
||||
return
|
||||
if(istype(tank_module))
|
||||
use_pupil_color = tank_module.pupil_color
|
||||
use_base_color = tank_module.base_color
|
||||
use_eye_color = tank_module.eye_color
|
||||
use_armor_color = tank_module.armor_color
|
||||
icon = tank_module.user_icon
|
||||
use_state = tank_module.user_icon_state
|
||||
use_decals = tank_module.decals
|
||||
else
|
||||
tank_module = /obj/item/robot_module/robot/platform
|
||||
use_pupil_color = initial(tank_module.pupil_color)
|
||||
use_base_color = initial(tank_module.base_color)
|
||||
use_eye_color = initial(tank_module.eye_color)
|
||||
use_armor_color = initial(tank_module.armor_color)
|
||||
icon = initial(tank_module.user_icon)
|
||||
use_state = initial(tank_module.user_icon_state)
|
||||
|
||||
// This is necessary due to Polaris' liberal use of KEEP_TOGETHER and propensity for scaling transforms.
|
||||
// If we just apply state/colour to the base icon, RESET_COLOR on the additional overlays is ignored.
|
||||
icon = tank_module.user_icon
|
||||
icon_state = "blank"
|
||||
color = null
|
||||
var/image/I = image(tank_module.user_icon, tank_module.user_icon_state)
|
||||
I.color = tank_module.base_color
|
||||
|
||||
var/image/I = image(icon, use_state)
|
||||
I.color = use_base_color
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
underlays += I
|
||||
|
||||
if(tank_module.armor_color)
|
||||
I = image(icon, "[tank_module.user_icon_state]_armour")
|
||||
I.color = tank_module.armor_color
|
||||
if(use_armor_color)
|
||||
I = image(icon, "[use_state]_armour")
|
||||
I.color = use_armor_color
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
add_overlay(I)
|
||||
|
||||
for(var/decal in tank_module.decals)
|
||||
I = image(icon, "[tank_module.user_icon_state]_[decal]")
|
||||
I.color = tank_module.decals[decal]
|
||||
for(var/decal in use_decals)
|
||||
I = image(icon, "[use_state]_[decal]")
|
||||
I.color = use_decals[decal]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
add_overlay(I)
|
||||
|
||||
if(tank_module.eye_color)
|
||||
I = image(icon, "[tank_module.user_icon_state]_eyes")
|
||||
I.color = tank_module.eye_color
|
||||
if(use_eye_color)
|
||||
I = image(icon, "[use_state]_eyes")
|
||||
I.color = use_eye_color
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
add_overlay(I)
|
||||
|
||||
if(client && key && stat == CONSCIOUS && tank_module.pupil_color)
|
||||
I = image(icon, "[tank_module.user_icon_state]_pupils")
|
||||
I.color = tank_module.pupil_color
|
||||
if(use_pupil_color && client && key && stat == CONSCIOUS)
|
||||
I = image(icon, "[use_state]_pupils")
|
||||
I.color = use_pupil_color
|
||||
I.plane = PLANE_LIGHTING_ABOVE
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
add_overlay(I)
|
||||
|
||||
if(opened)
|
||||
add_overlay("[tank_module.user_icon_state]-open")
|
||||
add_overlay("[use_state]-open")
|
||||
if(wiresexposed)
|
||||
I = image(icon, "[tank_module.user_icon_state]-wires")
|
||||
I = image(icon, "[use_state]-wires")
|
||||
else if(cell)
|
||||
I = image(icon, "[tank_module.user_icon_state]-cell")
|
||||
I = image(icon, "[use_state]-cell")
|
||||
else
|
||||
I = image(icon, "[tank_module.user_icon_state]-nowires")
|
||||
I = image(icon, "[use_state]-nowires")
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
add_overlay(I)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
/mob/living/silicon/robot/platform/attack_ghost(mob/observer/ghost/user)
|
||||
|
||||
if(client || key || stat == DEAD || !ticker || !ticker.mode)
|
||||
if(!mapped || client || key || stat == DEAD || !ticker || !ticker.mode)
|
||||
return ..()
|
||||
|
||||
var/confirm = alert("Do you wish to take control of \the [src]?", "Platform Control", "No", "Yes")
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
if(jobban_isbanned(user, "Robot"))
|
||||
to_chat(user, SPAN_WARNING("You are banned from synthetic roles and cannot take control of \the [src]."))
|
||||
return
|
||||
return
|
||||
|
||||
// Boilerplate from drone fabs, unsure if there's a shared proc to use instead.
|
||||
var/deathtime = world.time - user.timeofdeath
|
||||
|
||||
@@ -1,25 +1,36 @@
|
||||
/obj/item/robot_module/robot/platform
|
||||
|
||||
hide_on_manifest = TRUE
|
||||
module_category = ROBOT_MODULE_TYPE_PLATFORM
|
||||
unavailable_by_default = TRUE
|
||||
|
||||
var/pupil_color = COLOR_CYAN
|
||||
var/base_color = COLOR_WHITE
|
||||
var/eye_color = COLOR_BEIGE
|
||||
var/armor_color = "#68a2f2"
|
||||
var/user_icon = 'icons/mob/robots_thinktank.dmi'
|
||||
var/user_icon = 'icons/mob/robots/robots_platform.dmi'
|
||||
var/user_icon_state = "tachi"
|
||||
|
||||
var/list/decals
|
||||
var/list/available_decals = list(
|
||||
"Stripe" = "stripe",
|
||||
"Stripe" = "stripe",
|
||||
"Vertical Stripe" = "stripe_vertical"
|
||||
)
|
||||
|
||||
// Only show on manifest if they have a player.
|
||||
/obj/item/robot_module/robot/platform/hide_on_manifest()
|
||||
if(isrobot(loc))
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
return !R.key
|
||||
var/list/stored_atoms
|
||||
var/max_stored_atoms = 1
|
||||
var/static/list/can_store_types = list(
|
||||
/mob/living,
|
||||
/obj/item,
|
||||
/obj/structure,
|
||||
/obj/machinery
|
||||
)
|
||||
// Currently set to prevent tonks hauling a deliaminating SM into the middle of the station.
|
||||
var/static/list/cannot_store_types = list(
|
||||
/obj/machinery/power/supermatter
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/platform/Destroy()
|
||||
QDEL_NULL_LIST(stored_atoms)
|
||||
return ..()
|
||||
|
||||
/obj/item/robot_module/robot/platform/verb/set_eye_colour()
|
||||
@@ -31,11 +42,14 @@
|
||||
var/new_pupil_color = input(usr, "Select a pupil colour.", "Pupil Colour Selection") as color|null
|
||||
if(usr.incapacitated() || QDELETED(usr) || QDELETED(src) || loc != usr)
|
||||
return
|
||||
|
||||
|
||||
pupil_color = new_pupil_color || initial(pupil_color)
|
||||
usr.update_icon()
|
||||
|
||||
/obj/item/robot_module/robot/platform/explorer
|
||||
name = "recon platform module"
|
||||
display_name = "Recon"
|
||||
unavailable_by_default = FALSE
|
||||
armor_color = "#528052"
|
||||
eye_color = "#7b7b46"
|
||||
decals = list(
|
||||
@@ -46,32 +60,28 @@
|
||||
"Science" = 1,
|
||||
"Explorer" = 1
|
||||
)
|
||||
modules = list(
|
||||
/obj/item/tool/wrench/cyborg,
|
||||
/obj/item/weldingtool/electric/mounted/cyborg,
|
||||
/obj/item/tool/wirecutters/cyborg,
|
||||
/obj/item/tool/screwdriver/cyborg,
|
||||
/obj/item/pickaxe/plasmacutter,
|
||||
/obj/item/material/knife/machete/cyborg,
|
||||
/obj/item/gun/energy/phasegun/mounted/cyborg,
|
||||
/obj/item/stack/medical/bruise_pack
|
||||
)
|
||||
emag = /obj/item/chainsaw
|
||||
synths = list(
|
||||
/datum/matter_synth/medicine = 7500
|
||||
)
|
||||
|
||||
/obj/item/robot_module/robot/platform/explorer/Initialize()
|
||||
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
modules += new /obj/item/tool/wrench/cyborg(src)
|
||||
modules += new /obj/item/weldingtool/electric/mounted/cyborg(src)
|
||||
modules += new /obj/item/tool/wirecutters/cyborg(src)
|
||||
modules += new /obj/item/tool/screwdriver/cyborg(src)
|
||||
modules += new /obj/item/pickaxe/plasmacutter(src)
|
||||
modules += new /obj/item/material/knife/machete/cyborg(src)
|
||||
|
||||
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(7500)
|
||||
var/obj/item/stack/medical/bruise_pack/bandaid = new(src)
|
||||
/obj/item/robot_module/robot/platform/explorer/finalize_synths()
|
||||
..()
|
||||
var/datum/matter_synth/medicine/medicine = locate() in synths
|
||||
var/obj/item/stack/medical/bruise_pack/bandaid = locate() in modules
|
||||
bandaid.uses_charge = 1
|
||||
bandaid.charge_costs = list(1000)
|
||||
bandaid.synths = list(medicine)
|
||||
modules += bandaid
|
||||
synths += medicine
|
||||
|
||||
var/obj/item/gun/energy/phasegun/mounted/cyborg/phasegun = new(src)
|
||||
modules += phasegun
|
||||
|
||||
emag = new /obj/item/chainsaw(src)
|
||||
|
||||
/obj/item/robot_module/robot/platform/explorer/respawn_consumable(var/mob/living/silicon/robot/R, rate)
|
||||
. = ..()
|
||||
@@ -83,6 +93,9 @@
|
||||
pew.charge_tick = 0
|
||||
|
||||
/obj/item/robot_module/robot/platform/cargo
|
||||
name = "logistics platform module"
|
||||
display_name = "Logistics"
|
||||
unavailable_by_default = FALSE
|
||||
armor_color = "#d5b222"
|
||||
eye_color = "#686846"
|
||||
decals = list(
|
||||
@@ -91,17 +104,13 @@
|
||||
)
|
||||
channels = list("Supply" = 1)
|
||||
networks = list(NETWORK_MINE)
|
||||
|
||||
/obj/item/robot_module/robot/platform/cargo/Initialize()
|
||||
|
||||
. = ..()
|
||||
if(. != INITIALIZE_HINT_NORMAL)
|
||||
return
|
||||
|
||||
modules += new /obj/item/packageWrap(src)
|
||||
modules += new /obj/item/pen/multi(src)
|
||||
modules += new /obj/item/destTagger(src)
|
||||
emag = new /obj/item/stamp/denied
|
||||
max_stored_atoms = 3
|
||||
modules = list(
|
||||
/obj/item/packageWrap,
|
||||
/obj/item/pen/multi,
|
||||
/obj/item/destTagger,
|
||||
)
|
||||
emag = /obj/item/stamp/denied
|
||||
|
||||
/obj/item/robot_module/robot/platform/cargo/respawn_consumable(mob/living/silicon/robot/R, rate)
|
||||
. = ..()
|
||||
|
||||
@@ -9,18 +9,24 @@
|
||||
recharging_atom.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),30)
|
||||
recharging = null
|
||||
|
||||
if(length(stored_atoms))
|
||||
for(var/weakref/stored_ref in stored_atoms)
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(istype(thinktank_module) && length(thinktank_module.stored_atoms))
|
||||
for(var/weakref/stored_ref in thinktank_module.stored_atoms)
|
||||
var/atom/movable/dropping = stored_ref.resolve()
|
||||
if(istype(dropping) && !QDELETED(dropping) && dropping.loc == src)
|
||||
dropping.dropInto(loc)
|
||||
dropping.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),30)
|
||||
stored_atoms = null
|
||||
thinktank_module.stored_atoms = null
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/robot/platform/proc/can_store_atom(var/atom/movable/storing, var/mob/user)
|
||||
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(!istype(thinktank_module))
|
||||
to_chat(user, SPAN_WARNING("Select a module first!"))
|
||||
return FALSE
|
||||
|
||||
if(!istype(storing))
|
||||
var/storing_target = (user == src) ? "yourself" : "\the [src]"
|
||||
to_chat(user, SPAN_WARNING("You cannot store that inside [storing_target]."))
|
||||
@@ -38,7 +44,7 @@
|
||||
to_chat(user, SPAN_WARNING("You cannot store [storing_target] inside [storing_target]!"))
|
||||
return FALSE
|
||||
|
||||
if(length(stored_atoms) >= max_stored_atoms)
|
||||
if(length(thinktank_module.stored_atoms) >= thinktank_module.max_stored_atoms)
|
||||
var/storing_target = (user == src) ? "Your" : "\The [src]'s"
|
||||
to_chat(user, SPAN_WARNING("[storing_target] cargo compartment is full."))
|
||||
return FALSE
|
||||
@@ -50,13 +56,13 @@
|
||||
to_chat(user, SPAN_WARNING("\The [storing] is too big for [storing_target]."))
|
||||
return FALSE
|
||||
|
||||
for(var/store_type in can_store_types)
|
||||
for(var/store_type in thinktank_module.can_store_types)
|
||||
if(istype(storing, store_type))
|
||||
. = TRUE
|
||||
break
|
||||
|
||||
if(.)
|
||||
for(var/store_type in cannot_store_types)
|
||||
for(var/store_type in thinktank_module.cannot_store_types)
|
||||
if(istype(storing, store_type))
|
||||
. = FALSE
|
||||
break
|
||||
@@ -65,20 +71,25 @@
|
||||
to_chat(user, SPAN_WARNING("You cannot store \the [storing] inside [storing_target]."))
|
||||
|
||||
/mob/living/silicon/robot/platform/proc/store_atom(var/atom/movable/storing, var/mob/user)
|
||||
if(istype(storing))
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(istype(thinktank_module) && istype(storing))
|
||||
storing.forceMove(src)
|
||||
LAZYDISTINCTADD(stored_atoms, weakref(storing))
|
||||
LAZYDISTINCTADD(thinktank_module.stored_atoms, weakref(storing))
|
||||
|
||||
/mob/living/silicon/robot/platform/proc/drop_stored_atom(var/atom/movable/ejecting, var/mob/user)
|
||||
|
||||
if(!ejecting && length(stored_atoms))
|
||||
var/weakref/stored_ref = stored_atoms[1]
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(!istype(thinktank_module))
|
||||
return
|
||||
|
||||
if(!ejecting && length(thinktank_module.stored_atoms))
|
||||
var/weakref/stored_ref = thinktank_module.stored_atoms[1]
|
||||
if(!istype(stored_ref))
|
||||
LAZYREMOVE(stored_atoms, stored_ref)
|
||||
LAZYREMOVE(thinktank_module.stored_atoms, stored_ref)
|
||||
else
|
||||
ejecting = stored_ref?.resolve()
|
||||
|
||||
LAZYREMOVE(stored_atoms, weakref(ejecting))
|
||||
LAZYREMOVE(thinktank_module.stored_atoms, weakref(ejecting))
|
||||
if(istype(ejecting) && !QDELETED(ejecting) && ejecting.loc == src)
|
||||
ejecting.dropInto(loc)
|
||||
if(user == src)
|
||||
@@ -90,14 +101,15 @@
|
||||
if(isrobot(user) && user.Adjacent(src))
|
||||
return try_remove_cargo(user)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/silicon/robot/platform/proc/try_remove_cargo(var/mob/user)
|
||||
if(!length(stored_atoms) || !istype(user))
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(!istype(thinktank_module) || !length(thinktank_module.stored_atoms) || !istype(user))
|
||||
return FALSE
|
||||
var/weakref/remove_ref = stored_atoms[length(stored_atoms)]
|
||||
var/weakref/remove_ref = thinktank_module.stored_atoms[length(thinktank_module.stored_atoms)]
|
||||
var/atom/movable/removing = remove_ref?.resolve()
|
||||
if(!istype(removing) || QDELETED(removing) || removing.loc != src)
|
||||
LAZYREMOVE(stored_atoms, remove_ref)
|
||||
LAZYREMOVE(thinktank_module.stored_atoms, remove_ref)
|
||||
else
|
||||
user.visible_message(SPAN_NOTICE("\The [user] begins unloading \the [removing] from \the [src]'s cargo compartment."))
|
||||
if(do_after(user, 3 SECONDS, src) && !QDELETED(removing) && removing.loc == src)
|
||||
@@ -113,7 +125,8 @@
|
||||
to_chat(src, SPAN_WARNING("You are not in any state to do that."))
|
||||
return
|
||||
|
||||
if(length(stored_atoms))
|
||||
var/obj/item/robot_module/robot/platform/thinktank_module = module
|
||||
if(istype(thinktank_module) && length(thinktank_module.stored_atoms))
|
||||
drop_stored_atom(user = src)
|
||||
else
|
||||
to_chat(src, SPAN_WARNING("You have nothing in your cargo compartment."))
|
||||
@@ -136,4 +149,4 @@
|
||||
return FALSE
|
||||
if(user.incapacitated() || !Adjacent(user) || !dropping.Adjacent(user))
|
||||
return FALSE
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/mob/living/silicon/robot/platform/explorer
|
||||
name = "recon platform"
|
||||
desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence. This one is lightly armoured and fitted with all-terrain wheels."
|
||||
modtype = "Recon"
|
||||
module = /obj/item/robot_module/robot/platform/explorer
|
||||
|
||||
/mob/living/silicon/robot/platform/explorer/Initialize()
|
||||
. = ..()
|
||||
laws = new /datum/ai_laws/explorer
|
||||
|
||||
/mob/living/silicon/robot/platform/explorer/welcome_client()
|
||||
..()
|
||||
if(client) // ganbatte tachikoma-san
|
||||
to_chat(src, SPAN_NOTICE("You are tasked with supporting the Exploration and Science staff as they unearth the secrets of the planet. Do your best!"))
|
||||
|
||||
/obj/effect/landmark/robot_platform/explorer
|
||||
platform_type = /mob/living/silicon/robot/platform/explorer
|
||||
|
||||
/mob/living/silicon/robot/platform/cargo
|
||||
name = "logistics platform"
|
||||
desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence. This one has an expanded storage compartment."
|
||||
modtype = "Logistics"
|
||||
module = /obj/item/robot_module/robot/platform/cargo
|
||||
max_stored_atoms = 3
|
||||
|
||||
/mob/living/silicon/robot/platform/cargo/welcome_client()
|
||||
..()
|
||||
if(client)
|
||||
to_chat(src, SPAN_NOTICE("You are tasked with supporting the Cargo and Supply staff as they handle operational logistics. Do your best!"))
|
||||
|
||||
/obj/effect/landmark/robot_platform/cargo
|
||||
platform_type = /mob/living/silicon/robot/platform/cargo
|
||||
@@ -99,4 +99,4 @@
|
||||
icon_scale_y = 0.5
|
||||
|
||||
/decl/mob_organ_names/bird
|
||||
hit_zones = list("head", "chest", "left leg", "right leg", "left wing", "right wing")
|
||||
hit_zones = list("head", "chest", "left leg", "right leg", "left wing", "right wing")
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
|
||||
// They can also, you know, move around, in space
|
||||
/mob/living/simple_mob/animal/space/Process_Spacemove(var/check_drift = 0)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -430,4 +430,4 @@
|
||||
/obj/random/projectile/scrapped_grenadelauncher = 100,
|
||||
/obj/item/grenade/spawnergrenade/manhacks/mercenary = 50,
|
||||
/obj/item/grenade/spawnergrenade/manhacks/mercenary = 30
|
||||
)
|
||||
)
|
||||
|
||||
@@ -150,4 +150,4 @@
|
||||
|
||||
|
||||
/decl/mob_organ_names/miningdrone
|
||||
hit_zones = list("chassis", "comms array", "sensor suite", "left excavator module", "right excavator module", "maneuvering thruster")
|
||||
hit_zones = list("chassis", "comms array", "sensor suite", "left excavator module", "right excavator module", "maneuvering thruster")
|
||||
|
||||
@@ -44,4 +44,4 @@
|
||||
return TRUE
|
||||
|
||||
/decl/mob_organ_names/hoverpod
|
||||
hit_zones = list("central chassis", "control module", "hydraulics", "left manipulator", "right manipulator", "left landing strut", "right landing strut", "maneuvering thruster", "sensor suite", "radiator", "power supply")
|
||||
hit_zones = list("central chassis", "control module", "hydraulics", "left manipulator", "right manipulator", "left landing strut", "right landing strut", "maneuvering thruster", "sensor suite", "radiator", "power supply")
|
||||
|
||||
@@ -142,8 +142,8 @@
|
||||
. += "<span class='warning'><B>It looks severely dented!</B></span>"
|
||||
|
||||
//Constructs levitate, can fall from a shuttle with no harm, and are piloted by either damned spirits or some otherworldly entity. Let 'em float in space.
|
||||
/mob/living/simple_mob/construct/Process_Spacemove()
|
||||
return 1
|
||||
/mob/living/simple_mob/construct/Process_Spacemove(var/check_drift = 0)
|
||||
return TRUE
|
||||
|
||||
/*
|
||||
// Glowing Procs
|
||||
@@ -155,4 +155,4 @@
|
||||
|
||||
/mob/living/simple_mob/construct/proc/remove_glow()
|
||||
overlays.Cut()
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
minbodytemp = 0
|
||||
|
||||
/mob/living/simple_mob/faithless/Process_Spacemove(var/check_drift = 0)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/faithless/apply_melee_effects(var/atom/A)
|
||||
if(isliving(A))
|
||||
|
||||
@@ -238,4 +238,4 @@ var/global/list/_slime_default_emotes = list(
|
||||
visible_message("<b>\The [src]</b> squishes!")
|
||||
|
||||
/decl/mob_organ_names/slime
|
||||
hit_zones = list("cytoplasmic membrane")
|
||||
hit_zones = list("cytoplasmic membrane")
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
|
||||
// Can't control ourselves when drifting
|
||||
if((isspace(loc) || my_mob.lastarea?.has_gravity == 0) && isturf(loc))
|
||||
if(!my_mob.Process_Spacemove(0))
|
||||
if(!my_mob.Process_Spacemove(FALSE))
|
||||
return 0
|
||||
|
||||
// Inside an object, tell it we moved
|
||||
@@ -395,6 +395,18 @@
|
||||
/mob/proc/get_jetpack()
|
||||
return
|
||||
|
||||
// Checks whether this mob is allowed to move in space
|
||||
// Return 1 for movement, 0 for none,
|
||||
/mob/proc/Allow_Spacemove(var/dense_object)
|
||||
if(restrained())
|
||||
return FALSE
|
||||
var/obj/item/tank/jetpack/J = get_jetpack()
|
||||
if(J?.can_thrust(0.01))
|
||||
return TRUE
|
||||
if(!dense_object) //Nothing to push off of so end here
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
///Process_Spacemove
|
||||
///Called by /client/Move()
|
||||
///For moving in space
|
||||
@@ -402,26 +414,31 @@
|
||||
/mob/proc/Process_Spacemove(var/check_drift = 0)
|
||||
|
||||
if(is_incorporeal())
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(!Check_Dense_Object()) //Nothing to push off of so end here
|
||||
update_floating(0)
|
||||
return 0
|
||||
var/dense_object = Check_Dense_Object()
|
||||
if(!Allow_Spacemove())
|
||||
update_floating(dense_object)
|
||||
return FALSE
|
||||
|
||||
update_floating(1)
|
||||
|
||||
if(restrained()) //Check to see if we can do things
|
||||
return 0
|
||||
var/obj/item/tank/jetpack/thrust = get_jetpack()
|
||||
if(dense_object || ((!check_drift || thrust?.stabilization_on) && !lying && thrust.do_thrust(0.01, src)))
|
||||
inertia_dir = 0
|
||||
return TRUE
|
||||
else if(!dense_object) //Nothing to push off of so end here
|
||||
update_floating(FALSE)
|
||||
return FALSE
|
||||
|
||||
//Check to see if we slipped
|
||||
if(prob(Process_Spaceslipping(5)) && !buckled)
|
||||
to_chat(src, "<span class='notice'><B>You slipped!</B></span>")
|
||||
inertia_dir = last_move
|
||||
step(src, src.inertia_dir) // Not using Move for smooth glide here because this is a 'slip' so should be sudden.
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
//If not then we can reset inertia and move
|
||||
inertia_dir = 0
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/proc/Check_Dense_Object() //checks for anything to push off in the vicinity. also handles magboots on gravity-less floors tiles
|
||||
|
||||
|
||||
@@ -419,6 +419,13 @@
|
||||
|
||||
var/datum/job/J = SSjob.get_job(rank)
|
||||
|
||||
// Get the appropriate announcement title.
|
||||
var/announce_rank = rank
|
||||
if(J?.substitute_announce_title)
|
||||
announce_rank = J.substitute_announce_title
|
||||
else if(character.mind.role_alt_title)
|
||||
announce_rank = character.mind.role_alt_title
|
||||
|
||||
// AIs don't need a spawnpoint, they must spawn at an empty core
|
||||
if(J.mob_type & JOB_SILICON_AI)
|
||||
|
||||
@@ -431,7 +438,7 @@
|
||||
// AIize the character, but don't move them yet
|
||||
character = character.AIize(move = FALSE) // Dupe of code in /datum/controller/subsystem/ticker/proc/create_characters() for non-latespawn, unify?
|
||||
|
||||
AnnounceCyborg(character, rank, "has been transferred to the empty core in \the [character.loc.loc]")
|
||||
AnnounceCyborg(character, announce_rank, "has been transferred to the empty core in \the [character.loc.loc]")
|
||||
ticker.mode.latespawn(character)
|
||||
|
||||
qdel(C) //Deletes empty core (really?)
|
||||
@@ -453,10 +460,10 @@
|
||||
var/do_announce = join_props["announce"] && join_message && announce_channel
|
||||
if(J.mob_type & JOB_SILICON)
|
||||
if(do_announce)
|
||||
AnnounceCyborg(character, rank, join_message, announce_channel, character.z)
|
||||
AnnounceCyborg(character, announce_rank, join_message, announce_channel, character.z)
|
||||
else
|
||||
if(do_announce)
|
||||
AnnounceArrival(character, J?.substitute_announce_title || rank, join_message, announce_channel, character.z)
|
||||
AnnounceArrival(character, announce_rank, join_message, announce_channel, character.z)
|
||||
data_core.manifest_inject(character)
|
||||
ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
|
||||
|
||||
@@ -465,8 +472,6 @@
|
||||
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel)
|
||||
if (ticker.current_state == GAME_STATE_PLAYING)
|
||||
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE, om_range = DEFAULT_OVERMAP_RANGE) : null
|
||||
if(character.mind.role_alt_title)
|
||||
rank = character.mind.role_alt_title
|
||||
// can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc.
|
||||
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer", channel, zlevels)
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
return O
|
||||
|
||||
//human -> robot
|
||||
/mob/living/carbon/human/proc/Robotize()
|
||||
/mob/living/carbon/human/proc/Robotize(supplied_robot_type = /mob/living/silicon/robot)
|
||||
if (transforming)
|
||||
return
|
||||
for(var/obj/item/W in src)
|
||||
@@ -149,7 +149,7 @@
|
||||
for(var/t in organs)
|
||||
qdel(t)
|
||||
|
||||
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot( loc )
|
||||
var/mob/living/silicon/robot/O = new supplied_robot_type( loc )
|
||||
|
||||
// cyborgs produced by Robotize get an automatic power cell
|
||||
O.cell = new(O)
|
||||
@@ -171,15 +171,12 @@
|
||||
|
||||
O.loc = loc
|
||||
O.job = "Cyborg"
|
||||
if(O.mind.assigned_role == "Cyborg")
|
||||
if(O.mind.role_alt_title == "Robot")
|
||||
O.mmi = new /obj/item/mmi/digital/posibrain(O)
|
||||
else if(O.mind.role_alt_title == "Drone")
|
||||
O.mmi = new /obj/item/mmi/digital/robot(O)
|
||||
else
|
||||
O.mmi = new /obj/item/mmi(O)
|
||||
|
||||
O.mmi.transfer_identity(src)
|
||||
if(O.mind.assigned_role == "Cyborg")
|
||||
var/mmi_type = SSrobots.get_mmi_type_by_title(O.mind.role_alt_title ? O.mind.role_alt_title : O.mind.assigned_role)
|
||||
if(mmi_type)
|
||||
O.mmi = new mmi_type(O)
|
||||
O.mmi.transfer_identity(src)
|
||||
|
||||
if(O.client && O.client.prefs)
|
||||
var/datum/preferences/B = O.client.prefs
|
||||
|
||||
@@ -29,18 +29,6 @@
|
||||
if(length(A.name) + length(label) > 64)
|
||||
to_chat(user, SPAN_WARNING("\The [src]'s label too big."))
|
||||
return
|
||||
if(istype(A, /mob/living/silicon/robot/platform))
|
||||
var/mob/living/silicon/robot/platform/P = A
|
||||
if(!P.allowed(user))
|
||||
to_chat(usr, SPAN_WARNING("Access denied."))
|
||||
else if(P.client || P.key)
|
||||
to_chat(user, SPAN_NOTICE("You rename \the [P] to [label]."))
|
||||
to_chat(P, SPAN_NOTICE("\The [user] renames you to [label]."))
|
||||
P.custom_name = label
|
||||
P.SetName(P.custom_name)
|
||||
else
|
||||
to_chat(user, SPAN_WARNING("\The [src] is inactive and cannot be renamed."))
|
||||
return
|
||||
if(ishuman(A))
|
||||
to_chat(user, SPAN_WARNING("The label refuses to stick to [A.name]."))
|
||||
return
|
||||
@@ -80,4 +68,4 @@
|
||||
label = str
|
||||
to_chat(user, SPAN_NOTICE("You set the text to '[str]'."))
|
||||
else
|
||||
to_chat(user, SPAN_NOTICE("You turn off \the [src]."))
|
||||
to_chat(user, SPAN_NOTICE("You turn off \the [src]."))
|
||||
|
||||
@@ -277,10 +277,24 @@
|
||||
/datum/design/item/prosfab/cyborg/exoskeleton
|
||||
name = "Robot Exoskeleton"
|
||||
id = "robot_exoskeleton"
|
||||
build_path = /obj/item/robot_parts/robot_suit
|
||||
build_path = /obj/item/robot_parts/frame
|
||||
time = 50
|
||||
materials = list(MAT_STEEL = 37500)
|
||||
|
||||
/datum/design/item/prosfab/cyborg/exoskeleton_flying
|
||||
name = "Flying Robot Exoskeleton"
|
||||
id = "robot_exoskeleton_flyer"
|
||||
build_path = /obj/item/robot_parts/frame/flyer
|
||||
time = 40
|
||||
materials = list(MAT_STEEL = 32500)
|
||||
|
||||
/datum/design/item/prosfab/cyborg/exoskeleton_platform
|
||||
name = "Platform Exoskeleton"
|
||||
id = "robot_exoskeleton_platform"
|
||||
build_path = /obj/item/robot_parts/frame/platform
|
||||
time = 60
|
||||
materials = list(MAT_STEEL = 42500)
|
||||
|
||||
/datum/design/item/prosfab/cyborg/torso
|
||||
name = "Robot Torso"
|
||||
id = "robot_torso"
|
||||
@@ -366,6 +380,11 @@
|
||||
id = "platform_armour"
|
||||
build_path = /obj/item/robot_parts/robot_component/armour_platform
|
||||
|
||||
/datum/design/item/prosfab/cyborg/component/armour_light
|
||||
name = "Armour Plating (Light)"
|
||||
id = "light_armour"
|
||||
build_path = /obj/item/robot_parts/robot_component/armour_light
|
||||
|
||||
/datum/design/item/prosfab/cyborg/component/ai_shell
|
||||
name = "AI Remote Interface"
|
||||
id = "mmi_ai_shell"
|
||||
|
||||
@@ -424,7 +424,7 @@
|
||||
//robot remains
|
||||
apply_prefix = FALSE
|
||||
item_type = "[pick("mechanical","robotic","cyborg")] [pick("remains","chassis","debris")]"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon = 'icons/mob/robot_gibs.dmi'
|
||||
icon_state = "remainsrobot"
|
||||
additional_desc = pick("Almost mistakeable for the remains of a modern cyborg.",\
|
||||
"They are barely recognisable as anything other than a pile of waste metals.",\
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/datum/unit_test/robot_module_icons_shall_be_valid
|
||||
name = "ICONS: Robot module icons shall be valid"
|
||||
var/list/check_module_categories = list(
|
||||
ROBOT_MODULE_TYPE_GROUNDED,
|
||||
ROBOT_MODULE_TYPE_FLYING
|
||||
)
|
||||
var/list/panel_overlays = list(
|
||||
"ov-openpanel +w",
|
||||
"ov-openpanel +c",
|
||||
"ov-openpanel -c"
|
||||
)
|
||||
var/list/gear_to_check = list(
|
||||
/obj/item/borg/combat/shield = "-shield",
|
||||
/obj/item/borg/combat/mobility = "-roll"
|
||||
)
|
||||
|
||||
/datum/unit_test/robot_module_icons_shall_be_valid/start_test()
|
||||
|
||||
var/list/failures = list()
|
||||
// fetch our icon states to check against
|
||||
var/list/icon_state_cache = list(
|
||||
ROBOT_MODULE_TYPE_GROUNDED = icon_states('icons/mob/robots/robots_grounded.dmi'),
|
||||
ROBOT_MODULE_TYPE_FLYING = icon_states('icons/mob/robots/robots_flying.dmi')
|
||||
)
|
||||
|
||||
var/list/found_states = list() // Keep track of this for checking for unused states later.
|
||||
|
||||
// Kick it off by doing a sprite check on all flying and grounded modules.
|
||||
for(var/module_type in typesof(/obj/item/robot_module))
|
||||
|
||||
// Skip abstract modules and think-tanks as they do icon gen differently.
|
||||
var/obj/item/robot_module/module = module_type
|
||||
if(!initial(module.display_name) || !(initial(module.module_category) in check_module_categories))
|
||||
continue
|
||||
|
||||
module = new module // this will automatically qdelete, but we just want the sprites.
|
||||
|
||||
// Check that the expected states are actually in the icon file.
|
||||
var/check_states = icon_state_cache[module.module_category]
|
||||
for(var/sprite in module.sprites)
|
||||
|
||||
// Basic sprite.
|
||||
var/check_state = module.sprites[sprite]
|
||||
if(check_state in check_states)
|
||||
LAZYDISTINCTADD(found_states[module.module_category], check_state)
|
||||
else
|
||||
failures += "missing base state '[check_state]' for [module.display_name] ([module.module_category])"
|
||||
|
||||
// Eyes overlay.
|
||||
var/eye_check_state = "eyes-[check_state]"
|
||||
if(eye_check_state in check_states)
|
||||
LAZYDISTINCTADD(found_states[module.module_category], eye_check_state)
|
||||
else
|
||||
failures += "missing eyes state '[eye_check_state]' for [module.display_name] ([module.module_category])"
|
||||
|
||||
// Equipment overlays.
|
||||
for(var/geartype in gear_to_check)
|
||||
var/suffix = gear_to_check[geartype]
|
||||
for(var/gear in module.modules)
|
||||
if(!ispath(gear, geartype))
|
||||
continue
|
||||
var/gear_check_state = "[check_state][suffix]"
|
||||
if(gear_check_state in check_states)
|
||||
LAZYDISTINCTADD(found_states[module.module_category], gear_check_state)
|
||||
else
|
||||
failures += "missing gear state '[gear_check_state]' for [module.display_name] ([module.module_category])"
|
||||
break
|
||||
|
||||
// Check for drone AI eyes.
|
||||
if(istype(module, /obj/item/robot_module/drone))
|
||||
var/ai_eye_state = "[eye_check_state]-ai"
|
||||
if(ai_eye_state in check_states)
|
||||
LAZYDISTINCTADD(found_states[module.module_category], ai_eye_state)
|
||||
else
|
||||
failures += "missing drone AI control state '[ai_eye_state]' for [module.display_name] ([module.module_category])"
|
||||
|
||||
// Check for missing panel states.
|
||||
for(var/module_category in check_module_categories)
|
||||
var/list/check_states = icon_state_cache[module_category]
|
||||
for(var/panel_state in panel_overlays)
|
||||
if(panel_state in check_states)
|
||||
LAZYDISTINCTADD(found_states[module_category], panel_state)
|
||||
else
|
||||
failures += "missing panel state '[panel_state]' for [module_category]"
|
||||
|
||||
// Now we can do tachikoma sprites.
|
||||
var/list/tachikoma_icon_states = list()
|
||||
for(var/module_type in typesof(/obj/item/robot_module/robot/platform))
|
||||
// Skip abstract modules.
|
||||
var/obj/item/robot_module/robot/platform/module = module_type
|
||||
if(!initial(module.display_name) || !initial(module.module_category) || !initial(module.user_icon))
|
||||
continue
|
||||
|
||||
// We need a module instance to check the decal list.
|
||||
module = new module_type
|
||||
if(!tachikoma_icon_states[module.user_icon])
|
||||
tachikoma_icon_states[module.user_icon] = icon_states(module.user_icon)
|
||||
LAZYDISTINCTADD(icon_state_cache[ROBOT_MODULE_TYPE_PLATFORM], tachikoma_icon_states[module.user_icon])
|
||||
|
||||
/*
|
||||
unexpected state 'tachi_cross' for platform
|
||||
unexpected state 'tachi-open-wires' for platform
|
||||
unexpected state 'tachi-open-cell' for platform
|
||||
*/
|
||||
var/list/states_to_check = list(
|
||||
"blank",
|
||||
module.user_icon_state,
|
||||
"[module.user_icon_state]-open",
|
||||
"[module.user_icon_state]-wires",
|
||||
"[module.user_icon_state]-cell",
|
||||
"[module.user_icon_state]-nowires"
|
||||
)
|
||||
if(module.armor_color)
|
||||
states_to_check += "[module.user_icon_state]_armour"
|
||||
for(var/decal in module.decals)
|
||||
states_to_check += "[module.user_icon_state]_[decal]"
|
||||
if(module.eye_color)
|
||||
states_to_check += "[module.user_icon_state]_eyes"
|
||||
if(module.pupil_color)
|
||||
states_to_check += "[module.user_icon_state]_pupils"
|
||||
|
||||
for(var/check_state in states_to_check)
|
||||
if(check_state in tachikoma_icon_states[module.user_icon])
|
||||
LAZYDISTINCTADD(found_states[ROBOT_MODULE_TYPE_PLATFORM], check_state)
|
||||
else
|
||||
failures += "missing platform state '[check_state]' in icon file [module.user_icon]"
|
||||
|
||||
// Check that there aren't any unexpected states.
|
||||
for(var/module_category in icon_state_cache)
|
||||
var/list/check_found_states = LAZYACCESS(found_states, module_category)
|
||||
for(var/check_state in icon_state_cache[module_category])
|
||||
if(!(check_state in check_found_states))
|
||||
failures += "unexpected state '[check_state]' for [module_category]"
|
||||
|
||||
if(length(failures))
|
||||
fail("Some robot module sprites are invalid:\n" + failures.Join("\n"))
|
||||
else
|
||||
pass("All robot module sprites are valid.")
|
||||
return 1
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 566 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 402 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 579 B |
|
After Width: | Height: | Size: 915 B |
@@ -20941,7 +20941,6 @@
|
||||
/area/shuttle/exploration/general)
|
||||
"jDG" = (
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/landmark/robot_platform/cargo,
|
||||
/turf/simulated/floor/tiled/dark,
|
||||
/area/surface/station/quartermaster/lockerroom)
|
||||
"jDW" = (
|
||||
@@ -37761,7 +37760,6 @@
|
||||
/area/surface/station/library)
|
||||
"qCU" = (
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/landmark/robot_platform/explorer,
|
||||
/turf/simulated/floor/tiled/dark,
|
||||
/area/surface/station/garage)
|
||||
"qCW" = (
|
||||
@@ -43241,7 +43239,6 @@
|
||||
/area/surface/station/quartermaster/lockerroom)
|
||||
"tdK" = (
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/landmark/robot_platform/explorer,
|
||||
/obj/machinery/firealarm{
|
||||
pixel_y = 24
|
||||
},
|
||||
|
||||
@@ -7793,7 +7793,7 @@
|
||||
/turf/simulated/floor/tiled/milspec/dark,
|
||||
/area/shuttle/escape/centcom)
|
||||
"iNR" = (
|
||||
/obj/item/robot_parts/robot_suit,
|
||||
/obj/item/robot_parts/frame,
|
||||
/obj/item/robot_parts/r_leg,
|
||||
/obj/item/robot_parts/r_arm,
|
||||
/turf/simulated/shuttle/plating,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "cynosure_jobs.dm"
|
||||
#include "cynosure_elevator.dm"
|
||||
#include "cynosure_events.dm"
|
||||
#include "cynosure_overrides.dm"
|
||||
#include "cynosure_presets.dm"
|
||||
#include "cynosure_shuttles.dm"
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
/mob/living/silicon/robot/platform/explorer
|
||||
req_access = list(access_explorer)
|
||||
|
||||
/mob/living/silicon/robot/platform/cargo
|
||||
req_access = list(access_cargo_bot)
|
||||
|
||||
/obj/item/card/id/platform/Initialize()
|
||||
. = ..()
|
||||
access |= access_explorer
|
||||
@@ -2285,7 +2285,7 @@
|
||||
"RW" = (/obj/structure/table/rack,/obj/item/grenade/empgrenade,/obj/item/grenade/flashbang,/obj/item/grenade/spawnergrenade/manhacks,/turf/simulated/shuttle/floor/red,/area/skipjack_station/start)
|
||||
"RX" = (/obj/structure/table/steel,/obj/machinery/recharger,/obj/machinery/light/small{dir = 4},/turf/simulated/shuttle/floor/red,/area/skipjack_station/start)
|
||||
"RY" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"RZ" = (/obj/item/robot_parts/robot_suit,/obj/item/robot_parts/r_leg,/obj/item/robot_parts/r_arm,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"RZ" = (/obj/item/robot_parts/frame,/obj/item/robot_parts/r_leg,/obj/item/robot_parts/r_arm,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"Sa" = (/obj/machinery/computer/communications,/turf/unsimulated/floor{icon_state = "dark"},/area/wizard_station)
|
||||
"Sb" = (/obj/structure/sign/double/map/left{pixel_y = 32},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/wizard_station)
|
||||
"Sc" = (/obj/structure/sign/double/map/right{pixel_y = 32},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/wizard_station)
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
"cc" = (/obj/machinery/light/small{ icon_state = "bulb1"; dir = 4},/obj/machinery/atmospherics/pipe/simple{ icon_state = "intact"; dir = 2; level = 2},/turf/simulated/floor/plating,/area/ship/scrap/crew)
|
||||
"cd" = (/turf/simulated/wall/r_wall,/area/ship/scrap/crew/saloon)
|
||||
"ce" = (/obj/machinery/atmospherics/pipe/simple{ icon_state = "intact"; dir = 2; level = 2},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/airlock/maintenance_hatch{name = "Hatch"; normalspeed = 0},/turf/simulated/floor{icon_state = "white"},/area/ship/scrap/crew/saloon)
|
||||
"cf" = (/obj/machinery/light/small{ icon_state = "bulb1"; dir = 8},/obj/item/crowbar,/obj/machinery/atmospherics/pipe/simple{ icon_state = "intact"; dir = 2; level = 2},/turf/simulated/floor/plating,/area/ship/scrap/crew)
|
||||
"cf" = (/obj/machinery/light/small{ icon_state = "bulb1"; dir = 8},/obj/item/tool/crowbar,/obj/machinery/atmospherics/pipe/simple{ icon_state = "intact"; dir = 2; level = 2},/turf/simulated/floor/plating,/area/ship/scrap/crew)
|
||||
"cg" = (/turf/simulated/wall/r_wall,/area/ship/scrap/crew/dorms)
|
||||
"ch" = (/obj/structure/sign/poster,/turf/simulated/wall,/area/ship/scrap/crew/dorms)
|
||||
"ci" = (/obj/structure/window/reinforced{dir = 5; health = 1e+007},/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "scraplock"; name = "External Blast Doors"; opacity = 0},/obj/structure/window/reinforced{dir = 5; health = 1e+007},/turf/simulated/floor{icon_state = "white"},/area/ship/scrap/crew/dorms)
|
||||
@@ -229,7 +229,7 @@
|
||||
"eu" = (/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/ship/scrap/maintenance/engine)
|
||||
"ev" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/ship/scrap/maintenance/engine)
|
||||
"ew" = (/obj/structure/window/reinforced{dir = 1},/obj/machinery/light/small{ icon_state = "bulb1"; dir = 1},/turf/simulated/floor/plating/airless,/area/ship/scrap/maintenance/engine)
|
||||
"ex" = (/obj/item/screwdriver,/turf/simulated/floor/plating,/area)
|
||||
"ex" = (/obj/item/tool/screwdriver,/turf/simulated/floor/plating,/area)
|
||||
"ey" = (/turf/simulated/wall,/area/ship/scrap/crew/wash)
|
||||
"ez" = (/obj/structure/closet/crate,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/turf/simulated/floor{ icon_state = "bot"; dir = 2},/area/ship/scrap/cargo)
|
||||
"eA" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple{ icon_state = "intact"; dir = 2; level = 2},/turf/simulated/floor,/area/ship/scrap/cargo)
|
||||
@@ -326,7 +326,7 @@
|
||||
"gn" = (/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{ icon_state = "floorgrime"; dir = 6},/area/ship/scrap/maintenance)
|
||||
"go" = (/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/turf/simulated/floor/plating,/area/ship/scrap/maintenance)
|
||||
"gp" = (/obj/machinery/atmospherics/pipe/manifold4w{level = 2},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/light/small{dir = 8; icon_state = "bulb1"; pixel_y = 16},/turf/simulated/floor,/area/ship/scrap/maintenance)
|
||||
"gq" = (/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/obj/machinery/light/small{ icon_state = "bulb1"; dir = 1},/obj/item/crowbar,/turf/simulated/floor/plating,/area/ship/scrap/maintenance)
|
||||
"gq" = (/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/obj/machinery/light/small{ icon_state = "bulb1"; dir = 1},/obj/item/tool/crowbar,/turf/simulated/floor/plating,/area/ship/scrap/maintenance)
|
||||
"gr" = (/obj/machinery/atmospherics/pipe/simple{dir = 9; icon_state = "intact"; level = 2},/turf/simulated/floor{ icon_state = "wall_thermite"; dir = 2},/area/ship/scrap/maintenance)
|
||||
"gs" = (/turf/simulated/wall/r_wall,/area/ship/scrap/maintenance/atmos)
|
||||
"gt" = (/turf/simulated/wall,/area/ship/scrap/maintenance/atmos)
|
||||
|
||||
@@ -72947,7 +72947,6 @@
|
||||
},
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/floor_decal/industrial/hatch/yellow,
|
||||
/obj/effect/landmark/robot_platform/cargo,
|
||||
/turf/simulated/floor/tiled/steel,
|
||||
/area/quartermaster/warehouse)
|
||||
"cHa" = (
|
||||
|
||||
@@ -13977,7 +13977,6 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/landmark/robot_platform/explorer,
|
||||
/turf/simulated/floor/plating,
|
||||
/area/surface/outpost/main/garage)
|
||||
"GT" = (
|
||||
@@ -14102,7 +14101,6 @@
|
||||
"Lz" = (
|
||||
/obj/effect/floor_decal/industrial/hatch/yellow,
|
||||
/obj/machinery/mech_recharger,
|
||||
/obj/effect/landmark/robot_platform/explorer,
|
||||
/turf/simulated/floor/plating,
|
||||
/area/surface/outpost/main/garage)
|
||||
"LH" = (
|
||||
|
||||
@@ -2135,7 +2135,7 @@
|
||||
"Pc" = (/obj/structure/table/steel,/obj/machinery/recharger,/obj/machinery/light/small{dir = 4},/turf/simulated/shuttle/floor/darkred,/area/skipjack_station/start)
|
||||
"Pd" = (/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/shuttle/floor/darkred,/area/skipjack_station/start)
|
||||
"Pe" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"Pf" = (/obj/item/robot_parts/robot_suit,/obj/item/robot_parts/r_leg,/obj/item/robot_parts/r_arm,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"Pf" = (/obj/item/robot_parts/frame,/obj/item/robot_parts/r_leg,/obj/item/robot_parts/r_arm,/turf/simulated/shuttle/plating,/area/skipjack_station/start)
|
||||
"Pg" = (/obj/structure/flight_left{icon_state = "left"; dir = 8},/turf/simulated/shuttle/floor/voidcraft,/area/syndicate_station/start)
|
||||
"Ph" = (/obj/item/radio/intercom{desc = "Talk through this. Evilly"; frequency = 1213; name = "Syndicate Intercom"; pixel_x = 32; subspace_transmission = 1; syndie = 1},/turf/simulated/shuttle/floor/voidcraft/light,/area/syndicate_station/start)
|
||||
"Pi" = (/obj/item/radio/intercom{desc = "Talk through this. Evilly"; frequency = 1213; name = "Syndicate Intercom"; pixel_x = -32; subspace_transmission = 1; syndie = 1},/turf/simulated/shuttle/floor/voidcraft/dark,/area/syndicate_station/start)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "southern_cross_jobs.dm"
|
||||
#include "southern_cross_elevator.dm"
|
||||
#include "southern_cross_events.dm"
|
||||
#include "southern_cross_overrides.dm"
|
||||
#include "southern_cross_presets.dm"
|
||||
#include "southern_cross_shuttles.dm"
|
||||
|
||||
@@ -56,4 +55,4 @@
|
||||
|
||||
#warn A map has already been included, ignoring Southern Cross
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/mob/living/silicon/robot/platform/explorer
|
||||
req_access = list(access_explorer)
|
||||
|
||||
/mob/living/silicon/robot/platform/cargo
|
||||
req_access = list(access_cargo_bot)
|
||||
|
||||
/obj/item/card/id/platform/Initialize()
|
||||
. = ..()
|
||||
access |= access_explorer
|
||||
access |= access_pilot
|
||||
@@ -244,6 +244,7 @@
|
||||
#include "code\controllers\subsystems\persistence.dm"
|
||||
#include "code\controllers\subsystems\planets.dm"
|
||||
#include "code\controllers\subsystems\radiation.dm"
|
||||
#include "code\controllers\subsystems\robots.dm"
|
||||
#include "code\controllers\subsystems\shuttles.dm"
|
||||
#include "code\controllers\subsystems\skybox.dm"
|
||||
#include "code\controllers\subsystems\sqlite.dm"
|
||||
@@ -1017,6 +1018,7 @@
|
||||
#include "code\game\objects\items\devices\radio\jammer.dm"
|
||||
#include "code\game\objects\items\devices\radio\radio.dm"
|
||||
#include "code\game\objects\items\devices\radio\radiopack.dm"
|
||||
#include "code\game\objects\items\robot\robot_frame.dm"
|
||||
#include "code\game\objects\items\mines\_mine.dm"
|
||||
#include "code\game\objects\items\mines\_mine_payload.dm"
|
||||
#include "code\game\objects\items\mines\mine_assembly.dm"
|
||||
@@ -2447,10 +2449,12 @@
|
||||
#include "code\modules\mob\living\silicon\robot\drone\swarm.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\swarm_abilities.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\drone\swarm_items.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules\_module.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules\event.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules\station.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules\swarm.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_modules\syndicate.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\flying.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\gravekeeper.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\lost_drone.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\syndicate.dm"
|
||||
@@ -2459,7 +2463,6 @@
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\thinktank\thinktank_interactions.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\thinktank\thinktank_module.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\thinktank\thinktank_storage.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\subtypes\thinktank\thinktank_subtypes.dm"
|
||||
#include "code\modules\mob\living\simple_mob\appearance.dm"
|
||||
#include "code\modules\mob\living\simple_mob\butchering.dm"
|
||||
#include "code\modules\mob\living\simple_mob\combat.dm"
|
||||
@@ -3314,6 +3317,7 @@
|
||||
#include "code\modules\xgm\xgm_gas_data.dm"
|
||||
#include "code\modules\xgm\xgm_gas_mixture.dm"
|
||||
#include "code\unit_tests\decl_tests.dm"
|
||||
#include "code\unit_tests\icon_tests.dm"
|
||||
#include "code\unit_tests\language_tests.dm"
|
||||
#include "code\unit_tests\loadout_tests.dm"
|
||||
#include "code\unit_tests\map_tests.dm"
|
||||
|
||||