Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic human icons #3462

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
84dd7b8
dynamic human icons
FalloutFalcon Oct 1, 2024
71c6fa5
the helper
FalloutFalcon Oct 1, 2024
b2763d6
this is annoying
FalloutFalcon Oct 1, 2024
ffc02b5
ok this fixes it
FalloutFalcon Oct 1, 2024
d52784e
gives him his eyes back.
FalloutFalcon Oct 1, 2024
37f9915
cool!
FalloutFalcon Oct 1, 2024
2e1783e
refactor the frointersmen just a little to not reuse alot of code
FalloutFalcon Oct 1, 2024
b495ea0
Merge branch 'master' into dynamic-human-icons
FalloutFalcon Oct 1, 2024
d116e0c
fix unit tests
FalloutFalcon Oct 1, 2024
6e13b18
fix tests?
FalloutFalcon Oct 6, 2024
ace18d4
removes emmisives to test this
FalloutFalcon Oct 6, 2024
3312e73
porting some prs to fix issues i hope
FalloutFalcon Oct 7, 2024
3571925
handling for decals in unit test
FalloutFalcon Oct 7, 2024
b01244e
https://github.com/tgstation/tgstation/pull/71706
FalloutFalcon Oct 7, 2024
15704eb
small fix
FalloutFalcon Oct 7, 2024
247f0a4
i think that define was not true so should acctually work now
FalloutFalcon Oct 7, 2024
278e78a
test
FalloutFalcon Oct 7, 2024
3bdb037
Merge branch 'master' into dynamic-human-icons
FalloutFalcon Oct 8, 2024
4d9d42b
warning
FalloutFalcon Oct 10, 2024
b5d3aeb
these numbers were all inaccurate before i got here
FalloutFalcon Oct 10, 2024
8bf018c
Merge branch 'master' of https://github.com/shiptest-ss13/Shiptest in…
FalloutFalcon Oct 17, 2024
70c09f6
will this fix this?
FalloutFalcon Oct 18, 2024
d4775ec
Comment out validate overlay limit
FalloutFalcon Oct 18, 2024
a7a26a6
Acctually we can leave in the removal just dont error it.
FalloutFalcon Oct 18, 2024
44285dd
bad indentation
FalloutFalcon Oct 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions code/__DEFINES/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,31 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define CONDUCT_1 (1<<5)
/// For machines and structures that should not break into parts, eg, holodeck stuff
#define NODECONSTRUCT_1 (1<<7)
/// atom queued to SSoverlay
#define OVERLAY_QUEUED_1 (1<<8)
/// item has priority to check when entering or leaving
#define ON_BORDER_1 (1<<9)
#define ON_BORDER_1 (1<<8)
//Whether or not this atom shows screentips when hovered over
#define NO_SCREENTIPS_1 (1<<10)
#define NO_SCREENTIPS_1 (1<<9)
/// Prevent clicking things below it on the same turf eg. doors/ fulltile windows
#define PREVENT_CLICK_UNDER_1 (1<<11)
#define HOLOGRAM_1 (1<<12)
#define PREVENT_CLICK_UNDER_1 (1<<10)
#define HOLOGRAM_1 (1<<11)
/// Prevents mobs from getting chainshocked by teslas and the supermatter
#define SHOCKED_1 (1<<13)
#define SHOCKED_1 (1<<12)
///Whether /atom/Initialize() has already run for the object
#define INITIALIZED_1 (1<<14)
#define INITIALIZED_1 (1<<13)
/// was this spawned by an admin? used for stat tracking stuff.
#define ADMIN_SPAWNED_1 (1<<15)
#define ADMIN_SPAWNED_1 (1<<14)
/// should not get harmed if this gets caught by an explosion?
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16)
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<15)
/// should the contents of this atom be acted upon
#define RAD_PROTECT_CONTENTS_1 (1 << 17)
#define RAD_PROTECT_CONTENTS_1 (1 << 16)
/// should this object be allowed to be contaminated
#define RAD_NO_CONTAMINATE_1 (1 << 18)
#define RAD_NO_CONTAMINATE_1 (1 << 17)
///Use when this shouldn't be obscured by large icons, like trees.
#define SHOW_BEHIND_LARGE_ICONS_1 (1<<12)
#define SHOW_BEHIND_LARGE_ICONS_1 (1<<18)
/// Should we use the initial icon for display? Mostly used by overlay only objects
#define HTML_USE_INITAL_ICON_1 (1<<20)
#define HTML_USE_INITAL_ICON_1 (1<<19)
// Whether or not this atom is storing contents for a disassociated storage object
#define HAS_DISASSOCIATED_STORAGE_1 (1<<24)
#define HAS_DISASSOCIATED_STORAGE_1 (1<<20)

