Reimagines the imaginary friend as a fancy new smite. (#61218)

Fixed imaginary friends being unable to turn by movement or holding down ctrl. I assume this was broken when abstract_move was implemented.

Makes some tweaks to the Imaginary Friend mob. It no longer cares about any brain traumas and can exist standalone.

Added the ability to take a set of datum prefs as an argument. It will attempt to create an imaginary friend as per those datum prefs.

This imaginary friend can be a cyborg or an AI core.

Takes this improved behaviour and packages it into a brand new smite that allows admins to inflict anyone with a permanent imaginary friend. This is not tied to a brain trauma. You can probably give imaginary friends imaginary friends. You can probably give the AI eye an imaginary friend. I have not tested this. It is probably a bad idea.

You can give simplemobs imaginary friends. Basic mobs. Silicons.

You choose whether the imaginary friend takes on the preferences of the person you choose to be the imaginary friend or is random
This commit is contained in:
Timberpoes
2021-09-05 16:23:09 +01:00
committed by GitHub
parent bdd91deca1
commit 7df1931ab0
3 changed files with 111 additions and 9 deletions
+54 -9
View File
@@ -70,8 +70,7 @@
var/image/current_image
var/hidden = FALSE
var/move_delay = 0
var/mob/living/carbon/owner
var/datum/brain_trauma/special/imaginary_friend/trauma
var/mob/living/owner
var/datum/action/innate/imaginary_join/join
var/datum/action/innate/imaginary_hide/hide
@@ -88,16 +87,20 @@
to_chat(src, span_notice("You are absolutely loyal to your friend, no matter what."))
to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what [owner] cannot."))
/mob/camera/imaginary_friend/Initialize(mapload, _trauma)
if(!_trauma)
stack_trace("Imaginary friend created without trauma, wtf")
return INITIALIZE_HINT_QDEL
/**
* Arguments:
* * imaginary_friend_owner - The living mob that owns the imaginary friend.
* * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on these prefs.
*/
/mob/camera/imaginary_friend/Initialize(mapload, mob/living/imaginary_friend_owner, datum/preferences/appearance_from_prefs = null)
. = ..()
trauma = _trauma
owner = trauma.owner
owner = imaginary_friend_owner
INVOKE_ASYNC(src, .proc/setup_friend)
if(appearance_from_prefs)
INVOKE_ASYNC(src, .proc/setup_friend_from_prefs, appearance_from_prefs)
else
INVOKE_ASYNC(src, .proc/setup_friend)
join = new
join.Grant(src)
@@ -110,6 +113,43 @@
name = real_name
human_image = get_flat_human_icon(null, pick(SSjob.joinable_occupations))
/**
* Sets up the imaginary friend's name and look using a set of datum preferences.
*
* Arguments:
* * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on the currently selected character in them. Otherwise, it's random.
*/
/mob/camera/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs)
if(!istype(appearance_from_prefs))
stack_trace("Attempted to create imaginary friend appearance from null prefs. Using random appearance.")
setup_friend()
return
real_name = appearance_from_prefs.real_name
name = real_name
// Determine what job is marked as 'High' priority.
var/datum/job/appearance_job
var/highest_pref = 0
for(var/job in appearance_from_prefs.job_preferences)
var/this_pref = appearance_from_prefs.job_preferences[job]
if(this_pref > highest_pref)
appearance_job = SSjob.GetJob(job)
highest_pref = this_pref
if(!appearance_job)
appearance_job = SSjob.GetJob("Assistant")
if(istype(appearance_job, /datum/job/ai))
human_image = icon('icons/mob/ai.dmi', icon_state = resolve_ai_icon(appearance_from_prefs.preferred_ai_core_display), dir = SOUTH)
return
if(istype(appearance_job, /datum/job/cyborg))
human_image = icon('icons/mob/robots.dmi', icon_state = "robot")
return
human_image = get_flat_human_icon(null, appearance_job, appearance_from_prefs)
/mob/camera/imaginary_friend/proc/Show()
if(!client) //nobody home
return
@@ -185,6 +225,7 @@
/mob/camera/imaginary_friend/Move(NewLoc, Dir = 0)
if(world.time < move_delay)
return FALSE
setDir(Dir)
if(get_dist(src, owner) > 9)
recall()
move_delay = world.time + 10
@@ -192,6 +233,10 @@
abstract_move(NewLoc)
move_delay = world.time + 1
/mob/camera/imaginary_friend/keybind_face_direction(direction)
. = ..()
Show()
/mob/camera/imaginary_friend/abstract_move(atom/destination)
. = ..()
Show()