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))