// Update flags for [/atom/proc/update_appearance]
/// Update the atom's name
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -438,3 +438,6 @@

//Saves a proc call, life is suffering. If who has no targets_from var, we assume it's just who
#define GET_TARGETS_FROM(who) (who.targets_from ? who.get_targets_from() : who)

/// In dynamic human icon gen we don't replace the held item.
#define NO_REPLACE 0
28 changes: 28 additions & 0 deletions code/__DEFINES/overlays.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* I do want this however this currently only fails on decals specificly in create and destroy.
Updating the overlays in genral was already pretty unatomic.area
I've added porting some updated decal code from tg to resolve this to my list.
WARNING("Too many overlays on [changed_on.type] - [length(changed_on.overlays)], refusing to update and cutting.\
\n What follows is a printout of all existing overlays at the time of the overflow \n[text_lays]"); \
*/

// A reasonable number of maximum overlays an object needs
// If you think you need more, rethink it
#define MAX_ATOM_OVERLAYS 100

/// Checks if an atom has reached the overlay limit, and make a loud error if it does.
#define VALIDATE_OVERLAY_LIMIT(changed_on) \
if(length(changed_on.overlays) >= MAX_ATOM_OVERLAYS) { \
var/text_lays = overlays2text(changed_on.overlays); \
changed_on.overlays.Cut(); \
} \

/// Performs any operations that ought to run after an appearance change
#define POST_OVERLAY_CHANGE(changed_on) \
if(alternate_appearances) { \
for(var/I in changed_on.alternate_appearances){\
var/datum/atom_hud/alternate_appearance/AA = changed_on.alternate_appearances[I];\
if(AA.transfer_overlays){\
AA.copy_overlays(changed_on, TRUE);\
}\
} \
}
6 changes: 1 addition & 5 deletions code/__DEFINES/stat_tracking.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
#define STAT_LOG_ENTRY(entrylist, entryname) \
var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH)); \
STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME; \
var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT)); \
if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) { \
STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT; \
}; \

STAT_ENTRY[STAT_ENTRY_COUNT] += 1;


25 changes: 0 additions & 25 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -237,31 +237,6 @@
#define SSEXPLOSIONS_TURFS 2
#define SSEXPLOSIONS_THROWS 3

//! ## Overlays subsystem

///Compile all the overlays for an atom from the cache lists
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A) \
do{ \
var/list/ad = A.add_overlays; \
var/list/rm = A.remove_overlays; \
if(LAZYLEN(rm)){ \
A.overlays -= rm; \
rm.Cut(); \
} \
if(LAZYLEN(ad)){ \
A.overlays |= ad; \
ad.Cut(); \
} \
for(var/I in A.alternate_appearances){ \
var/datum/atom_hud/alternate_appearance/AA = A.alternate_appearances[I]; \
if(AA.transfer_overlays){ \
AA.copy_overlays(A, TRUE); \
} \
} \
A.flags_1 &= ~OVERLAY_QUEUED_1; \
}while(FALSE)

// Vote subsystem counting methods
/// First past the post. One selection per person, and the selection with the most votes wins.
#define VOTE_COUNT_METHOD_SINGLE 1
Expand Down
65 changes: 65 additions & 0 deletions code/__HELPERS/dynamic_human_icon_gen.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
///Global list of all dynamically generated icons, for caching, so we don't have to generate multiple times.
GLOBAL_LIST_EMPTY(dynamic_human_appearances)

