Skip to content

Commit

Permalink
[MIRROR] Generalize chameleon extension setup
Browse files Browse the repository at this point in the history
  • Loading branch information
PsiOmegaDelta authored and SierraHelper committed Dec 29, 2023
1 parent 7d41ad4 commit d45d56f
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 59 deletions.
1 change: 1 addition & 0 deletions code/__defines/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define ITEM_FLAG_NOCUFFS FLAG(13) // Gloves that have this flag prevent cuffs being applied
#define ITEM_FLAG_CAN_HIDE_IN_SHOES FLAG(14) // Items that can be hidden in shoes that permit it
#define ITEM_FLAG_WASHER_ALLOWED FLAG(15) // Items that can be washed in washing machines
#define ITEM_FLAG_IS_CHAMELEON_ITEM FLAG(16) // Setups the chameleon extension on init. Throws an exception if there is no compatible extension subtype.

// Flags for pass_flags.
#define PASS_FLAG_TABLE FLAG(0)
Expand Down
4 changes: 4 additions & 0 deletions code/_helpers/game.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31

#define IS_SUBTYPE(child_type, parent_type) (child_type != parent_type && istype(child_type, parent_type))

#define IS_SUBPATH(child_path, parent_path) (child_path != parent_path && ispath(child_path, parent_path))

/proc/is_on_same_plane_or_station(z1, z2)
if(z1 == z2)
return 1
Expand Down
22 changes: 22 additions & 0 deletions code/datums/extensions/chameleon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,25 @@
return outfit.l_ear
if (ispath(outfit.r_ear, expected_type))
return outfit.r_ear

/***************
* Setup Helper *
****************/
/obj/proc/SetupChameleonExtension(throw_runtime)
var/best_found_expected_type
var/best_found_extension
for (var/datum/extension/chameleon/chameleon_extension_type as anything in typesof(/datum/extension/chameleon))
var/expected_type = initial(chameleon_extension_type.expected_type)

if (istype(src, expected_type)) // If the type of src is a type expected by the extension then..
// Check if the expected type is a better match than the previously found best expected type (if any)
if (!best_found_expected_type || IS_SUBPATH(expected_type, best_found_expected_type))
best_found_expected_type = expected_type
best_found_extension = chameleon_extension_type

if (best_found_extension)
set_extension(src, best_found_extension)
return

if (throw_runtime)
CRASH("The type [type] does not have a compatible chameleon extension.")
2 changes: 2 additions & 0 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
if(armor[type]) // Don't set it if it gives no armor anyway, which is many items.
set_extension(src, armor_type, armor, armor_degradation_speed)
break
if (item_flags & ITEM_FLAG_IS_CHAMELEON_ITEM)
SetupChameleonExtension(TRUE)

/obj/item/Destroy()
QDEL_NULL(hidden_uplink)
Expand Down
66 changes: 11 additions & 55 deletions code/modules/clothing/chameleon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,119 +5,79 @@
worn_state = "jumpsuit"
desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/under/chameleon/Initialize()
. = ..()
set_extension(src,/datum/extension/chameleon/clothing/under)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/head/chameleon
name = "cap"
icon_state = "greysoft"
desc = "It looks like a plain hat, but upon closer inspection, there's an advanced holographic array installed inside. It seems to have a small dial inside."
origin_tech = list(TECH_ESOTERIC = 3)
body_parts_covered = 0
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/head/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/head)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/suit/chameleon
name = "armor"
icon_state = "armor"
item_state = "armor"
desc = "It appears to be a vest of standard armor, except this is embedded with a hidden holographic cloaker, allowing it to change it's appearance, but offering no protection.. It seems to have a small dial inside."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/suit/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/suit)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/shoes/chameleon
name = "shoes"
icon_state = "black"
item_state = "black"
desc = "They're comfy black shoes, with clever cloaking technology built in. It seems to have a small dial on the back of each shoe."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/shoes/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/shoes)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/storage/backpack/chameleon
name = "backpack"
icon_state = "backpack"
item_state = "backpack"
desc = "A backpack outfitted with cloaking tech. It seems to have a small dial inside, kept away from the storage."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/storage/backpack/chameleon/Initialize()
. = ..()
set_extension(src,/datum/extension/chameleon/backpack,/obj/item/storage/backpack)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/gloves/chameleon
name = "gloves"
icon_state = "black"
item_state = "bgloves"
desc = "It looks like a pair of gloves, but it seems to have a small dial inside."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/gloves/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/gloves)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/mask/chameleon
name = "mask"
icon_state = "fullgas"
item_state = "gas_alt"
desc = "It looks like a plain gask mask, but on closer inspection, it seems to have a small dial inside."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/mask/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/mask)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/glasses/chameleon
name = "goggles"
icon_state = "meson"
item_state = "glasses"
desc = "It looks like a plain set of mesons, but on closer inspection, it seems to have a small dial inside."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/glasses/chameleon/Initialize()
. = ..()
set_extension(src, /datum/extension/chameleon/clothing/glasses)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/device/radio/headset/chameleon
name = "radio headset"
icon_state = "headset"
item_state = "headset"
desc = "An updated, modular intercom that fits over the head. This one seems to have a small dial on it."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/device/radio/headset/chameleon/Initialize()
. = ..()
set_extension(src,/datum/extension/chameleon/headset)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/clothing/accessory/chameleon
name = "tie"
icon_state = "tie"
item_state = ""
desc = "A neosilk clip-on tie. It seems to have a small dial on its back."
origin_tech = list(TECH_ESOTERIC = 3)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON

