diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index b3016e3926..4376ba9c03 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -140,6 +140,8 @@
#define isstructure(A) (istype(A, /obj/structure))
+#define ismecha(A) (istype(A, /obj/mecha))
+
#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
#define isorgan(A) (istype(A, /obj/item/organ))
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 2bc6e144dd..0536d60a33 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -96,7 +96,7 @@
if(!modifiers["catcher"] && A.IsObscured())
return
- if(istype(loc, /obj/mecha))
+ if(ismecha(loc))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 07c17b891f..1d36f7d31e 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -28,7 +28,7 @@
icon_state = "act_equip"
/obj/screen/human/equip/Click()
- if(istype(usr.loc, /obj/mecha)) // stops inventory actions in a mech
+ if(ismecha(usr.loc)) // stops inventory actions in a mech
return 1
var/mob/living/carbon/human/H = usr
H.quick_equip()
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 2d94f41ba9..7bf73bb297 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -34,6 +34,7 @@
icon = null
icon_state = null
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+<<<<<<< HEAD
screen_loc = "CENTER-7,CENTER-7"
maptext_height = 480
maptext_width = 480
@@ -258,6 +259,232 @@
var/obj/item/clothing/mask/M = C.wear_mask
if(M.mask_adjusted) // if mask on face but pushed down
M.adjustmask(C) // adjust it back
+=======
+ screen_loc = "CENTER-7,CENTER-7"
+ maptext_height = 480
+ maptext_width = 480
+
+/obj/screen/swap_hand
+ layer = HUD_LAYER
+ plane = HUD_PLANE
+ name = "swap hand"
+
+/obj/screen/swap_hand/Click()
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+
+ if(usr.incapacitated())
+ return 1
+
+ if(ismob(usr))
+ var/mob/M = usr
+ M.swap_hand()
+ return 1
+
+/obj/screen/craft
+ name = "crafting menu"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "craft"
+ screen_loc = ui_crafting
+
+/obj/screen/craft/Click()
+ var/mob/living/M = usr
+ if(isobserver(usr))
+ return
+ M.OpenCraftingMenu()
+
+/obj/screen/area_creator
+ name = "create new area"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "area_edit"
+ screen_loc = ui_building
+
+/obj/screen/area_creator/Click()
+ if(usr.incapacitated())
+ return 1
+ var/area/A = get_area(usr)
+ if(!A.outdoors)
+ to_chat(usr, "There is already a defined structure here.")
+ return 1
+ create_area(usr)
+
+/obj/screen/language_menu
+ name = "language menu"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "talk_wheel"
+ screen_loc = ui_language_menu
+
+/obj/screen/language_menu/Click()
+ var/mob/M = usr
+ var/datum/language_holder/H = M.get_language_holder()
+ H.open_language_menu(usr)
+
+/obj/screen/inventory
+ var/slot_id // The indentifier for the slot. It has nothing to do with ID cards.
+ var/icon_empty // Icon when empty. For now used only by humans.
+ var/icon_full // Icon when contains an item. For now used only by humans.
+ layer = HUD_LAYER
+ plane = HUD_PLANE
+
+/obj/screen/inventory/Click(location, control, params)
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+
+ if(usr.incapacitated())
+ return 1
+ if(ismecha(usr.loc)) // stops inventory actions in a mech
+ return 1
+
+ if(hud && hud.mymob && slot_id)
+ var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
+ if(inv_item)
+ return inv_item.Click(location, control, params)
+
+ if(usr.attack_ui(slot_id))
+ usr.update_inv_hands()
+ return 1
+
+/obj/screen/inventory/update_icon()
+ if(!icon_empty)
+ icon_empty = icon_state
+
+ if(hud && hud.mymob && slot_id && icon_full)
+ if(hud.mymob.get_item_by_slot(slot_id))
+ icon_state = icon_full
+ else
+ icon_state = icon_empty
+
+/obj/screen/inventory/hand
+ var/mutable_appearance/handcuff_overlay
+ var/static/mutable_appearance/blocked_overlay = mutable_appearance('icons/mob/screen_gen.dmi', "blocked")
+ var/held_index = 0
+
+/obj/screen/inventory/hand/update_icon()
+ ..()
+
+ if(!handcuff_overlay)
+ var/state = (!(held_index % 2)) ? "markus" : "gabrielle"
+ handcuff_overlay = mutable_appearance('icons/mob/screen_gen.dmi', state)
+
+ cut_overlays()
+
+ if(hud && hud.mymob)
+ if(iscarbon(hud.mymob))
+ var/mob/living/carbon/C = hud.mymob
+ if(C.handcuffed)
+ add_overlay(handcuff_overlay)
+
+ if(held_index)
+ if(!C.has_hand_for_held_index(held_index))
+ add_overlay(blocked_overlay)
+
+ if(held_index == hud.mymob.active_hand_index)
+ add_overlay("hand_active")
+
+
+/obj/screen/inventory/hand/Click(location, control, params)
+ // At this point in client Click() code we have passed the 1/10 sec check and little else
+ // We don't even know if it's a middle click
+ if(world.time <= usr.next_move)
+ return 1
+ if(usr.incapacitated() || isobserver(usr))
+ return 1
+ if (ismecha(usr.loc)) // stops inventory actions in a mech
+ return 1
+
+ if(hud.mymob.active_hand_index == held_index)
+ var/obj/item/I = hud.mymob.get_active_held_item()
+ if(I)
+ I.Click(location, control, params)
+ else
+ hud.mymob.swap_hand(held_index)
+ return 1
+
+/obj/screen/close
+ name = "close"
+
+/obj/screen/close/Click()
+ if(istype(master, /obj/item/storage))
+ var/obj/item/storage/S = master
+ S.close(usr)
+ return 1
+
+
+/obj/screen/drop
+ name = "drop"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "act_drop"
+ layer = HUD_LAYER
+ plane = HUD_PLANE
+
+/obj/screen/drop/Click()
+ usr.drop_item_v()
+
+/obj/screen/act_intent
+ name = "intent"
+ icon_state = "help"
+ screen_loc = ui_acti
+
+/obj/screen/act_intent/Click(location, control, params)
+ usr.a_intent_change(INTENT_HOTKEY_RIGHT)
+
+/obj/screen/act_intent/segmented/Click(location, control, params)
+ if(usr.client.prefs.toggles & INTENT_STYLE)
+ var/_x = text2num(params2list(params)["icon-x"])
+ var/_y = text2num(params2list(params)["icon-y"])
+
+ if(_x<=16 && _y<=16)
+ usr.a_intent_change(INTENT_HARM)
+
+ else if(_x<=16 && _y>=17)
+ usr.a_intent_change(INTENT_HELP)
+
+ else if(_x>=17 && _y<=16)
+ usr.a_intent_change(INTENT_GRAB)
+
+ else if(_x>=17 && _y>=17)
+ usr.a_intent_change(INTENT_DISARM)
+ else
+ return ..()
+
+/obj/screen/act_intent/alien
+ icon = 'icons/mob/screen_alien.dmi'
+ screen_loc = ui_movi
+
+/obj/screen/act_intent/robot
+ icon = 'icons/mob/screen_cyborg.dmi'
+ screen_loc = ui_borg_intents
+
+/obj/screen/internals
+ name = "toggle internals"
+ icon_state = "internal0"
+ screen_loc = ui_internal
+
+/obj/screen/internals/Click()
+ if(!iscarbon(usr))
+ return
+ var/mob/living/carbon/C = usr
+ if(C.incapacitated())
+ return
+
+ if(C.internal)
+ C.internal = null
+ to_chat(C, "You are no longer running on internals.")
+ icon_state = "internal0"
+ else
+ if(!C.getorganslot("breathing_tube"))
+ if(!istype(C.wear_mask, /obj/item/clothing/mask))
+ to_chat(C, "You are not wearing an internals mask!")
+ return 1
+ else
+ var/obj/item/clothing/mask/M = C.wear_mask
+ if(M.mask_adjusted) // if mask on face but pushed down
+ M.adjustmask(C) // adjust it back
+>>>>>>> cc30923... ismecha define (#31192)
if( !(M.flags_1 & MASKINTERNALS_1) )
to_chat(C, "You are not wearing an internals mask!")
return
@@ -282,6 +509,7 @@
H.internal = H.r_store
//Separate so CO2 jetpacks are a little less cumbersome.
+<<<<<<< HEAD
if(!C.internal && istype(C.back, /obj/item/tank))
to_chat(C, "You are now running on internals from the [C.back] on your back.")
C.internal = C.back
@@ -468,6 +696,194 @@
name = "dmg"
blend_mode = BLEND_MULTIPLY
screen_loc = "CENTER-7,CENTER-7"
+=======
+ if(!C.internal && istype(C.back, /obj/item/tank))
+ to_chat(C, "You are now running on internals from the [C.back] on your back.")
+ C.internal = C.back
+
+ if(C.internal)
+ icon_state = "internal1"
+ else
+ to_chat(C, "You don't have an oxygen tank!")
+ return
+ C.update_action_buttons_icon()
+
+/obj/screen/mov_intent
+ name = "run/walk toggle"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "running"
+
+/obj/screen/mov_intent/Click()
+ toggle(usr)
+
+/obj/screen/mov_intent/proc/toggle(mob/user)
+ if(isobserver(user))
+ return
+ switch(user.m_intent)
+ if("run")
+ user.m_intent = MOVE_INTENT_WALK
+ icon_state = "walking"
+ if("walk")
+ user.m_intent = MOVE_INTENT_RUN
+ icon_state = "running"
+ user.update_icons()
+
+/obj/screen/pull
+ name = "stop pulling"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "pull"
+
+/obj/screen/pull/Click()
+ if(isobserver(usr))
+ return
+ usr.stop_pulling()
+
+/obj/screen/pull/update_icon(mob/mymob)
+ if(!mymob) return
+ if(mymob.pulling)
+ icon_state = "pull"
+ else
+ icon_state = "pull0"
+
+/obj/screen/resist
+ name = "resist"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "act_resist"
+ layer = HUD_LAYER
+ plane = HUD_PLANE
+
+/obj/screen/resist/Click()
+ if(isliving(usr))
+ var/mob/living/L = usr
+ L.resist()
+
+/obj/screen/storage
+ name = "storage"
+
+/obj/screen/storage/Click(location, control, params)
+ if(world.time <= usr.next_move)
+ return 1
+ if(usr.stat || usr.IsUnconscious() || usr.IsKnockdown() || usr.IsStun())
+ return 1
+ if (ismecha(usr.loc)) // stops inventory actions in a mech
+ return 1
+ if(master)
+ var/obj/item/I = usr.get_active_held_item()
+ if(I)
+ master.attackby(I, usr, params)
+ return 1
+
+/obj/screen/throw_catch
+ name = "throw/catch"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "act_throw_off"
+
+/obj/screen/throw_catch/Click()
+ if(iscarbon(usr))
+ var/mob/living/carbon/C = usr
+ C.toggle_throw_mode()
+
+/obj/screen/zone_sel
+ name = "damage zone"
+ icon_state = "zone_sel"
+ screen_loc = ui_zonesel
+ var/selecting = "chest"
+
+/obj/screen/zone_sel/Click(location, control,params)
+ if(isobserver(usr))
+ return
+
+ var/list/PL = params2list(params)
+ var/icon_x = text2num(PL["icon-x"])
+ var/icon_y = text2num(PL["icon-y"])
+ var/choice
+
+ switch(icon_y)
+ if(1 to 9) //Legs
+ switch(icon_x)
+ if(10 to 15)
+ choice = "r_leg"
+ if(17 to 22)
+ choice = "l_leg"
+ else
+ return 1
+ if(10 to 13) //Hands and groin
+ switch(icon_x)
+ if(8 to 11)
+ choice = "r_arm"
+ if(12 to 20)
+ choice = "groin"
+ if(21 to 24)
+ choice = "l_arm"
+ else
+ return 1
+ if(14 to 22) //Chest and arms to shoulders
+ switch(icon_x)
+ if(8 to 11)
+ choice = "r_arm"
+ if(12 to 20)
+ choice = "chest"
+ if(21 to 24)
+ choice = "l_arm"
+ else
+ return 1
+ if(23 to 30) //Head, but we need to check for eye or mouth
+ if(icon_x in 12 to 20)
+ choice = "head"
+ switch(icon_y)
+ if(23 to 24)
+ if(icon_x in 15 to 17)
+ choice = "mouth"
+ if(26) //Eyeline, eyes are on 15 and 17
+ if(icon_x in 14 to 18)
+ choice = "eyes"
+ if(25 to 27)
+ if(icon_x in 15 to 17)
+ choice = "eyes"
+
+ return set_selected_zone(choice, usr)
+
+/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user)
+ if(isobserver(user))
+ return
+
+ if(choice != selecting)
+ selecting = choice
+ update_icon(usr)
+ return 1
+
+/obj/screen/zone_sel/update_icon(mob/user)
+ cut_overlays()
+ add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[selecting]"))
+ user.zone_selected = selecting
+
+/obj/screen/zone_sel/alien
+ icon = 'icons/mob/screen_alien.dmi'
+
+/obj/screen/zone_sel/alien/update_icon(mob/user)
+ cut_overlays()
+ add_overlay(mutable_appearance('icons/mob/screen_alien.dmi', "[selecting]"))
+ user.zone_selected = selecting
+
+/obj/screen/zone_sel/robot
+ icon = 'icons/mob/screen_cyborg.dmi'
+
+
+/obj/screen/flash
+ name = "flash"
+ icon_state = "blank"
+ blend_mode = BLEND_ADD
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ layer = FLASH_LAYER
+ plane = FULLSCREEN_PLANE
+
+/obj/screen/damageoverlay
+ icon = 'icons/mob/screen_full.dmi'
+ icon_state = "oxydamageoverlay0"
+ name = "dmg"
+ blend_mode = BLEND_MULTIPLY
+ screen_loc = "CENTER-7,CENTER-7"
+>>>>>>> cc30923... ismecha define (#31192)
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm
index 2c2212fde5..a1dc9ece69 100644
--- a/code/datums/weather/weather_types/ash_storm.dm
+++ b/code/datums/weather/weather_types/ash_storm.dm
@@ -27,7 +27,7 @@
probability = 90
/datum/weather/ash_storm/proc/is_ash_immune(mob/living/L)
- if(istype(L.loc, /obj/mecha)) //Mechs are immune
+ if(ismecha(L.loc)) //Mechs are immune
return TRUE
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm b/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm
index 0a7a1b53b0..cdff486eea 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm
@@ -75,7 +75,7 @@
if(GLOB.ratvar_awakens && L)
L.adjust_fire_stacks(damage_per_tick)
L.IgniteMob()
- else if(istype(target, /obj/mecha))
+ else if(ismecha(target))
var/obj/mecha/M = target
M.take_damage(damage_per_tick * get_efficiency_mod(), BURN, "melee", 1, get_dir(src, M))
@@ -90,7 +90,7 @@
if(isliving(target))
var/mob/living/L = target
to_chat(L, "\"I SEE YOU!\"\n[src]'s gaze [GLOB.ratvar_awakens ? "melts you alive" : "burns you"]!")
- else if(istype(target, /obj/mecha))
+ else if(ismecha(target))
var/obj/mecha/M = target
to_chat(M.occupant, "\"I SEE YOU!\"" )
else if(prob(0.5)) //Extremely low chance because of how fast the subsystem it uses processes
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 25bbe1bc1d..883cc3986f 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -83,7 +83,7 @@
bumpopen(M)
return
- if(istype(AM, /obj/mecha))
+ if(ismecha(AM))
var/obj/mecha/mecha = AM
if(density)
if(mecha.occupant)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index f76412199c..4809f3ff49 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -62,7 +62,7 @@
if( operating || !src.density )
return
if (!( ismob(AM) ))
- if(istype(AM, /obj/mecha))
+ if(ismecha(AM))
var/obj/mecha/mecha = AM
if(mecha.occupant && src.allowed(mecha.occupant))
open_and_close()
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 17f573fe6d..9acd4730d8 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -20,7 +20,7 @@
var/O_limit
var/atom/target = get_edge_target_turf(src, dir)
for(var/atom/movable/O in loc)
- if(!O.anchored || istype(O, /obj/mecha)) //Mechs need their launch platforms.
+ if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
O_limit++
if(O_limit >= 20)
audible_message("[src] lets out a screech, it doesn't seem to be able to handle the load.")
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index e9f0f76bc9..8f8202fe19 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -390,7 +390,7 @@
if(!in_faction(C))
targets += C
- if(istype(A, /obj/mecha))
+ if(ismecha(A))
var/obj/mecha/M = A
//If there is a user and they're not in our faction
if(M.occupant && !in_faction(M.occupant))
diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm
index 6f1348c741..d4b79a0163 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/game/mecha/mecha_control_console.dm
@@ -4,6 +4,7 @@
icon_screen = "mecha"
icon_keyboard = "tech_key"
req_access = list(ACCESS_ROBOTICS)
+<<<<<<< HEAD
circuit = /obj/item/circuitboard/computer/mecha_control
var/list/located = list()
var/screen = 0
@@ -135,3 +136,136 @@
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
+=======
+ circuit = /obj/item/circuitboard/computer/mecha_control
+ var/list/located = list()
+ var/screen = 0
+ var/stored_data
+
+/obj/machinery/computer/mecha/attack_hand(mob/user)
+ if(..())
+ return
+ user.set_machine(src)
+ var/dat = "
[src.name]"
+ if(screen == 0)
+ dat += "Tracking beacons data
"
+ var/list/trackerlist = list()
+ for(var/obj/mecha/MC in GLOB.mechas_list)
+ trackerlist += MC.trackers
+ for(var/obj/item/mecha_parts/mecha_tracking/TR in trackerlist)
+ var/answer = TR.get_mecha_info()
+ if(answer)
+ dat += {"
[answer]
+ Send message
+ Show exosuit log | (EMP pulse)
"}
+
+ if(screen==1)
+ dat += "Log contents
"
+ dat += "Return
"
+ dat += "[stored_data]"
+
+ dat += "(Refresh)
"
+ dat += ""
+
+ user << browse(dat, "window=computer;size=400x500")
+ onclose(user, "computer")
+ return
+
+/obj/machinery/computer/mecha/Topic(href, href_list)
+ if(..())
+ return
+ var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
+ if(href_list["send_message"])
+ var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message")
+ var/message = stripped_input(usr,"Input message","Transmit message")
+ var/obj/mecha/M = MT.in_mecha()
+ if(trim(message) && M)
+ M.occupant_message(message)
+ return
+ if(href_list["shock"])
+ var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock")
+ MT.shock()
+ if(href_list["get_log"])
+ var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log")
+ stored_data = MT.get_mecha_log()
+ screen = 1
+ if(href_list["return"])
+ screen = 0
+ updateUsrDialog()
+ return
+
+/obj/item/mecha_parts/mecha_tracking
+ name = "exosuit tracking beacon"
+ desc = "Device used to transmit exosuit data."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "motion2"
+ w_class = WEIGHT_CLASS_SMALL
+ origin_tech = "programming=2;magnets=2"
+ var/ai_beacon = FALSE //If this beacon allows for AI control. Exists to avoid using istype() on checking.
+
+/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
+ if(!in_mecha())
+ return 0
+ var/obj/mecha/M = src.loc
+ var/cell_charge = M.get_charge()
+ var/answer = {"Name: [M.name]
+Integrity: [M.obj_integrity/M.max_integrity*100]%
+Cell charge: [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
+Airtank: [M.return_pressure()]kPa
+Pilot: [M.occupant||"None"]
+Location: [get_area(M)||"Unknown"]
+Active equipment: [M.selected||"None"] "}
+ if(istype(M, /obj/mecha/working/ripley))
+ var/obj/mecha/working/ripley/RM = M
+ answer += "Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
"
+
+ return answer
+
+/obj/item/mecha_parts/mecha_tracking/emp_act()
+ qdel(src)
+
+/obj/item/mecha_parts/mecha_tracking/Destroy()
+ if(ismecha(loc))
+ var/obj/mecha/M = loc
+ if(src in M.trackers)
+ M.trackers -= src
+ return ..()
+
+/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
+ if(ismecha(loc))
+ return loc
+ return 0
+
+/obj/item/mecha_parts/mecha_tracking/proc/shock()
+ var/obj/mecha/M = in_mecha()
+ if(M)
+ M.emp_act(EMP_LIGHT)
+ qdel(src)
+
+/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
+ if(!ismecha(loc))
+ return 0
+ var/obj/mecha/M = src.loc
+ return M.get_log_html()
+
+
+/obj/item/mecha_parts/mecha_tracking/ai_control
+ name = "exosuit AI control beacon"
+ desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit."
+ origin_tech = "programming=3;magnets=2;engineering=2"
+ ai_beacon = TRUE
+
+
+/obj/item/storage/box/mechabeacons
+ name = "exosuit tracking beacons"
+
+/obj/item/storage/box/mechabeacons/New()
+ ..()
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+ new /obj/item/mecha_parts/mecha_tracking(src)
+>>>>>>> cc30923... ismecha define (#31192)
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index 97d00c339f..0e77d3f28f 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal)
if(!istype(source) || !istype(destination))
@@ -154,3 +155,161 @@
real_target = get_turf(linked)
return real_target
+=======
+
+/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal)
+ if(!istype(source) || !istype(destination))
+ return
+ var/turf/actual_destination = get_teleport_turf(destination, accuracy)
+ var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE)
+ var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE)
+ if(!istype(P1)||!istype(P2))
+ return
+ P1.link_portal(P2)
+ P1.hardlinked = TRUE
+ return list(P1, P2)
+
+/obj/effect/portal
+ name = "portal"
+ desc = "Looks unstable. Best to test it with the clown."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "portal"
+ anchored = TRUE
+ var/mech_sized = FALSE
+ var/obj/effect/portal/linked
+ var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
+ var/creator
+ var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
+ var/atmos_link = FALSE //Link source/destination atmos.
+ var/turf/open/atmos_source //Atmos link source
+ var/turf/open/atmos_destination //Atmos link destination
+
+/obj/effect/portal/anom
+ name = "wormhole"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "anom"
+ mech_sized = TRUE
+
+/obj/effect/portal/Move(newloc)
+ for(var/T in newloc)
+ if(istype(T, /obj/effect/portal))
+ return FALSE
+ return ..()
+
+/obj/effect/portal/attackby(obj/item/W, mob/user, params)
+ if(user && Adjacent(user))
+ teleport(user)
+
+/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
+ if(get_turf(oldloc) == get_turf(linked))
+ return ..()
+ if(!teleport(AM))
+ return ..()
+
+/obj/effect/portal/attack_tk(mob/user)
+ return
+
+/obj/effect/portal/attack_hand(mob/user)
+ if(Adjacent(user))
+ teleport(user)
+
+/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
+ . = ..()
+ GLOB.portals += src
+ if(!istype(_linked) && automatic_link)
+ . = INITIALIZE_HINT_QDEL
+ CRASH("Somebody fucked up.")
+ if(_lifespan > 0)
+ QDEL_IN(src, _lifespan)
+ if(!isnull(atmos_link_override))
+ atmos_link = atmos_link_override
+ link_portal(_linked)
+ hardlinked = automatic_link
+ creator = _creator
+ if(isturf(hard_target_override))
+ hard_target = hard_target_override
+
+/obj/effect/portal/proc/link_portal(obj/effect/portal/newlink)
+ linked = newlink
+ if(atmos_link)
+ link_atmos()
+
+/obj/effect/portal/proc/link_atmos()
+ if(atmos_source || atmos_destination)
+ unlink_atmos()
+ if(!isopenturf(get_turf(src)))
+ return FALSE
+ if(linked)
+ if(isopenturf(get_turf(linked)))
+ atmos_source = get_turf(src)
+ atmos_destination = get_turf(linked)
+ else if(hard_target)
+ if(isopenturf(hard_target))
+ atmos_source = get_turf(src)
+ atmos_destination = hard_target
+ else
+ return FALSE
+ if(!istype(atmos_source) || !istype(atmos_destination))
+ return FALSE
+ LAZYINITLIST(atmos_source.atmos_adjacent_turfs)
+ LAZYINITLIST(atmos_destination.atmos_adjacent_turfs)
+ if(atmos_source.atmos_adjacent_turfs[atmos_destination] || atmos_destination.atmos_adjacent_turfs[atmos_source]) //Already linked!
+ return FALSE
+ atmos_source.atmos_adjacent_turfs[atmos_destination] = TRUE
+ atmos_destination.atmos_adjacent_turfs[atmos_source] = TRUE
+ atmos_source.air_update_turf(FALSE)
+ atmos_destination.air_update_turf(FALSE)
+
+/obj/effect/portal/proc/unlink_atmos()
+ if(istype(atmos_source))
+ if(istype(atmos_destination) && !atmos_source.Adjacent(atmos_destination) && !CANATMOSPASS(atmos_destination, atmos_source))
+ LAZYREMOVE(atmos_source.atmos_adjacent_turfs, atmos_destination)
+ atmos_source = null
+ if(istype(atmos_destination))
+ if(istype(atmos_source) && !atmos_destination.Adjacent(atmos_source) && !CANATMOSPASS(atmos_source, atmos_destination))
+ LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
+ atmos_destination = null
+
+/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
+ if(creator && hascall(creator, "on_portal_destroy"))
+ call(creator, "on_portal_destroy")(src, src.loc)
+ creator = null
+ GLOB.portals -= src
+ unlink_atmos()
+ if(hardlinked && !QDELETED(linked))
+ QDEL_NULL(linked)
+ else
+ linked = null
+ return ..()
+
+/obj/effect/portal/proc/teleport(atom/movable/M)
+ if(!istype(M) || istype(M, /obj/effect) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M))) //Things that shouldn't teleport.
+ return
+ var/turf/real_target = get_link_target_turf()
+ if(!istype(real_target))
+ return FALSE
+ if(ismegafauna(M))
+ message_admins("[M] has used a portal at [ADMIN_COORDJMP(src)] made by [usr].")
+ if(do_teleport(M, real_target, 0))
+ if(istype(M, /obj/item/projectile))
+ var/obj/item/projectile/P = M
+ P.ignore_source_check = TRUE
+ return TRUE
+ return FALSE
+
+/obj/effect/portal/proc/get_link_target_turf()
+ var/turf/real_target
+ if(!istype(linked) || QDELETED(linked))
+ if(hardlinked)
+ qdel(src)
+ if(!istype(hard_target) || QDELETED(hard_target))
+ hard_target = null
+ return
+ else
+ real_target = hard_target
+ linked = null
+ else
+ real_target = get_turf(linked)
+ return real_target
+
+>>>>>>> cc30923... ismecha define (#31192)
diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm
index 5a2b52184a..9a3769206c 100644
--- a/code/game/objects/items/storage/storage.dm
+++ b/code/game/objects/items/storage/storage.dm
@@ -34,7 +34,7 @@
if(!over_object)
return
- if (istype(usr.loc, /obj/mecha)) // stops inventory actions in a mech
+ if (ismecha(M.loc)) // stops inventory actions in a mech
return
// this must come before the screen objects only block, dunno why it wasn't before
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 2e1f0af991..949da6db09 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -56,6 +56,7 @@
return TryToSwitchState(user)
/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target)
+<<<<<<< HEAD
if(istype(mover, /obj/effect/beam))
return !opacity
return !density
@@ -89,6 +90,41 @@
set_opacity(FALSE)
flick("[initial_state]opening",src)
sleep(10)
+=======
+ if(istype(mover, /obj/effect/beam))
+ return !opacity
+ return !density
+
+/obj/structure/mineral_door/proc/TryToSwitchState(atom/user)
+ if(isSwitchingStates)
+ return
+ if(isliving(user))
+ var/mob/living/M = user
+ if(world.time - M.last_bumped <= 60)
+ return //NOTE do we really need that?
+ if(M.client)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(!C.handcuffed)
+ SwitchState()
+ else
+ SwitchState()
+ else if(ismecha(user))
+ SwitchState()
+
+/obj/structure/mineral_door/proc/SwitchState()
+ if(state)
+ Close()
+ else
+ Open()
+
+/obj/structure/mineral_door/proc/Open()
+ isSwitchingStates = 1
+ playsound(src, openSound, 100, 1)
+ set_opacity(FALSE)
+ flick("[initial_state]opening",src)
+ sleep(10)
+>>>>>>> cc30923... ismecha define (#31192)
density = FALSE
state = 1
air_update_turf(1)
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
index aa9e8364c4..16e77c1141 100644
--- a/code/game/objects/structures/plasticflaps.dm
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -76,7 +76,7 @@
if(C.move_delay)
return 0
- if(istype(A, /obj/mecha))
+ if(ismecha(A))
return 0
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index 630ded7daa..a597022448 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -111,12 +111,6 @@
if(istype(R.module_active, /obj/item/pickaxe))
src.attackby(R.module_active,R)
return
-/* else if(istype(AM, /obj/mecha))
- var/obj/mecha/M = AM
- if(istype(M.selected, /obj/item/mecha_parts/mecha_equipment/drill))
- src.attackby(M.selected,M)
- return*/
-//Aparantly mechs are just TOO COOL to call Collide())
else
return
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 9d8b25cebf..237714eb8e 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -48,7 +48,7 @@
if(pockets && over_object == M)
return pockets.MouseDrop(over_object)
- if(istype(usr.loc, /obj/mecha)) // stops inventory actions in a mech
+ if(ismecha(M.loc)) // stops inventory actions in a mech
return
if(!M.incapacitated() && loc == M && istype(over_object, /obj/screen/inventory/hand))
diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm
index 6404307d34..00b4ce4e98 100644
--- a/code/modules/events/wormholes.dm
+++ b/code/modules/events/wormholes.dm
@@ -58,7 +58,7 @@
if(istype(M, /obj/effect)) //sparks don't teleport
return
if(M.anchored)
- if(!(istype(M, /obj/mecha) && mech_sized))
+ if(!(ismecha(M) && mech_sized))
return
if(ismovableatom(M))
diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index e0197cc4e3..d72d0e5f73 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -94,7 +94,7 @@
if(!ismob(M) && !isobj(M)) //No don't teleport lighting and effects!
return
- if(M.anchored && (!ismob(M) || (istype(M, /obj/mecha) && !mech_sized)))
+ if(M.anchored && (!ismob(M) || (ismecha(M) && !mech_sized)))
return
if(do_teleport(M, hard_target, 6))
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 58c971024f..e16077fec1 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -435,7 +435,7 @@
if(!over_object)
return
- if (istype(usr.loc, /obj/mecha))
+ if(ismecha(usr.loc))
return
if(!M.incapacitated())
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index a1b67fbee1..282de04ede 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -29,7 +29,7 @@
dizziness = 0
jitteriness = 0
- if(istype(loc, /obj/mecha))
+ if(ismecha(loc))
var/obj/mecha/M = loc
if(M.occupant == src)
M.go_out()
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 9ab6f783f5..2b29283c28 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -165,7 +165,7 @@
return chosen_target
// Please do not add one-off mob AIs here, but override this function for your mob
-/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
+/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
return FALSE
@@ -187,7 +187,7 @@
return FALSE
return TRUE
- if(istype(the_target, /obj/mecha))
+ if(ismecha(the_target))
var/obj/mecha/M = the_target
if(M.occupant)//Just so we don't attack empty mechs
if(CanAttack(M.occupant))
diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
index b84f3c8682..378b5d9b8e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
@@ -184,7 +184,7 @@
mecha_face_target(target)
target.mech_melee_attack(mecha)
else
- if(istype(target, /obj/mecha))
+ if(ismecha(target))
var/obj/mecha/M = target
if(is_valid_mecha(M))
enter_mecha(M)
@@ -259,7 +259,7 @@
//Yes they actually try and pull this shit
//~simple animals~
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/CanAttack(atom/the_target)
- if(istype(the_target, /obj/mecha))
+ if(ismecha(the_target))
var/obj/mecha/M = the_target
if(mecha)
if(M == mecha || !CanAttack(M.occupant))
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
index 4aa067c9ab..c024cf5556 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
/mob/living/simple_animal/hostile/retaliate
var/list/enemies = list()
@@ -45,3 +46,52 @@
. = ..()
if(. > 0 && stat == CONSCIOUS)
Retaliate()
+=======
+/mob/living/simple_animal/hostile/retaliate
+ var/list/enemies = list()
+
+/mob/living/simple_animal/hostile/retaliate/Found(atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(!L.stat)
+ return L
+ else
+ enemies -= L
+ else if(ismecha(A))
+ var/obj/mecha/M = A
+ if(M.occupant)
+ return A
+
+/mob/living/simple_animal/hostile/retaliate/ListTargets()
+ if(!enemies.len)
+ return list()
+ var/list/see = ..()
+ see &= enemies // Remove all entries that aren't in enemies
+ return see
+
+/mob/living/simple_animal/hostile/retaliate/proc/Retaliate()
+ var/list/around = view(src, vision_range)
+
+ for(var/atom/movable/A in around)
+ if(A == src)
+ continue
+ if(isliving(A))
+ var/mob/living/M = A
+ if(faction_check_mob(M) && attack_same || !faction_check_mob(M))
+ enemies |= M
+ else if(ismecha(A))
+ var/obj/mecha/M = A
+ if(M.occupant)
+ enemies |= M
+ enemies |= M.occupant
+
+ for(var/mob/living/simple_animal/hostile/retaliate/H in around)
+ if(faction_check_mob(H) && !attack_same && !H.attack_same)
+ H.enemies |= enemies
+ return 0
+
+/mob/living/simple_animal/hostile/retaliate/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(. > 0 && stat == CONSCIOUS)
+ Retaliate()
+>>>>>>> cc30923... ismecha define (#31192)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 4e988c482c..4edf7a6dcb 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -317,7 +317,7 @@
var/mob/living/L = the_target
if(L.stat != CONSCIOUS)
return 0
- if (istype(the_target, /obj/mecha))
+ if (ismecha(the_target))
var/obj/mecha/M = the_target
if (M.occupant)
return 0
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4f4b99e1e1..c75e0a27fb 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -386,7 +386,7 @@
set category = "Object"
set src = usr
- if(istype(loc, /obj/mecha))
+ if(ismecha(loc))
return
if(incapacitated())
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index c64cb4f4ef..3d87de4e62 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -278,7 +278,7 @@
//dist_check - set to only shock mobs within 1 of source (vendors, airlocks, etc.)
//No animations will be performed by this proc.
/proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE)
- if(istype(M.loc, /obj/mecha))
+ if(ismecha(M.loc))
return 0 //feckin mechs are dumb
if(dist_check)
if(!in_range(source,M))
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index 32967e2537..f2610f97b0 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -58,7 +58,7 @@
if(isliving(mover))
shock(mover)
- if(istype(mover, /obj/machinery) || isstructure(mover) || istype(mover, /obj/mecha))
+ if(istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover))
bump_field(mover)
/obj/machinery/field/containment/proc/set_master(master1,master2)
@@ -90,13 +90,13 @@
if(isliving(mover))
shock(mover)
return
- if(istype(mover, /obj/machinery) || isstructure(mover) || istype(mover, /obj/mecha))
+ if(istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover))
bump_field(mover)
return
/obj/machinery/field/CanPass(atom/movable/mover, turf/target)
- if(hasShocked || isliving(mover) || istype(mover, /obj/machinery) || isstructure(mover) || istype(mover, /obj/mecha))
+ if(hasShocked || isliving(mover) || istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover))
return FALSE
return ..()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 84db583282..3aba80fe64 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -144,7 +144,7 @@
ignore_source_check = TRUE
return FALSE
if(firer && !ignore_source_check)
- if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech
+ if(A == firer || (A == firer.loc && ismecha(A))) //cannot shoot yourself or your mech
loc = A.loc
return FALSE
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 79a3d51eec..a5ba7c15a4 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -45,7 +45,7 @@
..()
explosion(target, -1, 1, 3, 1, 0, flame_range = 4)
- if(istype(target, /obj/mecha))
+ if(ismecha(target))
var/obj/mecha/M = target
M.take_damage(anti_armour_damage)
if(issilicon(target))