modsuit patch one (#63638)

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
Fikou
2021-12-27 23:47:59 +01:00
committed by GitHub
parent 4dbe04013f
commit f58848e2ec
27 changed files with 258 additions and 52 deletions
+28 -15
View File
@@ -2,29 +2,30 @@
background_icon_state = "bg_tech_blue"
icon_icon = 'icons/mob/actions/actions_mod.dmi'
check_flags = AB_CHECK_CONSCIOUS
/// Whether this action is intended for the AI. Stuff breaks a lot if this is done differently.
var/ai_action = FALSE
/// The MODsuit linked to this action
var/obj/item/mod/control/mod
/datum/action/item_action/mod/New(Target)
..()
mod = Target
if(ai_action)
background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND
/datum/action/item_action/mod/Grant(mob/M)
if(owner)
Share(M)
/datum/action/item_action/mod/Grant(mob/user)
if(ai_action && user != mod.ai)
return
..()
else if(!ai_action && user == mod.ai)
return
return ..()
/datum/action/item_action/mod/Remove(mob/M)
var/mob_to_grant
for(var/datum/weakref/reference as anything in sharers)
var/mob/freeloader = reference.resolve()
if(!freeloader)
continue
mob_to_grant = freeloader
break
..()
if(mob_to_grant)
Grant(mob_to_grant)
/datum/action/item_action/mod/Remove(mob/user)
if(ai_action && user != mod.ai)
return
else if(!ai_action && user == mod.ai)
return
return ..()
/datum/action/item_action/mod/deploy
name = "Deploy MODsuit"
@@ -37,6 +38,9 @@
mod.choose_deploy(usr)
return TRUE
/datum/action/item_action/mod/deploy/ai
ai_action = TRUE
/datum/action/item_action/mod/activate
name = "Activate MODsuit"
desc = "Activate/Deactivate the MODsuit."
@@ -48,6 +52,9 @@
mod.toggle_activate(usr)
return TRUE
/datum/action/item_action/mod/activate/ai
ai_action = TRUE
/datum/action/item_action/mod/module
name = "Toggle Module"
desc = "Toggle a MODsuit module."
@@ -59,6 +66,9 @@
mod.quick_module(usr)
return TRUE
/datum/action/item_action/mod/module/ai
ai_action = TRUE
/datum/action/item_action/mod/panel
name = "MODsuit Panel"
desc = "Open the MODsuit's panel."
@@ -69,3 +79,6 @@
return FALSE
mod.ui_interact(usr)
return TRUE
/datum/action/item_action/mod/panel/ai
ai_action = TRUE
+56 -4
View File
@@ -22,10 +22,7 @@
intAI.forceMove(card)
card.AI = intAI
for(var/datum/action/action as anything in actions)
if(action.owner == intAI)
action.Remove(intAI)
else
action.Unshare(intAI)
action.Remove(intAI)
intAI.controlled_equipment = null
intAI.remote_control = null
balloon_alert(intAI, "transferred to a card")
@@ -67,6 +64,7 @@
#define WEARER_DELAY 1
#define LONE_DELAY 5
#define CELL_PER_STEP DEFAULT_CELL_DRAIN * 2.5
#define AI_FALL_TIME 1 SECONDS
/obj/item/mod/control/relaymove(mob/user, direction)
if((!active && wearer) || !cell || cell.charge < CELL_PER_STEP || user != ai || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE))
@@ -75,6 +73,9 @@
COOLDOWN_START(src, cooldown_mod_move, movedelay * timemodifier + slowdown)
playsound(src, 'sound/mecha/mechmove01.ogg', 25, TRUE)
cell.charge = max(0, cell.charge - CELL_PER_STEP)
if(wearer)
ADD_TRAIT(wearer, TRAIT_FORCED_STANDING, MOD_TRAIT)
addtimer(CALLBACK(src, .proc/ai_fall), AI_FALL_TIME, TIMER_UNIQUE | TIMER_OVERRIDE)
if(ismovable(wearer?.loc))
return wearer.loc.relaymove(wearer, direction)
if(wearer && !wearer.Process_Spacemove(direction))
@@ -86,3 +87,54 @@
#undef WEARER_DELAY
#undef LONE_DELAY
#undef CELL_PER_STEP
/obj/item/mod/control/proc/ai_fall()
if(!wearer)
return
REMOVE_TRAIT(wearer, TRAIT_FORCED_STANDING, MOD_TRAIT)
/obj/item/mod/ai_minicard
name = "AI mini-card"
desc = "A small card designed to eject dead AIs. You could use an intellicard to recover it."
icon = 'icons/obj/aicards.dmi'
icon_state = "minicard"
var/datum/weakref/stored_ai
/obj/item/mod/ai_minicard/Initialize(mapload, mob/living/silicon/ai/ai)
. = ..()
if(!ai)
return
ai.apply_damage(150, BURN)
INVOKE_ASYNC(ai, /mob/living/silicon/ai.proc/death)
ai.forceMove(src)
stored_ai = WEAKREF(ai)
icon_state = "minicard-filled"
/obj/item/mod/ai_minicard/Destroy()
QDEL_NULL(stored_ai)
return ..()
/obj/item/mod/ai_minicard/examine(mob/user)
. = ..()
. += span_notice("You see [stored_ai.resolve() || "no AI"] stored inside.")
/obj/item/mod/ai_minicard/transfer_ai(interaction, mob/user, mob/living/silicon/ai/intAI, obj/item/aicard/card)
. = ..()
if(!.)
return
if(interaction != AI_TRANS_TO_CARD)
return
var/mob/living/silicon/ai/ai = stored_ai.resolve()
if(!ai)
balloon_alert(user, "no AI!")
return
balloon_alert(user, "transferring to card...")
if(!do_after(user, 5 SECONDS, target = src) || !ai)
balloon_alert(user, "interrupted!")
return
icon_state = "minicard"
ai.forceMove(card)
card.AI = ai
ai.notify_ghost_cloning("You have been recovered from the wreckage!", source = card)
balloon_alert(user, "AI transferred to card")
stored_ai = null
+16 -1
View File
@@ -29,6 +29,9 @@
QDEL_NULL(mod)
return ..()
/obj/item/clothing/head/helmet/space/mod/atom_destruction(damage_flag)
return mod.atom_destruction(damage_flag)
/obj/item/clothing/suit/armor/mod
name = "MOD chestplate"
desc = "A chestplate for a MODsuit."
@@ -56,6 +59,9 @@
QDEL_NULL(mod)
return ..()
/obj/item/clothing/suit/armor/mod/atom_destruction(damage_flag)
return mod.atom_destruction(damage_flag)
/obj/item/clothing/gloves/mod
name = "MOD gauntlets"
desc = "A pair of gauntlets for a MODsuit."
@@ -80,8 +86,12 @@
QDEL_NULL(mod)
return ..()
/// Replaces these gloves on the wearer with the overslot ones
/obj/item/clothing/gloves/mod/atom_destruction(damage_flag)
overslot.forceMove(drop_location())
overslot = null
return mod.atom_destruction(damage_flag)
/// Replaces these gloves on the wearer with the overslot ones
/obj/item/clothing/gloves/mod/proc/show_overslot()
if(!overslot)
return
@@ -114,6 +124,11 @@
QDEL_NULL(mod)
return ..()
/obj/item/clothing/shoes/mod/atom_destruction(damage_flag)
overslot.forceMove(drop_location())
overslot = null
return mod.atom_destruction(damage_flag)
/// Replaces these shoes on the wearer with the overslot ones
/obj/item/clothing/shoes/mod/proc/show_overslot()
if(!overslot)
+74 -14
View File
@@ -16,7 +16,16 @@
strip_delay = 10 SECONDS
slowdown = 2
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 25, ACID = 25, WOUND = 10)
actions_types = list(/datum/action/item_action/mod/deploy, /datum/action/item_action/mod/activate, /datum/action/item_action/mod/module, /datum/action/item_action/mod/panel)
actions_types = list(
/datum/action/item_action/mod/deploy,
/datum/action/item_action/mod/activate,
/datum/action/item_action/mod/panel,
/datum/action/item_action/mod/module,
/datum/action/item_action/mod/deploy/ai,
/datum/action/item_action/mod/activate/ai,
/datum/action/item_action/mod/panel/ai,
/datum/action/item_action/mod/module/ai,
)
resistance_flags = NONE
max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
@@ -165,6 +174,41 @@
QDEL_NULL(cell)
return ..()
/obj/item/mod/control/atom_destruction(damage_flag)
for(var/obj/item/mod/module/module as anything in modules)
for(var/obj/item/item in module)
item.forceMove(drop_location())
if(ai)
ai.controlled_equipment = null
ai.remote_control = null
for(var/datum/action/action as anything in actions)
if(action.owner == ai)
action.Remove(ai)
new /obj/item/mod/ai_minicard(drop_location(), ai)
return ..()
/obj/item/mod/control/examine(mob/user)
. = ..()
if(active)
. += span_notice("Cell power: [cell ? "[round(cell.percent(), 1)]%" : "No cell"].")
. += span_notice("Selected module: [selected_module || "None"].")
if(!open && !active)
. += span_notice("You could put it on your <b>back</b> to turn it on.")
. += span_notice("You could open the cover with a <b>screwdriver</b>.")
else if(open)
. += span_notice("You could close the cover with a <b>screwdriver</b>.")
. += span_notice("You could use <b>modules</b> on it to install them.")
. += span_notice("You could remove modules with a <b>crowbar</b>.")
. += span_notice("You could update the access with an <b>ID</b>.")
if(cell)
. += span_notice("You could remove the cell with an <b>empty hand</b>.")
else
. += span_notice("You could use a <b>cell</b> on it to install one.")
if(ai)
. += span_notice("You could remove [ai] with an <b>intellicard</b>")
else
. += span_notice("You could install an AI with an <b>intellicard</b>.")
/obj/item/mod/control/process(delta_time)
if(seconds_electrified > MACHINE_NOT_ELECTRIFIED)
seconds_electrified--
@@ -248,13 +292,13 @@
balloon_alert(user, "deactivate suit first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
balloon_alert(user, "[open ? "closing" : "opening"] panel...")
balloon_alert(user, "[open ? "closing" : "opening"] cover...")
screwdriver.play_tool_sound(src, 100)
if(screwdriver.use_tool(src, user, 1 SECONDS))
if(active || activating)
balloon_alert(user, "deactivate suit first!")
screwdriver.play_tool_sound(src, 100)
balloon_alert(user, "panel [open ? "closed" : "opened"]")
balloon_alert(user, "cover [open ? "closed" : "opened"]")
open = !open
else
balloon_alert(user, "interrupted!")
@@ -263,7 +307,7 @@
/obj/item/mod/control/crowbar_act(mob/living/user, obj/item/crowbar)
. = ..()
if(!open)
balloon_alert(user, "open the panel first!")
balloon_alert(user, "open the cover first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(!allowed(user))
@@ -290,14 +334,14 @@
/obj/item/mod/control/attackby(obj/item/attacking_item, mob/living/user, params)
if(istype(attacking_item, /obj/item/mod/module))
if(!open)
balloon_alert(user, "open the panel first!")
balloon_alert(user, "open the cover first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
install(attacking_item, user)
return TRUE
else if(istype(attacking_item, /obj/item/stock_parts/cell))
if(!open)
balloon_alert(user, "open the panel first!")
balloon_alert(user, "open the cover first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(cell)
@@ -342,13 +386,15 @@
/obj/item/mod/control/emp_act(severity)
. = ..()
to_chat(wearer, span_notice("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!"))
if(!active || !wearer || . & EMP_PROTECT_CONTENTS)
if(!active || !wearer)
return
selected_module = null
to_chat(wearer, span_notice("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!"))
if(. & EMP_PROTECT_CONTENTS)
return
selected_module.on_deactivation()
wearer.apply_damage(10 / severity, BURN, spread_damage=TRUE)
to_chat(wearer, span_danger("You feel [src] heat up from the EMP, burning you slightly."))
if (wearer.stat < UNCONSCIOUS && prob(10))
if(wearer.stat < UNCONSCIOUS && prob(10))
wearer.emote("scream")
/obj/item/mod/control/on_outfit_equip(mob/living/carbon/human/outfit_wearer, visuals_only, item_slot)
@@ -377,6 +423,7 @@
wearer = user
RegisterSignal(wearer, COMSIG_ATOM_EXITED, .proc/on_exit)
RegisterSignal(wearer, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/on_borg_charge)
RegisterSignal(src, COMSIG_ITEM_PRE_UNEQUIP, .proc/on_unequip)
update_cell_alert()
for(var/obj/item/mod/module/module as anything in modules)
module.on_equip()
@@ -385,9 +432,17 @@
for(var/obj/item/mod/module/module as anything in modules)
module.on_unequip()
UnregisterSignal(wearer, list(COMSIG_ATOM_EXITED, COMSIG_PROCESS_BORGCHARGER_OCCUPANT))
UnregisterSignal(src, COMSIG_ITEM_PRE_UNEQUIP)
wearer.clear_alert("mod_charge")
wearer = null
/obj/item/mod/control/proc/on_unequip()
SIGNAL_HANDLER
for(var/obj/item/part in mod_parts)
if(part.loc != src)
return COMPONENT_ITEM_BLOCK_UNEQUIP
/obj/item/mod/control/proc/update_flags()
var/list/used_skin = theme.skins[skin]
for(var/obj/item/clothing/part as anything in mod_parts)
@@ -420,17 +475,21 @@
continue
display_names[module.name] = REF(module)
var/image/module_image = image(icon = module.icon, icon_state = module.icon_state)
if(module == selected_module)
module_image.underlays += image(icon = 'icons/hud/radial.dmi', icon_state = "module_selected")
else if(module.active)
module_image.underlays += image(icon = 'icons/hud/radial.dmi', icon_state = "module_active")
items += list(module.name = module_image)
if(!length(items))
return
var/pick = show_radial_menu(user, src, items, custom_check = FALSE, require_near = TRUE)
var/pick = show_radial_menu(user, src, items, custom_check = FALSE, require_near = TRUE, tooltips = TRUE)
if(!pick)
return
var/module_reference = display_names[pick]
var/obj/item/mod/module/selected_module = locate(module_reference) in modules
if(!istype(selected_module) || user.incapacitated())
var/obj/item/mod/module/picked_module = locate(module_reference) in modules
if(!istype(picked_module) || user.incapacitated())
return
selected_module.on_select()
picked_module.on_select()
/obj/item/mod/control/proc/paint(mob/user, obj/item/paint)
if(length(theme.skins) <= 1)
@@ -557,3 +616,4 @@
if(!cell)
return
cell.give(amount)
update_cell_alert()
-1
View File
@@ -529,7 +529,6 @@
CHESTPLATE_FLAGS = list(
UNSEALED_CLOTHING = THICKMATERIAL,
SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
SEALED_INVISIBILITY = HIDEJUMPSUIT,
),
GAUNTLETS_FLAGS = list(
UNSEALED_CLOTHING = THICKMATERIAL,
+4
View File
@@ -55,6 +55,10 @@
cell = /obj/item/stock_parts/cell/hyper
initial_modules = list(/obj/item/mod/module/storage/large_capacity, /obj/item/mod/module/welding, /obj/item/mod/module/holster, /obj/item/mod/module/pathfinder)
/obj/item/mod/control/pre_equipped/cosmohonk
theme = /datum/mod_theme/cosmohonk
initial_modules = list(/obj/item/mod/module/storage, /obj/item/mod/module/bikehorn)
/obj/item/mod/control/pre_equipped/traitor
theme = /datum/mod_theme/syndicate
cell = /obj/item/stock_parts/cell/super
+8 -1
View File
@@ -513,6 +513,8 @@
range = 10
hitsound = 'sound/weapons/batonextend.ogg'
hitsound_wall = 'sound/weapons/batonextend.ogg'
suppressed = SUPPRESSED_VERY
hit_threshhold = LATTICE_LAYER
var/line
/obj/projectile/tether/fire(setAngle)
@@ -1061,6 +1063,11 @@
playsound(src, 'sound/mecha/hydraulic.ogg', 25, TRUE)
drain_power(use_power_cost)
/obj/item/mod/module/clamp/on_uninstall()
for(var/atom/movable/crate as anything in stored_crates)
crate.forceMove(drop_location())
stored_crates -= crate
/obj/item/mod/module/bikehorn
name = "MOD bike horn module"
desc = "A shoulder-mounted piece of heavy sonic artillery, this module uses the finest femto-manipulator technology to \
@@ -1163,7 +1170,7 @@
if(!.)
return
for(var/obj/item/ore as anything in ores)
ore.forceMove(mod.drop_location())
ore.forceMove(drop_location())
ores -= ore
drain_power(use_power_cost)