/obj/item/clothing/accessory/chameleon/Initialize()
. = ..()
set_extension(src,/datum/extension/chameleon/clothing/accessory)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM

/obj/item/gun/energy/chameleon
name = "chameleon gun"
Expand All @@ -126,15 +86,11 @@
icon_state = "revolver"
w_class = ITEM_SIZE_SMALL
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ESOTERIC = 8)
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON
item_flags = ITEM_FLAG_INVALID_FOR_CHAMELEON | ITEM_FLAG_IS_CHAMELEON_ITEM
matter = list()

fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg'
projectile_type = /obj/item/projectile/chameleon
charge_meter = 0
charge_cost = 20 //uses next to no power, since it's just holograms
max_shots = 50

/obj/item/gun/energy/chameleon/Initialize()
. = ..()
set_extension(src,/datum/extension/chameleon/gun)
5 changes: 1 addition & 4 deletions code/modules/holodeck/HolodeckControl.dm
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,7 @@
for(var/obj/holo_obj in holographic_objs)
holo_obj.alpha *= 0.8 //give holodeck objs a slight transparency
holo_obj.holographic = TRUE
if(istype(holo_obj,/obj/item/storage))
set_extension(holo_obj,/datum/extension/chameleon/backpack)
if(istype(holo_obj,/obj/item/clothing))
set_extension(holo_obj,/datum/extension/chameleon/clothing)
holo_obj.SetupChameleonExtension()

if(HP.ambience)
linkedholodeck.forced_ambience = HP.ambience.Copy()
Expand Down
18 changes: 18 additions & 0 deletions code/unit_tests/unique_tests.dm
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,24 @@
pass("All space suit modifiers have unique names.")
return 1

// Purpose: /proc/SetupChameleonExtension() attempts to find the best chameleon extension for a given type
// Having multiple extensions expect the same type can technically lead to inconsistencies between compilations (if the types are moved around, etc.)
// Can be worked around by, for example, adding a flag that adds/removes a given extension from the list of possible extensions in the proc above
/datum/unit_test/chameleon_extensions_shall_have_unique_expected_types
name = "UNIQUENESS: Chameleon Extensions Shall Have Unique Expected Types"

/datum/unit_test/chameleon_extensions_shall_have_unique_expected_types/start_test()
var/list/expected_types_by_extension = list()
for (var/datum/extension/chameleon/chameleon_extension_type as anything in typesof(/datum/extension/chameleon))
group_by(expected_types_by_extension, initial(chameleon_extension_type.expected_type), chameleon_extension_type)

var/number_of_issues = number_of_issues(expected_types_by_extension, "Chameleon Extensions - Expected Types")
if(number_of_issues)
fail("[number_of_issues] duplicate expected type\s found.")
else
pass("All chameleon extensions have unique expected types.")
return 1

/datum/unit_test/proc/number_of_issues(list/entries, type, feedback = /singleton/noi_feedback)
var/issues = 0
for(var/key in entries)
Expand Down

0 comments on commit d45d56f

Please sign in to comment.