[MIRROR] Kinesis Module [MDB IGNORE] (#10815)
* Kinesis Module * Update security_officer.dm Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
@@ -64,8 +64,6 @@
|
||||
#define BURDENED /datum/mutation/human/burdened
|
||||
#define HONORBOUND /datum/mutation/human/honorbound
|
||||
|
||||
#define TK_MOD /datum/mutation/human/telekinesis/mod
|
||||
|
||||
#define UE_CHANGED "ue changed"
|
||||
#define UI_CHANGED "ui changed"
|
||||
#define UF_CHANGED "uf changed"
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/tk_grab/proc/check_if_focusable(obj/target)
|
||||
if(!tk_user || !istype(tk_user) || QDELETED(target) || !istype(target) || !(tk_user.dna.check_mutation(TK) || tk_user.dna.check_mutation(TK_MOD)))
|
||||
if(!tk_user || !istype(tk_user) || QDELETED(target) || !istype(target) || !tk_user.dna.check_mutation(TK))
|
||||
qdel(src)
|
||||
return
|
||||
if(!tkMaxRangeCheck(tk_user, target) || target.anchored || !isturf(target.loc))
|
||||
|
||||
@@ -128,3 +128,8 @@
|
||||
volume = 40
|
||||
falloff_distance = 5
|
||||
falloff_exponent = 20
|
||||
|
||||
/datum/looping_sound/gravgen/kinesis
|
||||
volume = 20
|
||||
falloff_distance = 2
|
||||
falloff_exponent = 5
|
||||
|
||||
@@ -38,14 +38,3 @@
|
||||
if(!tkMaxRangeCheck(source, target) || source.z != target.z)
|
||||
return
|
||||
return target.attack_tk(source)
|
||||
|
||||
/datum/mutation/human/telekinesis/mod
|
||||
name = "Kinesis"
|
||||
desc = "A modification that allows the wearer of a MODsuit to interact with objects through thought with the kinesis module."
|
||||
locked = TRUE
|
||||
text_gain_indication = null
|
||||
limb_req = null
|
||||
instability = 0
|
||||
|
||||
/datum/mutation/human/telekinesis/mod/get_visual_indicator()
|
||||
return
|
||||
|
||||
@@ -81,6 +81,9 @@
|
||||
/datum/effect_system/trail_follow/proc/set_dir(obj/effect/particle_effect/ion_trails/I)
|
||||
I.setDir(holder.dir)
|
||||
|
||||
/datum/effect_system/trail_follow/ion/grav_allowed
|
||||
nograv_required = FALSE
|
||||
|
||||
//Reagent-based explosion effect
|
||||
|
||||
/datum/effect_system/reagents_explosion
|
||||
|
||||
@@ -70,6 +70,12 @@
|
||||
chameleon_extras = /obj/item/stamp/clown
|
||||
implants = list(/obj/item/implant/sad_trombone)
|
||||
|
||||
/datum/outfit/job/clown/mod
|
||||
name = "Clown (MODsuit)"
|
||||
|
||||
suit_store = /obj/item/tank/internals/oxygen
|
||||
back = /obj/item/mod/control/pre_equipped/cosmohonk
|
||||
|
||||
/datum/outfit/job/clown/pre_equip(mob/living/carbon/human/H, visualsOnly)
|
||||
. = ..()
|
||||
if(HAS_TRAIT(SSstation, STATION_TRAIT_BANANIUM_SHIPMENTS))
|
||||
|
||||
@@ -231,7 +231,14 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
|
||||
//The helmet is necessary because /obj/item/clothing/head/helmet/sec is overwritten in the chameleon list by the standard helmet, which has the same name and icon state
|
||||
implants = list(/obj/item/implant/mindshield)
|
||||
|
||||
/datum/outfit/job/security/mod
|
||||
name = "Security Officer (MODsuit)"
|
||||
|
||||
suit_store = /obj/item/tank/internals/oxygen
|
||||
back = /obj/item/mod/control/pre_equipped/security
|
||||
suit = null
|
||||
head = null
|
||||
mask = /obj/item/clothing/mask/gas/sechailer
|
||||
|
||||
/obj/item/radio/headset/headset_sec/alt/department/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
gloves = /obj/item/clothing/gloves/color/fyellow/old
|
||||
l_pocket = /obj/item/tank/internals/emergency_oxygen
|
||||
|
||||
/datum/outfit/oldeng/mod
|
||||
name = "Ancient Engineer (MODsuit)"
|
||||
suit_store = /obj/item/tank/internals/oxygen
|
||||
back = /obj/item/mod/control/pre_equipped/prototype
|
||||
mask = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/oldsci
|
||||
name = "old cryogenics pod"
|
||||
desc = "A humming cryo pod. You can barely recognise a science uniform underneath the built up ice. The machine is attempting to wake up its occupant."
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
|
||||
balloon_alert(user, "suit finished")
|
||||
var/obj/item/mod = new /obj/item/mod/control(drop_location(), external_armor.theme, null, core)
|
||||
core = null
|
||||
qdel(src)
|
||||
user.put_in_hands(mod)
|
||||
else if(part.tool_behaviour == TOOL_SCREWDRIVER) //Construct
|
||||
|
||||
@@ -381,7 +381,7 @@
|
||||
balloon_alert(user, "not painted!")
|
||||
return TRUE
|
||||
else if(open && attacking_item.GetID())
|
||||
update_access(user, attacking_item)
|
||||
update_access(user, attacking_item.GetID())
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
var/obj/item/stock_parts/cell/charge_source = charge_source()
|
||||
if(!charge_source)
|
||||
return FALSE
|
||||
return charge_source.use(amount)
|
||||
return charge_source.use(amount, TRUE)
|
||||
|
||||
/obj/item/mod/core/standard/update_charge_alert()
|
||||
var/obj/item/stock_parts/cell/charge_source = charge_source()
|
||||
@@ -158,9 +158,9 @@
|
||||
return
|
||||
mod.balloon_alert(user, "cell removed")
|
||||
playsound(mod, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
uninstall_cell()
|
||||
cell.forceMove(drop_location())
|
||||
user.put_in_hands(cell)
|
||||
var/obj/item/cell_to_move = cell
|
||||
cell_to_move.forceMove(drop_location())
|
||||
user.put_in_hands(cell_to_move)
|
||||
mod.update_charge_alert()
|
||||
|
||||
/obj/item/mod/core/standard/proc/on_attackby(datum/source, obj/item/attacking_item, mob/user)
|
||||
|
||||
@@ -522,7 +522,6 @@
|
||||
complexity_max = DEFAULT_MAX_COMPLEXITY + 5
|
||||
slowdown_inactive = 0.75
|
||||
slowdown_active = 0.25
|
||||
inbuilt_modules = list(/obj/item/mod/module/hat_stabilizer)
|
||||
skins = list(
|
||||
"magnate" = list(
|
||||
HELMET_LAYER = NECK_LAYER,
|
||||
@@ -764,7 +763,7 @@
|
||||
slowdown_inactive = 2
|
||||
slowdown_active = 1.5
|
||||
ui_theme = "hackerman"
|
||||
inbuilt_modules = list(/obj/item/mod/module/kinesis)
|
||||
inbuilt_modules = list(/obj/item/mod/module/anomaly_locked/kinesis/prebuilt/prototype)
|
||||
skins = list(
|
||||
"prototype" = list(
|
||||
HELMET_LAYER = null,
|
||||
@@ -912,7 +911,6 @@
|
||||
siemens_coefficient = 0
|
||||
slowdown_inactive = 0.5
|
||||
slowdown_active = 0
|
||||
inbuilt_modules = list(/obj/item/mod/module/hat_stabilizer)
|
||||
skins = list(
|
||||
"corporate" = list(
|
||||
HELMET_LAYER = null,
|
||||
|
||||
@@ -118,7 +118,8 @@
|
||||
applied_cell = /obj/item/stock_parts/cell/hyper
|
||||
initial_modules = list(
|
||||
/obj/item/mod/module/storage/large_capacity,
|
||||
/obj/item/mod/module/jetpack,
|
||||
/obj/item/mod/module/hat_stabilizer,
|
||||
/obj/item/mod/module/jetpack/advanced,
|
||||
/obj/item/mod/module/holster,
|
||||
/obj/item/mod/module/pathfinder,
|
||||
)
|
||||
@@ -148,7 +149,7 @@
|
||||
initial_modules = list(
|
||||
/obj/item/mod/module/storage/syndicate,
|
||||
/obj/item/mod/module/welding,
|
||||
/obj/item/mod/module/jetpack,
|
||||
/obj/item/mod/module/jetpack/advanced,
|
||||
/obj/item/mod/module/flashlight,
|
||||
/obj/item/mod/module/holster,
|
||||
/obj/item/mod/module/injector,
|
||||
@@ -161,7 +162,7 @@
|
||||
/obj/item/mod/module/storage/syndicate,
|
||||
/obj/item/mod/module/welding,
|
||||
/obj/item/mod/module/emp_shield,
|
||||
/obj/item/mod/module/jetpack,
|
||||
/obj/item/mod/module/jetpack/advanced,
|
||||
/obj/item/mod/module/flashlight,
|
||||
/obj/item/mod/module/holster,
|
||||
/obj/item/mod/module/injector,
|
||||
@@ -178,7 +179,7 @@
|
||||
|
||||
/obj/item/mod/control/pre_equipped/prototype
|
||||
theme = /datum/mod_theme/prototype
|
||||
applied_cell = /obj/item/stock_parts/cell/upgraded
|
||||
applied_cell = /obj/item/stock_parts/cell/high/plus
|
||||
initial_modules = list(
|
||||
/obj/item/mod/module/storage,
|
||||
/obj/item/mod/module/welding,
|
||||
@@ -278,6 +279,7 @@
|
||||
applied_core = /obj/item/mod/core/infinite
|
||||
initial_modules = list(
|
||||
/obj/item/mod/module/storage/bluespace,
|
||||
/obj/item/mod/module/hat_stabilizer,
|
||||
/obj/item/mod/module/holster,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
///MOD module - A special device installed in a MODsuit allowing the suit to do new stuff.
|
||||
///MOD Module - A special device installed in a MODsuit allowing the suit to do new stuff.
|
||||
/obj/item/mod/module
|
||||
name = "MOD module"
|
||||
icon = 'icons/obj/clothing/modsuit/mod_modules.dmi'
|
||||
@@ -159,6 +159,7 @@
|
||||
balloon_alert(mod.wearer, "on cooldown!")
|
||||
return FALSE
|
||||
if(!check_power(use_power_cost))
|
||||
balloon_alert(mod.wearer, "not enough charge!")
|
||||
return FALSE
|
||||
if(!allowed_in_phaseout && istype(mod.wearer.loc, /obj/effect/dummy/phased_mob))
|
||||
//specifically a to_chat because the user is phased out.
|
||||
@@ -207,6 +208,7 @@
|
||||
if(!check_power(amount))
|
||||
return FALSE
|
||||
mod.subtract_charge(amount)
|
||||
mod.update_charge_alert()
|
||||
return TRUE
|
||||
|
||||
/// Checks if there is enough power in the suit
|
||||
@@ -292,3 +294,90 @@
|
||||
action = new(mod, src, user)
|
||||
action.Grant(user)
|
||||
pinned_to[user] = action
|
||||
|
||||
///Anomaly Locked - Causes the module to not function without an anomaly.
|
||||
/obj/item/mod/module/anomaly_locked
|
||||
name = "MOD anomaly locked module"
|
||||
desc = "A form of a module, locked behind an anomalous core to function."
|
||||
incompatible_modules = list(/obj/item/mod/module/anomaly_locked)
|
||||
/// The core item the module runs off.
|
||||
var/obj/item/assembly/signaler/anomaly/core
|
||||
/// Accepted types of anomaly cores.
|
||||
var/list/accepted_anomalies = list(/obj/item/assembly/signaler/anomaly)
|
||||
/// If this one starts with a core in.
|
||||
var/prebuilt = FALSE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!prebuilt || !length(accepted_anomalies))
|
||||
return
|
||||
var/core_path = pick(accepted_anomalies)
|
||||
core = new core_path(src)
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/Destroy()
|
||||
QDEL_NULL(core)
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/examine(mob/user)
|
||||
. = ..()
|
||||
if(!length(accepted_anomalies))
|
||||
return
|
||||
if(core)
|
||||
. += span_notice("There is a [core.name] installed in it. You could remove it with a <b>screwdriver</b>...")
|
||||
else
|
||||
var/list/core_list = list()
|
||||
for(var/path in accepted_anomalies)
|
||||
var/atom/core_path = path
|
||||
core_list += initial(core_path.name)
|
||||
. += span_notice("You need to insert \a [english_list(core_list, and_text = " or ")] for this module to function.")
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_select()
|
||||
if(!core)
|
||||
balloon_alert(mod.wearer, "no core!")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_process(delta_time)
|
||||
. = ..()
|
||||
if(!core)
|
||||
return FALSE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_active_process(delta_time)
|
||||
if(!core)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/attackby(obj/item/item, mob/living/user, params)
|
||||
if(item.type in accepted_anomalies)
|
||||
if(core)
|
||||
balloon_alert(user, "core already in!")
|
||||
return
|
||||
if(!user.transferItemToLoc(item, src))
|
||||
return
|
||||
core = item
|
||||
balloon_alert(user, "core installed")
|
||||
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
|
||||
update_icon_state()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(!core)
|
||||
balloon_alert(user, "no core!")
|
||||
return
|
||||
balloon_alert(user, "removing core...")
|
||||
if(!do_after(user, 3 SECONDS, target = src))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
balloon_alert(user, "core removed")
|
||||
core.forceMove(drop_location())
|
||||
if(Adjacent(user) && !issilicon(user))
|
||||
user.put_in_hands(core)
|
||||
core = null
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/update_icon_state()
|
||||
icon_state = initial(icon_state) + (core ? "-core" : "")
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
///Kinesis - Gives you the ability to move and launch objects.
|
||||
/obj/item/mod/module/anomaly_locked/kinesis
|
||||
name = "MOD kinesis module"
|
||||
desc = "A modular plug-in to the forearm, this module was presumed lost for many years, \
|
||||
despite the suits it used to be mounted on still seeing some circulation. \
|
||||
This piece of technology allows the user to generate precise anti-gravity fields, \
|
||||
letting them move objects as small as a titanium rod to as large as industrial machinery. \
|
||||
Oddly enough, it doesn't seem to work on living creatures."
|
||||
icon_state = "kinesis"
|
||||
module_type = MODULE_ACTIVE
|
||||
complexity = 3
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN*3
|
||||
incompatible_modules = list(/obj/item/mod/module/anomaly_locked/kinesis)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
overlay_state_inactive = "module_kinesis"
|
||||
overlay_state_active = "module_kinesis_on"
|
||||
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav)
|
||||
var/grab_range = 5
|
||||
var/hit_cooldown_time = 1 SECONDS
|
||||
var/movement_animation
|
||||
var/atom/movable/grabbed_atom
|
||||
var/datum/beam/kinesis_beam
|
||||
var/mutable_appearance/kinesis_icon
|
||||
var/atom/movable/screen/fullscreen/kinesis/kinesis_catcher
|
||||
var/datum/looping_sound/gravgen/kinesis/soundloop
|
||||
COOLDOWN_DECLARE(hit_cooldown)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/Initialize(mapload)
|
||||
. = ..()
|
||||
soundloop = new(src)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/Destroy()
|
||||
if(grabbed_atom)
|
||||
kinesis_catcher = null
|
||||
mod.wearer.clear_fullscreen("kinesis")
|
||||
grabbed_atom.cut_overlay(kinesis_icon)
|
||||
QDEL_NULL(kinesis_beam)
|
||||
grabbed_atom.animate_movement = movement_animation
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/on_select_use(atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(grabbed_atom)
|
||||
launch()
|
||||
clear_grab(playsound = FALSE)
|
||||
return
|
||||
if(!range_check(target))
|
||||
balloon_alert(mod.wearer, "too far!")
|
||||
return
|
||||
if(!can_grab(target))
|
||||
balloon_alert(mod.wearer, "can't grab!")
|
||||
return
|
||||
drain_power(use_power_cost)
|
||||
grabbed_atom = target
|
||||
playsound(grabbed_atom, 'sound/effects/contractorbatonhit.ogg', 75, TRUE)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
kinesis_icon = mutable_appearance(icon='icons/effects/effects.dmi', icon_state="kinesis", layer=grabbed_atom.layer-0.1)
|
||||
kinesis_icon.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM
|
||||
grabbed_atom.add_overlay(kinesis_icon)
|
||||
kinesis_beam = mod.wearer.Beam(grabbed_atom, "kinesis")
|
||||
kinesis_catcher = mod.wearer.overlay_fullscreen("kinesis", /atom/movable/screen/fullscreen/kinesis, 0)
|
||||
kinesis_catcher.kinesis_user = mod.wearer
|
||||
kinesis_catcher.RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, /atom/movable/screen/fullscreen/kinesis.proc/on_move)
|
||||
soundloop.start()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/on_deactivation()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
clear_grab()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/process(delta_time)
|
||||
if(!mod.wearer.client || mod.wearer.incapacitated(ignore_grab = TRUE))
|
||||
clear_grab()
|
||||
return
|
||||
if(!range_check(grabbed_atom))
|
||||
balloon_alert(mod.wearer, "out of range!")
|
||||
clear_grab()
|
||||
return
|
||||
if(!kinesis_catcher.given_turf)
|
||||
return
|
||||
drain_power(use_power_cost/10)
|
||||
mod.wearer.setDir(get_dir(mod.wearer, grabbed_atom))
|
||||
grabbed_atom.set_glide_size()
|
||||
if(grabbed_atom.loc == kinesis_catcher.given_turf)
|
||||
if(grabbed_atom.pixel_x == kinesis_catcher.given_x - world.icon_size/2 && grabbed_atom.pixel_y == kinesis_catcher.given_y - world.icon_size/2)
|
||||
return //spare us redrawing if we are standing still
|
||||
animate(grabbed_atom, 0.2 SECONDS, pixel_x = grabbed_atom.base_pixel_x + kinesis_catcher.given_x - world.icon_size/2, pixel_y = grabbed_atom.base_pixel_y + kinesis_catcher.given_y - world.icon_size/2)
|
||||
kinesis_beam.redrawing()
|
||||
return
|
||||
animate(grabbed_atom, 0.2 SECONDS, pixel_x = grabbed_atom.base_pixel_x + kinesis_catcher.given_x - world.icon_size/2, pixel_y = grabbed_atom.base_pixel_y + kinesis_catcher.given_y - world.icon_size/2)
|
||||
kinesis_beam.redrawing()
|
||||
var/turf/next_turf = get_step_towards(grabbed_atom, kinesis_catcher.given_turf)
|
||||
if(grabbed_atom.Move(next_turf))
|
||||
if(isitem(grabbed_atom) && (mod.wearer in next_turf))
|
||||
var/obj/item/grabbed_item = grabbed_atom
|
||||
grabbed_item.pickup(mod.wearer)
|
||||
mod.wearer.put_in_hands(grabbed_item)
|
||||
return
|
||||
var/pixel_x_change
|
||||
var/pixel_y_change
|
||||
var/direction = get_dir(grabbed_atom, next_turf)
|
||||
if(direction & NORTH)
|
||||
pixel_y_change = world.icon_size/2
|
||||
else if(direction & SOUTH)
|
||||
pixel_y_change = -world.icon_size/2
|
||||
if(direction & EAST)
|
||||
pixel_x_change = world.icon_size/2
|
||||
else if(direction & WEST)
|
||||
pixel_x_change = -world.icon_size/2
|
||||
animate(grabbed_atom, 0.2 SECONDS, pixel_x = grabbed_atom.base_pixel_x + pixel_x_change, pixel_y = grabbed_atom.base_pixel_y + pixel_y_change)
|
||||
kinesis_beam.redrawing()
|
||||
if(!isitem(grabbed_atom) || !COOLDOWN_FINISHED(src, hit_cooldown))
|
||||
return
|
||||
var/atom/hitting_atom
|
||||
if(next_turf.density)
|
||||
hitting_atom = next_turf
|
||||
for(var/atom/movable/movable_content as anything in next_turf.contents)
|
||||
if(ismob(movable_content))
|
||||
continue
|
||||
if(movable_content.density)
|
||||
hitting_atom = movable_content
|
||||
break
|
||||
var/obj/item/grabbed_item = grabbed_atom
|
||||
grabbed_item.melee_attack_chain(mod.wearer, hitting_atom)
|
||||
COOLDOWN_START(src, hit_cooldown, hit_cooldown_time)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/proc/can_grab(atom/target)
|
||||
if(!ismovable(target))
|
||||
return FALSE
|
||||
if(iseffect(target))
|
||||
return FALSE
|
||||
var/atom/movable/movable_target = target
|
||||
if(movable_target.anchored)
|
||||
return FALSE
|
||||
if(movable_target.move_resist >= MOVE_FORCE_OVERPOWERING)
|
||||
return FALSE
|
||||
if(ismob(movable_target))
|
||||
if(!isliving(movable_target))
|
||||
return FALSE
|
||||
var/mob/living/living_target = movable_target
|
||||
if(living_target.stat != DEAD)
|
||||
return FALSE
|
||||
else if(isitem(movable_target))
|
||||
var/obj/item/item_target = movable_target
|
||||
if(item_target.w_class >= WEIGHT_CLASS_GIGANTIC)
|
||||
return FALSE
|
||||
if(item_target.item_flags & ABSTRACT)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/proc/clear_grab(playsound = TRUE)
|
||||
if(!grabbed_atom)
|
||||
return
|
||||
if(playsound)
|
||||
playsound(grabbed_atom, 'sound/effects/empulse.ogg', 75, TRUE)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
kinesis_catcher = null
|
||||
mod.wearer.clear_fullscreen("kinesis")
|
||||
grabbed_atom.cut_overlay(kinesis_icon)
|
||||
QDEL_NULL(kinesis_beam)
|
||||
if(!isitem(grabbed_atom))
|
||||
animate(grabbed_atom, 0.2 SECONDS, pixel_x = grabbed_atom.base_pixel_x, pixel_y = grabbed_atom.base_pixel_y)
|
||||
grabbed_atom = null
|
||||
soundloop.stop()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/proc/range_check(atom/target)
|
||||
if(!isturf(mod.wearer.loc))
|
||||
return FALSE
|
||||
if(ismovable(target) && !isturf(target.loc))
|
||||
return FALSE
|
||||
if(!can_see(mod.wearer, target, grab_range))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/proc/launch()
|
||||
playsound(grabbed_atom, 'sound/magic/repulse.ogg', 100, TRUE)
|
||||
RegisterSignal(grabbed_atom, COMSIG_MOVABLE_IMPACT, .proc/launch_impact)
|
||||
var/turf/target_turf = get_turf_in_angle(get_angle(mod.wearer, grabbed_atom), get_turf(src), 10)
|
||||
grabbed_atom.throw_at(target_turf, range = grab_range, speed = grabbed_atom.density ? 3 : 4, thrower = mod.wearer, spin = isitem(grabbed_atom))
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/proc/launch_impact(atom/movable/source, atom/hit_atom, datum/thrownthing/thrownthing)
|
||||
UnregisterSignal(source, COMSIG_MOVABLE_IMPACT)
|
||||
if(!(isstructure(source) || ismachinery(source) || isvehicle(source)))
|
||||
return
|
||||
var/damage_self = TRUE
|
||||
var/damage = 8
|
||||
if(source.density)
|
||||
damage_self = FALSE
|
||||
damage = 15
|
||||
if(isliving(hit_atom))
|
||||
var/mob/living/living_atom = hit_atom
|
||||
living_atom.apply_damage(damage, BRUTE)
|
||||
else if(hit_atom.uses_integrity)
|
||||
hit_atom.take_damage(damage, BRUTE, MELEE)
|
||||
if(damage_self && source.uses_integrity)
|
||||
source.take_damage(source.max_integrity/5, BRUTE, MELEE)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/prebuilt
|
||||
prebuilt = TRUE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/prebuilt/prototype
|
||||
name = "MOD prototype kinesis module"
|
||||
complexity = 0
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN * 5
|
||||
removable = FALSE
|
||||
|
||||
/atom/movable/screen/fullscreen/kinesis
|
||||
icon_state = "kinesis"
|
||||
plane = HUD_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
var/mob/kinesis_user
|
||||
var/given_x = 16
|
||||
var/given_y = 16
|
||||
var/turf/given_turf
|
||||
COOLDOWN_DECLARE(coordinate_cooldown)
|
||||
|
||||
/atom/movable/screen/fullscreen/kinesis/proc/on_move(atom/source, atom/oldloc, dir, forced)
|
||||
if(given_turf)
|
||||
var/x_offset = source.loc.x - oldloc.x
|
||||
var/y_offset = source.loc.y - oldloc.y
|
||||
given_turf = locate(given_turf.x+x_offset, given_turf.y+y_offset, given_turf.z)
|
||||
|
||||
/atom/movable/screen/fullscreen/kinesis/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
MouseMove(location, control, params)
|
||||
|
||||
/atom/movable/screen/fullscreen/kinesis/MouseMove(location, control, params)
|
||||
if(!kinesis_user?.client || usr != kinesis_user)
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, coordinate_cooldown))
|
||||
return
|
||||
COOLDOWN_START(src, coordinate_cooldown, 0.2 SECONDS)
|
||||
var/list/modifiers = params2list(params)
|
||||
var/icon_x = text2num(LAZYACCESS(modifiers, ICON_X))
|
||||
var/icon_y = text2num(LAZYACCESS(modifiers, ICON_Y))
|
||||
var/list/view = getviewsize(kinesis_user.client.view)
|
||||
icon_x *= view[1]/FULLSCREEN_OVERLAY_RESOLUTION_X
|
||||
icon_y *= view[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y
|
||||
var/our_x = round(icon_x / world.icon_size)
|
||||
var/our_y = round(icon_y / world.icon_size)
|
||||
var/mob_x = kinesis_user.x
|
||||
var/mob_y = kinesis_user.y
|
||||
var/mob_z = kinesis_user.z
|
||||
given_turf = locate(mob_x+our_x-round(view[1]/2),mob_y+our_y-round(view[2]/2),mob_z)
|
||||
given_x = round(icon_x - world.icon_size * our_x)
|
||||
given_y = round(icon_y - world.icon_size * our_y)
|
||||
@@ -0,0 +1,168 @@
|
||||
///Pathfinder - Can fly the suit from a long distance to an implant installed in someone.
|
||||
/obj/item/mod/module/pathfinder
|
||||
name = "MOD pathfinder module"
|
||||
desc = "This module, brought to you by Nakamura Engineering, has two components. \
|
||||
The first component is a series of thrusters and a computerized location subroutine installed into the \
|
||||
very control unit of the suit, allowing it flight at highway speeds, \
|
||||
and to be able to locate the second part of the system; \
|
||||
a pathfinding implant installed into the base of the user's spine, \
|
||||
broadcasting their location to the suit and allowing them to recall it to their back at any time. \
|
||||
The implant is stored in the module and needs to be injected in a human to function. \
|
||||
Nakamura Engineering swears up and down there's airbrakes."
|
||||
icon_state = "pathfinder"
|
||||
complexity = 2
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN * 10
|
||||
incompatible_modules = list(/obj/item/mod/module/pathfinder)
|
||||
/// The pathfinding implant.
|
||||
var/obj/item/implant/mod/implant
|
||||
|
||||
/obj/item/mod/module/pathfinder/Initialize(mapload)
|
||||
. = ..()
|
||||
implant = new(src)
|
||||
|
||||
/obj/item/mod/module/pathfinder/Destroy()
|
||||
implant = null
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/pathfinder/examine(mob/user)
|
||||
. = ..()
|
||||
if(implant)
|
||||
. += span_notice("Use it on a human to implant them.")
|
||||
else
|
||||
. += span_warning("The implant is missing.")
|
||||
|
||||
/obj/item/mod/module/pathfinder/attack(mob/living/target, mob/living/user, params)
|
||||
if(!ishuman(target) || !implant)
|
||||
return
|
||||
if(!do_after(user, 1.5 SECONDS, target = target))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
if(!implant.implant(target, user))
|
||||
balloon_alert(user, "can't implant!")
|
||||
return
|
||||
if(target == user)
|
||||
to_chat(user, span_notice("You implant yourself with [implant]."))
|
||||
else
|
||||
target.visible_message(span_notice("[user] implants [target]."), span_notice("[user] implants you with [implant]."))
|
||||
playsound(src, 'sound/effects/spray.ogg', 30, TRUE, -6)
|
||||
icon_state = "pathfinder_empty"
|
||||
implant = null
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/attach(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(human_user.get_item_by_slot(mod.slot_flags) && !human_user.dropItemToGround(human_user.get_item_by_slot(mod.slot_flags)))
|
||||
return
|
||||
if(!human_user.equip_to_slot_if_possible(mod, mod.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
|
||||
return
|
||||
mod.quick_deploy(user)
|
||||
human_user.update_action_buttons(TRUE)
|
||||
balloon_alert(human_user, "[mod] attached")
|
||||
playsound(mod, 'sound/machines/ping.ogg', 50, TRUE)
|
||||
drain_power(use_power_cost)
|
||||
|
||||
/obj/item/implant/mod
|
||||
name = "MOD pathfinder implant"
|
||||
desc = "Lets you recall a MODsuit to you at any time."
|
||||
actions_types = list(/datum/action/item_action/mod_recall)
|
||||
/// The pathfinder module we are linked to.
|
||||
var/obj/item/mod/module/pathfinder/module
|
||||
/// The jet icon we apply to the MOD.
|
||||
var/image/jet_icon
|
||||
|
||||
/obj/item/implant/mod/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!istype(loc, /obj/item/mod/module/pathfinder))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
module = loc
|
||||
jet_icon = image(icon = 'icons/obj/clothing/modsuit/mod_modules.dmi', icon_state = "mod_jet", layer = LOW_ITEM_LAYER)
|
||||
|
||||
/obj/item/implant/mod/Destroy()
|
||||
if(module?.mod?.ai_controller)
|
||||
end_recall(successful = FALSE)
|
||||
module = null
|
||||
jet_icon = null
|
||||
return ..()
|
||||
|
||||
/obj/item/implant/mod/get_data()
|
||||
var/dat = {"<b>Implant Specifications:</b><BR>
|
||||
<b>Name:</b> Nakamura Engineering Pathfinder Implant<BR>
|
||||
<b>Implant Details:</b> Allows for the recall of a Modular Outerwear Device by the implant owner at any time.<BR>"}
|
||||
return dat
|
||||
|
||||
/obj/item/implant/mod/proc/recall()
|
||||
if(!module?.mod)
|
||||
balloon_alert(imp_in, "no connected suit!")
|
||||
return FALSE
|
||||
if(module.mod.open)
|
||||
balloon_alert(imp_in, "suit is open!")
|
||||
return FALSE
|
||||
if(module.mod.ai_controller)
|
||||
balloon_alert(imp_in, "already in transit!")
|
||||
return FALSE
|
||||
if(ismob(get_atom_on_turf(module.mod)))
|
||||
balloon_alert(imp_in, "already on someone!")
|
||||
return FALSE
|
||||
if(module.z != z || get_dist(imp_in, module.mod) > MOD_AI_RANGE)
|
||||
balloon_alert(imp_in, "too far away!")
|
||||
return FALSE
|
||||
var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(module.mod)
|
||||
module.mod.ai_controller = mod_ai
|
||||
mod_ai.current_movement_target = imp_in
|
||||
mod_ai.blackboard[BB_MOD_TARGET] = imp_in
|
||||
mod_ai.blackboard[BB_MOD_IMPLANT] = src
|
||||
module.mod.interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
module.mod.AddElement(/datum/element/movetype_handler)
|
||||
ADD_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
animate(module.mod, 0.2 SECONDS, pixel_x = base_pixel_y, pixel_y = base_pixel_y)
|
||||
module.mod.add_overlay(jet_icon)
|
||||
RegisterSignal(module.mod, COMSIG_MOVABLE_MOVED, .proc/on_move)
|
||||
balloon_alert(imp_in, "suit recalled")
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/mod/proc/end_recall(successful = TRUE)
|
||||
if(!module?.mod)
|
||||
return
|
||||
QDEL_NULL(module.mod.ai_controller)
|
||||
module.mod.interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
REMOVE_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
module.mod.RemoveElement(/datum/element/movetype_handler)
|
||||
module.mod.cut_overlay(jet_icon)
|
||||
module.mod.transform = matrix()
|
||||
UnregisterSignal(module.mod, COMSIG_MOVABLE_MOVED)
|
||||
if(!successful)
|
||||
balloon_alert(imp_in, "suit lost connection!")
|
||||
|
||||
/obj/item/implant/mod/proc/on_move(atom/movable/source, atom/old_loc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/matrix/mod_matrix = matrix()
|
||||
mod_matrix.Turn(get_angle(source, imp_in))
|
||||
source.transform = mod_matrix
|
||||
|
||||
/datum/action/item_action/mod_recall
|
||||
name = "Recall MOD"
|
||||
desc = "Recall a MODsuit anyplace, anytime."
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_tech_blue"
|
||||
icon_icon = 'icons/mob/actions/actions_mod.dmi'
|
||||
button_icon_state = "recall"
|
||||
/// The cooldown for the recall.
|
||||
COOLDOWN_DECLARE(recall_cooldown)
|
||||
/// The implant we are linked to.
|
||||
var/obj/item/implant/mod/implant
|
||||
|
||||
/datum/action/item_action/mod_recall/New(Target)
|
||||
..()
|
||||
implant = Target
|
||||
|
||||
/datum/action/item_action/mod_recall/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, recall_cooldown))
|
||||
implant.balloon_alert(implant.imp_in, "on cooldown!")
|
||||
return
|
||||
if(implant.recall())
|
||||
COOLDOWN_START(src, recall_cooldown, 15 SECONDS)
|
||||
@@ -204,44 +204,3 @@
|
||||
return
|
||||
rcd_scan(src, fade_time = 10 SECONDS)
|
||||
drain_power(use_power_cost)
|
||||
|
||||
///Kinesis - Gives you a special form of telekinesis.
|
||||
/obj/item/mod/module/kinesis //TODO POST-MERGE MAKE NOT SUCK ASS, MAKE BALLER AS FUCK
|
||||
name = "MOD kinesis module"
|
||||
desc = "A modular plug-in to the forearm, this module was presumed lost for many years, \
|
||||
despite the suits it used to be mounted on still seeing some circulation. \
|
||||
This piece of technology allows the user to generate precise anti-gravity fields, \
|
||||
letting them move objects as small as a titanium rod to as large as industrial machinery. \
|
||||
Oddly enough, it doesn't seem to work on living creatures."
|
||||
icon_state = "kinesis"
|
||||
// module_type = MODULE_ACTIVE
|
||||
module_type = MODULE_TOGGLE
|
||||
// complexity = 3
|
||||
complexity = 0
|
||||
active_power_cost = DEFAULT_CHARGE_DRAIN*0.75
|
||||
// use_power_cost = DEFAULT_CHARGE_DRAIN*3
|
||||
removable = FALSE
|
||||
incompatible_modules = list(/obj/item/mod/module/kinesis)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
overlay_state_inactive = "module_kinesis"
|
||||
overlay_state_active = "module_kinesis_on"
|
||||
/// Whether the user had TK previously or not.
|
||||
var/has_tk = FALSE
|
||||
|
||||
/obj/item/mod/module/kinesis/on_activation()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(mod.wearer.dna.check_mutation(TK))
|
||||
has_tk = TRUE
|
||||
return
|
||||
mod.wearer.dna.add_mutation(TK_MOD)
|
||||
|
||||
/obj/item/mod/module/kinesis/on_deactivation()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(has_tk)
|
||||
has_tk = FALSE
|
||||
return
|
||||
mod.wearer.dna.remove_mutation(TK_MOD)
|
||||
|
||||
@@ -95,11 +95,11 @@
|
||||
/// Do we give the wearer a speed buff.
|
||||
var/full_speed = FALSE
|
||||
/// The ion trail particles left after the jetpack.
|
||||
var/datum/effect_system/trail_follow/ion/ion_trail
|
||||
var/datum/effect_system/trail_follow/ion/grav_allowed/ion_trail
|
||||
|
||||
/obj/item/mod/module/jetpack/Initialize(mapload)
|
||||
. = ..()
|
||||
ion_trail = new
|
||||
ion_trail = new()
|
||||
ion_trail.auto_process = FALSE
|
||||
ion_trail.set_up(src)
|
||||
|
||||
@@ -171,6 +171,11 @@
|
||||
ion_trail.generate_effect()
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/jetpack/advanced
|
||||
name = "MOD advanced ion jetpack module"
|
||||
icon_state = "jetpack_advanced"
|
||||
full_speed = TRUE
|
||||
|
||||
///Eating Apparatus - Lets the user eat/drink with the suit on.
|
||||
/obj/item/mod/module/mouthhole
|
||||
name = "MOD eating apparatus module"
|
||||
@@ -379,175 +384,6 @@
|
||||
/obj/item/mod/module/thermal_regulator/on_active_process(delta_time)
|
||||
mod.wearer.adjust_bodytemperature(get_temp_change_amount((temperature_setting - mod.wearer.bodytemperature), 0.08 * delta_time))
|
||||
|
||||
///Pathfinder - Can fly the suit from a long distance to an implant installed in someone.
|
||||
/obj/item/mod/module/pathfinder
|
||||
name = "MOD pathfinder module"
|
||||
desc = "This module, brought to you by Nakamura Engineering, has two components. \
|
||||
The first component is a series of thrusters and a computerized location subroutine installed into the \
|
||||
very control unit of the suit, allowing it flight at highway speeds, \
|
||||
and to be able to locate the second part of the system; \
|
||||
a pathfinding implant installed into the base of the user's spine, \
|
||||
broadcasting their location to the suit and allowing them to recall it to their back at any time. \
|
||||
The implant is stored in the module and needs to be injected in a human to function. \
|
||||
Nakamura Engineering swears up and down there's airbrakes."
|
||||
icon_state = "pathfinder"
|
||||
complexity = 2
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN * 10
|
||||
incompatible_modules = list(/obj/item/mod/module/pathfinder)
|
||||
/// The pathfinding implant.
|
||||
var/obj/item/implant/mod/implant
|
||||
|
||||
/obj/item/mod/module/pathfinder/Initialize(mapload)
|
||||
. = ..()
|
||||
implant = new(src)
|
||||
|
||||
/obj/item/mod/module/pathfinder/Destroy()
|
||||
implant = null
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/pathfinder/examine(mob/user)
|
||||
. = ..()
|
||||
if(implant)
|
||||
. += span_notice("Use it on a human to implant them.")
|
||||
else
|
||||
. += span_warning("The implant is missing.")
|
||||
|
||||
/obj/item/mod/module/pathfinder/attack(mob/living/target, mob/living/user, params)
|
||||
if(!ishuman(target) || !implant)
|
||||
return
|
||||
if(!do_after(user, 1.5 SECONDS, target = target))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
if(!implant.implant(target, user))
|
||||
balloon_alert(user, "can't implant!")
|
||||
return
|
||||
if(target == user)
|
||||
to_chat(user, span_notice("You implant yourself with [implant]."))
|
||||
else
|
||||
target.visible_message(span_notice("[user] implants [target]."), span_notice("[user] implants you with [implant]."))
|
||||
playsound(src, 'sound/effects/spray.ogg', 30, TRUE, -6)
|
||||
icon_state = "pathfinder_empty"
|
||||
implant = null
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/attach(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(human_user.get_item_by_slot(mod.slot_flags) && !human_user.dropItemToGround(human_user.get_item_by_slot(mod.slot_flags)))
|
||||
return
|
||||
if(!human_user.equip_to_slot_if_possible(mod, mod.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
|
||||
return
|
||||
mod.quick_deploy(user)
|
||||
human_user.update_action_buttons(TRUE)
|
||||
balloon_alert(human_user, "[mod] attached")
|
||||
playsound(mod, 'sound/machines/ping.ogg', 50, TRUE)
|
||||
drain_power(use_power_cost)
|
||||
|
||||
/obj/item/implant/mod
|
||||
name = "MOD pathfinder implant"
|
||||
desc = "Lets you recall a MODsuit to you at any time."
|
||||
actions_types = list(/datum/action/item_action/mod_recall)
|
||||
/// The pathfinder module we are linked to.
|
||||
var/obj/item/mod/module/pathfinder/module
|
||||
/// The jet icon we apply to the MOD.
|
||||
var/image/jet_icon
|
||||
|
||||
/obj/item/implant/mod/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!istype(loc, /obj/item/mod/module/pathfinder))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
module = loc
|
||||
jet_icon = image(icon = 'icons/obj/clothing/modsuit/mod_modules.dmi', icon_state = "mod_jet", layer = LOW_ITEM_LAYER)
|
||||
|
||||
/obj/item/implant/mod/Destroy()
|
||||
if(module?.mod?.ai_controller)
|
||||
end_recall(successful = FALSE)
|
||||
module = null
|
||||
jet_icon = null
|
||||
return ..()
|
||||
|
||||
/obj/item/implant/mod/get_data()
|
||||
var/dat = {"<b>Implant Specifications:</b><BR>
|
||||
<b>Name:</b> Nakamura Engineering Pathfinder Implant<BR>
|
||||
<b>Implant Details:</b> Allows for the recall of a Modular Outerwear Device by the implant owner at any time.<BR>"}
|
||||
return dat
|
||||
|
||||
/obj/item/implant/mod/proc/recall()
|
||||
if(!module?.mod)
|
||||
balloon_alert(imp_in, "no connected suit!")
|
||||
return FALSE
|
||||
if(module.mod.open)
|
||||
balloon_alert(imp_in, "suit is open!")
|
||||
return FALSE
|
||||
if(module.mod.ai_controller)
|
||||
balloon_alert(imp_in, "already in transit!")
|
||||
return FALSE
|
||||
if(ismob(get_atom_on_turf(module.mod)))
|
||||
balloon_alert(imp_in, "already on someone!")
|
||||
return FALSE
|
||||
if(module.z != z || get_dist(imp_in, module.mod) > MOD_AI_RANGE)
|
||||
balloon_alert(imp_in, "too far away!")
|
||||
return FALSE
|
||||
var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(module.mod)
|
||||
module.mod.ai_controller = mod_ai
|
||||
mod_ai.current_movement_target = imp_in
|
||||
mod_ai.blackboard[BB_MOD_TARGET] = imp_in
|
||||
mod_ai.blackboard[BB_MOD_IMPLANT] = src
|
||||
module.mod.interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
module.mod.AddElement(/datum/element/movetype_handler)
|
||||
ADD_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
animate(module.mod, 0.2 SECONDS, pixel_x = base_pixel_y, pixel_y = base_pixel_y)
|
||||
module.mod.add_overlay(jet_icon)
|
||||
RegisterSignal(module.mod, COMSIG_MOVABLE_MOVED, .proc/on_move)
|
||||
balloon_alert(imp_in, "suit recalled")
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/mod/proc/end_recall(successful = TRUE)
|
||||
if(!module?.mod)
|
||||
return
|
||||
QDEL_NULL(module.mod.ai_controller)
|
||||
module.mod.interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
REMOVE_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
module.mod.RemoveElement(/datum/element/movetype_handler)
|
||||
module.mod.cut_overlay(jet_icon)
|
||||
module.mod.transform = matrix()
|
||||
UnregisterSignal(module.mod, COMSIG_MOVABLE_MOVED)
|
||||
if(!successful)
|
||||
balloon_alert(imp_in, "suit lost connection!")
|
||||
|
||||
/obj/item/implant/mod/proc/on_move(atom/movable/source, atom/old_loc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/matrix/mod_matrix = matrix()
|
||||
mod_matrix.Turn(get_angle(source, imp_in))
|
||||
source.transform = mod_matrix
|
||||
|
||||
/datum/action/item_action/mod_recall
|
||||
name = "Recall MOD"
|
||||
desc = "Recall a MODsuit anyplace, anytime."
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_tech_blue"
|
||||
icon_icon = 'icons/mob/actions/actions_mod.dmi'
|
||||
button_icon_state = "recall"
|
||||
/// The cooldown for the recall.
|
||||
COOLDOWN_DECLARE(recall_cooldown)
|
||||
/// The implant we are linked to.
|
||||
var/obj/item/implant/mod/implant
|
||||
|
||||
/datum/action/item_action/mod_recall/New(Target)
|
||||
..()
|
||||
implant = Target
|
||||
|
||||
/datum/action/item_action/mod_recall/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, recall_cooldown))
|
||||
implant.balloon_alert(implant.imp_in, "on cooldown!")
|
||||
return
|
||||
if(implant.recall())
|
||||
COOLDOWN_START(src, recall_cooldown, 15 SECONDS)
|
||||
|
||||
///DNA Lock - Prevents people without the set DNA from activating the suit.
|
||||
/obj/item/mod/module/dna_lock
|
||||
name = "MOD DNA lock module"
|
||||
@@ -657,9 +493,9 @@
|
||||
incompatible_modules = list(/obj/item/mod/module/hat_stabilizer)
|
||||
/*Intentionally left inheriting 0 complexity and removable = TRUE;
|
||||
even though it comes inbuilt into the Magnate/Corporate MODS and spawns in maints, I like the idea of stealing them*/
|
||||
///Currently "stored" hat. No armor or function will be inherited, ONLY the icon.
|
||||
/// Currently "stored" hat. No armor or function will be inherited, ONLY the icon.
|
||||
var/obj/item/clothing/head/attached_hat
|
||||
///Whitelist of attachable hats; read note in Initialize() below this line
|
||||
/// Whitelist of attachable hats, read note in Initialize() below this line
|
||||
var/static/list/attachable_hats_list
|
||||
|
||||
/obj/item/mod/module/hat_stabilizer/Initialize()
|
||||
@@ -723,7 +559,7 @@
|
||||
return
|
||||
if(mod.wearer.transferItemToLoc(hitting_item, src, force = FALSE, silent = TRUE))
|
||||
attached_hat = hitting_item
|
||||
balloon_alert(user, "hat attached, right click to remove")
|
||||
balloon_alert(user, "hat attached, right-click to remove")
|
||||
mod.wearer.update_inv_back()
|
||||
|
||||
/obj/item/mod/module/hat_stabilizer/generate_worn_overlay()
|
||||
|
||||
@@ -52,7 +52,8 @@
|
||||
playsound(mod.wearer, 'sound/effects/splat.ogg', 50, TRUE, frequency = 0.5)
|
||||
mod.wearer.client?.give_award(/datum/award/achievement/misc/springlock, mod.wearer)
|
||||
mod.wearer.apply_damage(500, BRUTE, forced = TRUE, spread_damage = TRUE, sharpness = SHARP_POINTY) //boggers, bogchamp, etc
|
||||
mod.wearer.death() //just in case, for some reason, they're still alive
|
||||
if(!HAS_TRAIT(mod.wearer, TRAIT_NODEATH))
|
||||
mod.wearer.death() //just in case, for some reason, they're still alive
|
||||
flash_color(mod.wearer, flash_color = "#FF0000", flash_time = 10 SECONDS)
|
||||
|
||||
///Rave Visor - Gives you a rainbow visor and plays jukebox music to you.
|
||||
|
||||
@@ -79,11 +79,11 @@
|
||||
starting_circuit = circuit, \
|
||||
)
|
||||
|
||||
/*/obj/item/mod/module/circuit/on_install()
|
||||
circuit.set_cell(mod.cell)
|
||||
/obj/item/mod/module/circuit/on_install()
|
||||
circuit.set_cell(mod.get_cell())
|
||||
|
||||
/obj/item/mod/module/circuit/on_uninstall()
|
||||
circuit.set_cell(mod.cell)*/
|
||||
circuit.set_cell(mod.get_cell())
|
||||
|
||||
/obj/item/mod/module/circuit/on_suit_activation()
|
||||
circuit.set_on(TRUE)
|
||||
@@ -160,93 +160,6 @@
|
||||
return
|
||||
wearer.set_output(attached_module.mod.wearer)
|
||||
|
||||
///Anomaly Locked - Causes the module to not function without an anomaly.
|
||||
/obj/item/mod/module/anomaly_locked
|
||||
name = "MOD anomaly locked module"
|
||||
desc = "A form of a module, locked behind an anomalous core to function."
|
||||
incompatible_modules = list(/obj/item/mod/module/anomaly_locked)
|
||||
/// The core item the module runs off.
|
||||
var/obj/item/assembly/signaler/anomaly/core
|
||||
/// Accepted types of anomaly cores.
|
||||
var/list/accepted_anomalies = list(/obj/item/assembly/signaler/anomaly)
|
||||
/// If this one starts with a core in.
|
||||
var/prebuilt = FALSE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!prebuilt || !length(accepted_anomalies))
|
||||
return
|
||||
var/core_path = pick(accepted_anomalies)
|
||||
core = new core_path(src)
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/Destroy()
|
||||
QDEL_NULL(core)
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/examine(mob/user)
|
||||
. = ..()
|
||||
if(!length(accepted_anomalies))
|
||||
return
|
||||
if(core)
|
||||
. += span_notice("There is a [core.name] installed in it. You could remove it with a <b>screwdriver</b>...")
|
||||
else
|
||||
var/list/core_list = list()
|
||||
for(var/path in accepted_anomalies)
|
||||
var/atom/core_path = path
|
||||
core_list += initial(core_path.name)
|
||||
. += span_notice("You need to insert \a [english_list(core_list, and_text = " or ")] for this module to function.")
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_select()
|
||||
if(!core)
|
||||
balloon_alert(mod.wearer, "no core!")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_process(delta_time)
|
||||
. = ..()
|
||||
if(!core)
|
||||
return FALSE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/on_active_process(delta_time)
|
||||
if(!core)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/attackby(obj/item/item, mob/living/user, params)
|
||||
if(item.type in accepted_anomalies)
|
||||
if(core)
|
||||
balloon_alert(user, "core already in!")
|
||||
return
|
||||
if(!user.transferItemToLoc(item, src))
|
||||
return
|
||||
core = item
|
||||
balloon_alert(user, "core installed")
|
||||
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
|
||||
update_icon_state()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(!core)
|
||||
balloon_alert(user, "no core!")
|
||||
return
|
||||
balloon_alert(user, "removing core...")
|
||||
if(!do_after(user, 3 SECONDS, target = src))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
balloon_alert(user, "core removed")
|
||||
core.forceMove(drop_location())
|
||||
if(Adjacent(user) && !issilicon(user))
|
||||
user.put_in_hands(core)
|
||||
core = null
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/update_icon_state()
|
||||
icon_state = initial(icon_state) + (core ? "-core" : "")
|
||||
return ..()
|
||||
|
||||
///Anti-Gravity - Makes the user weightless.
|
||||
/obj/item/mod/module/anomaly_locked/antigrav
|
||||
name = "MOD anti-gravity module"
|
||||
|
||||
@@ -75,13 +75,13 @@
|
||||
return 100*charge/maxcharge
|
||||
|
||||
// use power from a cell
|
||||
/obj/item/stock_parts/cell/use(amount)
|
||||
/obj/item/stock_parts/cell/use(amount, force)
|
||||
if(rigged && amount > 0)
|
||||
explode()
|
||||
return FALSE
|
||||
if(charge < amount)
|
||||
if(!force && charge < amount)
|
||||
return FALSE
|
||||
charge = (charge - amount)
|
||||
charge = max(charge - amount, 0)
|
||||
if(!istype(loc, /obj/machinery/power/apc))
|
||||
SSblackbox.record_feedback("tally", "cell_used", 1, type)
|
||||
return TRUE
|
||||
@@ -213,6 +213,10 @@
|
||||
/obj/item/stock_parts/cell/get_part_rating()
|
||||
return rating * maxcharge
|
||||
|
||||
/obj/item/stock_parts/cell/attackby_storage_insert(datum/component/storage, atom/storage_holder, mob/user)
|
||||
var/obj/item/mod/control/mod = storage_holder
|
||||
return !(istype(mod) && mod.open)
|
||||
|
||||
/* Cell variants*/
|
||||
/obj/item/stock_parts/cell/empty/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -1354,22 +1354,29 @@
|
||||
materials = list(/datum/material/plasma = 1000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/mod/module/plasma_stabilizer
|
||||
|
||||
/datum/design/module/mod_glove_translator
|
||||
name = "MOD Module: Glove Translator"
|
||||
id = "mod_sign_radio"
|
||||
materials = list(/datum/material/iron = 750, /datum/material/glass = 500)
|
||||
build_path = /obj/item/mod/module/signlang_radio
|
||||
|
||||
/datum/design/module/mod_antigrav
|
||||
name = "MOD Module: Anti-Gravity"
|
||||
id = "mod_antigrav"
|
||||
materials = list(/datum/material/iron = 2500, /datum/material/glass = 2000, /datum/material/uranium = 1000)
|
||||
materials = list(/datum/material/iron = 2500, /datum/material/glass = 2000, /datum/material/uranium = 2000)
|
||||
build_path = /obj/item/mod/module/anomaly_locked/antigrav
|
||||
department_type = MODULE_SCIENCE
|
||||
|
||||
/datum/design/module/mod_teleporter
|
||||
name = "MOD Module: Teleporter"
|
||||
id = "mod_teleporter"
|
||||
materials = list(/datum/material/iron = 2500, /datum/material/glass = 2000, /datum/material/bluespace = 1000)
|
||||
materials = list(/datum/material/iron = 2500, /datum/material/glass = 2000, /datum/material/bluespace = 2000)
|
||||
build_path = /obj/item/mod/module/anomaly_locked/teleporter
|
||||
department_type = MODULE_SCIENCE
|
||||
|
||||
/datum/design/module/mod_glove_translator
|
||||
name = "MOD Module: Glove Translator"
|
||||
id = "mod_sign_radio"
|
||||
materials = list(/datum/material/iron = 750, /datum/material/glass = 500)
|
||||
build_path = /obj/item/mod/module/signlang_radio
|
||||
/datum/design/module/mod_kinesis
|
||||
name = "MOD Module: Kinesis"
|
||||
id = "mod_kinesis"
|
||||
materials = list(/datum/material/iron = 2500, /datum/material/glass = 2000, /datum/material/uranium = 1000, /datum/material/bluespace = 1000)
|
||||
build_path = /obj/item/mod/module/anomaly_locked/kinesis
|
||||
department_type = MODULE_ENGINEERING
|
||||
|
||||
@@ -123,13 +123,13 @@
|
||||
display_name = "Basic Modular Suits"
|
||||
description = "Specialized back mounted power suits with various different modules."
|
||||
design_ids = list(
|
||||
"mod_armor_standard",
|
||||
"mod_boots",
|
||||
"mod_chestplate",
|
||||
"mod_gauntlets",
|
||||
"mod_helmet",
|
||||
"mod_paint_kit",
|
||||
"mod_shell",
|
||||
"mod_armor_standard",
|
||||
"mod_storage",
|
||||
"mod_welding",
|
||||
"mod_mouthhole",
|
||||
@@ -1557,7 +1557,6 @@
|
||||
"mod_clamp",
|
||||
"mod_drill",
|
||||
"mod_orebag",
|
||||
"mod_pathfinder",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
|
||||
@@ -1642,7 +1641,17 @@
|
||||
"mod_antigrav",
|
||||
"mod_teleporter",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
|
||||
/datum/techweb_node/mod_anomaly_engi
|
||||
id = "mod_anomaly_engi"
|
||||
display_name = "Engineering Anomalock Modular Suits"
|
||||
description = "Advanced modules for modular suits, using anomaly cores to become even better engineers."
|
||||
prereq_ids = list("mod_advanced_engineering", "mod_anomaly")
|
||||
design_ids = list(
|
||||
"mod_kinesis",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
|
||||
|
||||
////////////////////////mech technology////////////////////////
|
||||
/datum/techweb_node/adv_mecha
|
||||
|
||||
@@ -903,9 +903,8 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/slimepotion/speed/attackby_storage_insert(datum/component/storage, atom/storage_holder, mob/user)
|
||||
. = ..()
|
||||
if(!isitem(storage_holder))
|
||||
return
|
||||
return TRUE
|
||||
if(istype(storage_holder, /obj/item/mod/control))
|
||||
var/obj/item/mod/control/mod = storage_holder
|
||||
return mod.slowdown_inactive <= 0
|
||||
|
||||
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 906 KiB After Width: | Height: | Size: 907 KiB |
|
Before Width: | Height: | Size: 4.8 MiB After Width: | Height: | Size: 6.4 MiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.2 KiB |
@@ -3347,6 +3347,8 @@
|
||||
#include "code\modules\mod\mod_types.dm"
|
||||
#include "code\modules\mod\mod_ui.dm"
|
||||
#include "code\modules\mod\modules\_module.dm"
|
||||
#include "code\modules\mod\modules\module_kinesis.dm"
|
||||
#include "code\modules\mod\modules\module_pathfinder.dm"
|
||||
#include "code\modules\mod\modules\modules_antag.dm"
|
||||
#include "code\modules\mod\modules\modules_engineering.dm"
|
||||
#include "code\modules\mod\modules\modules_general.dm"
|
||||
|
||||