diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 4dee15388de..dfb6de5e911 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -31,7 +31,7 @@ build_click(src, client.buildmode, params, A) return - if(control_disabled || stat) + if(stat) return var/list/modifiers = params2list(params) @@ -51,7 +51,7 @@ CtrlClickOn(A) return - if(!canClick()) + if(control_disabled || !canClick()) return if(aiCamera.in_camera_mode) @@ -89,13 +89,24 @@ */ /mob/living/silicon/ai/ShiftClickOn(var/atom/A) - A.AIShiftClick(src) + if(!control_disabled && A.AIShiftClick(src)) + return + ..() + /mob/living/silicon/ai/CtrlClickOn(var/atom/A) - A.AICtrlClick(src) + if(!control_disabled && A.AICtrlClick(src)) + return + ..() + /mob/living/silicon/ai/AltClickOn(var/atom/A) - A.AIAltClick(src) + if(!control_disabled && A.AIAltClick(src)) + return + ..() + /mob/living/silicon/ai/MiddleClickOn(var/atom/A) - A.AIMiddleClick(src) + if(!control_disabled && A.AIMiddleClick(src)) + return + ..() /* The following criminally helpful code is just the previous code cleaned up; @@ -105,11 +116,6 @@ /atom/proc/AICtrlShiftClick() return -/obj/machinery/door/airlock/AICtrlShiftClick() - if(emagged) - return - return - /atom/proc/AIShiftClick() return @@ -118,7 +124,7 @@ Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "1"), 1) // 1 meaning no window (consistency!) else Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "0"), 1) - return + return 1 /atom/proc/AICtrlClick() return @@ -128,15 +134,18 @@ Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "0"), 1)// 1 meaning no window (consistency!) else Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "1"), 1) + return 1 /obj/machinery/power/apc/AICtrlClick() // turns off/on APCs. Topic(src, list("src"= "\ref[src]", "breaker"="1"), 1) // 1 meaning no window (consistency!) + return 1 /obj/machinery/turretid/AICtrlClick() //turns off/on Turrets Topic(src, list("src"= "\ref[src]", "command"="enable", "value"="[!enabled]"), 1) // 1 meaning no window (consistency!) + return 1 /atom/proc/AIAltClick(var/atom/A) - AltClick(A) + return AltClick(A) /obj/machinery/door/airlock/AIAltClick() // Electrifies doors. if(!electrified_until) @@ -145,20 +154,25 @@ else // disable/6 is not in Topic; disable/5 disables both temporary and permanent shock Topic(src, list("src"= "\ref[src]", "command"="electrify_permanently", "activate" = "0"), 1) - return + return 1 /obj/machinery/turretid/AIAltClick() //toggles lethal on turrets Topic(src, list("src"= "\ref[src]", "command"="lethal", "value"="[!lethal]"), 1) // 1 meaning no window (consistency!) + return 1 -/atom/proc/AIMiddleClick() - return +/atom/proc/AIMiddleClick(var/mob/living/silicon/user) + return 0 /obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights. + + if(..()) + return + if(!src.lights) Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "1"), 1) // 1 meaning no window (consistency!) else Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "0"), 1) - return + return 1 // // Override AdjacentQuick for AltClicking diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 5a4ce2bb8ed..2261ceb3683 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -108,7 +108,7 @@ // faster access to objects already on you if(A.loc != src) setMoveCooldown(10) //getting something out of a backpack - + if(W) var/resolved = W.resolve_attackby(A, src) if(!resolved && A && W) @@ -128,7 +128,7 @@ if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1)) if(A.Adjacent(src)) // see adjacent.dm setMoveCooldown(5) - + if(W) // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example) var/resolved = W.resolve_attackby(A,src) @@ -224,10 +224,8 @@ Only used for swapping hands */ /mob/proc/MiddleClickOn(var/atom/A) - return - -/mob/living/carbon/MiddleClickOn(var/atom/A) swap_hand() + return // In case of use break glass /* @@ -278,7 +276,7 @@ else user.listed_turf = T user.client.statpanel = T.name - return + return 1 /mob/proc/TurfAdjacent(var/turf/T) return T.AdjacentQuick(src) diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index 600d8c56193..436e7353ec7 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -29,34 +29,53 @@ src << "Somehow you bugged the system. Setting your hardsuit mode to middle-click." hardsuit_click_mode = MIDDLE_CLICK -/mob/living/carbon/human/MiddleClickOn(atom/A) +/mob/living/MiddleClickOn(atom/A) if(client && client.hardsuit_click_mode == MIDDLE_CLICK) if(HardsuitClickOn(A)) return ..() -/mob/living/carbon/human/AltClickOn(atom/A) +/mob/living/AltClickOn(atom/A) if(client && client.hardsuit_click_mode == ALT_CLICK) if(HardsuitClickOn(A)) return ..() -/mob/living/carbon/human/CtrlClickOn(atom/A) +/mob/living/CtrlClickOn(atom/A) if(client && client.hardsuit_click_mode == CTRL_CLICK) if(HardsuitClickOn(A)) return ..() -/mob/living/carbon/human/proc/HardsuitClickOn(atom/A) - if(!canClick()) - return - if(back) - var/obj/item/weapon/rig/rig = back - if(istype(rig) && rig.selected_module) - rig.selected_module.engage(A) - if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - return 1 +/mob/living/proc/can_use_rig() + return 0 + +/mob/living/carbon/human/can_use_rig() + return 1 + +/mob/living/carbon/brain/can_use_rig() + return istype(loc, /obj/item/device/mmi) + +/mob/living/silicon/ai/can_use_rig() + return carded + +/mob/living/silicon/pai/can_use_rig() + return loc == card + +/mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0) + if(!can_use_rig() || !canClick()) + return 0 + var/obj/item/weapon/rig/rig = get_rig() + if(istype(rig) && !rig.offline && rig.selected_module) + if(src != rig.wearer) + if(rig.ai_can_move_suit(src, check_user_module = 1)) + message_admins("[key_name_admin(src, include_name = 1)] is trying to force \the [key_name_admin(rig.wearer, include_name = 1)] to use a hardsuit module.") + else + return 0 + rig.selected_module.engage(A, alert_ai) + if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns + setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + return 1 return 0 #undef MIDDLE_CLICK diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 577ee1010bf..356ee87f609 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -105,12 +105,13 @@ if(istype(ai.loc, /turf/)) new /obj/structure/AIcore/deactivated(get_turf(ai)) + ai.carded = 1 admin_attack_log(user, ai, "Carded with [src.name]", "Was carded with [src.name]", "used the [src.name] to card") src.name = "[initial(name)] - [ai.name]" ai.loc = src - ai.cancel_camera() ai.destroy_eyeobj(src) + ai.cancel_camera() ai.control_disabled = 1 ai.aiRestorePowerRoutine = 0 carded_ai = ai @@ -120,10 +121,14 @@ if(user.client) user << "Transfer successful: [ai.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." + ai.canmove = 1 update_icon() return 1 /obj/item/device/aicard/proc/clear() + if(carded_ai && istype(carded_ai.loc, /turf)) + carded_ai.canmove = 0 + carded_ai.carded = 0 name = initial(name) carded_ai = null update_icon() @@ -140,10 +145,9 @@ carded_ai.show_message(rendered, type) ..() -/* /obj/item/device/aicard/relaymove(var/mob/user, var/direction) - if(src.loc && istype(src.loc.loc, /obj/item/rig_module)) - var/obj/item/rig_module/module = src.loc.loc - if(!module.holder || !direction) - return - module.holder.forced_move(direction)*/ + if(user.stat || user.stunned) + return + var/obj/item/weapon/rig/rig = src.get_rig() + if(istype(rig)) + rig.forced_move(direction, user) diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index f7fa46678b0..685f2a90431 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -10,12 +10,12 @@ var/looking_for_personality = 0 var/mob/living/silicon/pai/pai -/*/obj/item/device/paicard/relaymove(var/mob/user, var/direction) - if(src.loc && istype(src.loc.loc, /obj/item/rig_module)) - var/obj/item/rig_module/module = src.loc.loc - if(!module.holder || !direction) - return - module.holder.forced_move(direction)*/ +/obj/item/device/paicard/relaymove(var/mob/user, var/direction) + if(user.stat || user.stunned) + return + var/obj/item/weapon/rig/rig = src.get_rig() + if(istype(rig)) + rig.forced_move(direction, user) /obj/item/device/paicard/New() ..() diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 6b1362a7666..778c30dedea 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -95,7 +95,7 @@ playsound(T, "sparks", 50, 1) anim(T,M,'icons/mob/mob.dmi',,"phaseout",,M.dir) -/obj/item/rig_module/teleporter/engage(atom/target) +/obj/item/rig_module/teleporter/engage(var/atom/target, var/notify_ai) if(!..()) return 0 diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index d2412dd6c8f..60a4c5ce24d 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -27,6 +27,8 @@ var/interface_path = "hardsuit.tmpl" var/ai_interface_path = "hardsuit.tmpl" var/interface_title = "Hardsuit Controller" + var/wearer_move_delay //Used for AI moving. + var/ai_controlled_move_delay = 10 // Keeps track of what this rig should spawn with. var/suit_type = "hardsuit" @@ -179,8 +181,8 @@ for(var/obj/item/piece in list(helmet,boots,gloves,chest)) if(!piece) continue piece.icon_state = "[initial(icon_state)]" - if(airtight) - piece.item_flags &= ~(STOPPRESSUREDAMAGE|AIRTIGHT) + if(airtight) + piece.item_flags &= ~(STOPPRESSUREDAMAGE|AIRTIGHT) update_icon(1) /obj/item/weapon/rig/proc/toggle_seals(var/mob/living/carbon/human/M,var/instant) @@ -268,9 +270,9 @@ for(var/obj/item/piece in list(helmet,boots,gloves,chest)) if(!piece) continue piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]" - canremove = !seal_target + canremove = !seal_target if(airtight) - update_component_sealed() + update_component_sealed() update_icon(1) return 0 @@ -289,9 +291,9 @@ for(var/obj/item/piece in list(helmet,boots,gloves,chest)) if(canremove) piece.item_flags &= ~(STOPPRESSUREDAMAGE|AIRTIGHT) - else + else piece.item_flags |= (STOPPRESSUREDAMAGE|AIRTIGHT) - update_icon(1) + update_icon(1) /obj/item/weapon/rig/process() @@ -324,6 +326,8 @@ else if(offline) offline = 0 + if(istype(wearer) && !wearer.wearing_rig) + wearer.wearing_rig = src chest.slowdown = initial(slowdown) if(offline) @@ -540,12 +544,10 @@ return 0 /obj/item/weapon/rig/proc/notify_ai(var/message) - if(!message || !installed_modules || !installed_modules.len) - return - for(var/obj/item/rig_module/module in installed_modules) - for(var/mob/living/silicon/ai/ai in module.contents) - if(ai && ai.client && !ai.stat) - ai << "[message]" + for(var/obj/item/rig_module/ai_container/module in installed_modules) + if(module.integrated_ai && module.integrated_ai.client && !module.integrated_ai.stat) + module.integrated_ai << "[message]" + . = 1 /obj/item/weapon/rig/equipped(mob/living/carbon/human/M) ..() @@ -562,6 +564,7 @@ if(istype(M) && M.back == src) M.visible_message("[M] struggles into \the [src].", "You struggle into \the [src].") wearer = M + wearer.wearing_rig = src update_icon() /obj/item/weapon/rig/proc/toggle_piece(var/piece, var/mob/living/carbon/human/H, var/deploy_mode) @@ -673,6 +676,7 @@ ..() for(var/piece in list("helmet","gauntlets","chest","boots")) toggle_piece(piece, user, ONLY_RETRACT) + wearer.wearing_rig = null wearer = null //Todo @@ -754,14 +758,128 @@ return 1 return 0 -/*/obj/item/weapon/rig/proc/forced_move(dir) - if(locked_down) +/obj/item/weapon/rig/proc/ai_can_move_suit(var/mob/user, var/check_user_module = 0, var/check_for_ai = 0) + + if(check_for_ai) + if(!(locate(/obj/item/rig_module/ai_container) in contents)) + return 0 + var/found_ai + for(var/obj/item/rig_module/ai_container/module in contents) + if(module.damage >= 2) + continue + if(module.integrated_ai && module.integrated_ai.client && !module.integrated_ai.stat) + found_ai = 1 + break + if(!found_ai) + return 0 + + if(check_user_module) + if(!user || !user.loc || !user.loc.loc) + return 0 + var/obj/item/rig_module/ai_container/module = user.loc.loc + if(!istype(module) || module.damage >= 2) + user << "Your host module is unable to interface with the suit." + return 0 + + if(offline || !cell || !cell.charge || locked_down) + if(user) user << "Your host rig is unpowered and unresponsive." return 0 - if(!control_overridden) - return if(!wearer || wearer.back != src) + if(user) user << "Your host rig is not being worn." return 0 - wearer.Move(null,dir)*/ + if(!wearer.stat && !control_overridden && !ai_override_enabled) + if(user) user << "You are locked out of the suit servo controller." + return 0 + return 1 + +/obj/item/weapon/rig/proc/force_rest(var/mob/user) + if(!ai_can_move_suit(user, check_user_module = 1)) + return + wearer.lay_down() + user << "\The [wearer] is now [wearer.resting ? "resting" : "getting up"]." + +/obj/item/weapon/rig/proc/forced_move(var/direction, var/mob/user) + + // Why is all this shit in client/Move()? Who knows? + if(world.time < wearer_move_delay) + return + + if(!wearer || !wearer.loc || !ai_can_move_suit(user, check_user_module = 1)) + return + + //This is sota the goto stop mobs from moving var + if(wearer.transforming || !wearer.canmove) + return + + if(locate(/obj/effect/stop/, wearer.loc)) + for(var/obj/effect/stop/S in wearer.loc) + if(S.victim == wearer) + return + + if(!wearer.lastarea) + wearer.lastarea = get_area(wearer.loc) + + if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0)) + if(!wearer.Process_Spacemove(0)) + return 0 + + if(malfunctioning) + direction = pick(cardinal) + + // Inside an object, tell it we moved. + if(isobj(wearer.loc) || ismob(wearer.loc)) + var/atom/O = wearer.loc + return O.relaymove(wearer, direction) + + if(isturf(wearer.loc)) + if(wearer.restrained())//Why being pulled while cuffed prevents you from moving + for(var/mob/M in range(wearer, 1)) + if(M.pulling == wearer) + if(!M.restrained() && M.stat == 0 && M.canmove && wearer.Adjacent(M)) + user << "Your host is restrained! They can't move!" + return 0 + else + M.stop_pulling() + + if(wearer.pinned.len) + src << "Your host is pinned to a wall by [wearer.pinned[1]]!" + return 0 + + // AIs are a bit slower than regular and ignore move intent. + wearer.last_move_intent = world.time + ai_controlled_move_delay + wearer_move_delay = world.time + ai_controlled_move_delay + + var/tickcomp = 0 + if(config.Tickcomp) + tickcomp = ((1/(world.tick_lag))*1.3) - 1.3 + wearer_move_delay += tickcomp + + if(istype(wearer.buckled, /obj/vehicle)) + //manually set move_delay for vehicles so we don't inherit any mob movement penalties + //specific vehicle move delays are set in code\modules\vehicles\vehicle.dm + wearer_move_delay = world.time + tickcomp + return wearer.buckled.relaymove(wearer, direction) + + if(istype(wearer.machine, /obj/machinery)) + if(wearer.machine.relaymove(wearer, direction)) + return + + if(wearer.pulledby || wearer.buckled) // Wheelchair driving! + if(istype(wearer.loc, /turf/space)) + return // No wheelchair driving in space + if(istype(wearer.pulledby, /obj/structure/bed/chair/wheelchair)) + return wearer.pulledby.relaymove(wearer, direction) + else if(istype(wearer.buckled, /obj/structure/bed/chair/wheelchair)) + if(ishuman(wearer.buckled)) + var/obj/item/organ/external/l_hand = wearer.get_organ("l_hand") + var/obj/item/organ/external/r_hand = wearer.get_organ("r_hand") + if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED))) + return // No hands to drive your chair? Tough luck! + wearer_move_delay += 2 + return wearer.buckled.relaymove(wearer,direction) + + cell.use(200) //Arbitrary, TODO + wearer.Move(get_step(get_turf(wearer),direction),direction) // This returns the rig if you are contained inside one, but not if you are wearing it /atom/proc/get_rig() @@ -772,6 +890,9 @@ /obj/item/weapon/rig/get_rig() return src +/mob/living/carbon/human/get_rig() + return back + #undef ONLY_DEPLOY #undef ONLY_RETRACT #undef SEAL_DELAY diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 4716a191b84..63c950058a6 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -126,7 +126,7 @@ /obj/machinery/portable_atmospherics/hydroponics/AltClick() if(mechanical && !usr.stat && !usr.lying && Adjacent(usr)) close_lid(usr) - return + return 1 return ..() /obj/machinery/portable_atmospherics/hydroponics/attack_ghost(var/mob/dead/observer/user) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 49e8c6ad528..d9b84ea3b06 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -122,6 +122,13 @@ locked = 1 return +/obj/item/device/mmi/relaymove(var/mob/user, var/direction) + if(user.stat || user.stunned) + return + var/obj/item/weapon/rig/rig = src.get_rig() + if(rig) + rig.forced_move(direction, user) + /obj/item/device/mmi/Destroy() if(isrobot(loc)) var/mob/living/silicon/robot/borg = loc diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index e72671d78ad..aaf947a13d4 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -49,12 +49,12 @@ return 1 return ..() - /mob/living/carbon/brain/update_canmove() - if(in_contents_of(/obj/mecha)) + if(in_contents_of(/obj/mecha) || istype(loc, /obj/item/device/mmi)) canmove = 1 - use_me = 1 //If it can move, let it emote - else canmove = 0 + use_me = 1 + else + canmove = 0 return canmove /mob/living/carbon/brain/binarycheck() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 73624912ece..65927322776 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -136,8 +136,10 @@ return shock_damage +/mob/proc/swap_hand() + return -/mob/living/carbon/proc/swap_hand() +/mob/living/carbon/swap_hand() var/obj/item/item_in_hand = src.get_active_hand() if(item_in_hand) //this segment checks if the item in your hand is twohanded. if(istype(item_in_hand,/obj/item/weapon/material/twohanded)) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 1eb0b53f04f..ff7255523d3 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -61,11 +61,13 @@ if(!gibbed && species.death_sound) playsound(loc, species.death_sound, 80, 1, 1) - if(ticker && ticker.mode) sql_report_death(src) ticker.mode.check_win() + if(wearing_rig) + wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.") + return ..(gibbed,species.death_message) /mob/living/carbon/human/proc/ChangeToHusk() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 65d1f0fa898..3b43c16543a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -7,6 +7,7 @@ var/list/hud_list[10] var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. + var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. /mob/living/carbon/human/New(var/new_loc, var/new_species = null) @@ -1370,6 +1371,16 @@ handle_regular_hud_updates() /mob/living/carbon/human/Check_Shoegrip() - if(istype(shoes, /obj/item/clothing/shoes/magboots) && (shoes.item_flags & NOSLIP)) //magboots + dense_object = no floating + if((shoes.item_flags & NOSLIP) && istype(shoes, /obj/item/clothing/shoes/magboots)) //magboots + dense_object = no floating + return 1 + return 0 + +/mob/living/carbon/human/can_stand_overridden() + if(wearing_rig && wearing_rig.ai_can_move_suit(check_for_ai = 1)) + // Actually missing a leg will screw you up. Everything else can be compensated for. + for(var/limbcheck in list("l_leg","r_leg")) + var/obj/item/organ/affecting = get_organ(limbcheck) + if(!affecting) + return 0 return 1 return 0 diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index efe203c51cc..575fa0c5316 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -144,6 +144,9 @@ /mob/living/carbon/human/Paralyse(amount) if(HULK in mutations) return + // Notify our AI if they can now control the suit. + if(wearing_rig && !stat && paralysis < amount) //We are passing out right this second. + wearing_rig.notify_ai("Warning: user consciousness failure. Mobility control passed to integrated intelligence system.") ..() /mob/living/carbon/human/getCloneLoss() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index ca5de28d739..d160d5c5e96 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -52,6 +52,10 @@ // update the current life tick, can be used to e.g. only do something every 4 ticks life_tick++ + // This is not an ideal place for this but it will do for now. + if(wearing_rig && wearing_rig.offline) + wearing_rig = null + in_stasis = istype(loc, /obj/structure/closet/body_bag/cryobag) && loc:opened == 0 if(in_stasis) loc:used++ diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c306bacdcde..40790cd04a0 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -657,7 +657,7 @@ default behaviour is: set category = "IC" resting = !resting - src << "\blue You are now [resting ? "resting" : "getting up"]" + src << "You are now [resting ? "resting" : "getting up"]." /mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null, var/ignore_items = 0) // -- TLE -- Merged by Carn if(stat) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index a183d49be95..8ff4a106524 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -81,7 +81,7 @@ var/list/ai_verbs_default = list( var/datum/ai_icon/selected_sprite // The selected icon set var/custom_sprite = 0 // Whether the selected icon is custom - + var/carded /mob/living/silicon/ai/proc/add_ai_verbs() src.verbs |= ai_verbs_default @@ -684,5 +684,15 @@ var/list/ai_verbs_default = list( icon_state = selected_sprite.alive_icon set_light(1, 1, selected_sprite.alive_light) +// Pass lying down or getting up to our pet human, if we're in a rig. +/mob/living/silicon/ai/lay_down() + set name = "Rest" + set category = "IC" + + resting = 0 + var/obj/item/weapon/rig/rig = src.get_rig() + if(rig) + rig.force_rest(src) + #undef AI_CHECK_WIRELESS #undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 4641c7d2de7..88c3e812f05 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -72,8 +72,6 @@ var/current_pda_messaging = null /mob/living/silicon/pai/New(var/obj/item/device/paicard) - - canmove = 0 src.loc = paicard card = paicard sradio = new(src) @@ -276,8 +274,6 @@ var/obj/item/device/pda/holder = card.loc holder.pai = null - canmove = 1 - src.client.perspective = EYE_PERSPECTIVE src.client.eye = src src.forceMove(get_turf(card)) @@ -339,12 +335,16 @@ set name = "Rest" set category = "IC" + // Pass lying down or getting up to our pet human, if we're in a rig. if(istype(src.loc,/obj/item/device/paicard)) resting = 0 + var/obj/item/weapon/rig/rig = src.get_rig() + if(istype(rig)) + rig.force_rest(src) else resting = !resting icon_state = resting ? "[chassis]_rest" : "[chassis]" - src << "\blue You are now [resting ? "resting" : "getting up"]" + src << "You are now [resting ? "resting" : "getting up"]" canmove = !resting @@ -393,7 +393,8 @@ card.loc = get_turf(card) src.forceMove(card) card.forceMove(card.loc) - canmove = 0 + canmove = 1 + resting = 0 icon_state = "[chassis]" /mob/living/silicon/pai/start_pulling(var/atom/movable/AM) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 43269113d9d..a0555a003dc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -692,40 +692,52 @@ if(transforming) return 0 return 1 +// Not sure what to call this. Used to check if humans are wearing an AI-controlled exosuit and hence don't need to fall over yet. +/mob/proc/can_stand_overridden() + return 0 + +/mob/proc/cannot_stand() + return incapacitated() || restrained() || resting || sleeping || (status_flags & FAKEDEATH) + //Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. /mob/proc/update_canmove() - if(istype(buckled, /obj/vehicle)) - var/obj/vehicle/V = buckled - if(stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH)) - lying = 1 - canmove = 0 - pixel_y = V.mob_offset_y - 5 - else - if(buckled.buckle_lying != -1) lying = buckled.buckle_lying - canmove = 1 - pixel_y = V.mob_offset_y - else if(buckled) - anchored = 1 - canmove = 0 - if(istype(buckled)) - if(buckled.buckle_lying != -1) - lying = buckled.buckle_lying - if(buckled.buckle_movable) - anchored = 0 - canmove = 1 - else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH)) - lying = 1 - canmove = 0 - else if(stunned) - canmove = 0 - else if(captured) - anchored = 1 - canmove = 0 - lying = 0 - else + if(!resting && cannot_stand() && can_stand_overridden()) lying = 0 canmove = 1 + else + if(istype(buckled, /obj/vehicle)) + var/obj/vehicle/V = buckled + if(cannot_stand()) + lying = 1 + canmove = 0 + pixel_y = V.mob_offset_y - 5 + else + if(buckled.buckle_lying != -1) lying = buckled.buckle_lying + canmove = 1 + pixel_y = V.mob_offset_y + else if(buckled) + anchored = 1 + canmove = 0 + if(istype(buckled)) + if(buckled.buckle_lying != -1) + lying = buckled.buckle_lying + if(buckled.buckle_movable) + anchored = 0 + canmove = 1 + + else if(cannot_stand()) + lying = 1 + canmove = 0 + else if(stunned) + canmove = 0 + else if(captured) + anchored = 1 + canmove = 0 + lying = 0 + else + lying = 0 + canmove = 1 if(lying) density = 0 diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 8f0c90062b3..e0235f6d5fc 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -233,7 +233,6 @@ if(Process_Grab()) return - if(!mob.canmove) return @@ -246,7 +245,6 @@ if((istype(mob.loc, /turf/space)) || (mob.lastarea.has_gravity == 0)) if(!mob.Process_Spacemove(0)) return 0 - if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved var/atom/O = mob.loc return O.relaymove(mob, direct) diff --git a/html/changelogs/Zuhayr-hardsuits.yml b/html/changelogs/Zuhayr-hardsuits.yml new file mode 100644 index 00000000000..187e90e25ff --- /dev/null +++ b/html/changelogs/Zuhayr-hardsuits.yml @@ -0,0 +1,4 @@ +author: Zuhayr +delete-after: True +changes: + - rscadd: "Added the ability for AIs in hardsuits to control suit modules and movement with a dead or unconcious wearer." \ No newline at end of file