diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index cb2c3adab5c..ef8a55e7d2e 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -14,8 +14,9 @@ #define DIAG_BATT_HUD "10"// Borg/Mech power meter #define DIAG_MECH_HUD "11"// Mech health bar #define DIAG_BOT_HUD "12"// Bot HUDs +#define DIAG_TRACK_HUD "13"// Mech tracking beacon //for antag huds. these are used at the /mob level -#define ANTAG_HUD "13" +#define ANTAG_HUD "14" //data HUD (medhud, sechud) defines //Don't forget to update human/New() if you change these! diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 4fafd007042..af2a1912730 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -45,7 +45,7 @@ hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD, WANTED_HUD) /datum/atom_hud/data/diagnostic - hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD) + hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD) /* MED/SEC/DIAG HUD HOOKS */ @@ -326,6 +326,19 @@ if(internal_damage) holder.icon_state = "hudwarn" +/obj/mecha/proc/diag_hud_set_mechtracking() //Shows tracking beacons on the mech + var/image/holder = hud_list[DIAG_TRACK_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size + var/new_icon_state //This var exists so that the holder's icon state is set only once in the event of multiple mech beacons. + for(var/obj/item/mecha_parts/mecha_tracking/T in trackers) + if(T.ai_beacon) //Beacon with AI uplink + new_icon_state = "hudtrackingai" + break //Immediately terminate upon finding an AI beacon to ensure it is always shown over the normal one, as mechs can have several trackers. + else + new_icon_state = "hudtracking" + holder.icon_state = new_icon_state + /*~~~~~~~~~ Bots! ~~~~~~~~~~*/ diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index a1ab848cc8d..03eff51f755 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -49,7 +49,6 @@ var/lights_power = 6 var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference - var/bumpsmash = 0 //Whether or not the mech destroys walls by running into it. //inner atmos var/use_internal_tank = 0 @@ -117,7 +116,7 @@ var/occupant_sight_flags = 0 //sight flags to give to the occupant (e.g. mech mining scanner gives meson-like vision) - hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD) + hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD) /obj/mecha/New() @@ -142,6 +141,7 @@ diag_hud_set_mechhealth() diag_hud_set_mechcell() diag_hud_set_mechstat() + diag_hud_set_mechtracking() /obj/mecha/Destroy() @@ -373,6 +373,7 @@ diag_hud_set_mechhealth() diag_hud_set_mechcell() diag_hud_set_mechstat() + diag_hud_set_mechtracking() /obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits. @@ -627,6 +628,21 @@ break //Nothing like a big, red link to make the player feel powerful! user << "ASSUME DIRECT CONTROL?
" + else + examine(user) + if(occupant) + user << "This exosuit has a pilot and cannot be controlled." + return + var/can_control_mech = 0 + for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in trackers) + can_control_mech = 1 + user << "\icon[src] Status of [name]:\n\ + [A.get_mecha_info()]" + break + if(!can_control_mech) + user << "You cannot control exosuits without AI control beacons installed." + return + user << "Take control of exosuit?
" /obj/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card) if(!..()) @@ -654,12 +670,13 @@ AI << "You have been downloaded to a mobile storage device. Wireless connection offline." user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory." - if(AI_MECH_HACK) //Called by Malf AI mob on the mech. - new /obj/structure/AIcore/deactivated(AI.loc) - if(occupant) //Oh, I am sorry, were you using that? - AI << "Pilot detected! Forced ejection initiated!" - occupant << "You have been forcibly ejected!" - go_out(1) //IT IS MINE, NOW. SUCK IT, RD! + if(AI_MECH_HACK) //Called by AIs on the mech + AI.linked_core = new /obj/structure/AIcore/deactivated(AI.loc) + if(AI.can_dominate_mechs) + if(occupant) //Oh, I am sorry, were you using that? + AI << "Pilot detected! Forced ejection initiated!" + occupant << "You have been forcibly ejected!" + go_out(1) //IT IS MINE, NOW. SUCK IT, RD! ai_enter_mech(AI, interaction) if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech. @@ -693,10 +710,10 @@ AI.remote_control = src AI.canmove = 1 //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow. AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES. - AI << "[interaction == AI_MECH_HACK ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" \ + AI << "[AI.can_dominate_mechs ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" \ : "You have been uploaded to a mech's onboard computer."]" AI << "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions." - GrantActions(AI) + GrantActions(AI, !AI.can_dominate_mechs) //An actual AI (simple_animal mecha pilot) entering the mech @@ -916,11 +933,25 @@ var/mob/living/brain/brain = occupant RemoveActions(brain) mob_container = brain.container - else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf. - RemoveActions(occupant) - occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced. - occupant = null - return + else if(isAI(occupant)) + var/mob/living/silicon/ai/AI = occupant + if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf. + RemoveActions(occupant) + occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced. + occupant = null + return + else + if(!AI.linked_core) + AI << "Inactive core destroyed. Unable to return." + AI.linked_core = null + return + AI << "Returning to core..." + AI.controlled_mech = null + AI.remote_control = null + RemoveActions(occupant, 1) + mob_container = AI + newloc = get_turf(AI.linked_core) + qdel(AI.linked_core) else return var/mob/living/L = occupant diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index 869801152e4..9d9505a01ef 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -37,7 +37,7 @@ button_icon_state = "mech_eject" /datum/action/innate/mecha/mech_eject/Activate() - if(!owner || !iscarbon(owner)) + if(!owner) return if(!chassis || chassis.occupant != owner) return diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 2f4eab7b37e..97b3cd959b4 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -68,6 +68,7 @@ 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()) @@ -115,6 +116,13 @@ 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/weapon/storage/box/mechabeacons name = "exosuit tracking beacons" diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 07f71f838ae..2a27a20cde4 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -264,6 +264,7 @@ W.forceMove(src) trackers += W user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src].") + diag_hud_set_mechtracking() return else return ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 10817470c91..76677b2ac95 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -900,7 +900,7 @@ //Mobs on Fire end // used by secbot and monkeys Crossed -/mob/living/proc/knockOver(var/mob/living/carbon/C) +/mob/living/proc/knockOver(var/mob/living/carbon/C) C.visible_message("[pick( \ "[C] dives out of [src]'s way!", \ "[C] stumbles over [src]!", \ diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f6365f5a23b..c3eea0e6dd2 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -82,6 +82,8 @@ var/list/ai_list = list() var/obj/machinery/camera/portable/builtInCamera + var/obj/structure/AIcore/deactivated/linked_core //For exosuit control + /mob/living/silicon/ai/New(loc, datum/ai_laws/L, mob/target_ai) ..() if(!target_ai) //If there is no player/brain inside. @@ -419,7 +421,16 @@ var/list/ai_list = list() if (href_list["ai_take_control"]) //Mech domination var/obj/mecha/M = locate(href_list["ai_take_control"]) if(controlled_mech) - src << "You are already loaded into an onboard computer!" + src << "You are already loaded into an onboard computer!" + return + if(!cameranet.checkCameraVis(M)) + src << "Exosuit is no longer near active cameras." + return + if(lacks_power()) + src << "You're depowered!" + return + if(!isturf(loc)) + src << "You aren't in your core!" return if(M) M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself. diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 3cf340ba549..6ce54089fea 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -728,6 +728,16 @@ construction_time = 50 category = list("Misc") +/datum/design/mecha_tracking_ai_control + name = "AI Control Beacon" + id = "mecha_tracking_ai_control" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_tracking/ai_control + materials = list(MAT_METAL = 1000, MAT_GLASS = 500, MAT_SILVER = 200) + req_tech = list("programming" = 3, "magnets" = 2, "engineering" = 2) + construction_time = 50 + category = list("Misc") + /datum/design/drone_shell name = "Drone Shell" desc = "A shell of a maintenance drone, an expendable robot built to perform station repairs." diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 105f56cc8ce..ce8da26271c 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