diff --git a/code/__HELPERS/custom_holoforms.dm b/code/__HELPERS/custom_holoforms.dm index 0e97314f1f..34b31cc1c7 100644 --- a/code/__HELPERS/custom_holoforms.dm +++ b/code/__HELPERS/custom_holoforms.dm @@ -46,17 +46,29 @@ I = getPAIHologramIcon(I) return I -//Errors go to user. -/proc/generate_custom_holoform_from_prefs_safe(datum/preferences/prefs, mob/user) - if(user) - if(user.client.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY) - to_chat(user, "You are attempting to set your custom holoform too fast!") - return - return generate_custom_holoform_from_prefs(prefs, null, null, TRUE, TRUE) - //Prompts this client for custom holoform parameters. /proc/user_interface_custom_holoform(client/C) var/datum/preferences/target_prefs = C.prefs + if(target_prefs.path) + var/list/characters = list() + var/savefile/S = new /savefile(target_prefs.path) + if(S) + var/name + var/max_save_slots = C.prefs.max_save_slots + for(var/i=1, i<=max_save_slots, i++) + S.cd = "/character[i]" + S["real_name"] >> name + if(name) + characters[name] = i + var/chosen_name = input(C, "Which character do you wish to use as your appearance.") as anything in characters + if(chosen_name) + if(C.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY) + to_chat(C.mob, "You are attempting to set your custom holoform too fast!") + return + target_prefs = new(C) + if(!target_prefs.load_character(characters[chosen_name], TRUE)) + target_prefs = C.prefs + ASSERT(target_prefs) //In the future, maybe add custom path allowances a la admin create outfit but for now.. - return generate_custom_holoform_from_prefs_safe(target_prefs, C.mob) + return generate_custom_holoform_from_prefs(target_prefs, null, null, TRUE, TRUE) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index d4b6199187..5683367c55 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -144,7 +144,7 @@ var/sound //Sound to play when emote is called var/vary = FALSE //used for the honk borg emote var/volume = 50 - mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon) + mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/camera/aiEye) /datum/emote/sound/run_emote(mob/user, params) . = ..() diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm index a381cc512a..99eb638ee0 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/camera/camera.dm @@ -12,6 +12,7 @@ sight = SEE_SELF move_on_shuttle = FALSE + /mob/camera/experience_pressure_difference() return @@ -23,5 +24,7 @@ /mob/camera/canUseStorage() return FALSE -/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE) +/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE, forced = FALSE) + if(forced) + return ..() return diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index ce8bbc5dab..cfebacb977 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -509,7 +509,7 @@ message = "beeps." message_param = "beeps at %t." sound = 'sound/machines/twobeep.ogg' - mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/living/carbon/human) + mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/living/carbon/human, /mob/camera/aiEye) /datum/emote/living/circle key = "circle" diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 7ce1c1e7cc..fbf2d27c31 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -86,6 +86,7 @@ var/mob/living/silicon/robot/deployed_shell = null //For shell control var/datum/action/innate/deploy_shell/deploy_action = new var/datum/action/innate/deploy_last_shell/redeploy_action = new + var/datum/action/innate/custom_holoform/custom_holoform = new var/chnotify = 0 @@ -152,6 +153,7 @@ aicamera = new/obj/item/camera/siliconcam/ai_camera(src) deploy_action.Grant(src) + custom_holoform.Grant(src) if(isturf(loc)) add_verb(src, list(/mob/living/silicon/ai/proc/ai_network_change, \ @@ -1032,3 +1034,8 @@ qdel(src) else return + +/mob/living/silicon/ai/emote(act, m_type=1, message = null, intentional = FALSE) + if(current && eyeobj) + return eyeobj.emote(act, m_type, message, intentional, forced = TRUE) + return ..() diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 8ec39095fb..17de811cdd 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -204,3 +204,7 @@ alpha = 100 layer = ABOVE_ALL_MOB_LAYER plane = GAME_PLANE + +/mob/camera/aiEye/emote(act, m_type=1, message = null, intentional = FALSE, forced = FALSE) + if(ai?.current) + ..() diff --git a/code/modules/mob/living/silicon/custom_holoform.dm b/code/modules/mob/living/silicon/custom_holoform.dm index 8ce6e9a29a..e4f7f6780b 100644 --- a/code/modules/mob/living/silicon/custom_holoform.dm +++ b/code/modules/mob/living/silicon/custom_holoform.dm @@ -1,28 +1,12 @@ -/mob/living/silicon/verb/clear_custom_holoform() - set name = "Clear Custom Holoform" - set desc = "Clear your current custom holoform" - set category = "OOC" - +/mob/living/silicon/proc/attempt_set_custom_holoform() if(!client.prefs) to_chat(src, "No preferences datum on your client, contact an admin/coder!") return - client.prefs.custom_holoform_icon = null - client.prefs.cached_holoform_icons = null - to_chat(src, "Holoform removed.") - -/mob/living/silicon/verb/set_custom_holoform() - set name = "Set Custom Holoform" - set desc = "Set your custom holoform using your current preferences slot and a specified set of gear." - set category = "OOC" - - if(!client.prefs) - to_chat(src, "No preferences datum on your client, contact an admin/coder!") - return - if(client.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY) - to_chat(src, "You are attempting to change custom holoforms too fast!") var/icon/new_holoform = user_interface_custom_holoform(client) + client.prefs.last_custom_holoform = world.time if(new_holoform) client.prefs.custom_holoform_icon = new_holoform client.prefs.cached_holoform_icons = null - client.prefs.last_custom_holoform = world.time to_chat(src, "Holoform set.") + return TRUE + return FALSE diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 6d2da187a1..786c121ad6 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -131,6 +131,7 @@ var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light + var/datum/action/innate/custom_holoform/custom_holoform = new /datum/action/innate/custom_holoform var/datum/action/language_menu/ALM = new SW.Grant(src) @@ -139,6 +140,7 @@ AR.Grant(src) AL.Grant(src) ALM.Grant(src) + custom_holoform.Grant(src) emitter_next_use = world.time + 10 SECONDS /mob/living/silicon/pai/ComponentInitialize() diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index c532e44ff5..d499c2abae 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -1,9 +1,9 @@ /datum/emote/silicon - mob_type_allowed_typecache = list(/mob/living/silicon) + mob_type_allowed_typecache = list(/mob/living/silicon, /mob/camera/aiEye) emote_type = EMOTE_AUDIBLE /datum/emote/sound/silicon - mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human) + mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human, /mob/camera/aiEye) emote_type = EMOTE_AUDIBLE var/unrestricted = TRUE diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 83df3ffba5..7db417b8fa 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1022,6 +1022,32 @@ R.undeploy() return TRUE +/datum/action/innate/custom_holoform + name = "Select Custom Holoform" + desc = "Select one of your existing avatars to use as a holoform." + icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon_state = "custom_holoform" + required_mobility_flags = NONE + +/datum/action/innate/custom_holoform/Trigger() + if(!..()) + return FALSE + var/mob/living/silicon/S = owner + + //if setting the holoform succeeds, attempt to set it as the current holoform for the pAI or AI + if(S.attempt_set_custom_holoform()) + if(istype(S, /mob/living/silicon/pai)) + var/mob/living/silicon/pai/P = S + P.chassis = "custom" + else if(istype(S, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/A = S + if(A.client?.prefs?.custom_holoform_icon) + A.holo_icon = A.client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI) + else + A.holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female")) + + return TRUE + /mob/living/silicon/robot/proc/undeploy() @@ -1043,6 +1069,8 @@ mainframe.laws.show_laws(mainframe) //Always remind the AI when switching mainframe = null + + /mob/living/silicon/robot/attack_ai(mob/user) if(shell && (!connected_ai || connected_ai == user)) var/mob/living/silicon/ai/AI = user diff --git a/icons/mob/actions/actions_silicon.dmi b/icons/mob/actions/actions_silicon.dmi index cf3d7a2a95..fa7edf111a 100644 Binary files a/icons/mob/actions/actions_silicon.dmi and b/icons/mob/actions/actions_silicon.dmi differ