diff --git a/code/__defines/span_vr.dm b/code/__defines/span_vr.dm index 618fd52b3d1..737d1a81ada 100644 --- a/code/__defines/span_vr.dm +++ b/code/__defines/span_vr.dm @@ -40,7 +40,7 @@ #define span_danger(str) ("" + str + "") #define span_warning(str) ("" + str + "") #define span_rose(str) ("" + str + "") -#define span_info(str) ("" + str + "" +#define span_info(str) ("" + str + "") #define span_notice(str) ("" + str + "") #define span_alium(str) ("" + str + "") #define span_cult(str) ("" + str + "") diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index f110251a17c..23df9d8ab1a 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -360,3 +360,40 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard) var/rendered = "[msg]" pai.show_message(rendered, type) ..() + + +// VoreEdit: Living Machine Stuff after this. +// This adds a var and proc for all machines to take a pAI. (The pAI can't control anything, it's just for RP.) +// You need to add usage of the proc to each machine to actually add support. For an example of this, see code\modules\food\kitchen\microwave.dm +/obj/machinery + var/obj/item/device/paicard/paicard = null + +/obj/machinery/proc/insertpai(mob/user, obj/item/device/paicard/card) + //var/obj/item/paicard/card = I + var/mob/living/silicon/pai/AI = card.pai + if(paicard) + to_chat(user, span_notice("This bot is already under PAI Control!")) + return + if(!istype(card)) // TODO: Add sleevecard support. + return + if(!card.pai) + to_chat(user, span_notice("This card does not currently have a personality!")) + return + paicard = card + user.unEquip(card) + card.forceMove(src) + AI.client.eye = src + to_chat(AI, span_notice("Your location is [card.loc].")) // DEBUG. TODO: Make unfolding the chassis trigger an eject. + name = AI.name + to_chat(AI, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)].")) + +/obj/machinery/proc/ejectpai(mob/user) + if(paicard) + var/mob/living/silicon/pai/AI = paicard.pai + paicard.forceMove(src.loc) + AI.client.eye = AI + paicard = null + name = initial(src.name) + to_chat(AI, span_notice("You feel a tad claustrophobic as your mind closes back into your card, ejecting from \the [initial(src.name)].")) + if(user) + to_chat(user, span_notice("You eject the card from \the [initial(src.name)].")) \ No newline at end of file diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index bab265f004b..b149aef9d2e 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -22,7 +22,7 @@ var/global/list/acceptable_items // List of the items you can put in var/global/list/available_recipes // List of the recipes you can use var/global/list/acceptable_reagents // List of the reagents you can put in - + var/global/max_n_of_items = 20 var/appliancetype = MICROWAVE var/datum/looping_sound/microwave/soundloop @@ -36,7 +36,7 @@ /obj/machinery/microwave/Initialize() . = ..() - + reagents = new/datum/reagents(100) reagents.my_atom = src @@ -47,7 +47,7 @@ for(var/datum/recipe/typepath as anything in subtypesof(/datum/recipe)) if((initial(typepath.appliance) & appliancetype)) available_recipes += new typepath - + acceptable_items = new acceptable_reagents = new for (var/datum/recipe/recipe in available_recipes) @@ -66,6 +66,8 @@ soundloop = new(list(src), FALSE) /obj/machinery/microwave/Destroy() + if(paicard) + ejectpai() // Lets not delete the pAI. QDEL_NULL(soundloop) return ..() @@ -125,7 +127,8 @@ to_chat(user, "It's dirty!") return 1 else if(is_type_in_list(O,acceptable_items)) - if(contents.len>=(max_n_of_items + component_parts.len + circuit_item_capacity)) //Adds component_parts to the maximum number of items. changed 1 to actually just be the circuit item capacity var. + var/list/workingList = cookingContents() + if(workingList.len>=(max_n_of_items + circuit_item_capacity)) //Adds component_parts to the maximum number of items. changed 1 to actually just be the circuit item capacity var. to_chat(user, "This [src] is full of ingredients, you cannot put more.") return 1 if(istype(O, /obj/item/stack) && O:get_amount() > 1) // This is bad, but I can't think of how to change it @@ -180,6 +183,9 @@ to_chat(user, "You decide not to do that.") else if(default_part_replacement(user, O)) return + else if(istype(O, /obj/item/device/paicard)) + if(!paicard) + insertpai(user, O) else to_chat(user, "You have no idea what you can cook with this [O].") ..() @@ -192,6 +198,10 @@ attack_hand(user) /obj/machinery/microwave/attack_hand(mob/user as mob) + if(user.a_intent == I_GRAB) + if(paicard) + ejectpai(user) + return user.set_machine(src) tgui_interact(user) @@ -211,7 +221,7 @@ data["operating"] = operating data["dirty"] = dirty == 100 data["items"] = get_items_list() - + return data /obj/machinery/microwave/proc/get_items_list() @@ -220,7 +230,8 @@ var/list/items_counts = list() var/list/items_measures = list() var/list/items_measures_p = list() - for(var/obj/O in ((contents - component_parts) - circuit)) + //for(var/obj/O in ((contents - component_parts) - circuit)) + for(var/obj/O in cookingContents()) var/display_name = O.name if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) items_measures[display_name] = "egg" @@ -283,7 +294,7 @@ if("dispose") dispose() return TRUE -/* +/* /obj/machinery/microwave/interact(mob/user as mob) // The microwave Menu var/dat = "" if(src.broken > 0) @@ -355,7 +366,7 @@ if(stat & (NOPOWER|BROKEN)) return start() - if(reagents.total_volume==0 && !(locate(/obj) in ((contents - component_parts) - circuit))) //dry run + if(reagents.total_volume==0 && !(locate(/obj) in cookingContents())) //dry run if(!wzhzhzh(16)) //VOREStation Edit - Quicker Microwaves (Undone during Auroraport, left note in case of reversion, was 5) abort() return @@ -390,7 +401,7 @@ cooked = fail() cooked.forceMove(src.loc) return - + //Making multiple copies of a recipe var/halftime = round(recipe.time*4/10/2) // VOREStation Edit - Quicker Microwaves (Undone during Auroraport, left note in case of reversion, was round(recipe.time/20/2)) if(!wzhzhzh(halftime)) @@ -451,7 +462,7 @@ /obj/machinery/microwave/proc/has_extra_item() //- coded to have different microwaves be able to handle different items if(item_level == 0) - for (var/obj/O in ((contents - component_parts) - circuit)) + for (var/obj/O in cookingContents()) if ( \ !istype(O,/obj/item/weapon/reagent_containers/food) && \ !istype(O, /obj/item/weapon/grown) \ @@ -459,7 +470,7 @@ return 1 return 0 if(item_level == 1) - for (var/obj/O in ((contents - component_parts) - circuit)) + for (var/obj/O in cookingContents()) if ( \ !istype(O, /obj/item/weapon/reagent_containers/food) && \ !istype(O, /obj/item/weapon/grown) && \ @@ -483,7 +494,7 @@ icon_state = "mw" SStgui.update_uis(src) soundloop.stop() - + /obj/machinery/microwave/proc/stop() playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) operating = FALSE // Turn it off again aferwards @@ -493,7 +504,7 @@ soundloop.stop() /obj/machinery/microwave/proc/dispose(var/message = 1) - for (var/atom/movable/A in ((contents-component_parts)-circuit)) + for (var/atom/movable/A in cookingContents()) A.forceMove(loc) if (src.reagents.total_volume) src.dirty++ @@ -527,11 +538,12 @@ src.operating = 0 // Turn it off again aferwards SStgui.update_uis(src) soundloop.stop() + src.ejectpai() // If it broke, time to yeet the PAI. /obj/machinery/microwave/proc/fail() var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/ffuu = new(src) var/amount = 0 - for (var/obj/O in (((contents - ffuu) - component_parts) - circuit)) + for (var/obj/O in cookingContents()) amount++ if(O.reagents) var/id = O.reagents.get_master_reagent_id() @@ -558,14 +570,14 @@ if(!do_after(usr, 1 SECONDS, target = src)) return - + if(operating) to_chat(usr, "You can't do that, [src] door is locked!") return usr.visible_message( - "[usr] opened [src] and has taken out [english_list(((contents-component_parts)-circuit))]." , - "You have opened [src] and taken out [english_list(((contents-component_parts)-circuit))]." + "[usr] opened [src] and has taken out [english_list(cookingContents())]." , + "You have opened [src] and taken out [english_list(cookingContents())]." ) dispose() @@ -594,7 +606,7 @@ /obj/item/weapon/holder ) result = /obj/effect/decal/cleanable/blood/gibs - + /datum/recipe/splat/before_cook(obj/container) if(istype(container, /obj/machinery/microwave)) var/obj/machinery/microwave/M = container @@ -617,3 +629,14 @@ var/obj/machinery/microwave/M = container M.muck_finish() . = ..() + +/obj/machinery/microwave/proc/cookingContents() //VOREEdit, this is a better way to deal with the contents of a microwave, since the previous method is stupid. + var/list/workingList = contents.Copy() // Using the copy proc because otherwise the two lists seem to become soul bonded. + workingList -= component_parts + workingList -= circuit + if(paicard) + workingList -= paicard + for(var/M in workingList) + if(istype(M, circuit)) // Yes, we remove circuit twice. Yes, it's necessary. Yes, it's stupid. + workingList -= M + return workingList \ No newline at end of file diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 2bc63f1bfea..206d9f0321b 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -17,7 +17,7 @@ var/emagged = 0 var/light_strength = 3 var/busy = 0 - + var/obj/item/device/paicard/paicard = null var/obj/access_scanner = null var/list/req_access = list() var/list/req_one_access = list() @@ -72,10 +72,27 @@ SetStunned(0) SetParalysis(0) - if(on && !client && !busy) + if(on && !client && !busy && !paicard) spawn(0) handleAI() - +/* +/mob/living/bot/examine(mob/user) + . = ..() + if(health < maxHealth) + if(health > maxHealth/3) + . += "[src]'s parts look loose." + else + . += "[src]'s parts look very loose!" + else + . += "[src] is in pristine condition." + . += span_notice("Its maintenance panel is [open ? "open" : "closed"].") + . += span_info("You can use a screwdriver to [open ? "close" : "open"] it.") + . += span_notice("Its control panel is [locked ? "locked" : "unlocked"].") + if(paicard) + . += span_notice("It has a pAI device installed.") + if(open) + . += span_info("You can use a crowbar to remove it.") +*/ /mob/living/bot/updatehealth() if(status_flags & GODMODE) health = getMaxHealth() @@ -138,6 +155,17 @@ qdel(O) else to_chat(user, "Unable to repair with the maintenance panel closed.") + else if(istype(O, /obj/item/device/paicard)) + if(open) + insertpai(user, O) + to_chat(user, span_notice("You slot the card into \the [initial(src.name)].")) + else + to_chat(user, span_notice("You must open the panel first!")) + else if(O.is_crowbar()) + if(open && paicard) + to_chat(user, span_notice("You are attempting to remove the pAI..")) + if(do_after(user,10 * O.toolspeed)) + ejectpai(user) else ..() @@ -203,6 +231,13 @@ if(LAZYLEN(can_go)) if(step_towards(src, pick(can_go))) return + for(var/mob in loc) + if(istype(mob, /mob/living/bot) && mob != src) // Same as above, but we also don't want to have bots ontop of bots. Cleanbots shouldn't stack >:( + var/turf/my_turf = get_turf(src) + var/list/can_go = my_turf.CardinalTurfsWithAccess(botcard) + if(LAZYLEN(can_go)) + if(step_towards(src, pick(can_go))) + return handleIdle() /mob/living/bot/proc/handleRegular() @@ -351,9 +386,14 @@ update_icons() /mob/living/bot/proc/explode() + if(paicard) + ejectpai() + release_vore_contents() qdel(src) /mob/living/bot/is_sentient() + if(paicard) + return TRUE return FALSE /******************************************************************/ @@ -443,3 +483,68 @@ /mob/living/bot/isSynthetic() //Robots are synthetic, no? return 1 + +/mob/living/bot/proc/insertpai(mob/user, obj/item/device/paicard/card) + //var/obj/item/paicard/card = I + var/mob/living/silicon/pai/AI = card.pai + if(paicard) + to_chat(user, span_notice("This bot is already under PAI Control!")) + return + if(!istype(card)) // TODO: Add sleevecard support. + return + if(client) + to_chat(user, span_notice("Higher levels of processing are already present!")) + return + if(!card.pai) + to_chat(user, span_notice("This card does not currently have a personality!")) + return + paicard = card + user.unEquip(card) + card.forceMove(src) + src.ckey = AI.ckey + name = AI.name + ooc_notes = AI.ooc_notes + to_chat(src, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)].")) + if(AI.idcard.access) + botcard.access |= AI.idcard.access + +/mob/living/bot/proc/ejectpai(mob/user) + if(paicard) + var/mob/living/silicon/pai/AI = paicard.pai + AI.ckey = src.ckey + AI.ooc_notes = ooc_notes + paicard.forceMove(src.loc) + paicard = null + name = initial(name) + botcard.access = botcard_access.Copy() + to_chat(AI, span_notice("You feel a tad claustrophobic as your mind closes back into your card, ejecting from \the [initial(src.name)].")) + + if(user) + to_chat(user, span_notice("You eject the card from \the [initial(src.name)].")) + +/mob/living/bot/verb/bot_nom(var/mob/living/T in oview(1)) + set name = "Bot Nom" + set category = "Bot Commands" + set desc = "Allows you to eat someone. Yum." + + if (stat != CONSCIOUS) + return + return feed_grabbed_to_self(src,T) + +/mob/living/bot/verb/ejectself() + set name = "Eject pAI" + set category = "Bot Commands" + set desc = "Eject your card, return to smole." + + return ejectpai() + +/mob/living/bot/Login() + no_vore = FALSE // ROBOT VORE + init_vore() // ROBOT VORE + verbs |= /mob/living/proc/insidePanel + +/mob/living/bot/Logout() + no_vore = TRUE // ROBOT VORE + release_vore_contents() + init_vore() // ROBOT VORE + verbs -= /mob/living/proc/insidePanel \ No newline at end of file diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm index 061574bd645..f60bccbfc32 100644 --- a/code/modules/mob/living/bot/cleanbot.dm +++ b/code/modules/mob/living/bot/cleanbot.dm @@ -140,8 +140,8 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - qdel(src) - return + //qdel(src) + return ..() /mob/living/bot/cleanbot/update_icons() if(busy) diff --git a/code/modules/mob/living/bot/ed209bot.dm b/code/modules/mob/living/bot/ed209bot.dm index 17d2da7878e..8700988e592 100644 --- a/code/modules/mob/living/bot/ed209bot.dm +++ b/code/modules/mob/living/bot/ed209bot.dm @@ -49,7 +49,7 @@ s.start() new /obj/effect/decal/cleanable/blood/oil(Tsec) - qdel(src) + return ..() /mob/living/bot/secbot/ed209/handleRangedTarget() RangedAttack(target) diff --git a/code/modules/mob/living/bot/edCLNbot.dm b/code/modules/mob/living/bot/edCLNbot.dm index bbb1e9861d8..ce0edabe088 100644 --- a/code/modules/mob/living/bot/edCLNbot.dm +++ b/code/modules/mob/living/bot/edCLNbot.dm @@ -68,8 +68,8 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - qdel(src) - return + //qdel(src) + return ..() /mob/living/bot/cleanbot/edCLN/tgui_data(mob/user) var/list/data = ..() diff --git a/code/modules/mob/living/bot/farmbot.dm b/code/modules/mob/living/bot/farmbot.dm index 083da22d3d1..969bfc1c831 100644 --- a/code/modules/mob/living/bot/farmbot.dm +++ b/code/modules/mob/living/bot/farmbot.dm @@ -286,8 +286,8 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - qdel(src) - return + //qdel(src) + return ..() /mob/living/bot/farmbot/confirmTarget(var/atom/targ) diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm index 9e869e0d81a..a7a7def771c 100644 --- a/code/modules/mob/living/bot/floorbot.dm +++ b/code/modules/mob/living/bot/floorbot.dm @@ -42,7 +42,7 @@ data["on"] = on data["open"] = open data["locked"] = locked - + data["vocal"] = vocal data["amount"] = amount @@ -75,7 +75,7 @@ /mob/living/bot/floorbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return TRUE - + add_fingerprint(src) switch(action) @@ -85,7 +85,7 @@ else turn_on() . = TRUE - + if(locked && !issilicon(usr)) return @@ -302,7 +302,8 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - qdel(src) + //qdel(src) + return ..() /mob/living/bot/floorbot/proc/addTiles(var/am) amount += am diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index 39b0b882bb1..ced48594f1c 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -268,10 +268,10 @@ /mob/living/bot/medbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return TRUE - + usr.set_machine(src) add_fingerprint(usr) - + . = TRUE switch(action) if("power") @@ -348,8 +348,8 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - qdel(src) - return + //qdel(src) + return ..() /mob/living/bot/medbot/handleRegular() . = ..() diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index 66134335725..f6a868d11aa 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -128,7 +128,7 @@ /mob/living/bot/secbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return - + add_fingerprint(usr) switch(action) @@ -379,7 +379,8 @@ s.start() new /obj/effect/decal/cleanable/blood/oil(Tsec) - qdel(src) + //qdel(src) + return ..() /mob/living/bot/secbot/proc/target_name(mob/living/T) if(ishuman(T)) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 7df66eaff46..a1764fbcd26 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -127,7 +127,7 @@ pda.ownjob = "Personal Assistant" pda.owner = text("[]", src) pda.name = pda.owner + " (" + pda.ownjob + ")" - + var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger) if(M) M.toff = TRUE @@ -247,6 +247,9 @@ last_special = world.time + 100 + if(istype(card.loc, /obj/machinery)) // VOREStation edit, this statement allows pAIs stuck in a machine to eject themselves. + var/obj/machinery/M = card.loc + M.ejectpai() //I'm not sure how much of this is necessary, but I would rather avoid issues. if(istype(card.loc,/obj/item/rig_module)) to_chat(src, "There is no room to unfold inside this rig module. You're good and stuck.")