/// Creates a human with the given parameters and returns an appearance of it
/proc/get_dynamic_human_appearance(outfit_path, species_path = /datum/species/human, mob_spawn_path, r_hand, l_hand, bloody_slots = NONE, animated = TRUE)
if(!species_path)
return FALSE
if(!ispath(species_path))
stack_trace("Attempted to call get_dynamic_human_appearance() with an instantiated species_path. Pass the species datum typepath instead.")
return FALSE
var/arg_string = "[outfit_path]_[species_path]_[mob_spawn_path]_[l_hand]_[r_hand]_[bloody_slots]"
if(GLOB.dynamic_human_appearances[arg_string]) //if already exists in our cache, just return that
return GLOB.dynamic_human_appearances[arg_string]
var/mob/living/carbon/human/dummy/consistent/dummy = new()
dummy.set_species(species_path)
dummy.stat = CONSCIOUS //He needs to be alive or he has no eyes. Scary
dummy.underwear = "Nude"
dummy.undershirt = "Nude"
dummy.socks = "Nude"
if(outfit_path)
var/datum/outfit/outfit = new outfit_path()
if(r_hand != NO_REPLACE) //we can still override to be null, no replace means just use outfit's
outfit.r_hand = r_hand
if(l_hand != NO_REPLACE)
outfit.l_hand = l_hand
dummy.equipOutfit(outfit, visualsOnly = TRUE)
else if(mob_spawn_path)
var/obj/effect/mob_spawn/human/spawner = new mob_spawn_path(null)
if(r_hand != NO_REPLACE)
spawner.r_hand = r_hand
if(l_hand != NO_REPLACE)
spawner.l_hand = l_hand
spawner.special(dummy, dummy)
spawner.equip(dummy)
for(var/obj/item/carried_item in dummy)
if(dummy.is_holding(carried_item))
var/datum/component/two_handed/twohanded = carried_item.GetComponent(/datum/component/two_handed)
if(twohanded)
twohanded.wield(dummy)
/*
var/datum/component/transforming/transforming = carried_item.GetComponent(/datum/component/transforming)
if(transforming)
transforming.set_active(carried_item)
*/
if(bloody_slots & carried_item.slot_flags)
carried_item.add_mob_blood(dummy)
//dummy.update_held_items()
dummy.regenerate_icons()
var/mutable_appearance/output = dummy.appearance
GLOB.dynamic_human_appearances[arg_string] = output
qdel(dummy)
return output

///This exists to apply the icons async, as that cannot be done in Initialize because of possible sleeps.
/proc/apply_dynamic_human_appearance(atom/target, outfit_path, species_path = /datum/species/human, mob_spawn_path, r_hand, l_hand, bloody_slots = NONE)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(set_dynamic_human_appearance), args)

///This proc gets an argument of a target and runs
/proc/set_dynamic_human_appearance(list/arguments)
var/atom/target = arguments[1] //1st argument is the target
var/dynamic_appearance = get_dynamic_human_appearance(arglist(arguments.Copy(2))) //the rest of the arguments starting from 2 matter to the proc
target.icon = 'icons/mob/human.dmi'
target.icon_state = ""
target.appearance_flags |= KEEP_TOGETHER
target.copy_overlays(dynamic_appearance, TRUE)
1 change: 0 additions & 1 deletion code/__HELPERS/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,6 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)


var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing")
COMPILE_OVERLAYS(body)
for(var/D in showDirs)
body.setDir(D)
var/icon/partial = getFlatIcon(body, defdir=D)
Expand Down
4 changes: 0 additions & 4 deletions code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,3 @@
#define RUIN_PLACEMENT_TEST
#define SHIP_PLACEMENT_TEST
#endif

// A reasonable number of maximum overlays an object needs
// If you think you need more, rethink it
#define MAX_ATOM_OVERLAYS 100
1 change: 0 additions & 1 deletion code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ DEFINE_BITFIELD(flags_1, list(
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
"NO_RUINS_1" = NO_RUINS_1,
"ON_BORDER_1" = ON_BORDER_1,
"OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
"PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1,
"RAD_NO_CONTAMINATE_1" = RAD_NO_CONTAMINATE_1,
Expand Down
2 changes: 2 additions & 0 deletions code/_globalvars/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ GLOBAL_LIST_EMPTY(poll_options)
GLOBAL_PROTECT(poll_options)

GLOBAL_VAR_INIT(internal_tick_usage, 0.2 * world.tick_lag) //This var is updated every tick by a DLL if present, used to reduce lag

GLOBAL_VAR_INIT(running_create_and_destroy, FALSE)
Loading
Loading