diff --git a/code/__HELPERS/custom_holoforms.dm b/code/__HELPERS/custom_holoforms.dm
index 90094bd42c..70137db4d3 100644
--- a/code/__HELPERS/custom_holoforms.dm
+++ b/code/__HELPERS/custom_holoforms.dm
@@ -1,6 +1,6 @@
// Generates a holoform appearance
// Equipment list is slot = path.
-/proc/generate_custom_holoform_from_prefs(datum/preferences/prefs, list/equipment_by_slot, list/inhand_equipment, copy_job_first = FALSE, debug)
+/proc/generate_custom_holoform_from_prefs(datum/preferences/prefs, list/equipment_by_slot, list/inhand_equipment, copy_job_first = FALSE)
ASSERT(prefs)
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_HOLOFORM)
prefs.copy_to(mannequin)
@@ -28,29 +28,34 @@
mannequin.setDir(WEST)
var/icon/west = getFlatIcon(mannequin)
- var/icon/
+ var/icon/combined = new
+ combined.Insert(north, dir = NORTH)
+ combined.Insert(south, dir = SOUTH)
+ combined.Insert(east, dir = EAST)
+ combined.Insert(west, dir = WEST)
- if(!debug)
- unset_busy_human_dummy(DUMMY_HUMAN_SLOT_HOLOFORM)
- return result
+ unset_busy_human_dummy(DUMMY_HUMAN_SLOT_HOLOFORM)
+ return combined
-/proc/process_holoform_icon_filter(icon/I, filter_type)
+/proc/process_holoform_icon_filter(icon/I, filter_type, clone = TRUE)
+ if(clone)
+ I = icon(I) //Clone
switch(filter_type)
if(HOLOFORM_FILTER_AI)
- I = getHologramIcon(I, FALSE)
+ I = getHologramIcon(I)
if(HOLOFORM_FILTER_STATIC)
- I = getStaticIcon(I, FALSE)
+ I = getStaticIcon(I)
if(HOLOFORM_FILTER_PAI)
- I = getPAIHologramIcon(I, FALSE)
+ I = getPAIHologramIcon(I)
return I
//Errors go to user.
-/proc/generate_custom_holoform_from_prefs_safe(datum/preferences/prefs, mob/user, debug = FALSE)
+/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, debug)
+ return generate_custom_holoform_from_prefs(prefs, null, null, TRUE)
//Prompts this client for custom holoform parameters.
/proc/user_interface_custom_holoform(client/C)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index a12772b6d2..68dd423527 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -949,7 +949,7 @@ world
/proc/getPAIHologramIcon(icon/A, safety = TRUE)
var/icon/flat_icon = safety? A : new(A)
- flat_icon.ColorTone(rgb(0, 102, 0))
+ flat_icon.SetIntensity(0.8, 1, 1)
flat_icon.ChangeOpacity(0.8)
return flat_icon
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 1e7d720ee9..b1783ba940 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -500,7 +500,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
else
return FALSE
-/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
+/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction)
if(LAZYLEN(masters) && masters[user])
var/obj/effect/overlay/holo_pad_hologram/holo = masters[user]
var/transfered = FALSE
@@ -512,6 +512,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
transfered = TRUE
//All is good.
holo.forceMove(new_turf)
+ if(direction)
+ holo.setDir(direction)
if(!transfered)
update_holoray(user,new_turf)
return TRUE
diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm
index e1e079cbae..8e1e5aab8d 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva.dm
@@ -14,10 +14,9 @@
var/max_grown = 100
var/time_of_birth
- rotate_on_lying = 0
+ rotate_on_lying = FALSE
bodyparts = list(/obj/item/bodypart/chest/larva, /obj/item/bodypart/head/larva)
-
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/larva/Initialize()
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index a1184613fe..9629dc3484 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -40,7 +40,7 @@
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
- var/rotate_on_lying = 1
+ rotate_on_lying = TRUE
var/tinttotal = 0 // Total level of visualy impairing items
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index 66be8058f1..0155f2575d 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -1,31 +1,3 @@
-//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
-/mob/living/carbon/update_transform()
- var/matrix/ntransform = matrix(transform) //aka transform.Copy()
- var/final_pixel_y = pixel_y
- var/final_dir = dir
- var/changed = 0
- if(lying != lying_prev && rotate_on_lying)
- changed++
- ntransform.TurnTo(lying_prev,lying)
- if(lying == 0) //Lying to standing
- final_pixel_y = get_standard_pixel_y_offset()
- else //if(lying != 0)
- if(lying_prev == 0) //Standing to lying
- pixel_y = get_standard_pixel_y_offset()
- final_pixel_y = get_standard_pixel_y_offset(lying)
- if(dir & (EAST|WEST)) //Facing east or west
- final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
-
- if(resize != RESIZE_DEFAULT_SIZE)
- changed++
- ntransform.Scale(resize)
- resize = RESIZE_DEFAULT_SIZE
-
- if(changed)
- animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
- setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
-
-
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 4d2a36907d..783e044492 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -111,4 +111,6 @@
var/list/diseases = list() // list of all diseases in a mob
var/list/disease_resistances = list()
- var/drag_slowdown = TRUE //Whether the mob is slowed down when dragging another prone mob
\ No newline at end of file
+ var/drag_slowdown = TRUE //Whether the mob is slowed down when dragging another prone mob
+
+ var/rotate_on_lying = FALSE
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 732a4d5cca..ec7c7826bf 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -698,7 +698,6 @@
holo_icon = getHologramIcon(icon(icon_list[input],"alienq"))
else
holo_icon = getHologramIcon(icon(icon_list[input], input))
- return
/mob/living/silicon/ai/proc/corereturn()
set category = "Malfunction"
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 7477ba7713..38afaf8313 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -68,7 +68,7 @@
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
-/mob/camera/aiEye/proc/setLoc(T, force_update = FALSE)
+/mob/camera/aiEye/proc/setLoc(T, force_update = FALSE, dir)
if(ai)
if(!isturf(ai.loc))
return
@@ -88,7 +88,7 @@
//Holopad
if(istype(ai.current, /obj/machinery/holopad))
var/obj/machinery/holopad/H = ai.current
- H.move_hologram(ai, T)
+ H.move_hologram(ai, T, dir)
if(ai.camera_light_on)
ai.light_cameras()
if(ai.master_multicam)
@@ -139,7 +139,7 @@
for(var/i = 0; i < max(user.sprint, initial); i += 20)
var/turf/step = get_turf(get_step(user.eyeobj, direct))
if(step)
- user.eyeobj.setLoc(step)
+ user.eyeobj.setLoc(step, null, direct)
user.cooldown = world.timeofday + 5
if(user.acceleration)
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index bd73de3513..756cae69ca 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -58,10 +58,10 @@
var/canholo = TRUE
var/obj/item/card/id/access_card = null
var/chassis = "repairbot"
- var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE,
- "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "borgi" = FALSE ,
- "parrot" = FALSE, "bear" = FALSE , "mushroom" = FALSE, "crow" = FALSE ,
- "fairy" = FALSE , "spiderbot" = FALSE, "custom" = FALSE) //assoc value is whether it can be picked up.
+ var/dynamic_chassis
+ var/list/possible_chassis //initialized in initialize.
+ var/list/dynamic_chassis_icons //ditto.
+ var/list/chassis_pixel_offsets_x //stupid dogborgs
var/static/item_head_icon = 'icons/mob/pai_item_head.dmi'
var/static/item_lh_icon = 'icons/mob/pai_item_lh.dmi'
var/static/item_rh_icon = 'icons/mob/pai_item_rh.dmi'
@@ -120,6 +120,13 @@
pda.owner = text("[]", src)
pda.name = pda.owner + " (" + pda.ownjob + ")"
+ possible_chassis = typelist(NAMEOF(src, possible_chassis), list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE,
+ "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "borgi" = FALSE ,
+ "parrot" = FALSE, "bear" = FALSE , "mushroom" = FALSE, "crow" = FALSE ,
+ "fairy" = FALSE , "spiderbot" = FALSE)) //assoc value is whether it can be picked up.
+ dynamic_chassis_icons = typelist(NAMEOF(src, dynamic_chassis_icons), initialize_dynamic_chassis_icons())
+ chassis_pixel_offsets_x = typelist(NAMEOF(src, chassis_pixel_offsets_x), default_chassis_pixel_offsets_x())
+
. = ..()
var/datum/action/innate/pai/software/SW = new
@@ -294,3 +301,45 @@
/mob/living/silicon/pai/process()
emitterhealth = CLAMP((emitterhealth + emitterregen), -50, emittermaxhealth)
+
+/mob/living/silicon/pai/proc/initialize_dynamic_chassis_icons()
+ . = list()
+ var/icon/curr //for inserts
+ var/icon/temp //for extracts
+
+ //This is a horrible system and I wish I was not as lazy and did something smarter, like just generating a new icon in memory which is probably more efficient.
+
+ //Basic /tg/ cyborgs
+ .["Cyborg - Engineering (default)"] = process_holoform_icon_filter(icon('icons/mob/robots.dmi', "engineer"), HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Medical (default)"] = process_holoform_icon_filter(icon('icons/mob/robots.dmi', "medical"), HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Security (default)"] = process_holoform_icon_filter(icon('icons/mob/robots.dmi', "sec"), HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Clown (default)"] = process_holoform_icon_filter(icon('icons/mob/robots.dmi', "clown"), HOLOFORM_FILTER_PAI, FALSE)
+
+ //Citadel dogborgs
+ curr = icon('modular_citadel/icons/mob/widerobot.dmi', "valeeng")
+ temp = icon('modular_citadel/icons/mob/widerobot.dmi', "valeeng-rest")
+ curr.Insert(temp, "rest")
+ process_holoform_icon_filter(curr, HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Engineering (dog - valeeng)"] = curr
+ curr = icon('modular_citadel/icons/mob/widerobot.dmi', "medihound")
+ temp = icon('modular_citadel/icons/mob/widerobot.dmi', "medihound-rest")
+ curr.Insert(temp, "rest")
+ process_holoform_icon_filter(curr, HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Medical (dog - medihound)"] = curr
+ curr = icon('modular_citadel/icons/mob/widerobot.dmi', "k9")
+ temp = icon('modular_citadel/icons/mob/widerobot.dmi', "k9-rest")
+ curr.Insert(temp, "rest")
+ process_holoform_icon_filter(curr, HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Security (dog - k9)"] = curr
+ curr = icon('modular_citadel/icons/mob/widerobot.dmi', "valesec")
+ temp = icon('modular_citadel/icons/mob/widerobot.dmi', "valesec-rest")
+ curr.Insert(temp, "rest")
+ process_holoform_icon_filter(curr, HOLOFORM_FILTER_PAI, FALSE)
+ .["Cyborg - Security (dog - valesec)"] = curr
+
+/mob/living/silicon/pai/proc/default_chassis_pixel_offsets_x()
+ . = list()
+ .["Cyborg - Engineering (dog - valeeng)"] = -16
+ .["Cyborg - Medical (dog - medihound)"] = -16
+ .["Cyborg - Security (dog - k9)"] = -16
+ .["Cyborg - Security (dog - valesec)"] = -16
diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm
index ede6fedaaf..1cc9f959cb 100644
--- a/code/modules/mob/living/silicon/pai/pai_shell.dm
+++ b/code/modules/mob/living/silicon/pai/pai_shell.dm
@@ -78,29 +78,32 @@
if(!isturf(loc) && loc != card)
to_chat(src, "You can not change your holochassis composite while not on the ground or in your card!")
return FALSE
- var/choice = input(src, "What would you like to use for your holochassis composite?") as null|anything in possible_chassis
- if(!choice)
+ var/choicetype = input(src, "What type of chassis do you want to use?") as null|anything in list("Preset - Basic", "Custom", "Preset - Dynamic")
+ if(!choicetype)
return FALSE
- chassis = choice
+ switch(choicetype)
+ if("Custom")
+ chassis = "custom"
+ if("Preset - Basic")
+ var/choice = input(src, "What would you like to use for your holochassis composite?") as null|anything in possible_chassis
+ if(!choice)
+ return FALSE
+ chassis = choice
+ if("Preset - Dynamic")
+ var/choice = input(src, "What would you like to use for your holochassis composite?") as null|anything in dynamic_chassis_icons
+ if(!choice)
+ return FALSE
+ chassis = "dynamic"
+ dynamic_chassis = choice
+ resist_a_rest(FALSE, TRUE)
update_icon()
to_chat(src, "You switch your holochassis projection composite to [chassis]")
/mob/living/silicon/pai/lay_down()
- ..()
- update_resting_icon(resting)
-
-/mob/living/silicon/pai/proc/update_resting_icon(rest)
- if(chassis == "custom")
- lying_prev = lying
- if(resting)
- lying = pick(90, 270)
- else
- lying = 0
- else
- lying = 0
- update_icon()
+ . = ..()
if(loc != card)
- visible_message("[src] [rest? "lays down for a moment..." : "perks up from the ground"]")
+ visible_message("[src] [resting? "lays down for a moment..." : "perks up from the ground"]")
+ update_icon()
/mob/living/silicon/pai/start_pulling(atom/movable/AM)
return FALSE
diff --git a/code/modules/mob/living/silicon/pai/update_icon.dm b/code/modules/mob/living/silicon/pai/update_icon.dm
index d18712dfc9..54eb275a76 100644
--- a/code/modules/mob/living/silicon/pai/update_icon.dm
+++ b/code/modules/mob/living/silicon/pai/update_icon.dm
@@ -1,29 +1,21 @@
/mob/living/silicon/pai/proc/update_icon()
- if(chassis == "custom")
+ if(chassis == "custom") //Make sure custom exists if it's set to custom
custom_holoform_icon = client?.prefs?.get_filtered_holoform(HOLOFORM_FILTER_PAI)
if(!custom_holoform_icon)
chassis = pick(possible_chassis - "custom")
- if(chassis != "custom")
- icon = initial(icon)
- icon_state = "[chassis]_[resting]"
- else
+ if(chassis == "dynamic") //handle dynamic generated icons
+ icon = dynamic_chassis_icons[dynamic_chassis]
+ var/list/states = icon_states(icon)
+ var/has_resting_state = ("rest" in states)
+ icon_state = (resting && has_resting_state)? "rest" : ""
+ rotate_on_lying = FALSE
+ else if(chassis == "custom")
icon = custom_holoform_icon
icon_state = ""
+ rotate_on_lying = TRUE
+ else
+ icon = initial(icon)
+ icon_state = "[chassis][resting? "_rest" : (stat == DEAD? "_dead" : "")]"
+ rotate_on_lying = FALSE
+ pixel_x = ((chassis == "dynamic") && chassis_pixel_offsets_x[dynamic_chassis]) || 0
update_transform()
-
-//Might be a copypaste from /mob/living/carbon/update_transform(), is it time to pull the combined code to /living yet? didn't want edge cases.
-/mob/living/silicon/pai/update_transform()
- var/matrix/ntransform = matrix(transform)
- var/final_pixel_y = pixel_y
- var/final_dir = dir
- if(lying != lying_prev)
- ntransform.TurnTo(lying_prev, lying)
- if(!lying) //standing
- final_pixel_y = get_standard_pixel_y_offset()
- else
- if(!lying_prev)
- pixel_y = get_standard_pixel_y_offset()
- final_pixel_y = get_standard_pixel_y_offset(lying)
- if(dir & (EAST|WEST))
- final_dir = pick(NORTH, SOUTH)
- animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN | EASE_OUT)
diff --git a/code/modules/mob/living/update_icons.dm b/code/modules/mob/living/update_icons.dm
new file mode 100644
index 0000000000..8bf0dc98a9
--- /dev/null
+++ b/code/modules/mob/living/update_icons.dm
@@ -0,0 +1,26 @@
+//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
+/mob/living/update_transform()
+ var/matrix/ntransform = matrix(transform) //aka transform.Copy()
+ var/final_pixel_y = pixel_y
+ var/final_dir = dir
+ var/changed = 0
+ if(lying != lying_prev && rotate_on_lying)
+ changed++
+ ntransform.TurnTo(lying_prev,lying)
+ if(lying == 0) //Lying to standing
+ final_pixel_y = get_standard_pixel_y_offset()
+ else //if(lying != 0)
+ if(lying_prev == 0) //Standing to lying
+ pixel_y = get_standard_pixel_y_offset()
+ final_pixel_y = get_standard_pixel_y_offset(lying)
+ if(dir & (EAST|WEST)) //Facing east or west
+ final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
+
+ if(resize != RESIZE_DEFAULT_SIZE)
+ changed++
+ ntransform.Scale(resize)
+ resize = RESIZE_DEFAULT_SIZE
+
+ if(changed)
+ animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
+ setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
diff --git a/tgstation.dme b/tgstation.dme
index c0fa268558..a7b22d7d7a 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2046,6 +2046,7 @@
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\status_procs.dm"
#include "code\modules\mob\living\taste.dm"
+#include "code\modules\mob\living\update_icons.dm"
#include "code\modules\mob\living\ventcrawling.dm"
#include "code\modules\mob\living\brain\brain.dm"
#include "code\modules\mob\living\brain\brain_item.dm"