diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4f36246bdd..28c5a82f859 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,7 +80,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - map_path: [example, tradeship, nexus, exodus, ministation, away_sites_testing, modpack_testing, planets_testing, outreach, kleibkhar] + map_path: [example, tradeship, exodus, ministation, away_sites_testing, modpack_testing, planets_testing, outreach, kleibkhar] steps: - uses: actions/checkout@v3 - name: Setup Cache diff --git a/code/__defines/appearance.dm b/code/__defines/appearance.dm index 5b7a35980c4..2c3ada675cb 100644 --- a/code/__defines/appearance.dm +++ b/code/__defines/appearance.dm @@ -1,3 +1,3 @@ // Consider these images/atoms as part of the UI/HUD -#define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE -#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE +#define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|DEFAULT_APPEARANCE_FLAGS +#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|DEFAULT_APPEARANCE_FLAGS diff --git a/code/__defines/aspects.dm b/code/__defines/aspects.dm index a0791e172e7..6e7619db774 100644 --- a/code/__defines/aspects.dm +++ b/code/__defines/aspects.dm @@ -11,61 +11,59 @@ #define ASPECTS_PHYSICAL BITFLAG(0) #define ASPECTS_MENTAL BITFLAG(1) -#define DEFINE_ROBOLIMB_MODEL_ASPECTS_WITH_SPECIES_BODYTYPE(MODEL_PATH, MODEL_ID, COST, SPECIES, BODYTYPE) \ +#define DEFINE_ROBOLIMB_MODEL_ASPECTS(MODEL_PATH, MODEL_ID, COST) \ /decl/aspect/prosthetic_limb/left_hand/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/left_hand; \ aspect_cost = COST * 0.5; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/left_arm/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/left_arm; \ aspect_cost = COST; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/right_hand/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/right_hand; \ aspect_cost = COST * 0.5; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/right_arm/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/right_arm; \ aspect_cost = COST; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/left_foot/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/left_foot; \ aspect_cost = COST * 0.5; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/left_leg/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/left_leg; \ aspect_cost = COST; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/right_foot/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/right_foot; \ aspect_cost = COST * 0.5; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ } \ /decl/aspect/prosthetic_limb/right_leg/##MODEL_ID { \ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/right_leg; \ aspect_cost = COST; \ - check_bodytype = BODYTYPE; \ - check_species = SPECIES; \ +} \ +/decl/aspect/prosthetic_limb/head/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/head; \ + aspect_cost = COST * 0.5; \ +} \ +/decl/aspect/prosthetic_limb/chest/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/chest; \ + aspect_cost = COST * 0.5; \ +} \ +/decl/aspect/prosthetic_limb/groin/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/groin; \ + aspect_cost = COST * 0.5; \ } -#define DEFINE_ROBOLIMB_MODEL_ASPECTS(MODEL_PATH, MODEL_ID, COST) DEFINE_ROBOLIMB_MODEL_ASPECTS_WITH_SPECIES_BODYTYPE(MODEL_PATH, MODEL_ID, COST, null, null) diff --git a/code/__defines/bodytype.dm b/code/__defines/bodytype.dm new file mode 100644 index 00000000000..cd09f120864 --- /dev/null +++ b/code/__defines/bodytype.dm @@ -0,0 +1,28 @@ +#define BODY_FLAG_EXCLUDE BITFLAG(0) +#define BODY_FLAG_HUMANOID BITFLAG(1) +#define BODY_FLAG_MONKEY BITFLAG(2) + +#define BODYTYPE_HUMANOID "humanoid body" +#define BODYTYPE_OTHER "alien body" +#define BODYTYPE_MONKEY "small humanoid body" + +// Bodytype appearance flags +#define HAS_SKIN_TONE_NORMAL BITFLAG(0) // Skin tone selectable in chargen for baseline humans (0-220) +#define HAS_SKIN_COLOR BITFLAG(1) // Skin colour selectable in chargen. (RGB) +#define HAS_LIPS BITFLAG(2) // Lips are drawn onto the mob icon. (lipstick) +#define HAS_UNDERWEAR BITFLAG(3) // Underwear is drawn onto the mob icon. +#define HAS_EYE_COLOR BITFLAG(4) // Eye colour selectable in chargen. (RGB) +#define HAS_HAIR_COLOR BITFLAG(5) // Hair colour selectable in chargen. (RGB) +#define RADIATION_GLOWS BITFLAG(6) // Radiation causes this character to glow. +#define HAS_SKIN_TONE_GRAV BITFLAG(7) // Skin tone selectable in chargen for grav-adapted humans (0-100) +#define HAS_SKIN_TONE_SPCR BITFLAG(8) // Skin tone selectable in chargen for spacer humans (0-165) +#define HAS_SKIN_TONE_TRITON BITFLAG(9) +#define HAS_A_SKIN_TONE (HAS_SKIN_TONE_NORMAL | HAS_SKIN_TONE_GRAV | HAS_SKIN_TONE_SPCR | HAS_SKIN_TONE_TRITON) // Bodytype has a numeric skintone + +// Bodytype feature flags +#define BODY_FLAG_NO_DNA BITFLAG(0) // Does not create DNA. Replaces SPECIES_FLAG_NO_SCAN. +#define BODY_FLAG_NO_PAIN BITFLAG(1) // Cannot suffer halloss/recieves deceptive health indicator. +#define BODY_FLAG_NO_EAT BITFLAG(2) // Cannot eat food/drink drinks even if a stomach organ is present. +#define BODY_FLAG_CRYSTAL_REFORM BITFLAG(3) // Can regenerate missing limbs from mineral baths. +#define BODY_FLAG_NO_STASIS BITFLAG(4) // Does not experience stasis effects (sleeper, cryo) +#define BODY_FLAG_NO_DEFIB BITFLAG(5) // Cannot be revived with a defibrilator. diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 721851ffaf3..3d24c1a3306 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -68,3 +68,5 @@ #define DEFAULT_GAS_ACCELERANT /decl/material/gas/hydrogen #define DEFAULT_GAS_OXIDIZER /decl/material/gas/oxygen + +#define CHEM_REACTION_FLAG_OVERFLOW_CONTAINER BITFLAG(0) diff --git a/code/__defines/computers.dm b/code/__defines/computers.dm index bffa88fba25..ffb231dc0b6 100644 --- a/code/__defines/computers.dm +++ b/code/__defines/computers.dm @@ -76,4 +76,5 @@ #define OS_FILE_NO_WRITE -5 #define OS_HARDDRIVE_SPACE -6 #define OS_NETWORK_ERROR -7 -#define OS_BAD_NAME -8 \ No newline at end of file +#define OS_BAD_NAME -8 +#define OS_BAD_TYPE -9 // File type is unsupported on this hardware. diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index feb53ecc9d3..36cc5ad868f 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -112,6 +112,6 @@ #define OPERATE_IDEAL 3 #define MODULAR_BODYPART_INVALID 0 // Cannot be detached or reattached. -#define MODULAR_BODYPART_PROSTHETIC 1 // Can be detached or reattached freely. +#define MODULAR_BODYPART_ANYWHERE 1 // Can be detached or reattached freely. #define MODULAR_BODYPART_CYBERNETIC 2 // Can be detached or reattached to compatible parent organs. diff --git a/code/__defines/fires.dm b/code/__defines/fires.dm new file mode 100644 index 00000000000..fa8f4f4a4e1 --- /dev/null +++ b/code/__defines/fires.dm @@ -0,0 +1,4 @@ +#define FUEL_VALUE_RETARDANT -1 +#define FUEL_VALUE_NONE 0 +#define FUEL_VALUE_ACCELERANT 1 +#define FUEL_VALUE_VOLATILE 2 diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 950e4dc9af1..d716d3f9484 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -1,11 +1,11 @@ -#define CLOSET_HAS_LOCK 1 -#define CLOSET_CAN_BE_WELDED 2 +#define CLOSET_HAS_LOCK BITFLAG(0) +#define CLOSET_CAN_BE_WELDED BITFLAG(1) -#define CLOSET_STORAGE_MISC 1 -#define CLOSET_STORAGE_ITEMS 2 -#define CLOSET_STORAGE_MOBS 4 -#define CLOSET_STORAGE_STRUCTURES 8 -#define CLOSET_STORAGE_ALL (~0) +#define CLOSET_STORAGE_MISC BITFLAG(0) +#define CLOSET_STORAGE_ITEMS BITFLAG(1) +#define CLOSET_STORAGE_MOBS BITFLAG(2) +#define CLOSET_STORAGE_STRUCTURES BITFLAG(3) +#define CLOSET_STORAGE_ALL (~0) /* Bitflags for flag variables. These are used instead of separate boolean vars to reduce the overall number of variables, @@ -34,70 +34,73 @@ The latter will result in a linter warning and will not work correctly. */ // Atom-level flags (/atom/var/atom_flags) -#define ATOM_FLAG_CHECKS_BORDER BITFLAG(0) // If a dense atom (potentially) only blocks movements from a given direction, i.e. window panes -#define ATOM_FLAG_CLIMBABLE BITFLAG(1) // This object can be climbed on -#define ATOM_FLAG_NO_BLOOD BITFLAG(2) // Used for items if they don't want to get a blood overlay. -#define ATOM_FLAG_NO_REACT BITFLAG(3) // Reagents don't react inside this container. -#define ATOM_FLAG_OPEN_CONTAINER BITFLAG(4) // Is an open container for chemistry purposes. -#define ATOM_FLAG_INITIALIZED BITFLAG(5) // Has this atom been initialized -#define ATOM_FLAG_NO_TEMP_CHANGE BITFLAG(6) // Reagents do not cool or heat to ambient temperature in this container. -#define ATOM_FLAG_CAN_BE_PAINTED BITFLAG(7) // Can be painted using a paint sprayer or similar. -#define ATOM_FLAG_SHIELD_CONTENTS BITFLAG(8) // Protects contents from some global effects (Solar storms) -#define ATOM_FLAG_ADJACENT_EXCEPTION BITFLAG(9) // Skips adjacent checks for atoms that should always be reachable in window tiles -#define ATOM_FLAG_NO_DISSOLVE BITFLAG(10) // Bypasses solvent reactions in the container. -#define ATOM_FLAG_NO_PHASE_CHANGE BITFLAG(11) // Bypasses heating and cooling product reactions in the container. -#define ATOM_FLAG_BLOCK_DIAGONAL_FACING BITFLAG(12) // Atom cannot face non-cardinal directions. +#define ATOM_FLAG_CHECKS_BORDER BITFLAG(0) // If a dense atom (potentially) only blocks movements from a given direction, i.e. window panes +#define ATOM_FLAG_CLIMBABLE BITFLAG(1) // This object can be climbed on +#define ATOM_FLAG_NO_BLOOD BITFLAG(2) // Used for items if they don't want to get a blood overlay. +#define ATOM_FLAG_NO_REACT BITFLAG(3) // Reagents don't react inside this container. +#define ATOM_FLAG_OPEN_CONTAINER BITFLAG(4) // Is an open container for chemistry purposes. +#define ATOM_FLAG_INITIALIZED BITFLAG(5) // Has this atom been initialized +#define ATOM_FLAG_NO_TEMP_CHANGE BITFLAG(6) // Reagents do not cool or heat to ambient temperature in this container. +#define ATOM_FLAG_CAN_BE_PAINTED BITFLAG(7) // Can be painted using a paint sprayer or similar. +#define ATOM_FLAG_SHIELD_CONTENTS BITFLAG(8) // Protects contents from some global effects (Solar storms) +#define ATOM_FLAG_ADJACENT_EXCEPTION BITFLAG(9) // Skips adjacent checks for atoms that should always be reachable in window tiles +#define ATOM_FLAG_NO_DISSOLVE BITFLAG(10) // Bypasses solvent reactions in the container. +#define ATOM_FLAG_NO_PHASE_CHANGE BITFLAG(11) // Bypasses heating and cooling product reactions in the container. +#define ATOM_FLAG_BLOCK_DIAGONAL_FACING BITFLAG(12) // Atom cannot face non-cardinal directions. -#define ATOM_IS_OPEN_CONTAINER(A) (A.atom_flags & ATOM_FLAG_OPEN_CONTAINER) +#define ATOM_FLAG_NO_CHEM_CHANGE (ATOM_FLAG_NO_REACT | ATOM_FLAG_NO_DISSOLVE | ATOM_FLAG_NO_PHASE_CHANGE) + +#define ATOM_IS_OPEN_CONTAINER(A) (A.atom_flags & ATOM_FLAG_OPEN_CONTAINER) // Movable-level flags (/atom/movable/movable_flags) -#define MOVABLE_FLAG_PROXMOVE BITFLAG(0) // Does this object require proximity checking in Enter()? -#define MOVABLE_FLAG_Z_INTERACT BITFLAG(1) // Should attackby and attack_hand be relayed through ladders and open spaces? -#define MOVABLE_FLAG_ALWAYS_SHUTTLEMOVE BITFLAG(2) // Is this an effect that should move? -#define MOVABLE_FLAG_DEL_SHUTTLE BITFLAG(3) // Shuttle transistion will delete this. -#define MOVABLE_FLAG_WHEELED BITFLAG(4) // Movable has reduced stamina cost/speed reduction when pulled. +#define MOVABLE_FLAG_PROXMOVE BITFLAG(0) // Does this object require proximity checking in Enter()? +#define MOVABLE_FLAG_Z_INTERACT BITFLAG(1) // Should attackby and attack_hand be relayed through ladders and open spaces? +#define MOVABLE_FLAG_ALWAYS_SHUTTLEMOVE BITFLAG(2) // Is this an effect that should move? +#define MOVABLE_FLAG_DEL_SHUTTLE BITFLAG(3) // Shuttle transistion will delete this. +#define MOVABLE_FLAG_WHEELED BITFLAG(4) // Movable has reduced stamina cost/speed reduction when pulled. // Object-level flags (/obj/obj_flags) -#define OBJ_FLAG_ANCHORABLE BITFLAG(0) // This object can be stuck in place with a tool -#define OBJ_FLAG_CONDUCTIBLE BITFLAG(1) // Conducts electricity. (metal etc.) -#define OBJ_FLAG_ROTATABLE BITFLAG(2) // Can be rotated with alt-click -#define OBJ_FLAG_NOFALL BITFLAG(3) // Will prevent mobs from falling -#define OBJ_FLAG_MOVES_UNSUPPORTED BITFLAG(4) // Object moves with shuttle transition even if turf below is a background turf. -#define OBJ_FLAG_HOLLOW BITFLAG(5) // Modifies initial matter values to be lower than w_class normally sets. +#define OBJ_FLAG_ANCHORABLE BITFLAG(0) // This object can be stuck in place with a tool +#define OBJ_FLAG_CONDUCTIBLE BITFLAG(1) // Conducts electricity. (metal etc.) +#define OBJ_FLAG_ROTATABLE BITFLAG(2) // Can be rotated with alt-click +#define OBJ_FLAG_NOFALL BITFLAG(3) // Will prevent mobs from falling +#define OBJ_FLAG_MOVES_UNSUPPORTED BITFLAG(4) // Object moves with shuttle transition even if turf below is a background turf. +#define OBJ_FLAG_HOLLOW BITFLAG(5) // Modifies initial matter values to be lower than w_class normally sets. // Item-level flags (/obj/item/item_flags) -#define ITEM_FLAG_NO_BLUDGEON BITFLAG(0) // When an item has this it produces no "X has been hit by Y with Z" message with the default handler. -#define ITEM_FLAG_NO_CONTAMINATION BITFLAG(1) // Does not get contaminated. -#define ITEM_FLAG_NO_PRINT BITFLAG(2) // This object does not leave the user's prints/fibres when using it -#define ITEM_FLAG_INVALID_FOR_CHAMELEON BITFLAG(3) // Chameleon items cannot mimick this. -#define ITEM_FLAG_THICKMATERIAL BITFLAG(4) // Prevents syringes, reagent pens, and hyposprays if equiped to slot_suit or slot_head_str. -#define ITEM_FLAG_AIRTIGHT BITFLAG(5) // Functions with internals. -#define ITEM_FLAG_NOSLIP BITFLAG(6) // Prevents from slipping on wet floors, in space, etc. -#define ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT BITFLAG(7) // Blocks the effect that chemical clouds would have on a mob -- glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL) -#define ITEM_FLAG_FLEXIBLEMATERIAL BITFLAG(8) // At the moment, masks with this flag will not prevent eating even if they are covering your face. -#define ITEM_FLAG_IS_BELT BITFLAG(9) // Items that can be worn on the belt slot, even with no undersuit equipped -#define ITEM_FLAG_SILENT BITFLAG(10) // sneaky shoes -#define ITEM_FLAG_NOCUFFS BITFLAG(11) // Gloves that have this flag prevent cuffs being applied -#define ITEM_FLAG_CAN_HIDE_IN_SHOES BITFLAG(12) // Items that can be hidden in shoes that permit it -#define ITEM_FLAG_PADDED BITFLAG(13) // When set on gloves, will act like pulling punches in unarmed combat. -#define ITEM_FLAG_CAN_TAPE BITFLAG(14) //Whether the item can be be taped onto something using tape +#define ITEM_FLAG_NO_BLUDGEON BITFLAG(0) // When an item has this it produces no "X has been hit by Y with Z" message with the default handler. +#define ITEM_FLAG_NO_CONTAMINATION BITFLAG(1) // Does not get contaminated. +#define ITEM_FLAG_NO_PRINT BITFLAG(2) // This object does not leave the user's prints/fibres when using it +#define ITEM_FLAG_INVALID_FOR_CHAMELEON BITFLAG(3) // Chameleon items cannot mimick this. +#define ITEM_FLAG_THICKMATERIAL BITFLAG(4) // Prevents syringes, reagent pens, and hyposprays if equiped to slot_suit or slot_head_str. +#define ITEM_FLAG_AIRTIGHT BITFLAG(5) // Functions with internals. +#define ITEM_FLAG_NOSLIP BITFLAG(6) // Prevents from slipping on wet floors, in space, etc. +#define ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT BITFLAG(7) // Blocks the effect that chemical clouds would have on a mob -- glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL) +#define ITEM_FLAG_FLEXIBLEMATERIAL BITFLAG(8) // At the moment, masks with this flag will not prevent eating even if they are covering your face. +#define ITEM_FLAG_IS_BELT BITFLAG(9) // Items that can be worn on the belt slot, even with no undersuit equipped +#define ITEM_FLAG_SILENT BITFLAG(10) // sneaky shoes +#define ITEM_FLAG_NOCUFFS BITFLAG(11) // Gloves that have this flag prevent cuffs being applied +#define ITEM_FLAG_CAN_HIDE_IN_SHOES BITFLAG(12) // Items that can be hidden in shoes that permit it +#define ITEM_FLAG_PADDED BITFLAG(13) // When set on gloves, will act like pulling punches in unarmed combat. +#define ITEM_FLAG_CAN_TAPE BITFLAG(14) // Whether the item can be be taped onto something using tape +#define ITEM_FLAG_IS_WEAPON BITFLAG(15) // Item is considered a weapon. Currently only used for force-based worth calculation. // Flags for pass_flags (/atom/var/pass_flags) -#define PASS_FLAG_TABLE BITFLAG(0) -#define PASS_FLAG_GLASS BITFLAG(1) -#define PASS_FLAG_GRILLE BITFLAG(2) -#define PASS_FLAG_MOB BITFLAG(3) +#define PASS_FLAG_TABLE BITFLAG(0) +#define PASS_FLAG_GLASS BITFLAG(1) +#define PASS_FLAG_GRILLE BITFLAG(2) +#define PASS_FLAG_MOB BITFLAG(3) // Overmap sector flags (/obj/effect/overmap/visitable/var/sector_flags) -#define OVERMAP_SECTOR_BASE BITFLAG(0) // Whether or not this sector is a starting sector. Z levels contained in this sector are added to station_levels -#define OVERMAP_SECTOR_KNOWN BITFLAG(1) // Makes the sector show up on nav computers -#define OVERMAP_SECTOR_IN_SPACE BITFLAG(2) // If the sector can be accessed by drifting off the map edge -#define OVERMAP_SECTOR_UNTARGETABLE BITFLAG(3) // If the sector is untargetable by missiles. +#define OVERMAP_SECTOR_BASE BITFLAG(0) // Whether or not this sector is a starting sector. Z levels contained in this sector are added to station_levels +#define OVERMAP_SECTOR_KNOWN BITFLAG(1) // Makes the sector show up on nav computers +#define OVERMAP_SECTOR_IN_SPACE BITFLAG(2) // If the sector can be accessed by drifting off the map edge +#define OVERMAP_SECTOR_UNTARGETABLE BITFLAG(3) // If the sector is untargetable by missiles. // Flags for reagent presentation (/obj/item/chems/var/presentation_flags) -#define PRESENTATION_FLAG_NAME BITFLAG(0) // This chems subtype presents the name of its main reagent/cocktail. -#define PRESENTATION_FLAG_DESC BITFLAG(1) // This chems subtype presents the description of its main reagent/cocktail. +#define PRESENTATION_FLAG_NAME BITFLAG(0) // This chems subtype presents the name of its main reagent/cocktail. +#define PRESENTATION_FLAG_DESC BITFLAG(1) // This chems subtype presents the description of its main reagent/cocktail. // Decl-level flags (/decl/var/decl_flags) -#define DECL_FLAG_ALLOW_ABSTRACT_INIT BITFLAG(0) // Abstract subtypes without this set will CRASH() if fetched with GET_DECL(). -#define DECL_FLAG_MANDATORY_UID BITFLAG(1) // Requires uid to be non-null. \ No newline at end of file +#define DECL_FLAG_ALLOW_ABSTRACT_INIT BITFLAG(0) // Abstract subtypes without this set will CRASH() if fetched with GET_DECL(). +#define DECL_FLAG_MANDATORY_UID BITFLAG(1) // Requires uid to be non-null. \ No newline at end of file diff --git a/code/__defines/fluids.dm b/code/__defines/fluids.dm index dc6827b2149..6cbd4a3da36 100644 --- a/code/__defines/fluids.dm +++ b/code/__defines/fluids.dm @@ -1,5 +1,5 @@ #define FLUID_QDEL_POINT 1 // Depth a fluid begins self-deleting -#define FLUID_MINIMUM_TRANSFER 10 // Minimum amount that a flowing fluid will transfer from one turf to another. +#define FLUID_MINIMUM_TRANSFER 5 // Minimum amount that a flowing fluid will transfer from one turf to another. #define FLUID_PUDDLE 25 // Minimum total depth that a fluid needs before it will start spreading. #define FLUID_SHALLOW 200 // Depth shallow icon is used #define FLUID_OVER_MOB_HEAD 300 // Depth icon layers over mobs. diff --git a/code/__defines/holomap.dm b/code/__defines/holomap.dm index 76517fb8f11..d82b18c02ab 100644 --- a/code/__defines/holomap.dm +++ b/code/__defines/holomap.dm @@ -29,9 +29,9 @@ #define HOLOMAP_AREACOLOR_LIFTS null // Handy defines to lookup the pixel offsets for holomap -// Currently set to 0, left here in case of need for per map offsets -#define HOLOMAP_PIXEL_OFFSET_X (0) -#define HOLOMAP_PIXEL_OFFSET_Y (0) +// world.maxx/y should always be greater than or equal to level_max_width/level_max_height +#define HOLOMAP_PIXEL_OFFSET_X(zlevel) (round((world.maxx - SSmapping.levels_by_z[zlevel]?.level_max_width)/2)) +#define HOLOMAP_PIXEL_OFFSET_Y(zlevel) (round((world.maxy - SSmapping.levels_by_z[zlevel]?.level_max_height)/2)) #define HOLOMAP_LEGEND_X 96 #define HOLOMAP_LEGEND_Y 156 \ No newline at end of file diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index a151c893876..6cb6f626c75 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -183,6 +183,8 @@ #define BP_R_LEG "r_leg" #define BP_L_HAND "l_hand" #define BP_R_HAND "r_hand" +#define BP_L_HAND_UPPER "l_u_hand" +#define BP_R_HAND_UPPER "r_u_hand" #define BP_L_ARM "l_arm" #define BP_R_ARM "r_arm" #define BP_HEAD "head" @@ -193,8 +195,38 @@ // Other inventory-related slots (also organs). #define BP_MOUTH "mouth" -var/global/list/all_limb_tags = list(BP_CHEST, BP_GROIN, BP_TAIL, BP_HEAD, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT) -var/global/list/all_limb_tags_by_depth = list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TAIL, BP_CHEST) +var/global/list/all_limb_tags = list( + BP_CHEST, + BP_GROIN, + BP_TAIL, + BP_HEAD, + BP_L_ARM, + BP_R_ARM, + BP_L_HAND, + BP_R_HAND, + BP_L_HAND_UPPER, + BP_R_HAND_UPPER, + BP_L_LEG, + BP_R_LEG, + BP_L_FOOT, + BP_R_FOOT +) +var/global/list/all_limb_tags_by_depth = list( + BP_HEAD, + BP_L_HAND, + BP_L_HAND_UPPER, + BP_R_HAND, + BP_R_HAND_UPPER, + BP_L_ARM, + BP_R_ARM, + BP_L_FOOT, + BP_R_FOOT, + BP_L_LEG, + BP_R_LEG, + BP_GROIN, + BP_TAIL, + BP_CHEST +) var/global/list/default_onmob_icons = list( BP_L_HAND = 'icons/mob/onmob/items/lefthand.dmi', @@ -205,6 +237,8 @@ var/global/list/default_onmob_icons = list( var/global/list/all_inventory_slots = list( BP_L_HAND, BP_R_HAND, + BP_L_HAND_UPPER, + BP_R_HAND_UPPER, BP_MOUTH, slot_w_uniform_str, slot_head_str, diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index 0c36d358f62..cddc481116b 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -176,4 +176,5 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define PART_SCANNER /obj/item/stock_parts/computer/scanner // One of several optional scanner attachments. #define PART_D_SLOT /obj/item/stock_parts/computer/drive_slot // Portable drive slot. #define PART_MSTICK /obj/item/stock_parts/computer/charge_stick_slot // Charge-slot component for transactions /w charge sticks. +#define PART_DSKSLOT /obj/item/stock_parts/computer/data_disk_drive // Temporary modcomp version of the disk reader component. #define PART_MPRINTER /obj/item/stock_parts/computer/money_printer \ No newline at end of file diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 999f4762c6e..a458bf40693 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -22,6 +22,7 @@ #define LEVEL_EDGE_CON 3 // Invisibility constants. +#define INVISIBILITY_NONE 0 #define INVISIBILITY_LIGHTING 20 #define INVISIBILITY_LEVEL_ONE 35 #define INVISIBILITY_LEVEL_TWO 45 @@ -304,4 +305,20 @@ #define ITEM_HEALTH_NO_DAMAGE -1 ///Formats into a readable string neatly an exception's details. -#define EXCEPTION_TEXT(E) "'[E.name]' ('[E.type]'): '[E.file]':[E.line][length(E.desc)? ":\n'[E.desc]'" : ""]" \ No newline at end of file +#define EXCEPTION_TEXT(E) "'[E.name]' ('[E.type]'): '[E.file]':[E.line][length(E.desc)? ":\n'[E.desc]'" : ""]" +/// Causes the atom to ignore clicks, hovers, etc. +#define MOUSE_OPACITY_UNCLICKABLE 0 +/// Causes the atom to catch clicks, hovers, etc. +#define MOUSE_OPACITY_NORMAL 1 +/// Causes the atom to catch clicks, hovers, etc, taking priority over NORMAL for a shared pointer target. +#define MOUSE_OPACITY_PRIORITY 2 + +// Set on many base types. +#define DEFAULT_APPEARANCE_FLAGS (PIXEL_SCALE) + +#define LEVEL_BELOW_PLATING 1 +#define LEVEL_ABOVE_PLATING 2 + +// Defines for fluorescence (/atom/var/fluorescent) +#define FLUORESCENT_GLOWS 1 // Glows when under flourescent light +#define FLUORESCENT_GLOWING 2 // Currently glowing due to flourescent light diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 2a480397054..1e00a6617af 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -230,6 +230,9 @@ #define TASTE_DULL 0.5 //anything below 30% #define TASTE_NUMB 0.1 //anything below 150% +// One 'unit' of taste sensitivity probability, used in mob/living/carbon/proc/ingest +#define TASTE_DEGREE_PROB 15 + //Used by show_message() and emotes #define VISIBLE_MESSAGE 1 #define AUDIBLE_MESSAGE 2 @@ -258,14 +261,6 @@ #define SPECIES_ALIEN "Humanoid" #define SPECIES_GOLEM "Golem" -#define BODY_FLAG_EXCLUDE BITFLAG(0) -#define BODY_FLAG_HUMANOID BITFLAG(1) -#define BODY_FLAG_MONKEY BITFLAG(2) - -#define BODYTYPE_HUMANOID "humanoid body" -#define BODYTYPE_OTHER "alien body" -#define BODYTYPE_MONKEY "small humanoid body" - #define SURGERY_CLOSED 0 #define SURGERY_OPEN 1 #define SURGERY_RETRACTED 2 @@ -307,13 +302,27 @@ #define MARKING_TARGET_HAIR 1 // Draw a /decl/sprite_accessory/marking to the mob's hair, eg. ears & horns #define DEXTERITY_NONE 0 -#define DEXTERITY_SIMPLE_MACHINES 1 -#define DEXTERITY_KEYBOARDS 2 -#define DEXTERITY_TOUCHSCREENS 3 -#define DEXTERITY_GRIP 4 -#define DEXTERITY_WEAPONS 5 -#define DEXTERITY_COMPLEX_TOOLS 6 -#define DEXTERITY_FULL 7 +#define DEXTERITY_SIMPLE_MACHINES BITFLAG(0) +#define DEXTERITY_HOLD_ITEM BITFLAG(1) +#define DEXTERITY_EQUIP_ITEM BITFLAG(2) +#define DEXTERITY_KEYBOARDS BITFLAG(3) +#define DEXTERITY_TOUCHSCREENS BITFLAG(4) +// TODO: actually get grab code to check this one. +#define DEXTERITY_GRAPPLE BITFLAG(5) +#define DEXTERITY_WEAPONS BITFLAG(6) +#define DEXTERITY_COMPLEX_TOOLS BITFLAG(7) +#define DEXTERITY_BASE (DEXTERITY_SIMPLE_MACHINES|DEXTERITY_HOLD_ITEM|DEXTERITY_EQUIP_ITEM) +#define DEXTERITY_FULL (DEXTERITY_BASE|DEXTERITY_KEYBOARDS|DEXTERITY_TOUCHSCREENS|DEXTERITY_GRAPPLE|DEXTERITY_WEAPONS|DEXTERITY_COMPLEX_TOOLS) + +// List of dexterity flags ordered by 'complexity' for use in brainloss dex malus checking. +var/global/list/dexterity_levels = list( + "[DEXTERITY_COMPLEX_TOOLS]", + "[DEXTERITY_WEAPONS]", + "[DEXTERITY_GRAPPLE]", + "[DEXTERITY_TOUCHSCREENS]", + "[DEXTERITY_KEYBOARDS]", + "[DEXTERITY_BASE]" +) // used in /mob/living/carbon/human/can_inject, and by various callers of that proc #define CAN_INJECT 1 @@ -335,4 +344,38 @@ #define MOB_ICON_HAS_SLEEP_STATE BITFLAG(3) #define MOB_ICON_HAS_GIB_STATE BITFLAG(4) #define MOB_ICON_HAS_PARALYZED_STATE BITFLAG(5) -#define NEUTER_ANIMATE "animate singular neutral" \ No newline at end of file +#define NEUTER_ANIMATE "animate singular neutral" + +// Equipment Overlays Indices // +#define HO_MUTATIONS_LAYER 1 +#define HO_SKIN_LAYER 2 +#define HO_DAMAGE_LAYER 3 +#define HO_SURGERY_LAYER 4 //bs12 specific. +#define HO_UNDERWEAR_LAYER 5 +#define HO_UNIFORM_LAYER 6 +#define HO_ID_LAYER 7 +#define HO_SHOES_LAYER 8 +#define HO_GLOVES_LAYER 9 +#define HO_BELT_LAYER 10 +#define HO_SUIT_LAYER 11 +#define HO_GLASSES_LAYER 12 +#define HO_BELT_LAYER_ALT 13 +#define HO_SUIT_STORE_LAYER 14 +#define HO_BACK_LAYER 15 +#define HO_TAIL_LAYER 16 //bs12 specific. this hack is probably gonna come back to haunt me +#define HO_HAIR_LAYER 17 //TODO: make part of head layer? +#define HO_GOGGLES_LAYER 18 +#define HO_L_EAR_LAYER 19 +#define HO_R_EAR_LAYER 20 +#define HO_FACEMASK_LAYER 21 +#define HO_HEAD_LAYER 22 +#define HO_COLLAR_LAYER 23 +#define HO_HANDCUFF_LAYER 24 +#define HO_INHAND_LAYER 25 +#define HO_FIRE_LAYER 26 //If you're on fire +#define TOTAL_OVER_LAYERS 26 +////////////////////////////////// + +// Underlay defines; vestigal implementation currently. +#define HU_TAIL_LAYER 1 +#define TOTAL_UNDER_LAYERS 1 \ No newline at end of file diff --git a/code/__defines/overmap.dm b/code/__defines/overmap.dm index 019c716fe12..11b0231b3d8 100644 --- a/code/__defines/overmap.dm +++ b/code/__defines/overmap.dm @@ -18,13 +18,14 @@ #define KM_OVERMAP_RATE 100 #define SHIP_MOVE_RESOLUTION 0.001 #define MOVING(speed, min_speed) (abs(speed) >= min_speed) -#define SANITIZE_SPEED(speed) (SIGN(speed) * clamp(abs(speed), 0, max_speed)) +// You can approach, but never reach, max_speed. +#define SANITIZE_SPEED(speed) (SIGN(speed) * clamp(NONUNIT_FLOOR(abs(speed), SHIP_MOVE_RESOLUTION), 0, max_speed - SHIP_MOVE_RESOLUTION)) #define CHANGE_SPEED_BY(speed_var, v_diff, min_speed) \ v_diff = SANITIZE_SPEED(v_diff);\ if(!MOVING(speed_var + v_diff, min_speed)) \ {speed_var = 0};\ else \ - {speed_var = round(SANITIZE_SPEED((speed_var + v_diff) / (1 + speed_var * v_diff / (max_speed ** 2))), SHIP_MOVE_RESOLUTION)} + {speed_var = SANITIZE_SPEED((speed_var + v_diff) / (1 + speed_var * v_diff / (max_speed ** 2)))} // Uses Lorentzian dynamics to avoid going too fast. #define SENSOR_COEFFICENT 1000 diff --git a/code/__defines/research.dm b/code/__defines/research.dm index 5c36a627958..59f6fad0e74 100644 --- a/code/__defines/research.dm +++ b/code/__defines/research.dm @@ -9,6 +9,7 @@ #define REAGENT_UNITS_PER_MATERIAL_SHEET 20 #define REAGENT_UNITS_PER_GAS_MOLE 10 #define MATERIAL_UNITS_TO_REAGENTS_UNITS(AMT) (AMT * REAGENT_UNITS_PER_MATERIAL_UNIT) +#define MOLES_PER_MATERIAL_UNIT(AMT) round(MATERIAL_UNITS_TO_REAGENTS_UNITS(AMT) / REAGENT_UNITS_PER_GAS_MOLE) #define MATTER_AMOUNT_PRIMARY SHEET_MATERIAL_AMOUNT #define MATTER_AMOUNT_SECONDARY (MATTER_AMOUNT_PRIMARY * 0.75) diff --git a/code/__defines/spawn.dm b/code/__defines/spawn.dm new file mode 100644 index 00000000000..c576e4f0ac4 --- /dev/null +++ b/code/__defines/spawn.dm @@ -0,0 +1,8 @@ +/// Allows the spawn point to be used for observers spawning. +#define SPAWN_FLAG_GHOSTS_CAN_SPAWN BITFLAG(0) +/// Allows admin prison releases to use this spawn point. +#define SPAWN_FLAG_PRISONERS_CAN_SPAWN BITFLAG(1) +/// Allows general job latejoining to use this spawn point. +#define SPAWN_FLAG_JOBS_CAN_SPAWN BITFLAG(2) +/// Allows persistence decls (currently just bookcases) to use this spawn point. +#define SPAWN_FLAG_PERSISTENCE_CAN_SPAWN BITFLAG(3) \ No newline at end of file diff --git a/code/__defines/species.dm b/code/__defines/species.dm index 75ab5d81503..0ff09486031 100644 --- a/code/__defines/species.dm +++ b/code/__defines/species.dm @@ -1,17 +1,13 @@ // Species flags. #define SPECIES_FLAG_NO_MINOR_CUT BITFLAG(0) // Can step on broken glass with no ill-effects. Either thick skin, cut resistant (slimes) or incorporeal (shadows) #define SPECIES_FLAG_IS_PLANT BITFLAG(1) // Is a treeperson. -#define SPECIES_FLAG_NO_SCAN BITFLAG(2) // Cannot be scanned in a DNA machine/genome-stolen. -#define SPECIES_FLAG_NO_PAIN BITFLAG(3) // Cannot suffer halloss/recieves deceptive health indicator. -#define SPECIES_FLAG_NO_SLIP BITFLAG(4) // Cannot fall over. -#define SPECIES_FLAG_NO_POISON BITFLAG(5) // Cannot not suffer toxloss. -#define SPECIES_FLAG_NO_EMBED BITFLAG(6) // Can step on broken glass with no ill-effects and cannot have shrapnel embedded in it. -#define SPECIES_FLAG_NO_TANGLE BITFLAG(7) // This species wont get tangled up in weeds -#define SPECIES_FLAG_NO_BLOCK BITFLAG(8) // Unable to block or defend itself from attackers. -#define SPECIES_FLAG_NEED_DIRECT_ABSORB BITFLAG(9) // This species can only have their DNA taken by direct absorption. -#define SPECIES_FLAG_LOW_GRAV_ADAPTED BITFLAG(10) // This species is used to lower than standard gravity, affecting stamina in high-grav -#define SPECIES_FLAG_CRYSTALLINE BITFLAG(11) // This species is made of crystalline material. Replaces var/is_crystalline. -#define SPECIES_FLAG_SYNTHETIC BITFLAG(12) // This species is synthetic/robotic and spawns with prosthetic limbs. +#define SPECIES_FLAG_NO_SLIP BITFLAG(2) // Cannot fall over. +#define SPECIES_FLAG_NO_POISON BITFLAG(3) // Cannot not suffer toxloss. +#define SPECIES_FLAG_NO_EMBED BITFLAG(4) // Can step on broken glass with no ill-effects and cannot have shrapnel embedded in it. +#define SPECIES_FLAG_NO_TANGLE BITFLAG(5) // This species wont get tangled up in weeds +#define SPECIES_FLAG_NO_BLOCK BITFLAG(6) // Unable to block or defend itself from attackers. +#define SPECIES_FLAG_NEED_DIRECT_ABSORB BITFLAG(7) // This species can only have their DNA taken by direct absorption. +#define SPECIES_FLAG_LOW_GRAV_ADAPTED BITFLAG(8) // This species is used to lower than standard gravity, affecting stamina in high-grav // Species spawn flags #define SPECIES_IS_WHITELISTED BITFLAG(0) // Must be whitelisted to play. @@ -19,19 +15,6 @@ #define SPECIES_CAN_JOIN BITFLAG(2) // Species is selectable in chargen. #define SPECIES_NO_ROBOTIC_INTERNAL_ORGANS BITFLAG(3) // Species cannot start with robotic organs or have them attached. -// Species appearance flags -#define HAS_SKIN_TONE_NORMAL BITFLAG(0) // Skin tone selectable in chargen for baseline humans (0-220) -#define HAS_SKIN_COLOR BITFLAG(1) // Skin colour selectable in chargen. (RGB) -#define HAS_LIPS BITFLAG(2) // Lips are drawn onto the mob icon. (lipstick) -#define HAS_UNDERWEAR BITFLAG(3) // Underwear is drawn onto the mob icon. -#define HAS_EYE_COLOR BITFLAG(4) // Eye colour selectable in chargen. (RGB) -#define HAS_HAIR_COLOR BITFLAG(5) // Hair colour selectable in chargen. (RGB) -#define RADIATION_GLOWS BITFLAG(6) // Radiation causes this character to glow. -#define HAS_SKIN_TONE_GRAV BITFLAG(7) // Skin tone selectable in chargen for grav-adapted humans (0-100) -#define HAS_SKIN_TONE_SPCR BITFLAG(8) // Skin tone selectable in chargen for spacer humans (0-165) -#define HAS_SKIN_TONE_TRITON BITFLAG(9) -#define HAS_A_SKIN_TONE (HAS_SKIN_TONE_NORMAL | HAS_SKIN_TONE_GRAV | HAS_SKIN_TONE_SPCR | HAS_SKIN_TONE_TRITON) // Species has a numeric skintone - // Skin Defines #define SKIN_NORMAL 0 #define SKIN_THREAT 1 diff --git a/code/__defines/subsystem-priority.dm b/code/__defines/subsystem-priority.dm index 52d3ebfcc92..abfb4875cb3 100644 --- a/code/__defines/subsystem-priority.dm +++ b/code/__defines/subsystem-priority.dm @@ -29,6 +29,7 @@ #define SS_PRIORITY_RADIATION 20 // Radiation processing and cache updates. #define SS_PRIORITY_OPEN_SPACE 20 // Open turf updates. #define SS_PRIORITY_AIRFLOW 15 // Object movement from ZAS airflow. +#define SS_PRIORITY_FLUIDS 11 // Liquid flows. #define SS_PRIORITY_VOTE 10 // Vote management. #define SS_PRIORITY_INACTIVITY 10 // Idle kicking. #define SS_PRIORITY_SUPPLY 10 // Supply point accumulation. diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm index c828786379a..2747a4a6987 100644 --- a/code/__defines/turfs.dm +++ b/code/__defines/turfs.dm @@ -23,9 +23,9 @@ //Here are a few macros to help with people always forgetting to round the coordinates somewhere, and forgetting that not everything automatically rounds decimals. ///Helper macro for the x coordinate of the turf at the center of the world. Handles rounding. -#define WORLD_CENTER_X round(world.maxx / 2) +#define WORLD_CENTER_X CEILING((1 + world.maxx) / 2) ///Helper macro for the y coordinate of the turf at the center of the world. Handles rounding. -#define WORLD_CENTER_Y round(world.maxy / 2) +#define WORLD_CENTER_Y CEILING((1 + world.maxy) / 2) ///Helper macro for getting the center turf on a given z-level. Handles rounding. #define WORLD_CENTER_TURF(Z) locate(WORLD_CENTER_X, WORLD_CENTER_Y, Z) ///Helper macro to check if a position is within the world's bounds. diff --git a/code/_global_vars/lists/clothing.dm b/code/_global_vars/lists/clothing.dm index 9087a3f054c..a65b597aefc 100644 --- a/code/_global_vars/lists/clothing.dm +++ b/code/_global_vars/lists/clothing.dm @@ -28,67 +28,6 @@ var/global/list/airtight_slots = list( slot_head_str ) -var/global/list/equipped_slots = list( - slot_belt_str, - slot_l_ear_str, - slot_r_ear_str, - slot_glasses_str, - slot_gloves_str, - slot_head_str, - slot_shoes_str, - slot_wear_id_str, - slot_wear_suit_str, - slot_w_uniform_str -) - -//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. -var/global/list/slot_equipment_priority = list( - slot_back_str, - slot_wear_id_str, - slot_w_uniform_str, - slot_wear_suit_str, - slot_wear_mask_str, - slot_head_str, - slot_shoes_str, - slot_gloves_str, - slot_l_ear_str, - slot_r_ear_str, - slot_glasses_str, - slot_belt_str, - slot_s_store_str, - slot_tie_str, - slot_l_store_str, - slot_r_store_str -) - -var/global/list/carried_slots = list( - slot_l_store_str, - slot_r_store_str, - slot_handcuffed_str, - slot_s_store_str -) - -var/global/list/persistent_inventory_slots = list( - slot_s_store_str, - slot_wear_id_str, - slot_belt_str, - slot_back_str, - slot_l_store_str, - slot_r_store_str -) - -var/global/list/hidden_inventory_slots = list( - slot_head_str, - slot_shoes_str, - slot_l_ear_str, - slot_r_ear_str, - slot_gloves_str, - slot_glasses_str, - slot_w_uniform_str, - slot_wear_suit_str, - slot_wear_mask_str -) - var/global/list/abstract_inventory_slots = list( slot_in_backpack_str, slot_tie_str, diff --git a/code/_global_vars/lists/objects.dm b/code/_global_vars/lists/objects.dm index 1f9f606d7b3..3d70d223a0b 100644 --- a/code/_global_vars/lists/objects.dm +++ b/code/_global_vars/lists/objects.dm @@ -4,7 +4,6 @@ var/global/list/jani_hud_users = list() var/global/list/hud_icon_reference = list() var/global/list/listening_objects = list() // List of objects that need to be able to hear, used to avoid recursive searching through contents. var/global/list/global_mutations = list() // List of hidden mutation things. -var/global/list/reg_dna = list() var/global/list/global_map = list() var/global/host = null //only here until check @ code\modules\ghosttrap\trap.dm:112 is fixed diff --git a/code/_helpers/cmp.dm b/code/_helpers/cmp.dm index 2528da61c1c..1e9f0b6a0df 100644 --- a/code/_helpers/cmp.dm +++ b/code/_helpers/cmp.dm @@ -129,4 +129,10 @@ return A.sort_priority - B.sort_priority /proc/cmp_submap_asc(var/datum/submap/A, var/datum/submap/B) - return A.archetype.sort_priority - B.archetype.sort_priority \ No newline at end of file + return A.archetype.sort_priority - B.archetype.sort_priority + +/proc/cmp_gripper_asc(datum/inventory_slot/gripper/a, datum/inventory_slot/gripper/b) + return a.hand_sort_priority - b.hand_sort_priority + +/proc/cmp_inventory_slot_desc(datum/inventory_slot/a, datum/inventory_slot/b) + return b.quick_equip_priority - a.quick_equip_priority diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 372c9fca931..a9a0839a4af 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -79,16 +79,22 @@ var/global/list/string_slot_flags = list( return 1 // This is all placeholder procs for an eventual PR to change them to use decls. -var/global/list/all_species = list() -var/global/list/playable_species = list() // A list of ALL playable species, whitelisted, latejoin or otherwise. +var/global/list/all_species +var/global/list/playable_species // A list of ALL playable species, whitelisted, latejoin or otherwise. +var/global/list/all_bodytypes = list() +var/global/list/bodytype_species_pairs = list() // A list of bodytypes -> species, used for mainly unit testing. /proc/build_species_lists() - global.all_species.Cut() - global.playable_species.Cut() + if(global.all_species) + return + global.all_species = list() + global.playable_species = list() var/list/species_decls = decls_repository.get_decls_of_subtype(/decl/species) for(var/species_type in species_decls) var/decl/species/species = species_decls[species_type] if(species.name) global.all_species[species.name] = species + for(var/decl/bodytype/bodytype in species.available_bodytypes) + global.bodytype_species_pairs[GET_DECL(bodytype)] = species if(!(species.spawn_flags & SPECIES_IS_RESTRICTED)) global.playable_species += species.name if(global.using_map.default_species) @@ -103,3 +109,9 @@ var/global/list/playable_species = list() // A list of ALL playable species, whi /proc/get_playable_species() build_species_lists() . = global.playable_species +/proc/get_all_bodytypes() + build_species_lists() + . = global.all_bodytypes +/proc/get_bodytype_species_pairs() + build_species_lists() + . = global.bodytype_species_pairs \ No newline at end of file diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 0826de1981c..7c29332f3d4 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -227,7 +227,7 @@ world Shift(EAST,1) // Multiply all alpha values by this float -/icon/proc/ChangeOpacity(opacity = 1.0) +/icon/proc/ChangeOpacity(opacity = TRUE) MapColors(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,opacity, 0,0,0,0) // Convert to grayscale @@ -900,16 +900,20 @@ The _flatIcons list is a cache for generated icon files. // - Collecting list of atoms to render - var/list/render_atoms = list() + // This is a workaround for the lighting planemaster not being factored in. + // If it's ever removed, or if a better way is found, please replace this. + var/list/render_lighting = list() for(var/turf/T as anything in render_turfs) render_atoms.Add(T) for(var/atom/A as anything in T) - // In some cases we want to filter lighting overlays. - if(istype(A, /atom/movable/lighting_overlay) && show_lighting) - render_atoms.Add(A) + // We need to handle lighting separately if we're including it, and if not, skip it entirely. + if(istype(A, /atom/movable/lighting_overlay)) + if(show_lighting) + render_lighting.Add(A) continue - if(!A.alpha || A.invisibility) + if(!A.alpha || (A.invisibility > SEE_INVISIBLE_LIVING)) continue render_atoms.Add(A) @@ -932,4 +936,12 @@ The _flatIcons list is a cache for generated icon files. var/y_offset = (A.y - target_y) * world.icon_size capture.Blend(atom_icon, blendMode2iconMode(A.blend_mode), A.pixel_x + x_offset, A.pixel_y + y_offset) + // TODO: for custom exposure/flash/etc simulation on the camera, you could set the alpha on the overlay copy icons here + if(show_lighting) + for(var/atom/movable/lighting_overlay/lighting_overlay as anything in render_lighting) + var/icon/lighting_overlay_icon = getFlatIcon(lighting_overlay) + var/x_offset = (lighting_overlay.x - target_x) * world.icon_size + var/y_offset = (lighting_overlay.y - target_y) * world.icon_size + capture.Blend(lighting_overlay_icon, ICON_MULTIPLY, lighting_overlay.pixel_x + x_offset, lighting_overlay.pixel_y + y_offset) + return capture diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm index bf708dc5fdd..75f6b2f4433 100644 --- a/code/_helpers/lists.dm +++ b/code/_helpers/lists.dm @@ -76,18 +76,22 @@ return counting_english_list(input, output_icons, determiners, nothing_text, and_text, comma_text, final_comma_text) //Checks for specific types in a list -/proc/is_type_in_list(var/atom/A, var/list/L) - for(var/type in L) - if(istype(A, type)) - return 1 - return 0 +/proc/is_type_in_list(datum/thing, list/type_list) + if(!length(type_list) || !istype(thing)) + return FALSE + for(var/check_type in type_list) + if(istype(thing, check_type)) + return TRUE + return FALSE //Checks for specific paths in a list -/proc/is_path_in_list(var/path, var/list/L) - for(var/type in L) - if(ispath(path, type)) - return 1 - return 0 +/proc/is_path_in_list(var/check_path, list/type_list) + if(!length(type_list) || !ispath(check_path)) + return FALSE + for(var/check_type in type_list) + if(ispath(check_path, check_type)) + return TRUE + return FALSE //returns a new list with only atoms that are in typecache L /proc/typecache_filter_list(list/atoms, list/typecache) @@ -797,7 +801,7 @@ var/global/list/json_cache = list() else if(decoded) return decoded catch(var/exception/e) - log_error("Exception during JSON decoding ([json_to_decode]): [e]") + log_error("Exception during JSON decoding ([json_to_decode]): [EXCEPTION_TEXT(e)]") return list() /proc/load_text_from_directory(var/directory, var/expected_extension = ".txt", var/recursive = TRUE) @@ -855,7 +859,7 @@ var/global/list/json_cache = list() loaded_files[checkfile] = safe_file2text(checkfile) item_count++ catch(var/exception/e) - PRINT_STACK_TRACE("Exception loading [checkfile]: [e] on [e.file]:[e.line]") + PRINT_STACK_TRACE("Exception loading [checkfile]: [EXCEPTION_TEXT(e)]") // Return a manifest for further processing. return list( diff --git a/code/_helpers/maths.dm b/code/_helpers/maths.dm index 050a150f865..91510342d34 100644 --- a/code/_helpers/maths.dm +++ b/code/_helpers/maths.dm @@ -137,12 +137,12 @@ mid = (mid - start) < 0 ? mid - start + 360 : mid - start return mid <= end -#define POLAR_TO_CART_X(R,T) ((R) * sin(T)) -#define POLAR_TO_CART_Y(R,T) ((R) * cos(T)) +#define POLAR_TO_BYOND_X(R,T) ((R) * sin(T)) +#define POLAR_TO_BYOND_Y(R,T) ((R) * cos(T)) /proc/polar2turf(x, y, z, angle, distance) - var/x_offset = POLAR_TO_CART_X(distance, angle) - var/y_offset = POLAR_TO_CART_Y(distance, angle) + var/x_offset = POLAR_TO_BYOND_X(distance, angle) + var/y_offset = POLAR_TO_BYOND_Y(distance, angle) return locate(CEILING(x + x_offset), CEILING(y + y_offset), z) /proc/get_turf_from_angle(x, y, z, angle, ideal_distance) diff --git a/code/_helpers/matrices.dm b/code/_helpers/matrices.dm index 7eaf04da437..e705300c4f3 100644 --- a/code/_helpers/matrices.dm +++ b/code/_helpers/matrices.dm @@ -101,6 +101,25 @@ return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0) +#define LUMR 0.2126 +#define LUMG 0.7152 +#define LUMB 0.0722 +/proc/legacy_color_saturation(value) + if(value == 0) + return + value = clamp(value, -100, 100) + if(value > 0) + value *= 3 + var/x = 1 + value / 100 + var/inv = 1 - x + var/R = LUMR * inv + var/G = LUMG * inv + var/B = LUMB * inv + return list(R + x,R,R, G,G + x,G, B,B,B + x) +#undef LUMR +#undef LUMG +#undef LUMB + /// Changes distance colors have from rgb(127,127,127) grey /// * 1 is identity. 0 makes everything grey >1 blows out colors and greys /proc/color_matrix_contrast(value) diff --git a/code/_helpers/medical_scans.dm b/code/_helpers/medical_scans.dm index c2ee562d36b..38e5f245d2d 100644 --- a/code/_helpers/medical_scans.dm +++ b/code/_helpers/medical_scans.dm @@ -25,7 +25,7 @@ else if(H.status_flags & FAKEDEATH) pulse_result = 0 else - pulse_result = H.get_pulse(GETPULSE_TOOL) + pulse_result = H.get_pulse_as_string(GETPULSE_TOOL) else pulse_result = -1 @@ -84,9 +84,9 @@ scan["internal_organs"] += list(O) scan["missing_organs"] = list() - - for(var/organ_name in H.species.has_organ) - if(!locate(H.species.has_organ[organ_name]) in internal_organs) + var/decl/bodytype/root_bodytype = get_bodytype() + for(var/organ_name in root_bodytype.has_organ) + if(!GET_INTERNAL_ORGAN(H, organ_name)) scan["missing_organs"] += organ_name if(H.sdisabilities & BLINDED) scan["blind"] = TRUE @@ -332,7 +332,7 @@ else dat += subdat for(var/organ_name in scan["missing_organs"]) - if(organ_name != "appendix") + if(organ_name != BP_APPENDIX) dat += "No [organ_name] detected." else dat += "No [organ_name] detected" diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 8f28e6d132b..9d714318131 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -7,16 +7,6 @@ if(M) LAZYDISTINCTADD(., M) -/proc/random_hair_style(gender, species) - var/decl/species/mob_species = get_species_by_key(species || global.using_map.default_species) - var/list/valid_styles = mob_species?.get_hair_style_types(gender) - return length(valid_styles) ? pick(valid_styles) : /decl/sprite_accessory/hair/bald - -/proc/random_facial_hair_style(gender, var/species) - var/decl/species/mob_species = get_species_by_key(species || global.using_map.default_species) - var/list/valid_styles = mob_species?.get_facial_hair_style_types(gender) - return length(valid_styles) ? pick(valid_styles) : /decl/sprite_accessory/facial_hair/shaved - /proc/random_name(gender, species) if(species) var/decl/species/current_species = get_species_by_key(species) @@ -26,17 +16,17 @@ return current_culture.get_random_name(null, gender) return capitalize(pick(gender == FEMALE ? global.first_names_female : global.first_names_male)) + " " + capitalize(pick(global.last_names)) -/proc/random_skin_tone(var/decl/species/current_species) - var/species_tone = current_species ? 35 - current_species.max_skin_tone() : -185 +/proc/random_skin_tone(var/decl/bodytype/current_bodytype) + var/bodytype_tone = current_bodytype ? 35 - current_bodytype.max_skin_tone() : -185 switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino")) if("caucasian") . = -10 if("afroamerican") . = -115 if("african") . = -165 if("latino") . = -55 if("albino") . = 34 - else . = rand(species_tone,34) + else . = rand(bodytype_tone,34) - return min(max(. + rand(-25, 25), species_tone), 34) + return min(max(. + rand(-25, 25), bodytype_tone), 34) /proc/skintone2racedescription(tone) switch (tone) @@ -61,9 +51,9 @@ /proc/is_robot_module(var/obj/item/thing) if(!thing) return FALSE - if(istype(thing.loc, /mob/living/exosuit)) + if(isexosuit(thing.loc)) return FALSE - if(!istype(thing.loc, /mob/living/silicon/robot)) + if(!isrobot(thing.loc)) return FALSE var/mob/living/silicon/robot/R = thing.loc return (thing in R.module.equipment) @@ -242,7 +232,7 @@ if((M.stat != DEAD) || (!M.client)) continue //They need a brain! - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.should_have_organ(BP_BRAIN) && !H.has_brain()) continue diff --git a/code/_helpers/names.dm b/code/_helpers/names.dm index 0e50a77eac0..4146cdc9e44 100644 --- a/code/_helpers/names.dm +++ b/code/_helpers/names.dm @@ -138,9 +138,11 @@ var/global/syndicate_name = null return name -//Traitors and traitor silicons will get these. Revs will not. -var/global/syndicate_code_phrase//Code phrase for traitors. -var/global/syndicate_code_response//Code response for traitors. +// Traitors and traitor silicons will get these. Revs will not. +/// Code phrase for traitors. +var/global/syndicate_code_phrase +/// Code response for traitors. +var/global/syndicate_code_response /* Should be expanded. diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm index 608a65e36e9..8c47ac8734b 100644 --- a/code/_helpers/type2type.dm +++ b/code/_helpers/type2type.dm @@ -254,4 +254,4 @@ error("File not found ([filename])") catch(var/exception/E) if(error_on_invalid_return) - error("Exception when loading file as string: [E]") + error("Exception when loading file as string: [EXCEPTION_TEXT(E)]") diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 2dc73e09440..df4fcaf4d26 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -38,7 +38,7 @@ .+=360 //Returns location. Returns null if no location was found. -/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = 0, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) +/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no). Random error in tile placement x, error in tile placement y, and block offset. @@ -322,7 +322,7 @@ Turf and target are seperate in case you want to teleport some distance from a t var/select = null var/list/borgs = list() for (var/mob/living/silicon/robot/A in global.player_list) - if (A.stat == 2 || A.connected_ai || A.scrambledcodes || istype(A,/mob/living/silicon/robot/drone) || !(get_z(A) in zs)) + if (A.stat == DEAD || A.connected_ai || A.scrambledcodes || isdrone(A) || !(get_z(A) in zs)) continue var/name = "[A.real_name] ([A.modtype] [A.braintype])" borgs[name] = A @@ -462,6 +462,10 @@ Turf and target are seperate in case you want to teleport some distance from a t cant_pass = 1 return cant_pass +/proc/get_step_resolving_mimic(var/atom/source, var/direction) + var/turf/turf = get_step(get_turf(source), direction) + return turf?.resolve_to_actual_turf() + /proc/get_step_towards2(var/atom/ref , var/atom/trg) var/base_dir = get_dir(ref, get_step_towards(ref,trg)) var/turf/temp = get_step_towards(ref,trg) @@ -594,6 +598,7 @@ Turf and target are seperate in case you want to teleport some distance from a t var/old_icon1 = T.icon var/old_overlays = T.overlays.Copy() var/old_underlays = T.underlays.Copy() + var/old_decals = T.decals?.Copy() if(platingRequired) if(istype(B, get_base_turf_by_area(B))) @@ -604,8 +609,10 @@ Turf and target are seperate in case you want to teleport some distance from a t X.set_dir(old_dir1) X.icon_state = old_icon_state1 X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi + X.decals = old_decals X.overlays = old_overlays X.underlays = old_underlays + X.update_icon() // necessary to update decals properly var/list/objs = new/list() var/list/newobjs = new/list() @@ -629,7 +636,7 @@ Turf and target are seperate in case you want to teleport some distance from a t for(var/mob/M in T) - if(!istype(M,/mob) || !M.simulated) continue // If we need to check for more mobs, I'll add a variable + if(!ismob(M) || !M.simulated) continue // If we need to check for more mobs, I'll add a variable mobs += M for(var/mob/M in mobs) diff --git a/code/_macros.dm b/code/_macros.dm index 5e69faaf196..9cee22e70fc 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -34,7 +34,7 @@ #define iscorgi(A) istype(A, /mob/living/simple_animal/corgi) -#define is_drone(A) istype(A, /mob/living/silicon/robot/drone) +#define isdrone(A) istype(A, /mob/living/silicon/robot/drone) #define isEye(A) istype(A, /mob/observer/eye) @@ -44,8 +44,14 @@ #define isliving(A) istype(A, /mob/living) +#define isdeity(A) istype(A, /mob/living/deity) + #define ismouse(A) istype(A, /mob/living/simple_animal/mouse) +#define islizard(A) istype(A, /mob/living/simple_animal/lizard) + +#define isconstruct(A) istype(A, /mob/living/simple_animal/construct) + #define isnewplayer(A) istype(A, /mob/new_player) #define isobj(A) istype(A, /obj) @@ -70,6 +76,10 @@ #define issilicon(A) istype(A, /mob/living/silicon) +#define isbot(A) istype(A, /mob/living/bot) + +#define isexosuit(A) istype(A, /mob/living/exosuit) + #define isunderwear(A) istype(A, /obj/item/underwear) #define isvirtualmob(A) istype(A, /mob/observer/virtual) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 383bab17729..b7ec77eacc7 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -108,7 +108,7 @@ if(W == A) // Handle attack_self W.attack_self(src) trigger_aiming(TARGET_CAN_CLICK) - update_inv_hands(0) + usr.update_inhand_overlays(FALSE) return 1 //Atoms on your person @@ -354,7 +354,7 @@ var/global/list/click_catchers icon = 'icons/mob/screen_gen.dmi' icon_state = "click_catcher" plane = CLICKCATCHER_PLANE - mouse_opacity = 2 + mouse_opacity = MOUSE_OPACITY_PRIORITY screen_loc = "CENTER-7,CENTER-7" var/x_offset = 0 var/y_offset = 0 @@ -365,7 +365,7 @@ var/global/list/click_catchers /obj/screen/click_catcher/Click(location, control, params) var/list/modifiers = params2list(params) - if(modifiers["middle"] && istype(usr, /mob/living/carbon)) + if(modifiers["middle"] && iscarbon(usr)) var/mob/living/carbon/C = usr C.swap_hand() else diff --git a/code/_onclick/click_handling.dm b/code/_onclick/click_handling.dm index 4914613c94c..472249544ec 100644 --- a/code/_onclick/click_handling.dm +++ b/code/_onclick/click_handling.dm @@ -13,10 +13,6 @@ if(!click_handlers) { \ /mob/Destroy() QDEL_NULL(status_markers) QDEL_NULL_LIST(click_handlers) - var/datum/extension/hattable/hattable = get_extension(src, /datum/extension/hattable) - if(hattable?.hat) - hattable.hat.dropInto(get_turf(src)) - hattable.hat = null . = ..() var/global/const/CLICK_HANDLER_NONE = BITFLAG(0) diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index d01a671bebd..4d2168073f8 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -10,11 +10,11 @@ . = ..() /atom/proc/handle_mouse_drop(var/atom/over, var/mob/user) - . = over.receive_mouse_drop(src, user) + . = over?.receive_mouse_drop(src, user) // Can the user drop something onto this atom? /atom/proc/user_can_mousedrop_onto(var/mob/user, var/atom/being_dropped, var/incapacitation_flags) - return !user.incapacitated(incapacitation_flags) && check_mousedrop_interactivity(user) && user.check_dexterity(DEXTERITY_GRIP) + return !user.incapacitated(incapacitation_flags) && check_mousedrop_interactivity(user) && user.check_dexterity(DEXTERITY_EQUIP_ITEM) /atom/proc/check_mousedrop_interactivity(var/mob/user) return CanPhysicallyInteract(user) @@ -31,7 +31,7 @@ return TRUE /atom/proc/check_mousedrop_adjacency(var/atom/over, var/mob/user) - . = (Adjacent(user) && over.Adjacent(user)) + . = (Adjacent(user) && ((over in user?.client?.screen) || over.Adjacent(user))) // Receive a mouse drop. // Returns false if the atom is valid for dropping further up the chain, true if the drop has been handled. diff --git a/code/_onclick/hud/ability_screen_objects.dm b/code/_onclick/hud/ability_screen_objects.dm index 8dcbdfa1ffb..54094c25e4b 100644 --- a/code/_onclick/hud/ability_screen_objects.dm +++ b/code/_onclick/hud/ability_screen_objects.dm @@ -82,9 +82,9 @@ /obj/screen/ability_master/on_update_icon() if(ability_objects.len) - set_invisibility(0) + set_invisibility(INVISIBILITY_NONE) else - set_invisibility(101) + set_invisibility(INVISIBILITY_ABSTRACT) /obj/screen/ability_master/proc/add_ability(var/name_given) if(!name) return diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 1c99ce6d77d..40b6339f64d 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -13,5 +13,4 @@ ai_hud.input_procs, ai_hud.input_args ) - if(mymob?.client) - mymob.client.screen = list(adding) + ..() diff --git a/code/_onclick/hud/animal.dm b/code/_onclick/hud/animal.dm index 129d39f259a..81868526a39 100644 --- a/code/_onclick/hud/animal.dm +++ b/code/_onclick/hud/animal.dm @@ -3,6 +3,7 @@ hud_type = /datum/hud/animal /datum/hud/animal/FinalizeInstantiation() - mymob.client.screen = list() action_intent = new /obj/screen/intent() - mymob.client.screen |= action_intent \ No newline at end of file + adding += action_intent + ..() + diff --git a/code/_onclick/hud/deity.dm b/code/_onclick/hud/deity.dm index df18fb9ff53..f570e96b1e2 100644 --- a/code/_onclick/hud/deity.dm +++ b/code/_onclick/hud/deity.dm @@ -2,19 +2,12 @@ hud_type = /datum/hud/deity /datum/hud/deity/FinalizeInstantiation() - src.adding = list() - src.other = list() - - var/obj/screen/intent/deity/D = new() - - src.adding += D - action_intent = D - - mymob.client.screen = list() - mymob.client.screen += src.adding + action_intent = new /obj/screen/intent/deity + adding += action_intent + ..() + var/obj/screen/intent/deity/D = action_intent D.sync_to_mob(mymob) - /obj/screen/intent/deity var/list/desc_screens = list() screen_loc = "RIGHT-5:122,BOTTOM:8" @@ -28,7 +21,7 @@ for(var/i in 1 to D.control_types.len) var/obj/screen/S = new() S.SetName(null) //Don't want them to be able to actually right click it. - S.mouse_opacity = 0 + S.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE S.icon_state = "blank" desc_screens[D.control_types[i]] = S S.maptext_width = 128 @@ -41,7 +34,7 @@ update_text() /obj/screen/intent/deity/proc/update_text() - if(!istype(usr, /mob/living/deity)) + if(!isdeity(usr)) return var/mob/living/deity/D = usr for(var/i in D.control_types) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 4da06f9b575..cf42a0e99ab 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -75,7 +75,8 @@ icon_state = "default" screen_loc = ui_center_fullscreen plane = FULLSCREEN_PLANE - mouse_opacity = 0 + layer = FULLSCREEN_LAYER + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE var/severity = 0 var/allstate = 0 //shows if it should show up for dead people too @@ -127,21 +128,19 @@ icon = 'icons/mob/screen1.dmi' screen_loc = ui_entire_screen icon_state = "druggy" - alpha = 127 + alpha = 180 blend_mode = BLEND_MULTIPLY /obj/screen/fullscreen/noise icon = 'icons/effects/static.dmi' icon_state = "1 light" screen_loc = ui_entire_screen - layer = FULLSCREEN_LAYER alpha = 127 /obj/screen/fullscreen/fadeout icon = 'icons/mob/screen1.dmi' icon_state = "black" screen_loc = ui_entire_screen - layer = FULLSCREEN_LAYER alpha = 0 allstate = 1 @@ -154,7 +153,6 @@ icon_state = "scanlines" screen_loc = ui_entire_screen alpha = 50 - layer = FULLSCREEN_LAYER /obj/screen/fullscreen/fishbed icon_state = "fishbed" @@ -169,4 +167,3 @@ icon_state = "base" screen_loc = ui_entire_screen alpha = 100 - layer = FULLSCREEN_LAYER \ No newline at end of file diff --git a/code/_onclick/hud/global_hud.dm b/code/_onclick/hud/global_hud.dm index 70e7aa2f7df..8bcfb40027f 100644 --- a/code/_onclick/hud/global_hud.dm +++ b/code/_onclick/hud/global_hud.dm @@ -24,12 +24,10 @@ var/global/datum/global_hud/hud screen.icon_state = icon_state screen.plane = FULLSCREEN_PLANE screen.layer = FULLSCREEN_LAYER - screen.mouse_opacity = 0 + screen.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE screen.alpha = 125 - screen.blend_mode = BLEND_MULTIPLY screen.color = color - return screen /datum/global_hud/New() @@ -46,4 +44,4 @@ var/global/datum/global_hud/hud holomap.icon = null holomap.layer = HUD_BASE_LAYER holomap.screen_loc = UI_HOLOMAP - holomap.mouse_opacity = 0 \ No newline at end of file + holomap.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE \ No newline at end of file diff --git a/code/_onclick/hud/gun_mode.dm b/code/_onclick/hud/gun_mode.dm index ab5cecbff9c..349fce96b0f 100644 --- a/code/_onclick/hud/gun_mode.dm +++ b/code/_onclick/hud/gun_mode.dm @@ -1,7 +1,6 @@ /obj/screen/gun name = "gun" icon = 'icons/mob/screen1.dmi' - master = null dir = SOUTH /obj/screen/gun/Click(location, control, params) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 25c888d24ad..e308e449aef 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -32,8 +32,9 @@ var/obj/screen/move_intent var/obj/screen/stamina/stamina_bar - var/list/adding - var/list/other + var/list/adding = list() + var/list/other = list() + var/list/hud_elements = list() var/list/obj/screen/hotkeybuttons var/obj/screen/action_button/hide_toggle/hide_actions_toggle @@ -59,10 +60,10 @@ /datum/hud/proc/update_stamina() if(mymob && stamina_bar) - stamina_bar.invisibility = INVISIBILITY_MAXIMUM + stamina_bar.set_invisibility(INVISIBILITY_MAXIMUM) var/stamina = mymob.get_stamina() if(stamina < 100) - stamina_bar.invisibility = 0 + stamina_bar.set_invisibility(INVISIBILITY_NONE) stamina_bar.icon_state = "prog_bar_[FLOOR(stamina/5)*5][(stamina >= 5) && (stamina <= 25) ? "_fail" : null]" /datum/hud/proc/hide_inventory() @@ -99,6 +100,7 @@ continue // We're not showing anything, hide it. + gear.reconsider_client_screen_presence(mymob?.client, slot) if(!show_hud) inv_slot.hide_slot() else @@ -111,7 +113,21 @@ return FALSE /datum/hud/proc/FinalizeInstantiation() - return + SHOULD_CALL_PARENT(TRUE) + BuildInventoryUI() + if(mymob.client) + mymob.client.screen = list() + if(length(hand_hud_objects)) + mymob.client.screen |= hand_hud_objects + if(length(swaphand_hud_objects)) + mymob.client.screen |= swaphand_hud_objects + if(length(hud_elements)) + mymob.client.screen |= hud_elements + if(length(adding)) + mymob.client.screen |= adding + if(length(hotkeybuttons)) + mymob.client.screen |= hotkeybuttons + hide_inventory() /datum/hud/proc/get_ui_style() return ui_style2icon(mymob?.client?.prefs?.UI_style) || 'icons/mob/screen/white.dmi' @@ -130,26 +146,36 @@ // Build held item boxes for missing slots. var/list/held_slots = mymob.get_held_item_slots() + + // Sort our slots for display. + var/list/gripper_datums = list() for(var/hand_tag in held_slots) + gripper_datums += mymob.get_inventory_slot_datum(hand_tag) + gripper_datums = sortTim(gripper_datums, /proc/cmp_gripper_asc) + + for(var/datum/inventory_slot/inv_slot in gripper_datums) + + // Re-order the held slot list so it aligns with the display order. + var/hand_tag = inv_slot.slot_id + held_slots -= hand_tag + held_slots += hand_tag + var/obj/screen/inventory/inv_box for(var/obj/screen/inventory/existing_box in hand_hud_objects) if(existing_box.slot_id == hand_tag) inv_box = existing_box break if(!inv_box) - inv_box = new /obj/screen/inventory() - var/datum/inventory_slot/inv_slot = mymob.get_inventory_slot_datum(hand_tag) + inv_box = new /obj/screen/inventory(null, mymob) inv_box.SetName(hand_tag) inv_box.icon = ui_style inv_box.icon_state = "hand_base" inv_box.cut_overlays() - inv_box.add_overlay("hand_[hand_tag]") + inv_box.add_overlay("hand_[hand_tag]", TRUE) if(inv_slot.ui_label) - inv_box.add_overlay("hand_[inv_slot.ui_label]") - if(mymob.get_active_held_item_slot() == hand_tag) - inv_box.add_overlay("hand_selected") - inv_box.compile_overlays() + inv_box.add_overlay("hand_[inv_slot.ui_label]", TRUE) + inv_box.update_icon() inv_box.slot_id = hand_tag inv_box.color = ui_color @@ -224,7 +250,7 @@ if(gear_slot in held_slots) continue - inv_box = new /obj/screen/inventory() + inv_box = new /obj/screen/inventory(null, mymob) inv_box.icon = ui_style inv_box.color = ui_color inv_box.alpha = ui_alpha @@ -275,7 +301,7 @@ var/list/held_slots = mymob.get_held_item_slots() if(length(held_slots) > 1) - using = new /obj/screen/inventory() + using = new /obj/screen/inventory(null, mymob) using.SetName("hand") using.icon = ui_style using.icon_state = "hand1" @@ -284,7 +310,7 @@ src.adding += using LAZYADD(swaphand_hud_objects, using) - using = new /obj/screen/inventory() + using = new /obj/screen/inventory(null, mymob) using.SetName("hand") using.icon = ui_style using.icon_state = "hand2" @@ -309,8 +335,6 @@ return if(!client) return - if(client.view != world.view) - return if(hud_used.hud_shown) hud_used.hud_shown = 0 if(src.hud_used.adding) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index a40889dc4d6..f90bd824fde 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -12,18 +12,13 @@ if(hud_data.icon) ui_style = hud_data.icon - adding = list() - other = list() - src.hotkeybuttons = list() //These can be disabled for hotkey usersx + hotkeybuttons = list() //These can be disabled for hotkey usersx - var/list/hud_elements = list() var/obj/screen/using stamina_bar = new adding += stamina_bar - BuildInventoryUI() - // Draw the attack intent dialogue. if(hud_data.has_a_intent) using = new /obj/screen/intent() @@ -201,19 +196,7 @@ mymob.radio_use_icon.color = ui_color mymob.radio_use_icon.alpha = ui_alpha - mymob.client.screen = list() - if(length(hand_hud_objects)) - mymob.client.screen += hand_hud_objects - if(length(swaphand_hud_objects)) - mymob.client.screen += swaphand_hud_objects - if(length(hud_elements)) - mymob.client.screen += hud_elements - mymob.client.screen += src.adding + src.hotkeybuttons - - hide_inventory() - - hidden_inventory_update() - persistant_inventory_update() + ..() /mob/living/carbon/human/verb/toggle_hotkey_verbs() set category = "OOC" diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index 5b6b03616b4..d7eb03aac29 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -1,34 +1,42 @@ /mob/living/simple_animal/construct hud_type = /datum/hud/construct -/datum/hud/construct/FinalizeInstantiation() - var/constructtype +/mob/living/simple_animal/construct + var/hud_construct_type + +/mob/living/simple_animal/construct/armoured + hud_construct_type = "juggernaut" + +/mob/living/simple_animal/construct/behemoth + hud_construct_type = "juggernaut" + +/mob/living/simple_animal/construct/builder + hud_construct_type = "artificer" - if(istype(mymob,/mob/living/simple_animal/construct/armoured) || istype(mymob,/mob/living/simple_animal/construct/behemoth)) - constructtype = "juggernaut" - else if(istype(mymob,/mob/living/simple_animal/construct/builder)) - constructtype = "artificer" - else if(istype(mymob,/mob/living/simple_animal/construct/wraith)) - constructtype = "wraith" - else if(istype(mymob,/mob/living/simple_animal/construct/harvester)) - constructtype = "harvester" +/mob/living/simple_animal/construct/wraith + hud_construct_type = "wraith" +/mob/living/simple_animal/construct/harvester + hud_construct_type = "harvester" + +/datum/hud/construct/FinalizeInstantiation() + var/constructtype + if(isconstruct(mymob)) + var/mob/living/simple_animal/construct/construct = mymob + constructtype = construct.hud_construct_type if(constructtype) mymob.fire = new /obj/screen() mymob.fire.icon = 'icons/mob/screen1_construct.dmi' mymob.fire.icon_state = "fire0" mymob.fire.SetName("fire") mymob.fire.screen_loc = ui_construct_fire - mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_construct.dmi' mymob.healths.icon_state = "[constructtype]_health0" mymob.healths.SetName("health") mymob.healths.screen_loc = ui_construct_health - mymob.zone_sel = new mymob.zone_sel.icon = 'icons/mob/screen1_construct.dmi' mymob.zone_sel.update_icon() - - mymob.client.screen = list() - mymob.client.screen += list(mymob.fire, mymob.healths, mymob.zone_sel) + adding += list(mymob.fire, mymob.healths, mymob.zone_sel) + ..() diff --git a/code/_onclick/hud/pai.dm b/code/_onclick/hud/pai.dm index 8f305d4153c..c2926b006ff 100644 --- a/code/_onclick/hud/pai.dm +++ b/code/_onclick/hud/pai.dm @@ -1,29 +1,21 @@ /datum/hud/pai/FinalizeInstantiation() - adding = list() var/obj/screen/using - using = new /obj/screen/pai/software() using.SetName("Software Interface") adding += using - using = new /obj/screen/pai/subsystems() using.SetName("Subsystems") adding += using - using = new /obj/screen/pai/shell() using.SetName("Toggle Chassis") adding += using - using = new /obj/screen/pai/rest() using.SetName("Rest") adding += using - using = new /obj/screen/pai/light() using.SetName("Toggle Light") adding += using - - mymob.client.screen = list() - mymob.client.screen += adding + ..() hide_inventory() /obj/screen/pai diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index db934e72f25..49fe49e32da 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -169,7 +169,7 @@ var/global/list/radial_menus = list() E.alpha = 0 E.name = "None" E.maptext = null - E.mouse_opacity = 0 + E.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE E.choice = null E.next_page = FALSE @@ -190,7 +190,7 @@ var/global/list/radial_menus = list() //Visuals E.alpha = 255 - E.mouse_opacity = 1 + E.mouse_opacity = MOUSE_OPACITY_NORMAL E.overlays.Cut() if(choice_id == NEXT_PAGE_ID) E.name = "Next Page" @@ -355,4 +355,4 @@ var/global/list/radial_menus = list() /proc/make_item_radial_menu_choices(var/list/items, var/name_prefix = "", var/name_suffix = "") for(var/atom/movable/AM in items) LAZYSET(., AM, make_item_radial_menu_button(AM, name_prefix, name_suffix)) - + diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index fe5be57d956..3a9c97bd923 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -13,7 +13,7 @@ var/global/obj/screen/robot_inventory if(isrobot(usr) && !usr.incapacitated()) var/mob/living/silicon/robot/R = usr R.drop_item() - invisibility = INVISIBILITY_MAXIMUM + set_invisibility(INVISIBILITY_MAXIMUM) alpha = 0 /mob/living/silicon/robot @@ -21,13 +21,10 @@ var/global/obj/screen/robot_inventory /datum/hud/robot/FinalizeInstantiation() - if(!isrobot(mymob)) - return - var/mob/living/silicon/robot/R = mymob - - adding = list() - other = list() + if(!istype(R)) + ..() + return var/obj/screen/using @@ -164,9 +161,8 @@ var/global/obj/screen/robot_inventory R.gun_move_icon = new /obj/screen/gun/move(null) R.radio_use_icon = new /obj/screen/gun/radio(null) - R.client.screen = list() - R.client.screen += list(R.throw_icon, R.zone_sel, R.oxygen, R.fire, R.up_hint, R.hands, R.healths, R.cells, robot_inventory, R.gun_setting_icon) - R.client.screen += adding + other + hud_elements = list(R.throw_icon, R.zone_sel, R.oxygen, R.fire, R.up_hint, R.hands, R.healths, R.cells, robot_inventory, R.gun_setting_icon) + ..() /datum/hud/proc/toggle_show_robot_modules() if(!isrobot(mymob)) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 0fd29bfb984..4662c1fdc8d 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -12,8 +12,7 @@ plane = HUD_PLANE layer = HUD_BASE_LAYER appearance_flags = NO_CLIENT_COLOR - unacidable = 1 - var/obj/master = null //A reference to the object in the slot. Grabs or items, generally. + is_spawnable_type = FALSE var/globalscreen = FALSE //Global screens are not qdeled when the holding mob is destroyed. /obj/screen/receive_mouse_drop(atom/dropping, mob/user) @@ -22,25 +21,92 @@ /obj/screen/check_mousedrop_interactivity(var/mob/user) return user.client && (src in user.client.screen) -/obj/screen/Destroy() - master = null - return ..() - /obj/screen/text icon = null icon_state = null - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE screen_loc = "CENTER-7,CENTER-7" maptext_height = 480 maptext_width = 480 - /obj/screen/inventory var/slot_id //The indentifier for the slot. It has nothing to do with ID cards. + var/weakref/mouse_over_atom_ref + var/weakref/owner_ref + +/obj/screen/inventory/Initialize(var/ml, var/mob/_owner) + if(!istype(_owner)) + PRINT_STACK_TRACE("Inventory screen object supplied a non-mob owner!") + owner_ref = weakref(_owner) + return ..() + +/obj/screen/inventory/MouseDrop() + . = ..() + mouse_over_atom_ref = null + update_icon() + +/obj/screen/inventory/Click() + . = ..() + mouse_over_atom_ref = null + update_icon() + +/obj/screen/inventory/MouseEntered(location, control, params) + . = ..() + if(!slot_id || !usr) + return + var/equipped_item = usr.get_active_hand() + if(equipped_item) + var/new_mouse_over_atom = weakref(equipped_item) + if(new_mouse_over_atom != mouse_over_atom_ref) + mouse_over_atom_ref = new_mouse_over_atom + update_icon() + +/obj/screen/inventory/MouseExited(location, control, params) + . = ..() + if(mouse_over_atom_ref) + mouse_over_atom_ref = null + update_icon() + +/obj/screen/inventory/on_update_icon() + + cut_overlays() + + // Validate our owner still exists. + var/mob/owner = owner_ref?.resolve() + if(!istype(owner) || QDELETED(owner) || !(src in owner.client?.screen)) + return + + // Mark our selected hand. + if(owner.get_active_held_item_slot() == slot_id) + add_overlay("hand_selected") + + // Mark anything we're potentially trying to equip. + var/obj/item/mouse_over_atom = mouse_over_atom_ref?.resolve() + if(istype(mouse_over_atom) && !QDELETED(mouse_over_atom) && !usr.get_equipped_item(slot_id)) + var/mutable_appearance/MA = new /mutable_appearance(mouse_over_atom) + MA.layer = HUD_ABOVE_ITEM_LAYER + MA.plane = HUD_PLANE + MA.alpha = 80 + MA.color = mouse_over_atom.mob_can_equip(owner, slot_id, TRUE) ? COLOR_GREEN : COLOR_RED + MA.pixel_x = mouse_over_atom.default_pixel_x + MA.pixel_y = mouse_over_atom.default_pixel_y + MA.pixel_w = mouse_over_atom.default_pixel_w + MA.pixel_z = mouse_over_atom.default_pixel_z + add_overlay(MA) + else + mouse_over_atom_ref = null + // UI needs to be responsive so avoid the subsecond update delay. + compile_overlays() /obj/screen/close name = "close" + // A reference to the storage item this atom is associated with. + var/obj/master + +/obj/screen/close/Destroy() + master = null + return ..() /obj/screen/close/Click() if(master) @@ -51,7 +117,7 @@ /obj/screen/default_attack_selector name = "default attack selector" - icon_state = "attack_selector" + icon_state = "attack_none" screen_loc = ui_attack_selector var/mob/living/carbon/human/owner @@ -61,13 +127,11 @@ var/list/modifiers = params2list(params) if(modifiers["shift"]) - var/decl/natural_attack/attack = owner.get_unarmed_attack() - to_chat(owner, SPAN_NOTICE("Your current default attack is [attack?.name || "unset"].")) - if(attack) - var/summary = attack.summarize() + to_chat(owner, SPAN_NOTICE("Your current default attack is [owner.default_attack?.name || "unset"].")) + if(owner.default_attack) + var/summary = owner.default_attack.summarize() if(summary) to_chat(owner, SPAN_NOTICE(summary)) - return owner.set_default_unarmed_attack(src) @@ -88,11 +152,8 @@ update_icon() /obj/screen/default_attack_selector/on_update_icon() - var/decl/natural_attack/attack = owner?.get_unarmed_attack() - if(!attack) - maptext = "
[STYLE_SMALLFONTS_OUTLINE("NONE", 5, COLOR_WHITE, COLOR_BLACK)]
" - else - maptext = "
[STYLE_SMALLFONTS_OUTLINE("[uppertext(attack.name)]", 5, COLOR_WHITE, COLOR_BLACK)]
" + var/decl/natural_attack/attack = owner?.default_attack + icon_state = attack?.selector_icon_state || "attack_none" /obj/screen/item_action var/obj/item/owner @@ -118,6 +179,12 @@ /obj/screen/storage name = "storage" + // A reference to the storage item this atom is associated with. + var/obj/master + +/obj/screen/storage/Destroy() + master = null + return ..() /obj/screen/storage/Click() if(!usr.canClick()) @@ -346,7 +413,7 @@ else usr.select_held_item_slot(name) else if(usr.attack_ui(slot_id)) - usr.update_inv_hands(0) + usr.update_inhand_overlays(FALSE) return TRUE @@ -374,7 +441,7 @@ /obj/screen/lighting_plane_master screen_loc = "CENTER" appearance_flags = PLANE_MASTER - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE plane = LIGHTING_PLANE blend_mode = BLEND_MULTIPLY alpha = 255 diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index 9bd447bf94b..3de900748eb 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -1,7 +1,7 @@ var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, used for offsets/scaling /obj/skybox name = "skybox" - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE anchored = TRUE simulated = FALSE plane = SKYBOX_PLANE @@ -49,7 +49,6 @@ var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, u if(rebuild) skybox.overlays.Cut() var/image/I = SSskybox.get_skybox(T.z) - I.appearance_flags |= PIXEL_SCALE skybox.overlays += I screen |= skybox set_skybox_offsets(last_view_x_dim, last_view_y_dim) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 1b4b1dad91b..e9c5a42cbfa 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -49,17 +49,6 @@ avoid code duplication. This includes items that may sometimes act as a standard return 0 if(can_operate(src,user) != OPERATE_DENY && I.do_surgery(src,user)) //Surgery return 1 - - if(user.a_intent == I_HELP && istype(I, /obj/item/clothing/head)) - var/datum/extension/hattable/hattable = get_extension(src, /datum/extension/hattable) - if(hattable) - if(hattable.hat) - to_chat(user, SPAN_WARNING("\The [src] is already wearing \the [hattable.hat].")) - return TRUE - if(user.try_unequip(I) && hattable.wear_hat(src, I)) - user.visible_message(SPAN_NOTICE("\The [user] puts \the [I] on \the [src].")) - return TRUE - return I.attack(src, user, user.get_target_zone() || ran_zone()) /mob/living/carbon/human/attackby(obj/item/I, mob/user) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 87ed57f9f3e..d529f620b2f 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -29,7 +29,7 @@ SHOULD_CALL_PARENT(TRUE) if(handle_grab_interaction(user)) return TRUE - if(!LAZYLEN(climbers) || (user in climbers) || !user.check_dexterity(DEXTERITY_GRIP, TRUE)) + if(!LAZYLEN(climbers) || (user in climbers) || !user.check_dexterity(DEXTERITY_HOLD_ITEM, TRUE)) return FALSE user.visible_message( SPAN_DANGER("\The [user] shakes \the [src]!"), @@ -93,7 +93,7 @@ if(!..()) return setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - if(istype(A,/mob/living)) + if(isliving(A)) if(a_intent == I_HELP || !get_natural_weapon()) custom_emote(1,"[friendly] [A]!") return diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index aed434653b6..187edb24ef3 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -1,5 +1,3 @@ -var/global/list/gamemode_cache = list() - /datum/configuration var/server_name = "Nebula 13" // server name (for world name / status) var/server_suffix = 0 // generate numeric suffix based on server port @@ -288,25 +286,26 @@ var/global/list/gamemode_cache = list() var/exoplanet_max_day_duration = 40 MINUTES ///If true, exoplanets won't have daycycles var/disable_daycycle = FALSE + /// Whether or not you will show a message when examining something. + var/visible_examine = TRUE + /// Whether or not loadout options will get free name and desc entry by default. + var/allow_loadout_customization = FALSE /datum/configuration/VV_hidden() . = ..() | protected_vars /datum/configuration/New() - var/list/L = subtypesof(/datum/game_mode) - for (var/T in L) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - var/datum/game_mode/M = new T() - if (M.config_tag) - gamemode_cache[M.config_tag] = M // So we don't instantiate them repeatedly. - if(!(M.config_tag in modes)) // ensure each mode is added only once - log_misc("Adding game mode [M.name] ([M.config_tag]) to configuration.") - src.modes += M.config_tag - src.mode_names[M.config_tag] = M.name - src.probabilities[M.config_tag] = M.probability - if (M.votable) - src.votable_modes += M.config_tag + var/list/all_modes = decls_repository.get_decls_of_subtype(/decl/game_mode) + for (var/mode_type in all_modes) + var/decl/game_mode/game_mode = all_modes[mode_type] + if (!game_mode.uid || !(game_mode.uid in modes)) + continue + log_misc("Adding game mode [game_mode.name] ([game_mode.uid]) to configuration.") + src.modes += game_mode.uid + src.mode_names[game_mode.uid] = game_mode.name + src.probabilities[game_mode.uid] = game_mode.probability + if (game_mode.votable) + src.votable_modes += game_mode.uid src.votable_modes += "secret" /datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist @@ -847,8 +846,14 @@ var/global/list/gamemode_cache = list() if("show_typing_indicator_for_whispers") config.show_typing_indicator_for_whispers = TRUE + if("visible_examine") + config.visible_examine = text2num(value) + + if("allow_loadout_customization") + config.allow_loadout_customization = TRUE + else - //Shitty hook to get our extra settings to load until config options code is less dumb + //crappy hook to get modpacks to load any extra config if(!load_mod_config(name, value)) log_misc("Unknown setting in configuration: '[name]'") @@ -978,9 +983,9 @@ var/global/list/gamemode_cache = list() config.disable_daycycle = TRUE else - //Shitty hook to get our extra settings to load until config options code is less dumb - if(!load_mod_game_options(name, value)) - log_misc("Unknown setting in configuration: '[name]'") + //crappy hook to get modpacks to load any extra config + if(!load_mod_config(name, value)) + log_misc("Unknown setting in game_options configuration: '[name]'") fps = round(fps) if(fps <= 0) @@ -1024,24 +1029,17 @@ var/global/list/gamemode_cache = list() if ("password") sqlpass = value else + //crappy hook to get modpacks to load any extra config if(!load_mod_dbconfig(name, value)) - log_misc("Unknown setting in configuration: '[name]'") - -/datum/configuration/proc/pick_mode(mode_name) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - for (var/game_mode in gamemode_cache) - var/datum/game_mode/M = gamemode_cache[game_mode] - if (M.config_tag && M.config_tag == mode_name) - return M + log_misc("Unknown setting in DB configuration: '[name]'") /datum/configuration/proc/get_runnable_modes() - var/list/runnable_modes = list() - for(var/game_mode in gamemode_cache) - var/datum/game_mode/M = gamemode_cache[game_mode] - if(M && !M.startRequirements() && !isnull(config.probabilities[M.config_tag]) && config.probabilities[M.config_tag] > 0) - runnable_modes[M.config_tag] = config.probabilities[M.config_tag] - return runnable_modes + . = list() + var/list/all_modes = decls_repository.get_decls_of_subtype(/decl/game_mode) + for(var/mode_type in all_modes) + var/decl/game_mode/game_mode = all_modes[mode_type] + if(!game_mode.startRequirements() && !isnull(config.probabilities[game_mode.uid]) && config.probabilities[game_mode.uid] > 0) + .[game_mode.uid] = config.probabilities[game_mode.uid] /datum/configuration/proc/load_event(filename) var/event_info = safe_file2text(filename, FALSE) @@ -1050,12 +1048,16 @@ var/global/list/gamemode_cache = list() ///Hook stub for loading modpack specific configs. Just override in modpack. /datum/configuration/proc/load_mod_config(var/name, var/value) + //Force it to run parents overrides, so other modpacks don't just completely break config loading for one another + SHOULD_CALL_PARENT(TRUE) return ///Hook stub for loading modpack specific game_options. Just override in modpack. /datum/configuration/proc/load_mod_game_options(var/name, var/value) + SHOULD_CALL_PARENT(TRUE) return ///Hook stub for loading modpack specific dbconfig. Just override in modpack. /datum/configuration/proc/load_mod_dbconfig(var/name, var/value) - return \ No newline at end of file + SHOULD_CALL_PARENT(TRUE) + return diff --git a/code/controllers/evacuation/evacuation_pods.dm b/code/controllers/evacuation/evacuation_pods.dm index 76e91690c19..06d0aabc77e 100644 --- a/code/controllers/evacuation/evacuation_pods.dm +++ b/code/controllers/evacuation/evacuation_pods.dm @@ -137,7 +137,6 @@ screen_loc = ui_entire_screen color = "#ff9900" blend_mode = BLEND_SUBTRACT - layer = FULLSCREEN_LAYER #undef EVAC_OPT_ABANDON_SHIP #undef EVAC_OPT_JUMP diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 0072bd2612a..c7a3c84f63e 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -280,7 +280,7 @@ var/global/datum/controller/master/Master = new //(higher subsystems will be sooner in the queue, adding them later in the loop means we don't have to loop thru them next queue add) sortTim(tickersubsystems, /proc/cmp_subsystem_priority) for(var/I in runlevel_sorted_subsystems) - sortTim(runlevel_sorted_subsystems, /proc/cmp_subsystem_priority) + sortTim(I, /proc/cmp_subsystem_priority) I += tickersubsystems var/cached_runlevel = current_runlevel diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm index 793f85d10fb..313c3e64001 100644 --- a/code/controllers/subsystems/air.dm +++ b/code/controllers/subsystems/air.dm @@ -411,7 +411,9 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun return edge else for(var/connection_edge/unsimulated/edge in A.edges) - if(has_same_air(edge.B,B)) + var/datum/gas_mixture/opponent_air = edge.B.return_air() + var/turf/our_turf = B + if(opponent_air.compare(our_turf.return_air())) return edge var/connection_edge/edge = new/connection_edge/unsimulated(A,B) edges += edge diff --git a/code/controllers/subsystems/fluids.dm b/code/controllers/subsystems/fluids.dm index 7d41807b725..f9671d442ed 100644 --- a/code/controllers/subsystems/fluids.dm +++ b/code/controllers/subsystems/fluids.dm @@ -1,6 +1,7 @@ SUBSYSTEM_DEF(fluids) name = "Fluids" wait = 1 SECOND + priority = SS_PRIORITY_FLUIDS flags = SS_NO_INIT var/tmp/list/water_sources = list() @@ -115,18 +116,21 @@ SUBSYSTEM_DEF(fluids) current_depth = reagent_holder?.total_volume || 0 // How is this happening - if(current_depth == -1.#IND || current_depth == 1.#IND) + if(QDELETED(reagent_holder) || current_depth == -1.#IND || current_depth == 1.#IND) qdel(current_fluid) continue // Evaporation: todo, move liquid into current_turf.zone air contents if applicable. - if(current_depth <= FLUID_MINIMUM_TRANSFER && prob(15)) + if(current_depth <= FLUID_PUDDLE && prob(60)) current_turf.remove_fluids(min(current_depth, 1), defer_update = TRUE) current_depth = current_turf.get_fluid_depth() if(current_depth <= FLUID_QDEL_POINT) qdel(current_fluid) continue + // Wash our turf. + current_turf.fluid_act(reagent_holder) + if(isspaceturf(current_turf) || istype(current_turf, /turf/exterior)) removing = round(current_depth * 0.5) if(removing > 0) diff --git a/code/controllers/subsystems/holomap.dm b/code/controllers/subsystems/holomap.dm index dd544596c29..25785fec3b1 100644 --- a/code/controllers/subsystems/holomap.dm +++ b/code/controllers/subsystems/holomap.dm @@ -5,8 +5,6 @@ /datum/holomapdata var/icon/holomap_base var/list/icon/holomap_areas = list() - var/icon/holomap_combined - var/icon/holomap_areas_combined var/icon/holomap_small SUBSYSTEM_DEF(minimap) @@ -41,23 +39,17 @@ SUBSYSTEM_DEF(minimap) single.Blend(A.holomap_color, ICON_MULTIPLY) combinedareas.Blend(single, ICON_OVERLAY) - data.holomap_areas_combined = combinedareas - - var/icon/map_base = icon(data.holomap_base) - - // Generate the full sized map by blending the base and areas onto the backdrop - var/icon/big_map = icon(HOLOMAP_ICON, "stationmap") - big_map.Blend(map_base, ICON_OVERLAY) - big_map.Blend(combinedareas, ICON_OVERLAY) - data.holomap_combined = big_map - // Generate the "small" map var/icon/small_map = icon(HOLOMAP_ICON, "blank") + //Make it green. - small_map.Blend(map_base, ICON_OVERLAY) + var/icon/map_base = icon(data.holomap_base) + small_map.Blend(map_base, ICON_OVERLAY, HOLOMAP_PIXEL_OFFSET_X(zlevel), HOLOMAP_PIXEL_OFFSET_Y(zlevel)) small_map.Blend(COLOR_HOLOMAP_HOLOFIER, ICON_MULTIPLY) - small_map.Blend(combinedareas, ICON_OVERLAY) + small_map.Blend(combinedareas, ICON_OVERLAY, HOLOMAP_PIXEL_OFFSET_X(zlevel), HOLOMAP_PIXEL_OFFSET_Y(zlevel)) small_map.Scale(WORLD_ICON_SIZE, WORLD_ICON_SIZE) + var/const/border_size = 6 // the width of the border (non-map) section of the icon + small_map.Shift(NORTHEAST, border_size) // And rotate it in every direction of course! var/icon/actual_small_map = icon(small_map) @@ -72,8 +64,8 @@ SUBSYSTEM_DEF(minimap) // Generates the "base" holomap for one z-level, showing only the physical structure of walls and paths. /datum/controller/subsystem/minimap/proc/generateBaseHolomap(zlevel = 1) // Save these values now to avoid a bazillion array lookups - var/offset_x = HOLOMAP_PIXEL_OFFSET_X - var/offset_y = HOLOMAP_PIXEL_OFFSET_Y + var/offset_x = HOLOMAP_PIXEL_OFFSET_X(zlevel) + var/offset_y = HOLOMAP_PIXEL_OFFSET_Y(zlevel) // Sanity checks - Better to generate a helpful error message now than have DrawBox() runtime var/icon/canvas = icon(HOLOMAP_ICON, "blank") @@ -97,16 +89,17 @@ SUBSYSTEM_DEF(minimap) /datum/controller/subsystem/minimap/proc/generateHolomapAreaOverlays(zlevel) var/list/icon/areas = list() - var/offset_x = HOLOMAP_PIXEL_OFFSET_X - var/offset_y = HOLOMAP_PIXEL_OFFSET_Y + var/offset_x = HOLOMAP_PIXEL_OFFSET_X(zlevel) + var/offset_y = HOLOMAP_PIXEL_OFFSET_Y(zlevel) for(var/x = 1 to world.maxx) for(var/y = 1 to world.maxy) var/turf/tile = locate(x, y, zlevel) if(tile && tile.loc) var/area/areaToPaint = tile.loc - if(areaToPaint.holomap_color) - if(!areas[areaToPaint]) - areas[areaToPaint] = icon(HOLOMAP_ICON, "blank") - areas[areaToPaint].DrawBox(HOLOMAP_AREACOLOR_BASE, x + offset_x, y + offset_y) //We draw white because we want a generic version to use later. However if there is no colour we ignore it + if((areaToPaint.area_flags & AREA_FLAG_HIDE_FROM_HOLOMAP) || !areaToPaint.holomap_color) + continue + if(!areas[areaToPaint]) + areas[areaToPaint] = icon(HOLOMAP_ICON, "blank") + areas[areaToPaint].DrawBox(HOLOMAP_AREACOLOR_BASE, x + offset_x, y + offset_y) //We draw white because we want a generic version to use later. However if there is no colour we ignore it return areas \ No newline at end of file diff --git a/code/controllers/subsystems/initialization/codex.dm b/code/controllers/subsystems/initialization/codex.dm index 0437bac3503..878d9ba30c0 100644 --- a/code/controllers/subsystems/initialization/codex.dm +++ b/code/controllers/subsystems/initialization/codex.dm @@ -7,11 +7,11 @@ SUBSYSTEM_DEF(codex) var/regex/trailingLinebreakRegexStart var/regex/trailingLinebreakRegexEnd - var/list/all_entries = list() - var/list/entries_by_path = list() - var/list/entries_by_string = list() - var/list/index_file = list() - var/list/search_cache = list() + var/list/datum/codex_entry/all_entries = list() + var/list/datum/codex_entry/entries_by_path = list() + var/list/datum/codex_entry/entries_by_string = list() + var/list/index_file = list() + var/list/search_cache = list() /datum/controller/subsystem/codex/Initialize() // Codex link syntax is such: @@ -27,8 +27,9 @@ SUBSYSTEM_DEF(codex) // Create general hardcoded entries. for(var/ctype in subtypesof(/datum/codex_entry)) var/datum/codex_entry/centry = ctype - if(initial(centry.name)) - centry = new centry() + if(TYPE_IS_ABSTRACT(centry) || !initial(centry.store_codex_entry) || initial(centry.skip_hardcoded_generation)) + continue + centry = new centry() // Create categorized entries. var/list/deferred_population = list() diff --git a/code/controllers/subsystems/initialization/materials.dm b/code/controllers/subsystems/initialization/materials.dm index a3def5cb238..b544be7ef2f 100644 --- a/code/controllers/subsystems/initialization/materials.dm +++ b/code/controllers/subsystems/initialization/materials.dm @@ -156,7 +156,7 @@ SUBSYSTEM_DEF(materials) mat_name = lowertext(mat_name) return materials_by_name[mat_name] -/datum/controller/subsystem/materials/proc/get_strata_material_type(var/turf/exterior/wall/location) +/datum/controller/subsystem/materials/proc/get_strata_material_type(var/turf/exterior/location) if(!istype(location)) return @@ -183,4 +183,32 @@ SUBSYSTEM_DEF(materials) //#TODO: allow specifying rock color per z-level maybe? if(istype(location.owner)) - return location.owner.get_rock_color() \ No newline at end of file + return location.owner.get_rock_color() + +// There is a disconnect between legacy damage and armor code. This here helps bridge the gap. +// This could eventually be removed if we used decls for damage types. +/datum/controller/subsystem/materials/proc/get_armor_key(damage_type, damage_flags) + var/key + switch(damage_type) + if(BRUTE) + if(damage_flags & DAM_BULLET) + key = ARMOR_BULLET + else if(damage_flags & DAM_EXPLODE) + key = ARMOR_BOMB + else + key = ARMOR_MELEE + if(BURN) + if(damage_flags & DAM_LASER) + key = ARMOR_LASER + else if(damage_flags & DAM_EXPLODE) + key = ARMOR_BOMB + else + key = ARMOR_ENERGY + if(TOX) + if(damage_flags & DAM_BIO) + key = ARMOR_BIO // Otherwise just not blocked by default. + if(IRRADIATE) + key = ARMOR_RAD + if(ELECTROCUTE) + key = ARMOR_ENERGY + return key \ No newline at end of file diff --git a/code/controllers/subsystems/initialization/secrets.dm b/code/controllers/subsystems/initialization/secrets.dm index 28244e6a939..fa4d027ade0 100644 --- a/code/controllers/subsystems/initialization/secrets.dm +++ b/code/controllers/subsystems/initialization/secrets.dm @@ -272,5 +272,5 @@ SUBSYSTEM_DEF(secrets) try file_cache[file_location] = file(file_location) catch(var/exception/e) - error("SSsecrets get_file caught exception: [e.name] - [e.file] - [e.line]\n[e.desc]") + error("SSsecrets get_file caught exception: [EXCEPTION_TEXT(e)]") return file_cache[file_location] diff --git a/code/controllers/subsystems/jobs.dm b/code/controllers/subsystems/jobs.dm index 06515ee5a2c..585412ca6a0 100644 --- a/code/controllers/subsystems/jobs.dm +++ b/code/controllers/subsystems/jobs.dm @@ -210,7 +210,7 @@ SUBSYSTEM_DEF(jobs) log_and_message_admins("User [spawner] spawned at spawn point with dangerous atmosphere.") return TRUE -/datum/controller/subsystem/jobs/proc/assign_role(var/mob/new_player/player, var/rank, var/latejoin = 0, var/datum/game_mode/mode = SSticker.mode) +/datum/controller/subsystem/jobs/proc/assign_role(var/mob/new_player/player, var/rank, var/latejoin = 0, var/decl/game_mode/mode = SSticker.mode) if(player && player.mind && rank) var/datum/job/job = get_by_title(rank) if(!job) @@ -251,7 +251,7 @@ SUBSYSTEM_DEF(jobs) candidates += player return candidates -/datum/controller/subsystem/jobs/proc/give_random_job(var/mob/new_player/player, var/datum/game_mode/mode = SSticker.mode) +/datum/controller/subsystem/jobs/proc/give_random_job(var/mob/new_player/player, var/decl/game_mode/mode = SSticker.mode) for(var/datum/job/job in shuffle(primary_job_datums)) if(!job) continue @@ -275,7 +275,7 @@ SUBSYSTEM_DEF(jobs) break ///This proc is called before the level loop of divide_occupations() and will try to select a head, ignoring ALL non-head preferences for every level until it locates a head or runs out of levels to check -/datum/controller/subsystem/jobs/proc/fill_head_position(var/datum/game_mode/mode) +/datum/controller/subsystem/jobs/proc/fill_head_position(var/decl/game_mode/mode) for(var/level = 1 to 3) for(var/command_position in must_fill_titles) var/datum/job/job = get_by_title(command_position) @@ -311,7 +311,7 @@ SUBSYSTEM_DEF(jobs) return 0 ///This proc is called at the start of the level loop of divide_occupations() and will cause head jobs to be checked before any other jobs of the same level -/datum/controller/subsystem/jobs/proc/CheckHeadPositions(var/level, var/datum/game_mode/mode) +/datum/controller/subsystem/jobs/proc/CheckHeadPositions(var/level, var/decl/game_mode/mode) for(var/command_position in must_fill_titles) var/datum/job/job = get_by_title(command_position) if(!job) continue @@ -324,7 +324,7 @@ SUBSYSTEM_DEF(jobs) * fills var "assigned_role" for all ready players. * This proc must not have any side effect besides of modifying "assigned_role". **/ -/datum/controller/subsystem/jobs/proc/divide_occupations(datum/game_mode/mode) +/datum/controller/subsystem/jobs/proc/divide_occupations(decl/game_mode/mode) if(global.triai) for(var/datum/job/A in primary_job_datums) if(A.title == "AI") @@ -399,7 +399,7 @@ SUBSYSTEM_DEF(jobs) unassigned_roundstart -= player return TRUE -/datum/controller/subsystem/jobs/proc/attempt_role_assignment(var/mob/new_player/player, var/datum/job/job, var/level, var/datum/game_mode/mode) +/datum/controller/subsystem/jobs/proc/attempt_role_assignment(var/mob/new_player/player, var/datum/job/job, var/level, var/decl/game_mode/mode) if(!jobban_isbanned(player, job.title) && \ job.player_old_enough(player.client) && \ player.client.prefs.CorrectLevel(job, level) && \ @@ -469,32 +469,32 @@ SUBSYSTEM_DEF(jobs) return spawn_in_storage -/datum/controller/subsystem/jobs/proc/equip_rank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0) +/datum/controller/subsystem/jobs/proc/equip_job_title(var/mob/living/carbon/human/H, var/job_title, var/joined_late = 0) if(!H) return - var/datum/job/job = get_by_title(rank) + var/datum/job/job = get_by_title(job_title) var/list/spawn_in_storage if(job) if(H.client) if(global.using_map.flags & MAP_HAS_BRANCH) - H.char_branch = mil_branches.get_branch(H.client.prefs.branches[rank]) + H.char_branch = mil_branches.get_branch(H.client.prefs.branches[job_title]) if(global.using_map.flags & MAP_HAS_RANK) - H.char_rank = mil_branches.get_rank(H.client.prefs.branches[rank], H.client.prefs.ranks[rank]) + H.char_rank = mil_branches.get_rank(H.client.prefs.branches[job_title], H.client.prefs.ranks[job_title]) // Transfers the skill settings for the job to the mob H.skillset.obtain_from_client(job, H.client) //Equip job items. - job.equip(H, H.mind ? H.mind.role_alt_title : "", H.char_branch, H.char_rank) + job.setup_account(H) + job.equip_job(H, H.mind?.role_alt_title, H.char_branch, H.char_rank) job.apply_fingerprints(H) spawn_in_storage = equip_custom_loadout(H, job) - job.setup_account(H) else - to_chat(H, "Your job is [rank] and the game just can't handle it! Please report this bug to an administrator.") + to_chat(H, "Your job is [job_title] and the game just can't handle it! Please report this bug to an administrator.") - H.job = rank + H.job = job_title if(!joined_late || job.latejoin_at_spawnpoints) var/obj/S = job.get_roundstart_spawnpoint() @@ -503,7 +503,7 @@ SUBSYSTEM_DEF(jobs) H.forceMove(S.loc) else var/decl/spawnpoint/spawnpoint = job.get_spawnpoint(H.client) - H.forceMove(pick(spawnpoint.turfs)) + H.forceMove(DEFAULTPICK(spawnpoint.get_spawn_turfs(H), get_random_spawn_turf(SPAWN_FLAG_JOBS_CAN_SPAWN))) spawnpoint.after_join(H) // Moving wheelchair if they have one @@ -531,23 +531,26 @@ SUBSYSTEM_DEF(jobs) var/alt_title = null if(!H.mind) H.mind_initialize() - H.mind.assigned_job = job - H.mind.assigned_role = rank + H.mind.assigned_job = job + H.mind.assigned_role = job_title alt_title = H.mind.role_alt_title var/mob/other_mob = job.handle_variant_join(H, alt_title) if(other_mob) - job.post_equip_rank(other_mob, alt_title || rank) + job.post_equip_job_title(other_mob, alt_title || job_title) return other_mob if(spawn_in_storage) for(var/decl/loadout_option/G in spawn_in_storage) G.spawn_in_storage_or_drop(H, H.client.prefs.Gear()[G.name]) - to_chat(H, "You are [job.total_positions == 1 ? "the" : "a"] [alt_title ? alt_title : rank].") + to_chat(H, "You are [job.total_positions == 1 ? "the" : "a"] [alt_title || job_title].") + + if(job.description) + to_chat(H, SPAN_BOLD("[job.description]")) if(job.supervisors) - to_chat(H, "As the [alt_title ? alt_title : rank] you answer directly to [job.supervisors]. Special circumstances may change this.") + to_chat(H, "As the [alt_title || job_title] you answer directly to [job.supervisors]. Special circumstances may change this.") if(H.has_headset_in_ears()) to_chat(H, "To speak on your department's radio channel use [H.get_department_radio_prefix()]h. For the use of other channels, examine your headset.") @@ -562,7 +565,7 @@ SUBSYSTEM_DEF(jobs) BITSET(H.hud_updateflag, IMPLOYAL_HUD) BITSET(H.hud_updateflag, SPECIALROLE_HUD) - job.post_equip_rank(H, alt_title || rank) + job.post_equip_job_title(H, alt_title || job_title) H.client.show_location_blurb(30) diff --git a/code/controllers/subsystems/mapping.dm b/code/controllers/subsystems/mapping.dm index 05ed500bca1..844f5b790bc 100644 --- a/code/controllers/subsystems/mapping.dm +++ b/code/controllers/subsystems/mapping.dm @@ -22,9 +22,9 @@ SUBSYSTEM_DEF(mapping) * Z-Level Handling Stuff */ /// Associative list of levels by strict z-level - var/list/levels_by_z = list() + var/list/datum/level_data/levels_by_z = list() /// Associative list of levels by string ID - var/list/levels_by_id = list() + var/list/datum/level_data/levels_by_id = list() /// List of z-levels containing the 'main map' var/list/station_levels = list() /// List of z-levels for admin functionality (Centcom, shuttle transit, etc) @@ -55,12 +55,16 @@ SUBSYSTEM_DEF(mapping) var/list/planetoid_data_by_z = list() /// List of z-levels that regenerates mining turfs periodically var/list/mining_levels = list() + ///A list of queued markers to initialize during SSmapping init. + var/list/obj/abstract/landmark/map_load_mark/queued_markers = list() /datum/controller/subsystem/mapping/PreInit() reindex_lists() /datum/controller/subsystem/mapping/Initialize(timeofday) + reindex_lists() + // Load our banned map list, if we have one. if(banned_dmm_location && fexists(banned_dmm_location)) banned_maps = cached_json_decode(safe_file2text(banned_dmm_location)) @@ -69,19 +73,6 @@ SUBSYSTEM_DEF(mapping) for(var/datum/map_template/MT as anything in get_all_template_instances()) register_map_template(MT) - // Resize the world to the max template size to fix a BYOND bug with world resizing breaking events. - // REMOVE WHEN THIS IS FIXED: https://www.byond.com/forum/post/2833191 - var/new_maxx = world.maxx - var/new_maxy = world.maxy - for(var/map_template_name in map_templates) - var/datum/map_template/map_template = map_templates[map_template_name] - new_maxx = max(map_template.width, new_maxx) - new_maxy = max(map_template.height, new_maxy) - if (new_maxx > world.maxx) - world.maxx = new_maxx - if (new_maxy > world.maxy) - world.maxy = new_maxy - // Populate overmap. if(length(global.using_map.overmap_ids)) for(var/overmap_id in global.using_map.overmap_ids) @@ -90,27 +81,49 @@ SUBSYSTEM_DEF(mapping) // This needs to be non-null even if the overmap isn't created for this map. overmap_event_handler = GET_DECL(/decl/overmap_event_handler) + var/old_maxz + for(var/z = 1 to world.maxz) + var/datum/level_data/level = levels_by_z[z] + if(!istype(level)) + level = new /datum/level_data/space(z) + PRINT_STACK_TRACE("Missing z-level data object for z[num2text(z)]!") + level.setup_level_data() + + old_maxz = world.maxz //PS13 Build main map sites templates global.using_map.build_main_sites() // Build away sites. global.using_map.build_away_sites() global.using_map.build_planets() - - // Initialize z-level objects. -#ifdef UNIT_TEST - config.roundstart_level_generation = FALSE -#endif - for(var/z = 1 to world.maxz) + for(var/z = old_maxz + 1 to world.maxz) var/datum/level_data/level = levels_by_z[z] if(!istype(level)) level = new /datum/level_data/space(z) PRINT_STACK_TRACE("Missing z-level data object for z[num2text(z)]!") level.setup_level_data() - // Generate turbolifts last!!! + // Generate turbolifts last, since away sites may have elevators to generate too. for(var/obj/abstract/turbolift_spawner/turbolift as anything in turbolifts_to_initialize) turbolift.build_turbolift() + // Resize the world to the max template size to fix a BYOND bug with world resizing breaking events. + // REMOVE WHEN THIS IS FIXED: https://www.byond.com/forum/post/2833191 + var/new_maxx = world.maxx + var/new_maxy = world.maxy + for(var/map_template_name in map_templates) + var/datum/map_template/map_template = map_templates[map_template_name] + new_maxx = max(map_template.width, new_maxx) + new_maxy = max(map_template.height, new_maxy) + if (new_maxx > world.maxx) + world.maxx = new_maxx + if (new_maxy > world.maxy) + world.maxy = new_maxy + + // Initialize z-level objects. +#ifdef UNIT_TEST + config.roundstart_level_generation = FALSE //#FIXME: Shouldn't this be set before running level_data/setup_level_data()? +#endif + . = ..() /datum/controller/subsystem/mapping/Recover() diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm index 61d8f7f626f..689c5f1bd68 100644 --- a/code/controllers/subsystems/overlays.dm +++ b/code/controllers/subsystems/overlays.dm @@ -179,7 +179,7 @@ SUBSYSTEM_DEF(overlays) if(NOT_QUEUED_ALREADY) QUEUE_FOR_COMPILE -/atom/proc/set_overlays(list/overlays_list, priority = FALSE) // Sets overlays to a list, equivalent to cut_overlays() + add_overlays(). +/atom/proc/set_overlays(list/overlays_list, priority = FALSE) // Sets overlays to a list, equivalent to cut_overlays() + add_overlay(). if (!overlays_list) return diff --git a/code/controllers/subsystems/processing/airflow.dm b/code/controllers/subsystems/processing/airflow.dm index 968e35e237c..ee06f067672 100644 --- a/code/controllers/subsystems/processing/airflow.dm +++ b/code/controllers/subsystems/processing/airflow.dm @@ -5,7 +5,7 @@ TARGET.airflow_time = 0; \ TARGET.airflow_skip_speedcheck = FALSE; \ if (TARGET.airflow_od) { \ - TARGET.density = 0; \ + TARGET.density = FALSE; \ } PROCESSING_SUBSYSTEM_DEF(airflow) @@ -54,7 +54,7 @@ PROCESSING_SUBSYSTEM_DEF(airflow) if (target.airflow_speed > 7) if (target.airflow_time++ >= target.airflow_speed - 7) if (target.airflow_od) - target.density = 0 + target.density = FALSE target.airflow_skip_speedcheck = TRUE if (MC_TICK_CHECK) @@ -62,7 +62,7 @@ PROCESSING_SUBSYSTEM_DEF(airflow) continue else if (target.airflow_od) - target.density = 0 + target.density = FALSE target.airflow_process_delay = max(1, 10 - (target.airflow_speed + 3)) target.airflow_skip_speedcheck = TRUE @@ -73,7 +73,7 @@ PROCESSING_SUBSYSTEM_DEF(airflow) target.airflow_skip_speedcheck = FALSE if (target.airflow_od) - target.density = 1 + target.density = TRUE if (!target.airflow_dest || target.loc == target.airflow_dest) target.airflow_dest = locate(min(max(target.x + target.airflow_xo, 1), world.maxx), min(max(target.y + target.airflow_yo, 1), world.maxy), target.z) @@ -135,7 +135,7 @@ PROCESSING_SUBSYSTEM_DEF(airflow) airflow_od = 0 if (!density) - density = 1 + density = TRUE airflow_od = 1 return TRUE diff --git a/code/controllers/subsystems/skybox.dm b/code/controllers/subsystems/skybox.dm index 6846f2308c2..56f789d94d4 100644 --- a/code/controllers/subsystems/skybox.dm +++ b/code/controllers/subsystems/skybox.dm @@ -39,7 +39,7 @@ SUBSYSTEM_DEF(skybox) /datum/controller/subsystem/skybox/proc/build_space_appearances() //Create our 'normal' space appearance normal_space = new /mutable_appearance(/turf/space) - normal_space.appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER + normal_space.appearance_flags = TILE_BOUND|DEFAULT_APPEARANCE_FLAGS|KEEP_TOGETHER normal_space.plane = SKYBOX_PLANE normal_space.icon_state = "white" @@ -112,12 +112,12 @@ SUBSYSTEM_DEF(skybox) /datum/controller/subsystem/skybox/proc/generate_skybox(z) var/image/res = image(skybox_icon) - res.appearance_flags = PIXEL_SCALE | KEEP_TOGETHER + res.appearance_flags |= KEEP_TOGETHER - var/image/base = overlay_image(skybox_icon, background_icon, background_color, PIXEL_SCALE) + var/image/base = overlay_image(skybox_icon, background_icon, background_color, DEFAULT_APPEARANCE_FLAGS) if(use_stars) - var/image/stars = overlay_image(stars_icon, star_state, flags = PIXEL_SCALE | RESET_COLOR) + var/image/stars = overlay_image(stars_icon, star_state, flags = DEFAULT_APPEARANCE_FLAGS | RESET_COLOR) base.overlays += stars res.overlays += base @@ -130,7 +130,7 @@ SUBSYSTEM_DEF(skybox) for(var/obj/effect/overmap/visitable/other in O.loc) if(other != O) overmap.overlays += other.get_skybox_representation() - overmap.appearance_flags = PIXEL_SCALE | RESET_COLOR + overmap.appearance_flags |= RESET_COLOR res.overlays += overmap for(var/datum/event/E in SSevent.active_events) diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm index ad07ef44091..ef71515dbf0 100644 --- a/code/controllers/subsystems/supply.dm +++ b/code/controllers/subsystems/supply.dm @@ -63,7 +63,7 @@ SUBSYSTEM_DEF(supply) //To stop things being sent to centcomm which should not be sent to centcomm. Recursively checks for these types. /datum/controller/subsystem/supply/proc/forbidden_atoms_check(atom/A) - if(istype(A,/mob/living)) + if(isliving(A)) return 1 if(istype(A,/obj/item/disk/nuclear)) return 1 @@ -89,24 +89,21 @@ SUBSYSTEM_DEF(supply) add_points_from_source(CR.get_single_monetary_worth() * crate_return_rebate * 0.1, "crate") var/find_slip = 1 - for(var/atom in CR) + for(var/atom/atom as anything in CR) // Sell manifests - var/atom/A = atom - if(find_slip && istype(A,/obj/item/paper/manifest)) - var/obj/item/paper/manifest/slip = A + if(find_slip && istype(atom, /obj/item/paper/manifest)) + var/obj/item/paper/manifest/slip = atom if(!LAZYACCESS(slip.metadata, "is_copy") && LAZYLEN(slip.applied_stamps)) add_points_from_source(LAZYACCESS(slip.metadata, "order_total") * slip_return_rebate, "manifest") find_slip = 0 continue // Sell materials - if(is_type_in_list(A.type, saleable_materials)) - add_points_from_source(A.get_combined_monetary_worth() * goods_sale_modifier * 0.1, "goods") - + if(is_type_in_list(atom, saleable_materials)) + add_points_from_source(atom.get_combined_monetary_worth() * goods_sale_modifier * 0.1, "goods") // Must sell ore detector disks in crates - if(istype(A, /obj/item/disk/survey)) - var/obj/item/disk/survey/D = A - add_points_from_source(D.get_combined_monetary_worth() * 0.005, "data") + else if(istype(atom, /obj/item/disk/survey)) + add_points_from_source(atom.get_combined_monetary_worth() * 0.005, "data") qdel(AM) diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm index 4c6dfbb6ccd..f10c02c06cf 100644 --- a/code/controllers/subsystems/throwing.dm +++ b/code/controllers/subsystems/throwing.dm @@ -170,11 +170,10 @@ SUBSYSTEM_DEF(throwing) thrownthing.throwing = null if (!hit) - for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on. - var/atom/A = thing - if (A == target) + for (var/atom/thing as anything in get_turf(thrownthing)) //looking for our target on the turf we land on. + if (thing == target) hit = TRUE - thrownthing.throw_impact(A, src) + thrownthing.throw_impact(thing, src) break if(QDELETED(thrownthing)) @@ -182,9 +181,10 @@ SUBSYSTEM_DEF(throwing) if(!hit) thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. - thrownthing.space_drift(init_dir) + if(!QDELETED(thrownthing)) + thrownthing.space_drift(init_dir) - if(t_target) + if(t_target && !QDELETED(thrownthing)) thrownthing.throw_impact(t_target, src) if (callback) diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 7bd02bedd58..ac86a586db1 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -8,11 +8,11 @@ SUBSYSTEM_DEF(ticker) var/pregame_timeleft = 3 MINUTES var/start_ASAP = FALSE //the game will start as soon as possible, bypassing all pre-game nonsense - var/list/gamemode_vote_results //Will be a list, in order of preference, of form list(config_tag = number of votes). + var/list/gamemode_vote_results //Will be a list, in order of preference, of form list(uid = number of votes). var/bypass_gamemode_vote = 0 //Intended for use with admin tools. Will avoid voting and ignore any results. - var/master_mode = "extended" //The underlying game mode (so "secret" or the voted mode). Saved to default back to previous round's mode in case the vote failed. This is a config_tag. - var/datum/game_mode/mode //The actual gamemode, if selected. + var/master_mode = "extended" //The underlying game mode (so "secret" or the voted mode). Saved to default back to previous round's mode in case the vote failed. This is a uid. + var/decl/game_mode/mode //The actual gamemode, if selected. var/round_progressing = 1 //Whether the lobby clock is ticking down. var/list/bad_modes = list() //Holds modes we tried to start and failed to. @@ -206,7 +206,7 @@ Helpers . = (revotes_allowed && !bypass_gamemode_vote) ? CHOOSE_GAMEMODE_REVOTE : CHOOSE_GAMEMODE_RESTART var/mode_to_try = master_mode //This is the config tag - var/datum/game_mode/mode_datum + var/decl/game_mode/mode_datum //Decide on the mode to try. if(!bypass_gamemode_vote && gamemode_vote_results) @@ -223,20 +223,20 @@ Helpers return //Find the relevant datum, resolving secret in the process. - var/list/base_runnable_modes = config.get_runnable_modes() //format: list(config_tag = weight) + var/list/base_runnable_modes = config.get_runnable_modes() //format: list(uid = weight) if((mode_to_try=="random") || (mode_to_try=="secret")) var/list/runnable_modes = base_runnable_modes - bad_modes if(secret_force_mode != "secret") // Config option to force secret to be a specific mode. - mode_datum = config.pick_mode(secret_force_mode) + mode_datum = decls_repository.get_decl_by_id(secret_force_mode, validate_decl_type = FALSE) else if(!length(runnable_modes)) // Indicates major issues; will be handled on return. bad_modes += mode_to_try return else - mode_datum = config.pick_mode(pickweight(runnable_modes)) + mode_datum = decls_repository.get_decl_by_id(pickweight(runnable_modes), validate_decl_type = FALSE) if(length(runnable_modes) > 1) // More to pick if we fail; we won't tell anyone we failed unless we fail all possibilities, though. . = CHOOSE_GAMEMODE_SILENT_REDO else - mode_datum = config.pick_mode(mode_to_try) + mode_datum = decls_repository.get_decl_by_id(mode_to_try, validate_decl_type = FALSE) if(!istype(mode_datum)) bad_modes += mode_to_try return @@ -250,7 +250,7 @@ Helpers if(mode_datum.startRequirements()) mode_datum.fail_setup() SSjobs.reset_occupations() - bad_modes += mode_datum.config_tag + bad_modes += mode_datum.uid return //Declare victory, make an announcement. @@ -261,7 +261,7 @@ Helpers to_world("The current game mode is Secret!") var/list/mode_names = list() for (var/mode_tag in base_runnable_modes) - var/datum/game_mode/M = gamemode_cache[mode_tag] + var/decl/game_mode/M = decls_repository.get_decl_by_id(mode_tag, validate_decl_type = FALSE) if(M) mode_names += M.name if (config.secret_hide_possibilities) @@ -291,11 +291,11 @@ Helpers if(player.mind.assigned_role == "Captain") captainless=0 if(!player_is_antag(player.mind, only_offstation_roles = 1)) - SSjobs.equip_rank(player, player.mind.assigned_role, 0) + SSjobs.equip_job_title(player, player.mind.assigned_role, 0) SScustomitems.equip_custom_items(player) if(captainless) for(var/mob/M in global.player_list) - if(!istype(M,/mob/new_player)) + if(!isnewplayer(M)) to_chat(M, "Captainship not forced on anyone.") /datum/controller/subsystem/ticker/proc/attempt_late_antag_spawn(var/list/antag_choices) @@ -383,7 +383,7 @@ Helpers to_world("
") for (var/mob/living/silicon/ai/aiPlayer in SSmobs.mob_list) - if (aiPlayer.stat != 2) + if (aiPlayer.stat != DEAD) to_world("[aiPlayer.name] (Played by: [aiPlayer.key])'s laws at the end of the round were:") else @@ -401,12 +401,12 @@ Helpers for (var/mob/living/silicon/robot/robo in SSmobs.mob_list) - if(istype(robo,/mob/living/silicon/robot/drone)) + if(isdrone(robo)) dronecount++ continue if (!robo.connected_ai) - if (robo.stat != 2) + if (robo.stat != DEAD) to_world("[robo.name] (Played by: [robo.key]) survived as an AI-less synthetic! Its laws were:") else diff --git a/code/controllers/subsystems/typing.dm b/code/controllers/subsystems/typing.dm index c6ac9dce6a1..8f68fa0e711 100644 --- a/code/controllers/subsystems/typing.dm +++ b/code/controllers/subsystems/typing.dm @@ -146,7 +146,7 @@ Updated 09/10/2022 to include chatbar using Spookerton's SStyping system from Po /atom/movable/typing_indicator icon = 'icons/mob/talk.dmi' icon_state = "typing" - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE vis_flags = VIS_INHERIT_ID var/atom/movable/master @@ -182,7 +182,7 @@ Updated 09/10/2022 to include chatbar using Spookerton's SStyping system from Po /atom/movable/typing_indicator/proc/show_typing_indicator() // Make it visible after being hidden. - set_invisibility(0) + set_invisibility(INVISIBILITY_NONE) // Update the appearance. if(ismob(master)) diff --git a/code/controllers/subsystems/weather.dm b/code/controllers/subsystems/weather.dm index 539ceba1bdc..46e00772251 100644 --- a/code/controllers/subsystems/weather.dm +++ b/code/controllers/subsystems/weather.dm @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(weather) /datum/controller/subsystem/weather/proc/register_weather_system(var/obj/abstract/weather_system/WS) if(weather_by_z[WS.z]) CRASH("Trying to register another weather system on the same z-level([WS.z]) as an existing one!") - LAZYDISTINCTADD(weather_systems, WS) + weather_systems |= WS //Mark all affected z-levels var/list/affected = SSmapping.get_connected_levels(WS.z) @@ -62,10 +62,4 @@ SUBSYSTEM_DEF(weather) for(var/Z = 1 to length(weather_by_z)) if(weather_by_z[Z] == WS) weather_by_z[Z] = null - LAZYREMOVE(weather_systems, WS) - -///Returns the weather obj for a given z-level if it exists -/datum/controller/subsystem/weather/proc/get_weather_for_level(var/z_level) - if(z_level > length(weather_by_z)) - return null - return weather_by_z[z_level] \ No newline at end of file + weather_systems -= WS diff --git a/code/datums/beam.dm b/code/datums/beam.dm index 94b45c39201..c2cc3738f24 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -134,7 +134,7 @@ var/global/list/beam_icon_cache = list() // shut up chinsky I do not have a cach /obj/effect/ebeam simulated = FALSE anchored = TRUE - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE /atom/proc/Beam(atom/BeamTarget, icon_state="b_beam", icon='icons/effects/beam.dmi', time = 5 SECONDS, maxdistance = 10, beam_type = /obj/effect/ebeam, beam_sleep_time = 3, beam_color = null) var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time,beam_color) diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index 3d3b054bdf2..8c135bfed32 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -7,16 +7,16 @@ var/global/datum/cinematic/cinematic = new var/obj/screen/cinematic_screen = null //Plus it provides an easy way to make cinematics for other events. Just use this as a template :) -/datum/cinematic/proc/station_explosion_cinematic(var/station_missed=0, var/datum/game_mode/override) +/datum/cinematic/proc/station_explosion_cinematic(var/station_missed=0, var/decl/game_mode/override) set waitfor = FALSE - if(cinematic_screen) + if(cinematic_screen) return //already a cinematic in progress! if(!override) override = SSticker.mode if(!override) - override = gamemode_cache["extended"] + override = GET_DECL(/decl/game_mode/extended) if(!override) return @@ -26,7 +26,7 @@ var/global/datum/cinematic/cinematic = new cinematic_screen.icon_state = "station_intact" cinematic_screen.plane = HUD_PLANE cinematic_screen.layer = HUD_ABOVE_ITEM_LAYER - cinematic_screen.mouse_opacity = 0 + cinematic_screen.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE cinematic_screen.screen_loc = "LEFT+1,BOTTOM" //Let's not discuss how this worked previously. diff --git a/code/datums/extensions/access_provider.dm b/code/datums/extensions/access_provider.dm index f9f367c070e..845ff159f48 100644 --- a/code/datums/extensions/access_provider.dm +++ b/code/datums/extensions/access_provider.dm @@ -13,6 +13,6 @@ /datum/extension/access_provider/proc/unregister_id(atom/movable/to_unregister) LAZYREMOVE(registered_ids, to_unregister) -/datum/extension/access_provider/proc/GetIdCards() +/datum/extension/access_provider/proc/GetIdCards(list/exceptions) for(var/atom/movable/registered_id in registered_ids) - LAZYDISTINCTADD(., registered_id.GetIdCards()) + LAZYDISTINCTADD(., registered_id.GetIdCards(exceptions)) diff --git a/code/datums/extensions/appearance/universally_visible.dm b/code/datums/extensions/appearance/universally_visible.dm index 7dfc753e177..76de6559b8c 100644 --- a/code/datums/extensions/appearance/universally_visible.dm +++ b/code/datums/extensions/appearance/universally_visible.dm @@ -53,7 +53,7 @@ var/global/list/universally_visible_atom_extensions = list() I = image(null) I.appearance = visible_atom - I.mouse_opacity = 0 + I.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE I.pixel_x = world.icon_size * (atom_turf.x - mob_turf.x) + visible_atom.pixel_x I.pixel_y = world.icon_size * (atom_turf.y - mob_turf.y) + visible_atom.pixel_y I.loc = get_turf(mob_turf) diff --git a/code/datums/extensions/armor/ablative.dm b/code/datums/extensions/armor/ablative.dm index 9082d7fe2cf..fe7c215f4be 100644 --- a/code/datums/extensions/armor/ablative.dm +++ b/code/datums/extensions/armor/ablative.dm @@ -14,7 +14,7 @@ if(!(damage_type == BRUTE || damage_type == BURN)) return if(armor_degradation_coef) - var/key = get_armor_key(damage_type, damage_flags) + var/key = SSmaterials.get_armor_key(damage_type, damage_flags) var/damage_blocked = round(damage * blocked) if(damage_blocked) var/new_armor = max(0, get_value(key) - armor_degradation_coef * damage_blocked) diff --git a/code/datums/extensions/armor/armor.dm b/code/datums/extensions/armor/armor.dm index dbb0e7ad84c..8e9dd0055ba 100644 --- a/code/datums/extensions/armor/armor.dm +++ b/code/datums/extensions/armor/armor.dm @@ -52,7 +52,7 @@ // A simpler proc used as a helper for above but can also be used externally. Does not modify state. /datum/extension/armor/proc/get_blocked(damage_type, damage_flags, armor_pen = 0, damage = 5) - var/key = get_armor_key(damage_type, damage_flags) + var/key = SSmaterials.get_armor_key(damage_type, damage_flags) if(!key) return 0 @@ -71,33 +71,6 @@ /datum/extension/armor/proc/set_value(key, newval) armor_values[key] = clamp(newval, 0, 100) -// There is a disconnect between legacy damage and armor code. This here helps bridge the gap. -/proc/get_armor_key(damage_type, damage_flags) - var/key - switch(damage_type) - if(BRUTE) - if(damage_flags & DAM_BULLET) - key = ARMOR_BULLET - else if(damage_flags & DAM_EXPLODE) - key = ARMOR_BOMB - else - key = ARMOR_MELEE - if(BURN) - if(damage_flags & DAM_LASER) - key = ARMOR_LASER - else if(damage_flags & DAM_EXPLODE) - key = ARMOR_BOMB - else - key = ARMOR_ENERGY - if(TOX) - if(damage_flags & DAM_BIO) - key = ARMOR_BIO // Otherwise just not blocked by default. - if(IRRADIATE) - key = ARMOR_RAD - if(ELECTROCUTE) - key = ARMOR_ENERGY - return key - /datum/extension/armor/toggle var/active = TRUE diff --git a/code/datums/extensions/assembly/assembly_interaction.dm b/code/datums/extensions/assembly/assembly_interaction.dm index e068d5e9305..e59c7d531da 100644 --- a/code/datums/extensions/assembly/assembly_interaction.dm +++ b/code/datums/extensions/assembly/assembly_interaction.dm @@ -72,6 +72,15 @@ drive_slot.insert_drive(I, user) return TRUE + if(istype(W, /obj/item/disk)) + var/obj/item/disk/disk = W + var/obj/item/stock_parts/computer/data_disk_drive/disk_drive = get_component(PART_DSKSLOT) + if(!disk_drive) + to_chat(user, SPAN_WARNING("You try to insert [disk] into [holder], but it does not have a disk slot installed.")) + return TRUE + disk_drive.insert_disk(disk, user) + return TRUE + if(istype(W, /obj/item/paper)) var/obj/item/paper/paper = W if(paper.info) diff --git a/code/datums/extensions/deity_be_near.dm b/code/datums/extensions/deity_be_near.dm index ad95104e24a..fa8f07b6a46 100644 --- a/code/datums/extensions/deity_be_near.dm +++ b/code/datums/extensions/deity_be_near.dm @@ -24,7 +24,7 @@ /datum/extension/deity_be_near/proc/check_movement() var/obj/item/I = holder - if(!istype(I.loc, /mob/living)) + if(!isliving(I.loc)) return var/min_dist = INFINITY for(var/s in connected_deity.structures) diff --git a/code/datums/extensions/extensions.dm b/code/datums/extensions/extensions.dm index 75ec04ea73a..84887ae548b 100644 --- a/code/datums/extensions/extensions.dm +++ b/code/datums/extensions/extensions.dm @@ -42,6 +42,8 @@ //Variadic - Additional positional arguments can be given. Named arguments might not work so well /proc/set_extension(var/datum/source, var/datum/extension/extension_type) + if(QDELETED(source)) + CRASH("Invalid extension source datum: source was qdeleted, was [log_info_line(source)]") var/datum/extension/extension_base_type = initial(extension_type.base_type) if(!ispath(extension_base_type, /datum/extension)) CRASH("Invalid base type: Expected /datum/extension, was [log_info_line(extension_base_type)]") diff --git a/code/datums/extensions/hattable.dm b/code/datums/extensions/hattable.dm deleted file mode 100644 index a12f3fc2916..00000000000 --- a/code/datums/extensions/hattable.dm +++ /dev/null @@ -1,65 +0,0 @@ -// Note that humans handle hats on their own without this extension. -// This is primarily for diona nymphs and maintenance drones. -/datum/extension/hattable - base_type = /datum/extension/hattable - flags = EXTENSION_FLAG_IMMEDIATE - var/list/offsets - var/obj/item/hat - -/datum/extension/hattable/New(var/datum/holder, var/new_offsets) - offsets = islist(new_offsets) ? new_offsets : list(0, 0) - ..() - -/datum/extension/hattable/proc/wear_hat(var/mob/wearer, var/obj/item/clothing/head/new_hat) - if(hat || !istype(new_hat)) - return FALSE - hat = new_hat - hat.forceMove(wearer) - hat.equipped(wearer) - wearer.update_icon() - return TRUE - -/datum/extension/hattable/proc/get_hat_overlay(var/mob/wearer, var/apply_offsets = TRUE) - var/image/I = hat?.get_mob_overlay(wearer, slot_head_str) - if(I && apply_offsets) - I.pixel_x += offsets[1] - I.pixel_y += offsets[2] - return I - -/datum/extension/hattable/proc/drop_hat(var/mob/wearer) - if((hat in wearer) && !QDELETED(hat)) - wearer.remove_from_mob(hat) - hat = null - wearer.update_icon() - -var/global/list/mob_hat_cache = list() -/datum/extension/hattable/directional/proc/offset_image(var/image/I) - - if(!istype(I)) - return - - var/mob/owner = holder - if(!istype(owner)) - return I - - var/cache_key = "[I.icon]-[I.icon_state]-[json_encode(offsets)]-[owner.icon]" - if(!global.mob_hat_cache[cache_key]) - var/icon/final = icon(owner.icon, "template") // whoever makes a mob hattable should also check it has a template state in its image - for(var/dir in offsets) - var/list/facing_list = offsets[dir] - var/icon/canvas = icon(owner.icon, "template") - var/use_dir = text2num(dir) - canvas.Blend(icon(I.icon, I.icon_state, dir = use_dir), ICON_OVERLAY, facing_list[1]+1, facing_list[2]+1) - final.Insert(canvas, dir = use_dir) - global.mob_hat_cache[cache_key] = final - - I.icon = global.mob_hat_cache[cache_key] - I.icon_state = "" - for(var/thing in I.overlays) - I.overlays -= thing - I.overlays += offset_image(thing) - - return I - -/datum/extension/hattable/directional/get_hat_overlay(var/mob/wearer, var/apply_offsets = TRUE) - return offset_image(..(wearer, FALSE)) diff --git a/code/datums/extensions/state_machine.dm b/code/datums/extensions/state_machine.dm index 4d573c68494..914f633541e 100644 --- a/code/datums/extensions/state_machine.dm +++ b/code/datums/extensions/state_machine.dm @@ -93,7 +93,10 @@ var/global/list/state_machines = list() var/datum/holder_instance = get_holder() if(istype(current_state)) current_state.exited_state(holder_instance) - current_state = GET_DECL(new_state_type) + if(ispath(new_state_type)) + current_state = GET_DECL(new_state_type) + else // need to include null here, so we can't do an istype + current_state = new_state_type if(istype(current_state)) current_state.entered_state(holder_instance) return current_state diff --git a/code/datums/inventory_slots/_inventory_slot.dm b/code/datums/inventory_slots/_inventory_slot.dm index 7b97bc2dd17..e6c7b968d96 100644 --- a/code/datums/inventory_slots/_inventory_slot.dm +++ b/code/datums/inventory_slots/_inventory_slot.dm @@ -18,6 +18,10 @@ var/skip_on_strip_display = FALSE var/requires_slot_flags var/requires_organ_tag + var/quick_equip_priority = 0 // Higher priority means it will be checked first. + + var/mob_overlay_layer + var/alt_mob_overlay_layer /datum/inventory_slot/Destroy(force) _holding = null @@ -25,12 +29,8 @@ /datum/inventory_slot/proc/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE) - // Clear up any preexisting item. + // Save any preexisting item to clean up later. var/atom/movable/held = get_equipped_item() - if(held) - user.drop_from_inventory(held) - if(delete_old_item && !QDELETED(held)) - qdel(held) // Set slot vars. set_slot(prop) @@ -38,22 +38,47 @@ prop.hud_layerise() prop.equipped(user, slot_id) + // Clean up the preexisting item. + if(held) + // Force the unequip call because it's technically no longer equipped anymore. + unequipped(user, held, redraw_mob) + user.drop_from_inventory(held) + if(delete_old_item && !QDELETED(held)) + qdel(held) + // Redraw overlays if needed. - update_overlay(user, prop, redraw_mob) + update_mob_equipment_overlay(user, prop, redraw_mob) return TRUE /datum/inventory_slot/proc/unequipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) SHOULD_CALL_PARENT(TRUE) - clear_slot() + // Only empty the slot if it's actually our equipped item. + // Sometimes this runs on the old item after a new item is equipped in-place (like via the loadout) + // so we need to check this. + if(prop == get_equipped_item()) + clear_slot() for(var/slot in drop_slots_on_unequip) - var/obj/item/thing = user.get_equipped_item(slot) - if(thing) + var/datum/inventory_slot/slot_to_drop = user.get_inventory_slot_datum(slot) + if(!slot_to_drop) + continue + var/obj/item/thing = slot_to_drop.get_equipped_item() + if(thing && !slot_to_drop.can_equip_to_slot(user, thing, TRUE)) user.drop_from_inventory(thing) - update_overlay(user, prop, redraw_mob) + update_mob_equipment_overlay(user, prop, redraw_mob) return TRUE -/datum/inventory_slot/proc/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - return +/datum/inventory_slot/proc/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + if(!mob_overlay_layer || !slot_id) + return + if(alt_mob_overlay_layer) + if(_holding) + user.set_current_mob_overlay((_holding.use_alt_layer ? alt_mob_overlay_layer : mob_overlay_layer), _holding.get_mob_overlay(user, slot_id), FALSE) + user.set_current_mob_overlay((_holding.use_alt_layer ? mob_overlay_layer : alt_mob_overlay_layer), null, redraw_mob) + else + user.set_current_mob_overlay(mob_overlay_layer, null, FALSE) + user.set_current_mob_overlay(alt_mob_overlay_layer, null, redraw_mob) + else + user.set_current_mob_overlay(mob_overlay_layer, _holding?.get_mob_overlay(user, slot_id), redraw_mob) /datum/inventory_slot/proc/set_slot(var/obj/item/prop) _holding = prop @@ -134,7 +159,7 @@ return TRUE /datum/inventory_slot/proc/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning, var/ignore_equipped) - return ((!_holding || (ignore_equipped && _holding == prop)) && prop && slot_id && prop_can_fit_in_slot(prop)) + return ((!_holding || (ignore_equipped || _holding == prop)) && prop && slot_id && prop_can_fit_in_slot(prop)) /datum/inventory_slot/proc/prop_can_fit_in_slot(var/obj/item/prop) return (isnull(requires_slot_flags) || (requires_slot_flags & prop.slot_flags)) diff --git a/code/datums/inventory_slots/inventory_gripper.dm b/code/datums/inventory_slots/inventory_gripper.dm index aab683f39c9..27a94728c48 100644 --- a/code/datums/inventory_slots/inventory_gripper.dm +++ b/code/datums/inventory_slots/inventory_gripper.dm @@ -1,13 +1,19 @@ /datum/inventory_slot/gripper + var/hand_sort_priority = 1 var/can_use_held_item = TRUE + var/dexterity = DEXTERITY_FULL + var/covering_slot_flags + // For reference, grippers do not use ui_loc, they have it set dynamically during /datum/hud/proc/rebuild_hands() +/datum/inventory_slot/gripper/proc/get_dexterity() + return dexterity + /datum/inventory_slot/gripper/GetCloneArgs() return list(slot_id, ui_loc, overlay_slot, ui_label) -/datum/inventory_slot/gripper/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - . = ..() - user.update_inv_hands(redraw_mob) +/datum/inventory_slot/gripper/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + user.update_inhand_overlays(redraw_mob) /datum/inventory_slot/gripper/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE) . = ..() @@ -21,18 +27,27 @@ return "You are holding [_holding.get_examine_line()] in your [E?.name || lowertext(slot_name)]." return "[pronouns.He] [pronouns.is] holding [_holding.get_examine_line()] in [pronouns.his] [E?.name || lowertext(slot_name)]." +/datum/inventory_slot/gripper/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning) + return ..() && user.check_dexterity(DEXTERITY_EQUIP_ITEM) + // Hand subtypes below -// Mouths are used by diona nymphs and Ascent babies to eat stuff, not just hold stuff in the mouth. /datum/inventory_slot/gripper/mouth slot_name = "Mouth" slot_id = BP_MOUTH - requires_organ_tag = null + requires_organ_tag = BP_HEAD can_use_held_item = FALSE + overlay_slot = BP_MOUTH + ui_label = "M" + hand_sort_priority = 3 /datum/inventory_slot/gripper/mouth/can_equip_to_slot(mob/user, obj/item/prop, disable_warning, ignore_equipped) . = ..() && prop.w_class <= user.can_pull_size -/datum/inventory_slot/gripper/mouth/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE) +// Mouths are used by diona nymphs and Ascent babies to eat stuff, not just hold stuff in the mouth. +/datum/inventory_slot/gripper/mouth/nymph + requires_organ_tag = null + +/datum/inventory_slot/gripper/mouth/nymph/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE) . = ..() if(.) @@ -57,6 +72,7 @@ requires_organ_tag = BP_L_HAND overlay_slot = BP_L_HAND ui_label = "L" + covering_slot_flags = SLOT_HAND_LEFT /datum/inventory_slot/gripper/right_hand slot_name = "Right Hand" @@ -64,3 +80,4 @@ requires_organ_tag = BP_R_HAND overlay_slot = BP_R_HAND ui_label = "R" + covering_slot_flags = SLOT_HAND_RIGHT diff --git a/code/datums/inventory_slots/slots/slot_back.dm b/code/datums/inventory_slots/slots/slot_back.dm index 2bf8fcc7b08..0fa0cbed807 100644 --- a/code/datums/inventory_slots/slots/slot_back.dm +++ b/code/datums/inventory_slots/slots/slot_back.dm @@ -5,9 +5,8 @@ slot_state = "back" requires_organ_tag = BP_CHEST requires_slot_flags = SLOT_BACK - -/datum/inventory_slot/back/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_back(redraw_mob) + mob_overlay_layer = HO_BACK_LAYER + quick_equip_priority = 13 /datum/inventory_slot/back/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding) diff --git a/code/datums/inventory_slots/slots/slot_belt.dm b/code/datums/inventory_slots/slots/slot_belt.dm index e4d34f0d2f5..c2521798b6c 100644 --- a/code/datums/inventory_slots/slots/slot_belt.dm +++ b/code/datums/inventory_slots/slots/slot_belt.dm @@ -5,20 +5,23 @@ ui_loc = ui_belt requires_organ_tag = BP_CHEST requires_slot_flags = SLOT_LOWER_BODY - -/datum/inventory_slot/belt/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_belt(redraw_mob) + mob_overlay_layer = HO_BELT_LAYER + alt_mob_overlay_layer = HO_BELT_LAYER_ALT + quick_equip_priority = 4 /datum/inventory_slot/belt/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning, var/ignore_equipped) . = ..() if(.) - // If they have a uniform slot, they need a uniform to wear a belt. + // Things with this flag can be worn on the belt slot without a uniform. + if(prop.item_flags & ITEM_FLAG_IS_BELT) + return TRUE + // Otherwise, if they have a uniform slot, they need a uniform to wear a belt. var/datum/inventory_slot/check_slot = user.get_inventory_slot_datum(slot_w_uniform_str) - if(check_slot && !check_slot.get_equipped_item()) - if(!disable_warning) - to_chat(user, SPAN_WARNING("You need to be wearing something on your body before you can wear \the [prop].")) - return FALSE - return (prop.item_flags & ITEM_FLAG_IS_BELT) + if(!check_slot || check_slot.get_equipped_item()) + return TRUE + if(!disable_warning) + to_chat(user, SPAN_WARNING("You need to be wearing something on your body before you can wear \the [prop].")) + return FALSE /datum/inventory_slot/belt/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding) diff --git a/code/datums/inventory_slots/slots/slot_cuffs.dm b/code/datums/inventory_slots/slots/slot_cuffs.dm index 5ff3c96b733..f49212d1e1e 100644 --- a/code/datums/inventory_slots/slots/slot_cuffs.dm +++ b/code/datums/inventory_slots/slots/slot_cuffs.dm @@ -7,9 +7,7 @@ BP_L_HAND, BP_R_HAND ) - -/datum/inventory_slot/handcuffs/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_handcuffed(redraw_mob) + mob_overlay_layer = HO_HANDCUFF_LAYER /datum/inventory_slot/handcuffs/equipped(mob/living/user, obj/item/prop, var/silent = FALSE) . = ..() diff --git a/code/datums/inventory_slots/slots/slot_ears.dm b/code/datums/inventory_slots/slots/slot_ears.dm index 86b7111e76b..b6dd92dd37f 100644 --- a/code/datums/inventory_slots/slots/slot_ears.dm +++ b/code/datums/inventory_slots/slots/slot_ears.dm @@ -8,9 +8,16 @@ can_be_hidden = TRUE requires_organ_tag = BP_HEAD requires_slot_flags = SLOT_EARS + mob_overlay_layer = HO_L_EAR_LAYER + quick_equip_priority = 7 -/datum/inventory_slot/ear/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_ears(redraw_mob) +/datum/inventory_slot/ear/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + for(var/slot in global.airtight_slots) + var/obj/item/gear = get_equipped_item(slot) + if(gear?.flags_inv & BLOCK_ALL_HAIR) + user.set_current_mob_overlay(mob_overlay_layer, null, redraw_mob) + return + ..() /datum/inventory_slot/ear/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDEEARS)) @@ -35,3 +42,5 @@ slot_name = "Right Ear" slot_id = slot_r_ear_str ui_loc = ui_r_ear + mob_overlay_layer = HO_R_EAR_LAYER + quick_equip_priority = 6 diff --git a/code/datums/inventory_slots/slots/slot_glasses.dm b/code/datums/inventory_slots/slots/slot_glasses.dm index f19bdc97d4a..0068fac4a1e 100644 --- a/code/datums/inventory_slots/slots/slot_glasses.dm +++ b/code/datums/inventory_slots/slots/slot_glasses.dm @@ -8,9 +8,9 @@ can_be_hidden = TRUE requires_organ_tag = BP_HEAD requires_slot_flags = SLOT_EYES - -/datum/inventory_slot/glasses/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_glasses(redraw_mob) + mob_overlay_layer = HO_GLASSES_LAYER + alt_mob_overlay_layer = HO_GOGGLES_LAYER + quick_equip_priority = 5 /datum/inventory_slot/glasses/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDEEYES)) diff --git a/code/datums/inventory_slots/slots/slot_gloves.dm b/code/datums/inventory_slots/slots/slot_gloves.dm index 3e482fe3f29..df07773f651 100644 --- a/code/datums/inventory_slots/slots/slot_gloves.dm +++ b/code/datums/inventory_slots/slots/slot_gloves.dm @@ -11,9 +11,24 @@ ) covering_flags = SLOT_HANDS requires_slot_flags = SLOT_HANDS + quick_equip_priority = 8 -/datum/inventory_slot/gloves/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_gloves(redraw_mob) +/datum/inventory_slot/gloves/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + var/obj/item/suit = user.get_equipped_item(slot_wear_suit_str) + if(_holding && !(suit && suit.flags_inv & HIDEGLOVES)) + user.set_current_mob_overlay(HO_GLOVES_LAYER, _holding.get_mob_overlay(user, slot_gloves_str), redraw_mob) + return + var/mob_blood_overlay = user.get_bodytype()?.get_blood_overlays(src) + if(mob_blood_overlay) + var/blood_color + for(var/obj/item/organ/external/grabber in user.get_hands_organs()) + if(grabber.coating) + blood_color = grabber.coating.get_color() + break + if(blood_color) + user.set_current_mob_overlay(HO_GLOVES_LAYER, overlay_image(mob_blood_overlay, "bloodyhands", blood_color, RESET_COLOR), redraw_mob) + return + user.set_current_mob_overlay(HO_GLOVES_LAYER, null, redraw_mob) /datum/inventory_slot/gloves/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDEGLOVES)) diff --git a/code/datums/inventory_slots/slots/slot_head.dm b/code/datums/inventory_slots/slots/slot_head.dm index 45e3a289981..3d375147147 100644 --- a/code/datums/inventory_slots/slots/slot_head.dm +++ b/code/datums/inventory_slots/slots/slot_head.dm @@ -7,15 +7,21 @@ requires_organ_tag = BP_HEAD covering_flags = SLOT_HEAD requires_slot_flags = SLOT_HEAD + mob_overlay_layer = HO_HEAD_LAYER + quick_equip_priority = 9 -/datum/inventory_slot/head/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - if(prop.flags_inv & (HIDEMASK|BLOCK_ALL_HAIR)) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.update_hair(0) //rebuild hair - user.update_inv_ears(0) - user.update_inv_wear_mask(0) - user.update_inv_head(redraw_mob) +/datum/inventory_slot/head/simple + requires_organ_tag = null + can_be_hidden = FALSE + ui_loc = "LEFT+1:16,BOTTOM:5" + +/datum/inventory_slot/head/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + if(prop?.flags_inv & (HIDEMASK|BLOCK_ALL_HAIR)) + user.update_hair(FALSE) + user.update_equipment_overlay(slot_l_ear_str, FALSE) + user.update_equipment_overlay(slot_r_ear_str, FALSE) + user.update_equipment_overlay(slot_wear_mask_str, FALSE) + ..() /datum/inventory_slot/head/unequipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) . = ..() diff --git a/code/datums/inventory_slots/slots/slot_id.dm b/code/datums/inventory_slots/slots/slot_id.dm index 9c2fff1dd74..2c015a2a9cf 100644 --- a/code/datums/inventory_slots/slots/slot_id.dm +++ b/code/datums/inventory_slots/slots/slot_id.dm @@ -4,9 +4,17 @@ ui_loc = ui_id slot_id = slot_wear_id_str requires_slot_flags = SLOT_ID + mob_overlay_layer = HO_ID_LAYER + quick_equip_priority = 12 -/datum/inventory_slot/id/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_wear_id(redraw_mob) +/datum/inventory_slot/id/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + var/obj/item/clothing/under/under = user.get_equipped_item(slot_w_uniform_str) + if(istype(under) && !under.displays_id && !under.rolled_down) + user.set_current_mob_overlay(HO_ID_LAYER, null, redraw_mob) + else + ..() + BITSET(user.hud_updateflag, ID_HUD) + BITSET(user.hud_updateflag, WANTED_HUD) /datum/inventory_slot/id/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning, var/ignore_equipped) . = ..() diff --git a/code/datums/inventory_slots/slots/slot_mask.dm b/code/datums/inventory_slots/slots/slot_mask.dm index 9959ca24e5a..7772cc4b5a4 100644 --- a/code/datums/inventory_slots/slots/slot_mask.dm +++ b/code/datums/inventory_slots/slots/slot_mask.dm @@ -8,12 +8,32 @@ requires_organ_tag = BP_HEAD requires_slot_flags = SLOT_FACE can_be_hidden = TRUE + mob_overlay_layer = HO_FACEMASK_LAYER + quick_equip_priority = 10 -/datum/inventory_slot/mask/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - if(prop.flags_inv & BLOCK_ALL_HAIR) +/datum/inventory_slot/mask/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + if(prop?.flags_inv & BLOCK_ALL_HAIR) user.update_hair(0) - user.update_inv_ears(0) - user.update_inv_wear_mask(redraw_mob) + user.update_equipment_overlay(slot_l_ear_str, FALSE) + user.update_equipment_overlay(slot_r_ear_str, FALSE) + ..() + +/mob/proc/check_for_airtight_internals(var/update_internals = TRUE) + for(var/slot in global.airtight_slots) + var/obj/item/gear = get_equipped_item(slot) + if(gear?.item_flags & ITEM_FLAG_AIRTIGHT) + return TRUE + if(update_internals) + set_internals(null) + return FALSE + +/datum/inventory_slot/mask/equipped(mob/living/user, obj/item/prop, redraw_mob, delete_old_item) + . = ..() + user.check_for_airtight_internals() + +/datum/inventory_slot/mask/unequipped(mob/living/user, obj/item/prop, redraw_mob) + . = ..() + user.check_for_airtight_internals() /datum/inventory_slot/mask/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDEMASK)) diff --git a/code/datums/inventory_slots/slots/slot_pockets.dm b/code/datums/inventory_slots/slots/slot_pockets.dm index 0be94287f06..9a075cd7e85 100644 --- a/code/datums/inventory_slots/slots/slot_pockets.dm +++ b/code/datums/inventory_slots/slots/slot_pockets.dm @@ -7,9 +7,10 @@ skip_on_strip_display = TRUE requires_organ_tag = BP_CHEST requires_slot_flags = SLOT_POCKET + quick_equip_priority = 2 -/datum/inventory_slot/pocket/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_pockets(redraw_mob) +/datum/inventory_slot/pocket/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + return /datum/inventory_slot/pocket/prop_can_fit_in_slot(var/obj/item/prop) return ..() || prop.w_class <= ITEM_SIZE_SMALL @@ -32,3 +33,4 @@ slot_name = "Right Pocket" ui_loc = ui_storage2 slot_id = slot_r_store_str + quick_equip_priority = 1 diff --git a/code/datums/inventory_slots/slots/slot_shoes.dm b/code/datums/inventory_slots/slots/slot_shoes.dm index 2685807c6c1..a3a6f054380 100644 --- a/code/datums/inventory_slots/slots/slot_shoes.dm +++ b/code/datums/inventory_slots/slots/slot_shoes.dm @@ -9,9 +9,27 @@ BP_R_FOOT ) requires_slot_flags = SLOT_FEET + quick_equip_priority = 3 -/datum/inventory_slot/shoes/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_shoes(redraw_mob) +/datum/inventory_slot/shoes/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + var/obj/item/suit = user.get_equipped_item(slot_wear_suit_str) + var/obj/item/uniform = user.get_equipped_item(slot_w_uniform_str) + if(_holding && !((suit && suit.flags_inv & HIDESHOES) || (uniform && uniform.flags_inv & HIDESHOES))) + user.set_current_mob_overlay(HO_SHOES_LAYER, _holding.get_mob_overlay(user, slot_shoes_str), redraw_mob) + return + var/mob_blood_overlay = user.get_bodytype()?.get_blood_overlays(src) + if(mob_blood_overlay) + var/blood_color + for(var/foot_tag in list(BP_L_FOOT, BP_R_FOOT)) + var/obj/item/organ/external/stomper = GET_EXTERNAL_ORGAN(user, foot_tag) + if(stomper && stomper.coating) + blood_color = stomper.coating.get_color() + break + if(blood_color) + var/image/bloodsies = overlay_image(mob_blood_overlay, "shoeblood", blood_color, RESET_COLOR) + user.set_current_mob_overlay(HO_SHOES_LAYER, bloodsies, redraw_mob) + return + user.set_current_mob_overlay(HO_SHOES_LAYER, null, redraw_mob) /datum/inventory_slot/shoes/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDESHOES)) diff --git a/code/datums/inventory_slots/slots/slot_suit.dm b/code/datums/inventory_slots/slots/slot_suit.dm index 8bce4327637..5319ac7ec70 100644 --- a/code/datums/inventory_slots/slots/slot_suit.dm +++ b/code/datums/inventory_slots/slots/slot_suit.dm @@ -7,12 +7,19 @@ drop_slots_on_unequip = list(slot_s_store_str) requires_organ_tag = BP_CHEST requires_slot_flags = SLOT_OVER_BODY + mob_overlay_layer = HO_SUIT_LAYER -/datum/inventory_slot/suit/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - if(prop.flags_inv & HIDESHOES) - user.update_inv_shoes(0) - if(prop.flags_inv & HIDEGLOVES) - user.update_inv_gloves(0) - if(prop.flags_inv & HIDEJUMPSUIT) - user.update_inv_w_uniform(0) - user.update_inv_wear_suit(redraw_mob) +/datum/inventory_slot/suit/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + if(prop) + if(prop.flags_inv & HIDESHOES) + user.update_equipment_overlay(slot_shoes_str, FALSE) + if(prop.flags_inv & HIDEGLOVES) + user.update_equipment_overlay(slot_gloves_str, FALSE) + if(prop.flags_inv & HIDEJUMPSUIT) + user.update_equipment_overlay(slot_w_uniform_str, FALSE) + user.update_tail_showing(FALSE) + ..() + // Adds a collar overlay above the helmet layer if the suit has one + // Suit needs an identically named sprite in icons/mob/collar.dmi + var/obj/item/clothing/suit/suit = _holding + user.set_current_mob_overlay(HO_COLLAR_LAYER, (istype(suit) ? suit.get_collar() : null), redraw_mob) diff --git a/code/datums/inventory_slots/slots/slot_suit_storage.dm b/code/datums/inventory_slots/slots/slot_suit_storage.dm index 9df281f409a..91a03c4610d 100644 --- a/code/datums/inventory_slots/slots/slot_suit_storage.dm +++ b/code/datums/inventory_slots/slots/slot_suit_storage.dm @@ -4,9 +4,7 @@ ui_loc = ui_sstore1 slot_id = slot_s_store_str requires_organ_tag = BP_CHEST - -/datum/inventory_slot/suit_storage/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - user.update_inv_s_store(redraw_mob) + mob_overlay_layer = HO_SUIT_STORE_LAYER /datum/inventory_slot/suit_storage/can_equip_to_slot(var/mob/user, var/obj/item/prop, var/disable_warning, var/ignore_equipped) . = ..() diff --git a/code/datums/inventory_slots/slots/slot_uniform.dm b/code/datums/inventory_slots/slots/slot_uniform.dm index f0594647116..ee61ee18748 100644 --- a/code/datums/inventory_slots/slots/slot_uniform.dm +++ b/code/datums/inventory_slots/slots/slot_uniform.dm @@ -13,11 +13,16 @@ ) requires_organ_tag = BP_CHEST requires_slot_flags = SLOT_UPPER_BODY + quick_equip_priority = 11 -/datum/inventory_slot/uniform/update_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) - if(prop.flags_inv & HIDESHOES) - user.update_inv_shoes(0) - user.update_inv_w_uniform(redraw_mob) +/datum/inventory_slot/uniform/update_mob_equipment_overlay(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE) + if(prop?.flags_inv & HIDESHOES) + user.update_equipment_overlay(slot_shoes_str, FALSE) + var/obj/item/suit = user.get_equipped_item(slot_wear_suit_str) + if(_holding && (!suit || !(suit.flags_inv & HIDEJUMPSUIT))) + user.set_current_mob_overlay(HO_UNIFORM_LAYER, _holding.get_mob_overlay(user, slot_w_uniform_str), redraw_mob) + else + user.set_current_mob_overlay(HO_UNIFORM_LAYER, null, redraw_mob) /datum/inventory_slot/uniform/get_examined_string(mob/owner, mob/user, distance, hideflags, decl/pronouns/pronouns) if(_holding && !(hideflags & HIDEJUMPSUIT)) diff --git a/code/datums/mind/mind.dm b/code/datums/mind/mind.dm index dd84169a143..94c7bba26be 100644 --- a/code/datums/mind/mind.dm +++ b/code/datums/mind/mind.dm @@ -213,19 +213,23 @@ else if(href_list["remove_antagonist"]) var/decl/special_role/antag = locate(href_list["remove_antagonist"]) - if(antag) antag.remove_antagonist(src) + if(istype(antag)) + antag.remove_antagonist(src) else if(href_list["equip_antagonist"]) var/decl/special_role/antag = locate(href_list["equip_antagonist"]) - if(antag) antag.equip(src.current) + if(istype(antag)) + antag.equip_role(src.current) else if(href_list["unequip_antagonist"]) var/decl/special_role/antag = locate(href_list["unequip_antagonist"]) - if(antag) antag.unequip(src.current) + if(istype(antag)) + antag.unequip_role(src.current) else if(href_list["move_antag_to_spawn"]) var/decl/special_role/antag = locate(href_list["move_antag_to_spawn"]) - if(antag) antag.place_mob(src.current) + if(istype(antag)) + antag.place_mob(src.current) else if (href_list["role_edit"]) var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in SSjobs.titles_to_datums @@ -293,7 +297,7 @@ var/list/possible_targets = list("Free objective") for(var/datum/mind/possible_target in SSticker.minds) - if ((possible_target != src) && istype(possible_target.current, /mob/living/carbon/human)) + if ((possible_target != src) && ishuman(possible_target.current)) possible_targets += possible_target.current var/mob/def_target = null @@ -417,7 +421,7 @@ log_admin("[key_name_admin(usr)] has unemag'ed [R].") if("unemagcyborgs") - if (istype(current, /mob/living/silicon/ai)) + if (isAI(current)) var/mob/living/silicon/ai/ai = current for (var/mob/living/silicon/robot/R in ai.connected_robots) R.emagged = 0 diff --git a/code/datums/observation/observation.dm b/code/datums/observation/observation.dm index efd43bc4f83..892e97ce7c9 100644 --- a/code/datums/observation/observation.dm +++ b/code/datums/observation/observation.dm @@ -225,8 +225,7 @@ try call(listener, proc_call)(arglist(args)) catch (var/exception/e) - error("[e.name] - [e.file] - [e.line]") - error(e.desc) + error(EXCEPTION_TEXT(e)) unregister_global(listener, proc_call) // Call the listeners for this specific event source, if they exist. @@ -240,7 +239,6 @@ try call(listener, proc_call)(arglist(args)) catch (var/exception/e) - error("[e.name] - [e.file] - [e.line]") - error(e.desc) + error(EXCEPTION_TEXT(e)) unregister(source, listener, proc_call) return TRUE diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index a2a3076ac49..7a71b98c7ab 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -74,17 +74,9 @@ var/global/list/outfits_decls_by_type_ J.toggle() J.toggle_valve() -/decl/hierarchy/outfit/proc/equip(mob/living/carbon/human/H, var/rank, var/assignment, var/equip_adjustments) +/decl/hierarchy/outfit/proc/equip_outfit(mob/living/carbon/human/H, assignment, equip_adjustments, datum/job/job, datum/mil_rank/rank) equip_base(H, equip_adjustments) - - rank = id_pda_assignment || rank - assignment = id_pda_assignment || assignment || rank - var/obj/item/card/id/W = equip_id(H, rank, assignment, equip_adjustments) - if(W) - rank = W.rank - assignment = W.assignment - equip_pda(H, rank, assignment, equip_adjustments) - + equip_id(H, assignment, equip_adjustments, job, rank) for(var/path in backpack_contents) var/number = backpack_contents[path] for(var/i=0,i 0, cnt--) + var/obj/item/I = locate(i) in container_contents + if (I && I.reagents) + container_contents -= I + I.reagents.trans_to_holder(buffer,I.reagents.total_volume) + qdel(I) //Find fruits if (LAZYLEN(fruit)) diff --git a/code/datums/repositories/atom_info.dm b/code/datums/repositories/atom_info.dm index c21c764b753..a15c4fd3739 100644 --- a/code/datums/repositories/atom_info.dm +++ b/code/datums/repositories/atom_info.dm @@ -26,13 +26,7 @@ var/global/repository/atom_info/atom_info_repository = new() var/atom/instance if(!matter_cache[key]) instance = get_instance_of(path, material, amount) - var/matter_list = instance.building_cost() - if(istype(instance, /obj/item/ammo_magazine) || istype(instance, /obj/item/storage)) - for(var/obj/thing in instance) - var/list/thing_matter = thing.building_cost() - for(var/mat in thing_matter) - matter_cache[mat] += thing_matter[mat] - matter_cache[key] = matter_list + matter_cache[key] = instance.get_contained_matter() if(!combined_worth_cache[key]) instance = instance || get_instance_of(path, material, amount) combined_worth_cache[key] = instance.get_combined_monetary_worth() diff --git a/code/datums/repositories/crew/binary.dm b/code/datums/repositories/crew/binary.dm index e73bb83275e..c4399ea37e0 100644 --- a/code/datums/repositories/crew/binary.dm +++ b/code/datums/repositories/crew/binary.dm @@ -4,7 +4,7 @@ if(!H.isSynthetic() && H.should_have_organ(BP_HEART)) var/obj/item/organ/internal/heart/O = H.get_organ(BP_HEART, /obj/item/organ/internal/heart) if (!O || !BP_IS_PROSTHETIC(O)) // Don't make medical freak out over prosthetic hearts - var/pulse = H.pulse() + var/pulse = H.get_pulse() if(pulse == PULSE_NONE || pulse == PULSE_THREADY) crew_data["alert"] = TRUE if(H.get_blood_oxygenation() < BLOOD_VOLUME_SAFE) diff --git a/code/datums/repositories/crew/crew.dm b/code/datums/repositories/crew/crew.dm index c12e23e918a..e0becfd3f77 100644 --- a/code/datums/repositories/crew/crew.dm +++ b/code/datums/repositories/crew/crew.dm @@ -52,7 +52,7 @@ var/global/datum/repository/crew/crew_repository = new() for(var/obj/item/clothing/under/C in tracked) var/turf/pos = get_turf(C) if(C.has_sensor && pos && pos.z == z_level && C.sensor_mode != SUIT_SENSOR_OFF) - if(istype(C.loc, /mob/living/carbon/human)) + if(ishuman(C.loc)) var/mob/living/carbon/human/H = C.loc if(H.get_equipped_item(slot_w_uniform_str) != C) continue diff --git a/code/datums/repositories/crew/vital.dm b/code/datums/repositories/crew/vital.dm index dbcae15ca8e..9e7aab0f869 100644 --- a/code/datums/repositories/crew/vital.dm +++ b/code/datums/repositories/crew/vital.dm @@ -6,8 +6,8 @@ if(!H.isSynthetic() && H.should_have_organ(BP_HEART)) var/obj/item/organ/internal/heart/O = H.get_organ(BP_HEART, /obj/item/organ/internal/heart) if (!O || !BP_IS_PROSTHETIC(O)) // Don't make medical freak out over prosthetic hearts - crew_data["true_pulse"] = H.pulse() - crew_data["pulse"] = H.get_pulse(GETPULSE_TOOL) + crew_data["true_pulse"] = H.get_pulse() + crew_data["pulse"] = H.get_pulse_as_string(GETPULSE_TOOL) switch(crew_data["true_pulse"]) if(PULSE_NONE) crew_data["pulse_span"] = "bad" diff --git a/code/datums/repositories/decls.dm b/code/datums/repositories/decls.dm index c27168179b4..0bc268c1a66 100644 --- a/code/datums/repositories/decls.dm +++ b/code/datums/repositories/decls.dm @@ -36,11 +36,38 @@ var/global/repository/decls/decls_repository = new if(decl_uid && (!TYPE_IS_ABSTRACT(decl) || (initial(decl.decl_flags) & DECL_FLAG_ALLOW_ABSTRACT_INIT))) fetched_decl_ids[decl_uid] = decl -/repository/decls/proc/get_decl_by_id(var/decl_id) - . = get_decl(fetched_decl_ids[decl_id]) +/repository/decls/proc/get_decl_by_id(var/decl_id, var/validate_decl_type = TRUE) + RETURN_TYPE(/decl) + . = get_decl(fetched_decl_ids[decl_id], validate_decl_type) + +// This proc and get_decl_by_id_or_var() are being added solely to grandfather in decls saved to player saves under name +// rather than UID. They should be considered deprecated for this purpose - uid and get_decl_by_id() should be used instead. +/repository/decls/proc/get_decl_by_var(var/decl_value, var/decl_prototype, var/check_var = "name") + var/list/all_decls = get_decls_of_type(decl_prototype) + var/decl/prototype = all_decls[all_decls[1]] // Can't just grab the prototype as it may be abstract + if(!(check_var in prototype.vars)) + CRASH("Attempted to retrieve a decl by a var that does not exist on the decl type ('[check_var]')") + for(var/decl_type in all_decls) + var/decl/decl = all_decls[decl_type] + if(decl.vars[check_var] == decl_value) + return decl + +/repository/decls/proc/get_decl_by_id_or_var(var/decl_id, var/decl_prototype, var/check_var = "name") + RETURN_TYPE(/decl) + return get_decl_by_id(decl_id, validate_decl_type = FALSE) || get_decl_by_var(decl_id, decl_prototype, check_var) + +/repository/decls/proc/get_decl_path_by_id(decl_id) + . = fetched_decl_ids[decl_id] + +/repository/decls/proc/get_decl(var/decl/decl_type, var/validate_decl_type = TRUE) + + RETURN_TYPE(/decl) + + if(!ispath(decl_type, /decl)) + if(validate_decl_type) + CRASH("Invalid decl_type supplied to get_decl(): [decl_type || "NULL"]") + return null -/repository/decls/proc/get_decl(var/decl/decl_type) - ASSERT(ispath(decl_type, /decl)) if(TYPE_IS_ABSTRACT(decl_type) && !(initial(decl_type.decl_flags) & DECL_FLAG_ALLOW_ABSTRACT_INIT)) return // We do not instantiate abstract decls. . = fetched_decls[decl_type] diff --git a/code/datums/supplypacks/galley.dm b/code/datums/supplypacks/galley.dm index 10f73834502..6f09cdb49f5 100644 --- a/code/datums/supplypacks/galley.dm +++ b/code/datums/supplypacks/galley.dm @@ -131,7 +131,7 @@ /decl/hierarchy/supply_pack/galley/beer_dispenser name = "Equipment - Booze dispenser" contains = list( - /obj/machinery/chemical_dispenser/bar_alc{anchored = 0} + /obj/machinery/chemical_dispenser/bar_alc{anchored = FALSE} ) containertype = /obj/structure/largecrate containername = "booze dispenser crate" @@ -139,7 +139,7 @@ /decl/hierarchy/supply_pack/galley/soda_dispenser name = "Equipment - Soda dispenser" contains = list( - /obj/machinery/chemical_dispenser/bar_soft{anchored = 0} + /obj/machinery/chemical_dispenser/bar_soft{anchored = FALSE} ) containertype = /obj/structure/largecrate containername = "soda dispenser crate" diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index 287226fa743..b1143cd2e2c 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -65,7 +65,7 @@ /decl/hierarchy/supply_pack/medical/blood name = "Refills - Synthetic Blood" - contains = list(/obj/item/chems/ivbag/nanoblood = 4) + contains = list(/obj/item/chems/ivbag/blood/nanoblood = 4) containername = "synthetic blood crate" /decl/hierarchy/supply_pack/medical/bodybag diff --git a/code/datums/supplypacks/nonessent.dm b/code/datums/supplypacks/nonessent.dm index 8cb4c18873b..4e03952f164 100644 --- a/code/datums/supplypacks/nonessent.dm +++ b/code/datums/supplypacks/nonessent.dm @@ -22,7 +22,7 @@ /obj/item/chems/glass/paint/purple, /obj/item/chems/glass/paint/black, /obj/item/chems/glass/paint/white, - /obj/item/contraband/poster, + /obj/item/poster, /obj/item/stack/package_wrap/fifty = 2, /obj/item/stack/package_wrap/gift/fifty = 2 ) diff --git a/code/datums/supplypacks/operations.dm b/code/datums/supplypacks/operations.dm index 68962df00d4..e8c748c515e 100644 --- a/code/datums/supplypacks/operations.dm +++ b/code/datums/supplypacks/operations.dm @@ -15,11 +15,13 @@ /decl/hierarchy/supply_pack/operations/contraband num_contained = 5 - contains = list(/obj/item/seeds/bloodtomatoseed, - /obj/item/storage/pill_bottle/zoom, - /obj/item/storage/pill_bottle/happy, - /obj/item/storage/pill_bottle/gleam, - /obj/item/chems/drinks/bottle/pwine) + contains = list( + /obj/item/seeds/bloodtomatoseed, + /obj/item/storage/pill_bottle/zoom, + /obj/item/storage/pill_bottle/happy, + /obj/item/storage/pill_bottle/gleam, + /obj/item/chems/drinks/bottle/pwine + ) name = "UNLISTED - Contraband crate" containername = "unlabeled crate" diff --git a/code/datums/supplypacks/science.dm b/code/datums/supplypacks/science.dm index 60388c5441f..c3730795c98 100644 --- a/code/datums/supplypacks/science.dm +++ b/code/datums/supplypacks/science.dm @@ -4,7 +4,7 @@ /decl/hierarchy/supply_pack/science/chemistry_dispenser name = "Equipment - Chemical Reagent dispenser" contains = list( - /obj/machinery/chemical_dispenser{anchored = 0} + /obj/machinery/chemical_dispenser{anchored = FALSE} ) containertype = /obj/structure/largecrate containername = "reagent dispenser crate" diff --git a/code/datums/trading/__trading_defines.dm b/code/datums/trading/__trading_defines.dm index ead3d66ddff..29b244ba8a6 100644 --- a/code/datums/trading/__trading_defines.dm +++ b/code/datums/trading/__trading_defines.dm @@ -1,20 +1,47 @@ -#define TRADER_THIS_TYPE 1 -#define TRADER_SUBTYPES_ONLY 2 -#define TRADER_ALL 3 -#define TRADER_BLACKLIST 4 -#define TRADER_BLACKLIST_SUB 8 -#define TRADER_BLACKLIST_ALL 12 +#define TRADER_THIS_TYPE BITFLAG(0) +#define TRADER_SUBTYPES_ONLY BITFLAG(1) +#define TRADER_ALL (TRADER_THIS_TYPE|TRADER_SUBTYPES_ONLY) +#define TRADER_BLACKLIST BITFLAG(2) +#define TRADER_BLACKLIST_SUB BITFLAG(3) +#define TRADER_BLACKLIST_ALL (TRADER_BLACKLIST|TRADER_BLACKLIST_SUB) -#define TRADER_WANTED_ONLY 1 //Do they only trade for wanted goods? -#define TRADER_MONEY 2 //Do they only accept money in return for goods. -#define TRADER_GOODS 4 //Do they accept goods in return for other goods. -#define TRADER_WANTED_ALL 8 //Like TRADER_WANTED_ONLY but they buy all possible wanted goods rather than a subset. +#define TRADER_WANTED_ONLY BITFLAG(0) // Do they only trade for wanted goods? +#define TRADER_MONEY BITFLAG(1) // Do they only accept money in return for goods. +#define TRADER_GOODS BITFLAG(2) // Do they accept goods in return for other goods. +#define TRADER_WANTED_ALL BITFLAG(3) // Like TRADER_WANTED_ONLY but they buy all possible wanted goods rather than a subset. +#define TRADER_BRIBABLE BITFLAG(4) // Determines if the trader can be bribed (stations cannot as they can't leave) + +// Tokens for constructing the hail tags (usually generic, species name or silicon). +// When merchants hail a person they use "trade_hail_[some token]". +#define TRADER_HAIL_START "trade_hail_" +#define TRADER_HAIL_GENERIC_END "generic" +#define TRADER_HAIL_SILICON_END "silicon" +#define TRADER_HAIL_GENERIC TRADER_HAIL_START + TRADER_HAIL_GENERIC_END // Default hail response token. +#define TRADER_HAIL_SILICON TRADER_HAIL_START + TRADER_HAIL_SILICON_END // Used when hailed by a robot or AI. +#define TRADER_HAIL_DENY TRADER_HAIL_START + "deny" // Used When merchant denies a hail. //Possible response defines for when offering an item for something -#define TRADER_NO_MONEY "trade_no_money" -#define TRADER_NO_GOODS "trade_no_goods" -#define TRADER_NOT_ENOUGH "trade_not_enough" -#define TRADER_NO_BLACKLISTED "trade_blacklist" -#define TRADER_FOUND_UNWANTED "trade_found_unwanted" +#define TRADER_NO_MONEY "trade_no_money" // Used when money is offered to a trader who does not accept money. +#define TRADER_NO_GOODS "trade_no_goods" // Used when goods are offered to a trader who does not accept goodds. +#define TRADER_NOT_ENOUGH "trade_not_enough" // Used when there is not enough money for the trade. +#define TRADER_NO_BLACKLISTED "trade_blacklist" // Used when a blacklisted item is offered by the player. +#define TRADER_FOUND_UNWANTED "trade_found_unwanted" // Used when an unwanted item is offered by the player. +#define TRADER_TRADE_COMPLETE "trade_complete" // When a trade is made successfully. +#define TRADER_HOW_MUCH "how_much" // When a merchant tells the player how much something is. +#define TRADER_WHAT_WANT "what_want" // What the person says when they are asked if they want something +#define TRADER_COMPLIMENT_DENY "compliment_deny" // When the merchant refuses a compliment +#define TRADER_COMPLIMENT_ACCEPT "compliment_accept" // When the merchant accepts a compliment +#define TRADER_INSULT_GOOD "insult_good" // When the player insults a merchant while they are on good disposition +#define TRADER_INSULT_BAD "insult_bad" // When a player insults a merchatn when they are not on good disposition +#define TRADER_BRIBE_REFUSAL "bribe_refusal" // When the trader refuses a bribe to stay longer. +#define TRADER_BRIBE_ACCEPT "bribe_accept" // When the trader accepts a bribe to stay longer. -#define TRADER_DEFAULT_NAME "Default" //Whether to just generate a name from the premade lists. \ No newline at end of file +// Tokens replaced with strings at runtime. +#define TRADER_TOKEN_ORIGIN "$ORIGIN$" // The selected origin of the trader station. +#define TRADER_TOKEN_VALUE "$VALUE$" // The value of the trade. +#define TRADER_TOKEN_CURRENCY "$CURRENCY$" // The plural name of the currency in use +#define TRADER_TOKEN_CUR_SINGLE "$CURRENCY_SINGULAR$" // The singular name of the unit of currency in use. +#define TRADER_TOKEN_ITEM "$ITEM$" // The relevant item being traded or offered. +#define TRADER_TOKEN_MERCHANT "$MERCHANT$" // The name of the current trader. +#define TRADER_TOKEN_MOB "$MOB$" // The player currently interacting with the trader. +#define TRADER_TOKEN_TIME "$TIME$" // How much longer a successful bribe has gained. diff --git a/code/datums/trading/_trader.dm b/code/datums/trading/_trader.dm index fe20bc27159..d567776ebd3 100644 --- a/code/datums/trading/_trader.dm +++ b/code/datums/trading/_trader.dm @@ -1,84 +1,51 @@ /datum/trader - var/name = "unsuspicious trader" //The name of the trader in question - var/origin = "some place" //The place that they are trading from - var/list/possible_origins //Possible names of the trader origin - var/disposition = 0 //The current disposition of them to us. - var/trade_flags = TRADER_MONEY //Flags - var/name_language //If this is set to a language name this will generate a name from the language - var/icon/portrait //The icon that shows up in the menu TODO: IMPLEMENT OR REMOVE - var/trader_currency - var/datum/trade_hub/hub - - var/list/wanted_items = list() //What items they enjoy trading for. Structure is (type = known/unknown) - var/list/possible_wanted_items //List of all possible wanted items. Structure is (type = mode) - var/list/possible_trading_items //List of all possible trading items. Structure is (type = mode) - var/list/trading_items = list() //What items they are currently trading away. - var/list/blacklisted_trade_items = list(/mob/living/carbon/human) - //Things they will automatically refuse - - var/list/speech = list() //The list of all their replies and messages. Structure is (id = talk) - /*SPEECH IDS: - hail_generic When merchants hail a person - hail_[race] Race specific hails - hail_deny When merchant denies a hail - - insult_good When the player insults a merchant while they are on good disposition - insult_bad When a player insults a merchatn when they are not on good disposition - complement_accept When the merchant accepts a complement - complement_deny When the merchant refuses a complement - - how_much When a merchant tells the player how much something is. - trade_complete When a trade is made - trade_refuse When a trade is refused - - what_want What the person says when they are asked if they want something - - */ - var/want_multiplier = 2 //How much wanted items are multiplied by when traded for - var/margin = 1.2 //Multiplier to price when selling to player - var/price_rng = 10 //Percentage max variance in sell prices. - var/insult_drop = 5 //How far disposition drops on insult - var/compliment_increase = 5 //How far compliments increase disposition - var/refuse_comms = 0 //Whether they refuse further communication - - var/mob_transfer_message = "You are transported to ORIGIN." //What message gets sent to mobs that get sold. - - var/static/list/blacklisted_types = list( - /obj, - /obj/structure, - /obj/machinery, - /obj/screen, - /obj/effect, - /obj/item, - /obj/item/twohanded, - /obj/item/organ, - /obj/item/organ/internal, - /obj/item/organ/external, - /obj/item/storage, - /obj/item/storage/internal, - /obj/item/chems, - /obj/item/chems/glass, - /obj/item/chems/food, - /obj/item/chems/food/old, - /obj/item/chems/food/grown, - /obj/item/chems/food/variable, - /obj/item/chems/condiment, - /obj/item/chems/drinks, - /obj/item/chems/drinks/bottle + abstract_type = /datum/trader + var/name = "unsuspicious trader" // The name of the trader in question + var/origin = "some place" // The place that they are trading from + var/list/possible_origins // Possible names of the trader origin + var/disposition = 0 // The current disposition of them to us. + var/trade_flags = TRADER_MONEY // Various flags for allowing or denying offers/interactions. + var/name_language // Language decl to use for trader name. If null, will use the generic name generator. + var/icon/portrait // The icon that shows up in the menu TODO: IMPLEMENT OR REMOVE + var/trader_currency // Currency decl to use. If blank, defaults to map. + var/datum/trade_hub/hub // Current associated trade hub, if any. + + var/list/wanted_items = list() // What items they enjoy trading for. Structure is (type = known/unknown) + var/list/possible_wanted_items // List of all possible wanted items. Structure is (type = mode) + var/list/possible_trading_items // List of all possible trading items. Structure is (type = mode) + var/list/trading_items = list() // What items they are currently trading away. + + // The list of all their replies and messages. + // Structure is (id = talk). Check __trading_defines.dm for specific tokens. + var/list/speech = list() + + var/want_multiplier = 2 // How much wanted items are multiplied by when traded for + var/margin = 1.2 // Multiplier to price when selling to player + var/price_rng = 10 // Percentage max variance in sell prices. + var/insult_drop = 5 // How far disposition drops on insult + var/compliment_increase = 5 // How far compliments increase disposition + var/refuse_comms = 0 // Whether they refuse further communication + + // What message gets sent to mobs that get sold. + var/mob_transfer_message = "You are transported to " + TRADER_TOKEN_ORIGIN + "." + + // Things they will automatically refuse + var/list/blacklisted_trade_items = list( + /mob/living/carbon/human ) /datum/trader/New() ..() if(!ispath(trader_currency, /decl/currency)) trader_currency = global.using_map.default_currency - if(name_language) - if(name_language == TRADER_DEFAULT_NAME) - name = capitalize(pick(global.first_names_female + global.first_names_male)) + " " + capitalize(pick(global.last_names)) - else - var/decl/language/L = GET_DECL(name_language) - if(istype(L)) - name = L.get_random_name(pick(MALE,FEMALE)) - if(possible_origins && possible_origins.len) + if(ispath(name_language, /decl/language)) + var/decl/language/L = GET_DECL(name_language) + if(istype(L)) + name = L.get_random_name(pick(MALE,FEMALE)) + if(!name) + name = capitalize(pick(global.first_names_female + global.first_names_male)) + " " + capitalize(pick(global.last_names)) + + if(length(possible_origins)) origin = pick(possible_origins) for(var/i in 3 to 6) @@ -107,44 +74,51 @@ if(new_item) pool |= new_item +// This is horrendous. TODO: cache all of this shit. +// May be possible to mutate trading_pool as this is passed in from the lists defined on the datum. /datum/trader/proc/get_possible_item(var/list/trading_pool) - if(!trading_pool || !trading_pool.len) + if(!length(trading_pool)) return var/list/possible = list() - for(var/type in trading_pool) - var/status = trading_pool[type] + for(var/trade_type in trading_pool) + var/status = trading_pool[trade_type] if(status & TRADER_THIS_TYPE) - possible += type + possible += trade_type if(status & TRADER_SUBTYPES_ONLY) - possible += subtypesof(type) + possible += subtypesof(trade_type) if(status & TRADER_BLACKLIST) - possible -= type + possible -= trade_type if(status & TRADER_BLACKLIST_SUB) - possible -= subtypesof(type) - + possible -= subtypesof(trade_type) + for(var/trade_type in possible) + var/atom/check_type = trade_type + if(!TYPE_IS_SPAWNABLE(check_type)) + possible -= check_type if(length(possible)) - var/picked = pick_n_take(possible) - while(length(possible) && (picked in blacklisted_types)) - picked = pick_n_take(possible) - if(!(picked in blacklisted_types)) - return picked + return pick(possible) /datum/trader/proc/get_response(var/key, var/default) if(speech && speech[key]) . = speech[key] else . = default - . = replacetext(., "MERCHANT", name) - . = replacetext(., "ORIGIN", origin) + . = replacetext(., TRADER_TOKEN_MERCHANT, name) + . = replacetext(., TRADER_TOKEN_ORIGIN, origin) var/decl/currency/cur = GET_DECL(trader_currency) - . = replacetext(.,"CURRENCY_SINGULAR", cur.name_singular) - . = replacetext(.,"CURRENCY", cur.name) + . = replacetext(.,TRADER_TOKEN_CUR_SINGLE, cur.name_singular) + . = replacetext(.,TRADER_TOKEN_CURRENCY, cur.name) /datum/trader/proc/print_trading_items(var/num) num = clamp(num,1,trading_items.len) - if(trading_items[num]) - return "[atom_info_repository.get_name_for(trading_items[num])]" + var/item_type = trading_items[num] + if(!item_type) + return + . = atom_info_repository.get_name_for(item_type) + if(ispath(item_type, /obj/item/stack)) + var/obj/item/stack/stack = item_type + . = "[initial(stack.amount)]x [.]" + . = "[.]" /datum/trader/proc/skill_curve(skill) switch(skill) @@ -193,12 +167,12 @@ for(var/item in offers) var/atom/movable/offer = item var/is_wanted = 0 - if((trade_flags & TRADER_WANTED_ONLY) && is_type_in_list(offer,wanted_items)) + if((trade_flags & TRADER_WANTED_ONLY) && is_type_in_list(offer, wanted_items)) is_wanted = 2 - if((trade_flags & TRADER_WANTED_ALL) && is_type_in_list(offer,possible_wanted_items)) + if((trade_flags & TRADER_WANTED_ALL) && is_type_in_list(offer, possible_wanted_items)) is_wanted = 1 - if(blacklisted_trade_items && blacklisted_trade_items.len && is_type_in_list(offer,blacklisted_trade_items)) - return 0 + if(length(blacklisted_trade_items) && is_type_in_list(offer, blacklisted_trade_items)) + return TRADER_NO_BLACKLISTED if(istype(offer,/obj/item/cash)) if(!(trade_flags & TRADER_MONEY)) @@ -206,7 +180,7 @@ else if(!(trade_flags & TRADER_GOODS)) return TRADER_NO_GOODS - else if((trade_flags & TRADER_WANTED_ONLY|TRADER_WANTED_ALL) && !is_wanted) + else if((trade_flags & (TRADER_WANTED_ONLY|TRADER_WANTED_ALL)) && !is_wanted) return TRADER_FOUND_UNWANTED offer_worth += get_buy_price(offer, is_wanted - 1, skill) @@ -222,16 +196,16 @@ /datum/trader/proc/hail(var/mob/user) var/specific - if(istype(user, /mob/living/carbon/human)) + if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.species) specific = H.species.name - else if(istype(user, /mob/living/silicon)) - specific = "silicon" - if(!speech["hail_[specific]"]) - specific = "generic" - . = get_response("hail_[specific]", "Greetings, MOB!") - . = replacetext(., "MOB", user.name) + else if(issilicon(user)) + specific = TRADER_HAIL_SILICON_END + if(!speech["[TRADER_HAIL_START][specific]"]) + specific = TRADER_HAIL_GENERIC_END + . = get_response("[TRADER_HAIL_START][specific]", "Greetings, " + TRADER_TOKEN_MOB + "!") + . = replacetext(., TRADER_TOKEN_MOB, user.name) /datum/trader/proc/can_hail() if(!refuse_comms && prob(-disposition)) @@ -243,23 +217,23 @@ if(prob(-disposition/10)) refuse_comms = 1 if(disposition > 50) - return get_response("insult_good","What? I thought we were cool!") + return get_response(TRADER_INSULT_GOOD,"What? I thought we were cool!") else - return get_response("insult_bad", "Right back at you asshole!") + return get_response(TRADER_INSULT_BAD, "Right back at you asshole!") /datum/trader/proc/compliment() if(prob(-disposition)) - return get_response("compliment_deny", "Fuck you!") + return get_response(TRADER_COMPLIMENT_DENY, "Fuck you!") if(prob(100-disposition)) disposition += rand(compliment_increase, compliment_increase * 2) - return get_response("compliment_accept", "Thank you!") + return get_response(TRADER_COMPLIMENT_ACCEPT, "Thank you!") /datum/trader/proc/trade(var/list/offers, var/num, var/turf/location) if(offers && offers.len) for(var/offer in offers) - if(istype(offer,/mob)) + if(ismob(offer)) var/text = mob_transfer_message - to_chat(offer, replacetext(text, "ORIGIN", origin)) + to_chat(offer, replacetext(text, TRADER_TOKEN_ORIGIN, origin)) qdel(offer) var/type = trading_items[num] @@ -272,17 +246,18 @@ return M /datum/trader/proc/how_much_do_you_want(var/num, skill = SKILL_MAX) - . = get_response("how_much", "Hmm.... how about VALUE CURRENCY?") - . = replacetext(.,"VALUE",get_item_value(num, skill)) - . = replacetext(.,"ITEM", atom_info_repository.get_name_for(trading_items[num])) + . = get_response(TRADER_HOW_MUCH, "Hmm.... how about " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + "?") + . = replacetext(.,TRADER_TOKEN_VALUE,get_item_value(num, skill)) + . = replacetext(.,TRADER_TOKEN_ITEM, atom_info_repository.get_name_for(trading_items[num])) /datum/trader/proc/what_do_you_want() if(!(trade_flags & TRADER_GOODS)) return get_response(TRADER_NO_GOODS, "I don't deal in goods.") - . = get_response("what_want", "Hm, I want") + . = get_response(TRADER_WHAT_WANT, "Hm, I want") var/list/want_english = list() for(var/wtype in wanted_items) - want_english += atom_info_repository.get_name_for(wtype) + var/item_name = atom_info_repository.get_name_for(wtype) + want_english += item_name . += " [english_list(want_english)]" /datum/trader/proc/sell_items(var/list/offers, skill = SKILL_MAX) @@ -306,8 +281,18 @@ for(var/offer in offers) qdel(offer) + +/datum/trader/proc/is_bribable() + SHOULD_CALL_PARENT(TRUE) + return (trade_flags & TRADER_BRIBABLE) + +/datum/trader/proc/is_bribed(var/staylength) + return get_response(TRADER_BRIBE_REFUSAL, "How about... no?") + /datum/trader/proc/bribe_to_stay_longer(var/amt) - return get_response("bribe_refusal", "How about... no?") + if(is_bribable()) + return is_bribed(round(amt/100)) + return get_response(TRADER_BRIBE_REFUSAL, "How about... no?") /datum/trader/Destroy(force) if(hub) diff --git a/code/datums/trading/traders/ai.dm b/code/datums/trading/traders/ai.dm index 469a112daf8..5bdc07be534 100644 --- a/code/datums/trading/traders/ai.dm +++ b/code/datums/trading/traders/ai.dm @@ -10,23 +10,21 @@ They sell generic supplies and ask for generic supplies. name = "AI" origin = "Trading Beacon" name_language = /decl/language/human/common - trade_flags = TRADER_MONEY|TRADER_GOODS - speech = list("hail_generic" = "Greetings, I am MERCHANT, Artifical Intelligence onboard ORIGIN, tasked with trading goods in return for CURRENCY and supplies.", - "hail_deny" = "We are sorry, your connection has been blacklisted. Have a nice day.", - - "trade_complete" = "Thank you for your patronage.", - "trade_not_enough" = "I'm sorry, your offer is not worth what you are asking for.", - "trade_blacklisted" = "You have offered a blacklisted item. My laws do not allow me to trade for that.", - "how_much" = "ITEM will cost you roughly VALUE CURRENCY, or something of equal worth.", - "what_want" = "I have logged need for", - - "compliment_deny" = "I'm sorry, I am not allowed to let compliments affect the trade.", - "compliment_accept" = "Thank you, but that will not not change our business interactions.", - "insult_good" = "I do not understand, are we not on good terms?", - "insult_bad" = "I do not understand, are you insulting me?", - - "bribe_refusal" = "You have given me money to stay, however, I am a station. I do not leave.", - ) + trade_flags = TRADER_MONEY | TRADER_GOODS + speech = list( + TRADER_HAIL_GENERIC = "Greetings, I am " + TRADER_TOKEN_MERCHANT + ", Artifical Intelligence onboard " + TRADER_TOKEN_ORIGIN + ", tasked with trading goods in return for " + TRADER_TOKEN_CURRENCY + " and supplies.", + TRADER_HAIL_DENY = "We are sorry, your connection has been blacklisted. Have a nice day.", + TRADER_TRADE_COMPLETE = "Thank you for your patronage.", + TRADER_NOT_ENOUGH = "I'm sorry, your offer is not worth what you are asking for.", + TRADER_NO_BLACKLISTED = "You have offered a blacklisted item. My laws do not allow me to trade for that.", + TRADER_HOW_MUCH = TRADER_TOKEN_ITEM + " will cost you roughly " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ", or something of equal worth.", + TRADER_WHAT_WANT = "I have logged need for", + TRADER_COMPLIMENT_DENY = "I'm sorry, I am not allowed to let compliments affect the trade.", + TRADER_COMPLIMENT_ACCEPT = "Thank you, but that will not not change our business interactions.", + TRADER_INSULT_GOOD = "I do not understand, are we not on good terms?", + TRADER_INSULT_BAD = "I do not understand, are you insulting me?", + TRADER_BRIBE_REFUSAL = "You have given me money to stay, however, I am a station. I do not leave.", + ) possible_wanted_items = list( /obj/item = TRADER_SUBTYPES_ONLY, /obj/item/assembly = TRADER_BLACKLIST_ALL, diff --git a/code/datums/trading/traders/books.dm b/code/datums/trading/traders/books.dm index 5bc123f0fa1..4744ac979e7 100644 --- a/code/datums/trading/traders/books.dm +++ b/code/datums/trading/traders/books.dm @@ -1,7 +1,14 @@ /datum/trader/books name = "strange book merchant" origin = "Uzed Buks" - possible_origins = list("Uzed Buks", "Ango & Mango (Still not a fruit shop stop wizh so many asking!)", "Prepipipi's Gently Used Books", "real-books.com.au", "We Sell Paper Wizh Words On", "Meeeena's Paper Recycling") + possible_origins = list( + "Uzed Buks", + "Ango & Mango (Still not a fruit shop stop wizh so many asking!)", + "Prepipipi's Gently Used Books", + "real-books.com.au", + "We Sell Paper Wizh Words On", + "Meeeena's Paper Recycling" + ) trade_flags = TRADER_MONEY possible_wanted_items = list() price_rng = 30 @@ -30,17 +37,17 @@ /obj/item/book/skill/medical/anatomy = TRADER_SUBTYPES_ONLY ) - speech = list("hail_generic" = "Yes hello hello! Many fine paperstacks for sale! Please buy!", - "hail_deny" = "Not in! I'm not here! Go away!!", - - "insult_good" = "Zhat hurts friend!", - "insult_bad" = "Ohhhhhh!! Why you picking a fight?! You will lose!", - "compliment_accept" = "You make my ears red you do! Hehehe!", - "compliment_deny" = "Haha! Nice try, but I am not falling for zhe smoozhy talk zhe fourzh time today!", - - "how_much" = "Hmmmmm, I give zhis to you for maybe... VALUE CURRENCY.", - "trade_complete" = "Yesssss zhank you for transactionings!!", - "trade_refuse" = "No! No no no no!", - "trade_blacklist" = "Aaaaaa! No want, no want! Go away!", - "trade_found_unwanted" = "Hmmm, no. Do not want.", - "trade_not_enough" = "Not enough! More! More!") + speech = list( + TRADER_HAIL_GENERIC = "Yes hello hello! Many fine paperstacks for sale! Please buy!", + TRADER_HAIL_DENY = "Not in! I'm not here! Go away!!", + TRADER_NO_GOODS = "No! No no no! Not goods! MONEY!", + TRADER_INSULT_GOOD = "Zhat hurts friend!", + TRADER_INSULT_BAD = "Ohhhhhh!! Why you picking a fight?! You will lose!", + TRADER_COMPLIMENT_ACCEPT = "You make my ears red you do! Hehehe!", + TRADER_COMPLIMENT_DENY = "Haha! Nice try, but I am not falling for zhe smoozhy talk zhe fourzh time today!", + TRADER_HOW_MUCH = "Hmmmmm, I give zhis to you for maybe... " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_TRADE_COMPLETE = "Yesssss zhank you for transactionings!", + TRADER_NO_BLACKLISTED = "Aaaaaa! No want, no want! Go away!", + TRADER_NOT_ENOUGH = "Not enough! More! More!", + TRADER_BRIBE_REFUSAL = "Zhis is a station, stupid!" + ) diff --git a/code/datums/trading/traders/food.dm b/code/datums/trading/traders/food.dm index 6325df8a7f4..7a6c4aee8d4 100644 --- a/code/datums/trading/traders/food.dm +++ b/code/datums/trading/traders/food.dm @@ -1,28 +1,34 @@ /datum/trader/pizzaria name = "Pizza Shop Employee" - name_language = TRADER_DEFAULT_NAME origin = "Pizzeria" - possible_origins = list("Papa Joe's", "Pizza Ship", "Dominator Pizza", "Little Kaezars", "Pizza Planet", "Cheese Louise", "Little Taste o' Neo-Italy", "Pizza Gestapo") + possible_origins = list( + "Papa Joseph's", + "Pizza Ship", + "Dominator Pizza", + "Little Kaezars", + "Pizza Planet", + "Cheese Louise", + "Little Taste o' Neo-Italy", + "Pizza Gestapo" + ) trade_flags = TRADER_MONEY possible_wanted_items = list() //They are a pizza shop, not a bargainer. possible_trading_items = list(/obj/item/chems/food/sliceable/pizza = TRADER_SUBTYPES_ONLY) - speech = list("hail_generic" = "Hello! Welcome to ORIGIN, may I take your order?", - "hail_deny" = "Beeeep... I'm sorry, your connection has been severed.", - - "trade_complete" = "Thank you for choosing ORIGIN!", - "trade_no_goods" = "I'm sorry but we only take cash.", - "trade_blacklisted" = "Sir that's... highly illegal.", - "trade_not_enough" = "Uhh... that's not enough money for pizza.", - "how_much" = "That pizza will cost you VALUE CURRENCY.", - - "compliment_deny" = "That's a bit forward, don't you think?", - "compliment_accept" = "Thanks, sir! You're very nice!", - "insult_good" = "Please stop that, sir.", - "insult_bad" = "Sir, just because I'm contractually obligated to keep you on the line for a minute doesn't mean I have to take this.", - - "bribe_refusal" = "Uh... thanks for the cash, sir. As long as you're in the area, we'll be here...", - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello! Welcome to " + TRADER_TOKEN_ORIGIN + ", may I take your order?", + TRADER_HAIL_DENY = "Beeeep... I'm sorry, your connection has been severed.", + TRADER_TRADE_COMPLETE = "Thank you for choosing " + TRADER_TOKEN_ORIGIN + "!", + TRADER_NO_GOODS = "I'm sorry but we only take cash.", + TRADER_NO_BLACKLISTED = "Sir that's... highly illegal.", + TRADER_NOT_ENOUGH = "Uhh... that's not enough money for pizza.", + TRADER_HOW_MUCH = "That pizza will cost you " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_COMPLIMENT_DENY = "That's a bit forward, don't you think?", + TRADER_COMPLIMENT_ACCEPT = "Thanks, sir! You're very nice!", + TRADER_INSULT_GOOD = "Please stop that, sir.", + TRADER_INSULT_BAD = "Sir, just because I'm contractually obligated to keep you on the line for a minute doesn't mean I have to take this.", + TRADER_BRIBE_REFUSAL = "Uh... thanks for the cash, sir. As long as you're in the area, we'll be here...", + ) /datum/trader/pizzaria/trade(var/list/offers, var/num, var/turf/location) . = ..() @@ -35,10 +41,13 @@ /datum/trader/ship/chinese name = "Chinese Restaurant" - name_language = TRADER_DEFAULT_NAME origin = "Captain Panda Bistro" - possible_origins = list("888 Shanghai Kitchen", "Mr. Lee's Greater Hong Kong", "The House of the Venerable and Inscrutable Colonel", "Lucky Dragon") - trade_flags = TRADER_MONEY + possible_origins = list( + "888 Shanghai Kitchen", + "Mr. Lee's Greater Hong Kong", + "The House of the Venerable and Inscrutable Colonel", + "Lucky Dragon" + ) possible_wanted_items = list() possible_trading_items = list( /obj/item/chems/food/meatkabob = TRADER_THIS_TYPE, @@ -50,35 +59,35 @@ /obj/item/chems/drinks/dry_ramen = TRADER_THIS_TYPE ) - var/list/fortunes = list("Today it's up to you to create the peacefulness you long for.", - "If you refuse to accept anything but the best, you very often get it.", - "A smile is your passport into the hearts of others.", - "Hard work pays off in the future, laziness pays off now.", - "Change can hurt, but it leads a path to something better.", - "Hidden in a valley beside an open stream- This will be the type of place where you will find your dream.", - "Never give up. You're not a failure if you don't give up.", - "Love can last a lifetime, if you want it to.", - "The love of your life is stepping into your planet this summer.", - "Your ability for accomplishment will follow with success.", - "Please help me, I'm trapped in a fortune cookie factory!") - - speech = list("hail_generic" = "There are two things constant in life, death and Chinese food. How may I help you?", - "hail_deny" = "We do not take orders from rude customers.", - - "trade_complete" = "Thank you, sir, for your patronage.", - "trade_blacklist" = "No, that is very odd. Why would you trade that away?", - "trade_no_goods" = "I only accept money transfers.", - "trade_not_enough" = "No, I am sorry, that is not possible. I need to make a living.", - "how_much" = "I give you ITEM, for VALUE CURRENCY. No more, no less.", - - "compliment_deny" = "That was an odd thing to say. You are very odd.", - "compliment_accept" = "Good philosophy, see good in bad, I like.", - "insult_good" = "As a man said long ago, \"When anger rises, think of the consequences.\" Think on that.", - "insult_bad" = "I do not need to take this from you.", + var/list/fortunes = list( + "Today it's up to you to create the peacefulness you long for.", + "If you refuse to accept anything but the best, you very often get it.", + "A smile is your passport into the hearts of others.", + "Hard work pays off in the future, laziness pays off now.", + "Change can hurt, but it leads a path to something better.", + "Hidden in a valley beside an open stream- This will be the type of place where you will find your dream.", + "Never give up. You're not a failure if you don't give up.", + "Love can last a lifetime, if you want it to.", + "The love of your life is stepping into your planet this summer.", + "Your ability for accomplishment will follow with success.", + "Please help me, I'm trapped in a fortune cookie factory!" + ) - "bribe_refusal" = "Hm... I'll think about it.", - "bribe_accept" = "Oh yes! I think I'll stay a few more minutes, then.", - ) + speech = list( + TRADER_HAIL_GENERIC = "There are two things constant in life, death and Chinese food. How may I help you?", + TRADER_HAIL_DENY = "We do not take orders from rude customers.", + TRADER_TRADE_COMPLETE = "Thank you, sir, for your patronage.", + TRADER_NO_BLACKLISTED = "No, that is very odd. Why would you trade that away?", + TRADER_NO_GOODS = "I only accept money transfers.", + TRADER_NOT_ENOUGH = "No, I am sorry, that is not possible. I need to make a living.", + TRADER_HOW_MUCH = "I give you " + TRADER_TOKEN_ITEM + ", for " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ". No more, no less.", + TRADER_COMPLIMENT_DENY = "That was an odd thing to say. You are very odd.", + TRADER_COMPLIMENT_ACCEPT = "Good philosophy, see good in bad, I like.", + TRADER_INSULT_GOOD = "As a man said long ago, \"When anger rises, think of the consequences.\" Think on that.", + TRADER_INSULT_BAD = "I do not need to take this from you.", + TRADER_BRIBE_REFUSAL = "Hm... I'll think about it.", + TRADER_BRIBE_ACCEPT = "Oh yes! I think I'll stay a few more minutes, then.", + ) /datum/trader/ship/chinese/trade(var/list/offers, var/num, var/turf/location) . = ..() @@ -89,8 +98,15 @@ /datum/trader/grocery name = "Grocer" - name_language = TRADER_DEFAULT_NAME - possible_origins = list("HyTee", "Kreugars", "Spaceway", "Privaxs", "FutureValue", "Phyvendyme", "Seller's Market") + possible_origins = list( + "HyTee", + "Kreugars", + "Spaceway", + "Privaxs", + "FutureValue", + "Phyvendyme", + "Seller's Market" + ) trade_flags = TRADER_MONEY possible_trading_items = list( @@ -108,45 +124,47 @@ /obj/item/chems/food/variable = TRADER_BLACKLIST_ALL ) - speech = list("hail_generic" = "Hello, welcome to ORIGIN, grocery store of the future!", - "hail_deny" = "I'm sorry, we've blacklisted your communications due to rude behavior.", - - "trade_complete" = "Thank you for shopping at ORIGIN!", - "trade_blacklist" = "I... wow, that's... no, sir. No.", - "trade_no_goods" = "ORIGIN only accepts cash, sir.", - "trade_not_enough" = "That is not enough money, sir.", - "how_much" = "Sir, that'll cost you VALUE CURRENCY. Will that be all?", - - "compliment_deny" = "Sir, this is a professional environment. Please don't make me get my manager.", - "compliment_accept" = "Thank you, sir!", - "insult_good" = "Sir, please do not make a scene.", - "insult_bad" = "Sir, I WILL get my manager if you don't calm down.", - - "bribe_refusal" = "Of course sir! ORIGIN is always here for you!", - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, welcome to " + TRADER_TOKEN_ORIGIN + ", grocery store of the future!", + TRADER_HAIL_DENY = "I'm sorry, we've blacklisted your communications due to rude behavior.", + TRADER_TRADE_COMPLETE = "Thank you for shopping at " + TRADER_TOKEN_ORIGIN + "!", + TRADER_NO_BLACKLISTED = "I... wow, that's... no, sir. No.", + TRADER_NO_GOODS = TRADER_TOKEN_ORIGIN + " only accepts cash, sir.", + TRADER_NOT_ENOUGH = "That is not enough money, sir.", + TRADER_HOW_MUCH = "Sir, that'll cost you " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ". Will that be all?", + TRADER_COMPLIMENT_DENY = "Sir, this is a professional environment. Please don't make me get my manager.", + TRADER_COMPLIMENT_ACCEPT = "Thank you, sir!", + TRADER_INSULT_GOOD = "Sir, please do not make a scene.", + TRADER_INSULT_BAD = "Sir, I WILL get my manager if you don't calm down.", + TRADER_BRIBE_REFUSAL = "Of course sir! " + TRADER_TOKEN_ORIGIN + " is always here for you!", + ) /datum/trader/bakery name = "Pastry Chef" - name_language = TRADER_DEFAULT_NAME origin = "Bakery" - possible_origins = list("Cakes By Design", "Corner Bakery Local", "My Favorite Cake & Pastry Cafe", "Mama Joes Bakery", "Sprinkles and Fun", "Cakestrosity") - - speech = list("hail_generic" = "Hello, welcome to ORIGIN! We serve baked goods, including pies, cakes, and anything sweet!", - "hail_deny" = "Our food is a privilege, not a right. Goodbye.", - - "trade_complete" = "Thank you for your purchase! Come again if you're hungry for more!", - "trade_blacklist" = "We only accept money. Not... that.", - "trade_no_goods" = "Cash for cakes! That's our business!", - "trade_not_enough" = "Our dishes are much more expensive than that, sir.", - "how_much" = "That lovely dish will cost you VALUE CURRENCY.", - - "compliment_deny" = "Oh wow, how nice of you...", - "compliment_accept" = "You're almost as sweet as my pies!", - "insult_good" = "My pies are NOT knockoffs!", - "insult_bad" = "Well, aren't you a sour apple?", + possible_origins = list( + "Cakes By Design", + "Corner Bakery Local", + "My Favorite Cake & Pastry Cafe", + "Mama Joes Bakery", + "Sprinkles and Fun", + "Cakestrosity" + ) - "bribe_refusal" = "Oh ho ho! I'd never think of taking ORIGIN on the road!", - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, welcome to " + TRADER_TOKEN_ORIGIN + "! We serve baked goods, including pies, cakes, and anything sweet!", + TRADER_HAIL_DENY = "Our food is a privilege, not a right. Goodbye.", + TRADER_TRADE_COMPLETE = "Thank you for your purchase! Come again if you're hungry for more!", + TRADER_NO_BLACKLISTED = "We only accept money. Not... that.", + TRADER_NO_GOODS = "Cash for cakes! That's our business!", + TRADER_NOT_ENOUGH = "Our dishes are much more expensive than that, sir.", + TRADER_HOW_MUCH = "That lovely dish will cost you " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_COMPLIMENT_DENY = "Oh wow, how nice of you...", + TRADER_COMPLIMENT_ACCEPT = "You're almost as sweet as my pies!", + TRADER_INSULT_GOOD = "My pies are NOT knockoffs!", + TRADER_INSULT_BAD = "Well, aren't you a sour apple?", + TRADER_BRIBE_REFUSAL = "Oh ho ho! I'd never think of taking " + TRADER_TOKEN_ORIGIN + " on the road!", + ) possible_trading_items = list( /obj/item/chems/food/slice/birthdaycake/filled = TRADER_THIS_TYPE, /obj/item/chems/food/slice/carrotcake/filled = TRADER_THIS_TYPE, diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index e8f1b0b2df7..76c338c2815 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -1,27 +1,31 @@ /datum/trader/ship/toyshop name = "Toy Shop Employee" - name_language = TRADER_DEFAULT_NAME origin = "Toy Shop" - trade_flags = TRADER_GOODS|TRADER_MONEY|TRADER_WANTED_ONLY - possible_origins = list("Toys R Ours", "LET'S GO", "Kay-Cee Toys", "Build-a-Cat", "Magic Box", "The Positronic's Dungeon and Baseball Card Shop") - speech = list("hail_generic" = "Uhh... hello? Welcome to ORIGIN, I hope you have a, uhh.... good shopping trip.", - "hail_deny" = "Nah, you're not allowed here. At all", - - "trade_complete" = "Thanks for shopping... here... at ORIGIN.", - "trade_blacklist" = "Uuuhhh.... no.", - "trade_found_unwanted" = "Nah! That's not what I'm looking for. Something rarer.", - "trade_not_enough" = "Just 'cause they're made of cardboard doesn't mean they don't cost money...", - "how_much" = "Uhh... I'm thinking like... VALUE. Right? Or something rare that complements my interest.", - "what_want" = "Ummmm..... I guess I want", - - "compliment_deny" = "Ha! Very funny! You should write your own television show.", - "compliment_accept" = "Why yes, I do work out.", - "insult_good" = "Well, well, well. Guess we learned who was the troll here.", - "insult_bad" = "I've already written a nasty Spacebook post in my mind about you.", - - "bribe_refusal" = "Nah. I need to get moving as soon as uhh... possible.", - "bribe_accept" = "You know what, I wasn't doing anything for TIME minutes anyways.", - ) + trade_flags = TRADER_GOODS | TRADER_MONEY | TRADER_WANTED_ONLY | TRADER_BRIBABLE + possible_origins = list( + "Toys R Ours", + "LET'S GO", + "Kay-Cee Toys", + "Build-a-Cat", + "Magic Box", + "The Positronic's Dungeon and Baseball Card Shop" + ) + speech = list( + TRADER_HAIL_GENERIC = "Uhh... hello? Welcome to " + TRADER_TOKEN_ORIGIN + ", I hope you have a, uhh.... good shopping trip.", + TRADER_HAIL_DENY = "Nah, you're not allowed here. At all", + TRADER_TRADE_COMPLETE = "Thanks for shopping... here... at " + TRADER_TOKEN_ORIGIN + ".", + TRADER_NO_BLACKLISTED = "Uuuhhh.... no.", + TRADER_FOUND_UNWANTED = "Nah! That's not what I'm looking for. Something rarer.", + TRADER_NOT_ENOUGH = "Just 'cause they're made of cardboard doesn't mean they don't cost money...", + TRADER_HOW_MUCH = "Uhh... I'm thinking like... " + TRADER_TOKEN_VALUE + ". Right? Or something rare that complements my interest.", + TRADER_WHAT_WANT = "Ummmm..... I guess I want", + TRADER_COMPLIMENT_DENY = "Ha! Very funny! You should write your own television show.", + TRADER_COMPLIMENT_ACCEPT = "Why yes, I do work out.", + TRADER_INSULT_GOOD = "Well, well, well. Guess we learned who was the troll here.", + TRADER_INSULT_BAD = "I've already written a nasty Spacebook post in my mind about you.", + TRADER_BRIBE_REFUSAL = "Nah. I need to get moving as soon as uhh... possible.", + TRADER_BRIBE_ACCEPT = "You know what, I wasn't doing anything for " + TRADER_TOKEN_TIME + " minutes anyways.", + ) possible_wanted_items = list( /obj/item/toy/figure = TRADER_THIS_TYPE, @@ -49,27 +53,32 @@ /datum/trader/ship/electronics name = "Electronic Shop Employee" - name_language = TRADER_DEFAULT_NAME origin = "Electronic Shop" - possible_origins = list("Best Sale", "Overstore", "Oldegg", "Circuit Citadel", "Silicon Village", "Positronic Solutions LLC", "Sunvolt Inc.") - - speech = list("hail_generic" = "Hello, sir! Welcome to ORIGIN, I hope you find what you are looking for.", - "hail_deny" = "Your call has been disconnected.", - - "trade_complete" = "Thank you for shopping at ORIGIN, would you like to get the extended warranty as well?", - "trade_blacklist" = "Sir, this is a /electronics/ store.", - "trade_no_goods" = "As much as I'd love to buy that from you, I can't.", - "trade_not_enough" = "Your offer isn't adequate, sir.", - "how_much" = "Your total comes out to VALUE CURRENCY.", - - "compliment_deny" = "Hahaha! Yeah... funny...", - "compliment_accept" = "That's very nice of you!", - "insult_good" = "That was uncalled for, sir. Don't make me get my manager.", - "insult_bad" = "Sir, I am allowed to hang up the phone if you continue, sir.", + possible_origins = list( + "Best Sale", + "Overstore", + "Oldegg", + "Circuit Citadel", + "Silicon Village", + "Positronic Solutions LLC", + "Sunvolt Inc." + ) - "bribe_refusal" = "Sorry, sir, but I can't really do that.", - "bribe_accept" = "Why not! Glad to be here for a few more minutes.", - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, sir! Welcome to " + TRADER_TOKEN_ORIGIN + ", I hope you find what you are looking for.", + TRADER_HAIL_DENY = "Your call has been disconnected.", + TRADER_TRADE_COMPLETE = "Thank you for shopping at " + TRADER_TOKEN_ORIGIN + ", would you like to get the extended warranty as well?", + TRADER_NO_BLACKLISTED = "Sir, this is a /electronics/ store.", + TRADER_NO_GOODS = "As much as I'd love to buy that from you, I can't.", + TRADER_NOT_ENOUGH = "Your offer isn't adequate, sir.", + TRADER_HOW_MUCH = "Your total comes out to " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_COMPLIMENT_DENY = "Hahaha! Yeah... funny...", + TRADER_COMPLIMENT_ACCEPT = "That's very nice of you!", + TRADER_INSULT_GOOD = "That was uncalled for, sir. Don't make me get my manager.", + TRADER_INSULT_BAD = "Sir, I am allowed to hang up the phone if you continue, sir.", + TRADER_BRIBE_REFUSAL = "Sorry, sir, but I can't really do that.", + TRADER_BRIBE_ACCEPT = "Why not! Glad to be here for a few more minutes.", + ) possible_trading_items = list( /obj/item/stock_parts/computer/battery_module = TRADER_SUBTYPES_ONLY, @@ -93,30 +102,31 @@ /* Clothing stores: each a different type. A hat/glove store, a shoe store, and a jumpsuit store. */ - /datum/trader/ship/clothingshop name = "Clothing Store Employee" - name_language = TRADER_DEFAULT_NAME origin = "Clothing Store" - possible_origins = list("Space Eagle", "Banana Democracy", "Forever 22", "Textiles Factory Warehouse Outlet", "Blocks Brothers") - speech = list("hail_generic" = "Hello, sir! Welcome to ORIGIN!", - "hail_Vox" = "Well hello, sir! I don't believe we have any clothes that fit you... but you can still look!", - "hail_deny" = "We do not trade with rude customers. Consider yourself blacklisted.", - - "trade_complete" = "Thank you for shopping at ORIGIN. Remember: We cannot accept returns without the original tags!", - "trade_blacklist" = "Hm, how about no?", - "trade_no_goods" = "We don't buy, sir. Only sell.", - "trade_not_enough" = "Sorry, ORIGIN policy to not accept trades below our marked prices.", - "how_much" = "Your total comes out to VALUE CURRENCY.", - - "compliment_deny" = "Excuse me?", - "compliment_accept" = "Aw, you're so nice!", - "insult_good" = "Sir.", - "insult_bad" = "Wow. I don't have to take this.", - - "bribe_refusal" = "ORIGIN policy clearly states we cannot stay for more than the designated time.", - "bribe_accept" = "Hm.... sure! We'll have a few minutes of 'engine troubles'.", - ) + possible_origins = list( + "Space Eagle", + "Banana Democracy", + "Forever 22", + "Textiles Factory Warehouse Outlet", + "Blocks Brothers" + ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, sir! Welcome to " + TRADER_TOKEN_ORIGIN + "!", + TRADER_HAIL_DENY = "We do not trade with rude customers. Consider yourself blacklisted.", + TRADER_TRADE_COMPLETE = "Thank you for shopping at " + TRADER_TOKEN_ORIGIN + ". Remember: We cannot accept returns without the original tags!", + TRADER_NO_BLACKLISTED = "Hm, how about no?", + TRADER_NO_GOODS = "We don't buy, sir. Only sell.", + TRADER_NOT_ENOUGH = "Sorry, " + TRADER_TOKEN_ORIGIN + " policy to not accept trades below our marked prices.", + TRADER_HOW_MUCH = "Your total comes out to " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_COMPLIMENT_DENY = "Excuse me?", + TRADER_COMPLIMENT_ACCEPT = "Aw, you're so nice!", + TRADER_INSULT_GOOD = "Sir.", + TRADER_INSULT_BAD = "Wow. I don't have to take this.", + TRADER_BRIBE_REFUSAL = TRADER_TOKEN_ORIGIN + " policy clearly states we cannot stay for more than the designated time.", + TRADER_BRIBE_ACCEPT = "Hm.... sure! We'll have a few minutes of 'engine troubles'.", + ) possible_trading_items = list( /obj/item/clothing/under = TRADER_SUBTYPES_ONLY, @@ -137,7 +147,13 @@ ) /datum/trader/ship/clothingshop/shoes - possible_origins = list("Foot Safe", "Paysmall", "Popular Footwear", "Grimbly's Shoes", "Right Steps") + possible_origins = list( + "Foot Safe", + "Paysmall", + "Popular Footwear", + "Grimbly's Shoes", + "Right Steps" + ) possible_trading_items = list( /obj/item/clothing/shoes = TRADER_SUBTYPES_ONLY, /obj/item/clothing/shoes/chameleon = TRADER_BLACKLIST, @@ -151,7 +167,12 @@ ) /datum/trader/ship/clothingshop/hatglovesaccessories - possible_origins = list("Baldie's Hats and Accessories", "The Right Fit", "Like a Glove", "Space Fashion") + possible_origins = list( + "Baldie's Hats and Accessories", + "The Right Fit", + "Like a Glove", + "Space Fashion" + ) possible_trading_items = list( /obj/item/clothing/accessory = TRADER_ALL, /obj/item/clothing/accessory/badge = TRADER_BLACKLIST_ALL, @@ -186,9 +207,16 @@ Sells devices, odds and ends, and medical stuff */ /datum/trader/devices name = "Drugstore Employee" - name_language = TRADER_DEFAULT_NAME origin = "Drugstore" - possible_origins = list("Buy 'n Save", "Drug Carnival", "C&B", "Fentles", "Dr. Goods", "Beevees", "McGillicuddy's") + possible_origins = list( + "Buy 'n Save", + "Drug Carnival", + "C&B", + "Fentles", + "Dr. Goods", + "Beevees", + "McGillicuddy's" + ) possible_trading_items = list( /obj/item/flashlight = TRADER_ALL, /obj/item/kit/paint = TRADER_SUBTYPES_ONLY, @@ -228,74 +256,81 @@ Sells devices, odds and ends, and medical stuff /obj/item/pinpointer/radio = TRADER_THIS_TYPE, /obj/item/stack/medical/advanced = TRADER_BLACKLIST ) - speech = list("hail_generic" = "Hello, hello! Bits and bobs and everything in between, I hope you find what you're looking for!", - "hail_silicon" = "Ah! Hello, robot. We only sell things that, ah.... people can hold in their hands, unfortunately. You are still allowed to buy, though!", - "hail_deny" = "Oh no. I don't want to deal with YOU.", - - "trade_complete" = "Thank you! Now remember, there isn't any return policy here, so be careful with that!", - "trade_blacklist" = "Hm. Well that would be illegal, so no.", - "trade_no_goods" = "I'm sorry, I only sell goods.", - "trade_not_enough" = "Gotta pay more than that to get that!", - "how_much" = "Well... I bought it for a lot, but I'll give it to you for VALUE.", - - "compliment_deny" = "Uh... did you say something?", - "compliment_accept" = "Mhm! I can agree to that!", - "insult_good" = "Wow, where was that coming from?", - "insult_bad" = "Don't make me blacklist your connection.", - - "bribe_refusal" = "Well, as much as I'd love to say 'yes', you realize I operate on a station, correct?", - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, hello! Bits and bobs and everything in between, I hope you find what you're looking for!", + TRADER_HAIL_SILICON = "Ah! Hello, robot. We only sell things that, ah.... people can hold in their hands, unfortunately. You are still allowed to buy, though!", + TRADER_HAIL_DENY = "Oh no. I don't want to deal with YOU.", + TRADER_TRADE_COMPLETE = "Thank you! Now remember, there isn't any return policy here, so be careful with that!", + TRADER_NO_BLACKLISTED = "Hm. Well that would be illegal, so no.", + TRADER_NO_GOODS = "I'm sorry, I only sell goods.", + TRADER_NOT_ENOUGH = "Gotta pay more than that to get that!", + TRADER_HOW_MUCH = "Well... I bought it for a lot, but I'll give it to you for " + TRADER_TOKEN_VALUE + ".", + TRADER_COMPLIMENT_DENY = "Uh... did you say something?", + TRADER_COMPLIMENT_ACCEPT = "Mhm! I can agree to that!", + TRADER_INSULT_GOOD = "Wow, where was that coming from?", + TRADER_INSULT_BAD = "Don't make me blacklist your connection.", + TRADER_BRIBE_REFUSAL = "Well, as much as I'd love to say 'yes', you realize I operate on a station, correct?", + ) /datum/trader/ship/robots name = "Robot Seller" - name_language = TRADER_DEFAULT_NAME origin = "Robot Store" - possible_origins = list("AI for the Straight Guy", "Mechanical Buddies", "Bot Chop Shop", "Omni Consumer Projects") + possible_origins = list( + "AI for the Straight Guy", + "Mechanical Buddies", + "Bot Chop Shop", + "Omni Consumer Projects" + ) possible_trading_items = list( /obj/item/bot_kit = TRADER_THIS_TYPE, /obj/item/paicard = TRADER_THIS_TYPE, /obj/item/aicard = TRADER_THIS_TYPE, /mob/living/bot = TRADER_SUBTYPES_ONLY ) - speech = list("hail_generic" = "Welcome to ORIGIN! Let me walk you through our fine robotic selection!", - "hail_silicon" = "Welcome to ORIGIN! Let- oh, you're a synth! Well, your money is good anyway. Welcome, welcome!", - "hail_deny" = "ORIGIN no longer wants to speak to you.", - - "trade_complete" = "I hope you enjoy your new robot!", - "trade_blacklist"= "I work with robots, sir. Not that.", - "trade_no_goods" = "You gotta buy the robots, sir. I don't do trades.", - "trade_not_enough" = "You're coming up short on cash.", - "how_much" = "My fine selection of robots will cost you VALUE!", - - "compliment_deny"= "Well, I almost believed that.", - "compliment_accept"= "Thank you! My craftsmanship is my life.", - "insult_good" = "Uncalled for.... uncalled for.", - "insult_bad" = "I've programmed AI better at insulting than you!", - - "bribe_refusal" = "I've got too many customers waiting in other sectors, sorry.", - "bribe_accept" = "Hm. Don't keep me waiting too long, though.", - ) + speech = list( + TRADER_HAIL_GENERIC = "Welcome to " + TRADER_TOKEN_ORIGIN + "! Let me walk you through our fine robotic selection!", + TRADER_HAIL_SILICON = "Welcome to " + TRADER_TOKEN_ORIGIN + "! Let- oh, you're a synth! Well, your money is good anyway. Welcome, welcome!", + TRADER_HAIL_DENY = TRADER_TOKEN_ORIGIN + " no longer wants to speak to you.", + TRADER_TRADE_COMPLETE = "I hope you enjoy your new robot!", + TRADER_NO_BLACKLISTED = "I work with robots, sir. Not that.", + TRADER_NO_GOODS = "You gotta buy the robots, sir. I don't do trades.", + TRADER_NOT_ENOUGH = "You're coming up short on cash.", + TRADER_HOW_MUCH = "My fine selection of robots will cost you " + TRADER_TOKEN_VALUE + "!", + TRADER_COMPLIMENT_DENY = "Well, I almost believed that.", + TRADER_COMPLIMENT_ACCEPT = "Thank you! My craftsmanship is my life.", + TRADER_INSULT_GOOD = "Uncalled for.... uncalled for.", + TRADER_INSULT_BAD = "I've programmed AI better at insulting than you!", + TRADER_BRIBE_REFUSAL = "I've got too many customers waiting in other sectors, sorry.", + TRADER_BRIBE_ACCEPT = "Hm. Don't keep me waiting too long, though.", + ) /datum/trader/xeno_shop name = "Xenolife Collector" origin = "CSV Not a Poacher" - trade_flags = TRADER_GOODS|TRADER_MONEY|TRADER_WANTED_ONLY|TRADER_WANTED_ALL - possible_origins = list("XenoHugs", "Exotic Specimen Acquisition", "Skinner Catering Reseller", "Corporate Companionship Division", "Lonely Pete's Exotic Companionship","Space Wei's Exotic Cuisine") - speech = list("hail_generic" = "Welcome! We are always looking to acquire more exotic life forms.", - "hail_deny" = "We no longer wish to speak to you. Please contact our legal representative if you wish to rectify this.", - - "trade_complete" = "Remember to give them attention and food. They are living beings, and you should treat them like so.", - "trade_blacklist" = "Legally I can't do that. Morally... well, I refuse to do that.", - "trade_found_unwanted" = "I only want animals. I don't need food or shiny things. I'm looking for specific ones, at that. Ones I already have the cage and food for.", - "trade_not_enough" = "I'd give you this for free, but I need the money to feed the specimens. So you must pay in full.", - "how_much" = "This is a good choice. I believe it will cost you VALUE CURRENCY.", - "what_want" = "I have the facilities, currently, to support", - - "compliment_deny" = "According to customs on 34 planets I traded with, this constitutes sexual harrasment.", - "compliment_accept" = "Thank you. I needed that.", - "insult_good" = "No need to be upset, I believe we can do business.", - "insult_bad" = "I have traded dogs with more bark than that.", - ) + trade_flags = TRADER_GOODS | TRADER_MONEY | TRADER_WANTED_ONLY | TRADER_WANTED_ALL + possible_origins = list( + "XenoHugs", + "Exotic Specimen Acquisition", + "Skinner Catering Reseller", + "Corporate Companionship Division", + "Lonely Pete's Exotic Companionship", + "Space Wei's Exotic Cuisine" + ) + speech = list( + TRADER_HAIL_GENERIC = "Welcome! We are always looking to acquire more exotic life forms.", + TRADER_HAIL_DENY = "We no longer wish to speak to you. Please contact our legal representative if you wish to rectify this.", + TRADER_TRADE_COMPLETE = "Remember to give them attention and food. They are living beings, and you should treat them like so.", + TRADER_NO_BLACKLISTED = "Legally I can't do that. Morally... well, I refuse to do that.", + TRADER_FOUND_UNWANTED = "I only want animals. I don't need food or shiny things. I'm looking for specific ones, at that. Ones I already have the cage and food for.", + TRADER_NOT_ENOUGH = "I'd give you this for free, but I need the money to feed the specimens. So you must pay in full.", + TRADER_HOW_MUCH = "This is a good choice. I believe it will cost you " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_WHAT_WANT = "I have the facilities, currently, to support", + TRADER_COMPLIMENT_DENY = "According to customs on 34 planets I traded with, this constitutes sexual harassment.", + TRADER_COMPLIMENT_ACCEPT = "Thank you. I needed that.", + TRADER_INSULT_GOOD = "No need to be upset, I believe we can do business.", + TRADER_INSULT_BAD = "I have traded dogs with more bark than that.", + TRADER_BRIBE_REFUSAL = "Uh, this is a station. I'm not going anywhere." + ) possible_wanted_items = list( /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, @@ -316,25 +351,31 @@ Sells devices, odds and ends, and medical stuff /datum/trader/medical name = "Medical Supplier" origin = "Infirmary of CSV Iniquity" - trade_flags = TRADER_GOODS|TRADER_MONEY|TRADER_WANTED_ONLY + trade_flags = TRADER_GOODS | TRADER_MONEY | TRADER_WANTED_ONLY want_multiplier = 1.2 margin = 2 - possible_origins = list("Dr.Krieger's Practice", "Legit Medical Supplies (No Refund)", "Mom's & Pop's Addictive Opoids", "Legitimate Pharmaceutical Firm", "Designer Drugs by Lil Xanny") - speech = list("hail_generic" = "Huh? How'd you get this number?! Oh well, if you wanna talk biz, I'm listening.", - "hail_deny" = "This is an automated message. Feel free to fuck the right off after the buzzer. *buzz*", - - "trade_complete" = "Good to have business with ya. Remember, no refunds.", - "trade_blacklist" = "Whoa whoa, I don't want this shit, put it away.", - "trade_found_unwanted" = "What the hell do you expect me to do with this junk?", - "trade_not_enough" = "Sorry, pal, full payment upfront, I don't write the rules. Well, I do, but that's beside the point.", - "how_much" = "Hmm, this is one damn fine item, but I'll part with it for VALUE CURRENCY.", - "what_want" = "I could always use some fucking", - - "compliment_deny" = "Haha, how nice of you. Why don't you go fall in an elevator shaft.", - "compliment_accept" = "Damn right I'm awesome, tell me more.", - "insult_good" = "Damn, pal, no need to get snippy.", - "insult_bad" = "*muffled laughter* Sorry, was that you trying to talk shit? Adorable.", - ) + possible_origins = list( + "Dr.Krieger's Practice", + "Legit Medical Supplies (No Refunds)", + "Mom's & Pop's Addictive Opoids", + "Legitimate Pharmaceutical Firm", + "Designer Drugs by Lil Xanny" + ) + speech = list( + TRADER_HAIL_GENERIC = "Huh? How'd you get this number?! Oh well, if you wanna talk biz, I'm listening.", + TRADER_HAIL_DENY = "This is an automated message. Feel free to fuck the right off after the buzzer. *buzz*", + TRADER_TRADE_COMPLETE = "Good to have business with ya. Remember, no refunds.", + TRADER_NO_BLACKLISTED = "Whoa whoa, I don't want this shit, put it away.", + TRADER_FOUND_UNWANTED = "What the hell do you expect me to do with this junk?", + TRADER_NOT_ENOUGH = "Sorry, pal, full payment upfront, I don't write the rules. Well, I do, but that's beside the point.", + TRADER_HOW_MUCH = "Hmm, this is one damn fine item, but I'll part with it for " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_WHAT_WANT = "I could always use some fucking", + TRADER_COMPLIMENT_DENY = "Haha, how nice of you. Why don't you go fall in an elevator shaft.", + TRADER_COMPLIMENT_ACCEPT = "Damn right I'm awesome, tell me more.", + TRADER_INSULT_GOOD = "Damn, pal, no need to get snippy.", + TRADER_INSULT_BAD = "*muffled laughter* Sorry, was that you trying to talk shit? Adorable.", + TRADER_BRIBE_REFUSAL = "Man I live here, I'm not leaving anytime soon." + ) possible_wanted_items = list( /obj/item/chems/drinks/bottle = TRADER_THIS_TYPE, @@ -371,25 +412,30 @@ Sells devices, odds and ends, and medical stuff /datum/trader/mining name = "Rock'n'Drill Mining Inc" origin = "Automated Smelter AH-532" - trade_flags = TRADER_GOODS|TRADER_MONEY|TRADER_WANTED_ONLY|TRADER_WANTED_ALL + trade_flags = TRADER_GOODS | TRADER_MONEY | TRADER_WANTED_ONLY | TRADER_WANTED_ALL want_multiplier = 1.5 margin = 2 - possible_origins = list("Automated Smelter AH-532", "CMV Locust", "The Galactic Foundry Company", "Crucible LLC") - speech = list("hail_generic" = "Welcome to R'n'D Mining. Please place your order.", - "hail_deny" = "There is no response on the line.", - - "trade_complete" = "Transaction complete. Please use our services again", - "trade_blacklist" = "Whoa whoa, I don't want this shit, put it away.", - "trade_found_unwanted" = "Sorry, we are currently not looking to purchase these items.", - "trade_not_enough" = "Sorry, this is an insufficient sum for this purchase.", - "how_much" = "For ONE entry of ITEM the price would be VALUE CURRENCY.", - "what_want" = "We are currently looking to procure", - - "compliment_deny" = "I am afraid this is beyond my competency.", - "compliment_accept" = "Thank you.", - "insult_good" = "Alright, we will reconsider the terms.", - "insult_bad" = "This is not acceptable, please cease.", - ) + possible_origins = list( + "Automated Smelter AH-532", + "CMV Locust", + "The Galactic Foundry Company", + "Crucible LLC" + ) + speech = list( + TRADER_HAIL_GENERIC = "Welcome to R'n'D Mining. Please place your order.", + TRADER_HAIL_DENY = "There is no response on the line.", + TRADER_TRADE_COMPLETE = "Transaction complete. Please use our services again", + TRADER_NO_BLACKLISTED = "Whoa whoa, I don't want this shit, put it away.", + TRADER_FOUND_UNWANTED = "Sorry, we are currently not looking to purchase these items.", + TRADER_NOT_ENOUGH = "Sorry, this is an insufficient sum for this purchase.", + TRADER_HOW_MUCH = "For ONE entry of " + TRADER_TOKEN_ITEM + " the price would be " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_WHAT_WANT = "We are currently looking to procure", + TRADER_COMPLIMENT_DENY = "I am afraid this is beyond my competency.", + TRADER_COMPLIMENT_ACCEPT = "Thank you.", + TRADER_INSULT_GOOD = "Alright, we will reconsider the terms.", + TRADER_INSULT_BAD = "This is not acceptable, please cease.", + TRADER_BRIBE_REFUSAL = "This facility is not mobile. Payment is unnecessary." + ) possible_wanted_items = list( /obj/item/stack/material/ore = TRADER_SUBTYPES_ONLY, diff --git a/code/datums/trading/traders/misc.dm b/code/datums/trading/traders/misc.dm index 80b69e2dbb5..75bdacd68bb 100644 --- a/code/datums/trading/traders/misc.dm +++ b/code/datums/trading/traders/misc.dm @@ -2,26 +2,30 @@ name = "Pet Shop Owner" name_language = /decl/language/human/common origin = "Pet Shop" - trade_flags = TRADER_GOODS|TRADER_MONEY|TRADER_WANTED_ONLY - possible_origins = list("Paws-Out", "Pets-R-Smart", "Tentacle Companions", "Xeno-Pets and Assorted Goods", "Barks and Drools") - speech = list("hail_generic" = "Welcome to my xeno-pet shop! Here you will find many wonderful companions. Some a bit more... aggressive than others. But companions none the less. I also buy pets, or trade them.", - "hail_deny" = "I no longer wish to speak to you.", - - "trade_complete" = "Remember to give them attention and food. They are living beings, and you should treat them like so.", - "trade_blacklist" = "Legally I can' do that. Morally, I refuse to do that.", - "trade_found_unwanted" = "I only want animals. I don't need food or shiny things. I'm looking for specific ones at that. Ones I already have the cage and food for.", - "trade_not_enough" = "I'd give you the animal for free, but I need the money to feed the others. So you must pay in full.", - "how_much" = "This is a fine specimen. I believe it will cost you VALUE CURRENCY.", - "what_want" = "I have the facilities, currently, to support", - - "compliment_deny" = "That was almost charming.", - "compliment_accept" = "Thank you. I needed that.", - "insult_good" = "I ask you to stop. We can be peaceful. I know we can.", - "insult_bad" = "My interactions with you are becoming less than fruitful.", - - "bribe_refusal" = "I'm not going to do that. I have places to be.", - "bribe_accept" = "Hm. It'll be good for the animals, so sure.", - ) + trade_flags = TRADER_GOODS | TRADER_MONEY | TRADER_WANTED_ONLY | TRADER_BRIBABLE + possible_origins = list( + "Paws-Out", + "Pets-R-Smart", + "Tentacle Companions", + "Xeno-Pets and Assorted Goods", + "Barks and Drools" + ) + speech = list( + TRADER_HAIL_GENERIC = "Welcome to my xeno-pet shop! Here you will find many wonderful companions. Some a bit more... aggressive than others. But companions none the less. I also buy pets, or trade them.", + TRADER_HAIL_DENY = "I no longer wish to speak to you.", + TRADER_TRADE_COMPLETE = "Remember to give them attention and food. They are living beings, and you should treat them like so.", + TRADER_NO_BLACKLISTED = "Legally I can' do that. Morally, I refuse to do that.", + TRADER_FOUND_UNWANTED = "I only want animals. I don't need food or shiny things. I'm looking for specific ones at that. Ones I already have the cage and food for.", + TRADER_NOT_ENOUGH = "I'd give you the animal for free, but I need the money to feed the others. So you must pay in full.", + TRADER_HOW_MUCH = "This is a fine specimen. I believe it will cost you " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_WHAT_WANT = "I have the facilities, currently, to support", + TRADER_COMPLIMENT_DENY = "That was almost charming.", + TRADER_COMPLIMENT_ACCEPT = "Thank you. I needed that.", + TRADER_INSULT_GOOD = "I ask you to stop. We can be peaceful. I know we can.", + TRADER_INSULT_BAD = "My interactions with you are becoming less than fruitful.", + TRADER_BRIBE_REFUSAL = "I'm not going to do that. I have places to be.", + TRADER_BRIBE_ACCEPT = "Hm. It'll be good for the animals, so sure.", + ) possible_wanted_items = list( /mob/living/simple_animal/corgi = TRADER_THIS_TYPE, @@ -75,24 +79,30 @@ origin = "Prank Shop" compliment_increase = 0 insult_drop = 0 - possible_origins = list("Yacks and Yucks Shop", "The Shop From Which I Sell Humorous Items", "The Prank Gestalt", "The Clown's Armory", "Uncle Knuckle's Chuckle Bunker", "A Place from Which to do Humorous Business") - speech = list("hail_generic" = "We welcome you to our shop of humorous items. We invite you to partake in the divine experience of being pranked, and pranking someone else.", - "hail_deny" = "We cannot do business with you. We are sorry.", - - "trade_complete" = "We thank you for purchasing something. We enjoyed the experience of you doing so and we hope to learn from it.", - "trade_blacklist"= "We are not allowed to do such. We are sorry.", - "trade_not_enough"="We have sufficiently experienced giving away goods for free. We wish to experience getting money in return.", - "how_much" = "We believe that is worth VALUE CURRENCY.", - "what_want" = "We wish only for the experiences you give us, in all else we want", - - "compliment_deny"= "You are attempting to compliment us.", - "compliment_accept"="You are attempting to compliment us.", - "insult_good" = "You are attempting to insult us, correct?", - "insult_bad" = "We do not understand.", - - "bribe_refusal" = "We are sorry, but we cannot accept.", - "bribe_accept" = "We are happy to say that we accept this bribe.", - ) + possible_origins = list( + "Yacks and Yucks Shop", + "The Shop From Which I Sell Humorous Items", + "The Prank Gestalt", + "The Clown's Armory", + "Uncle Knuckle's Chuckle Bunker", + "A Place from Which to do Humorous Business" + ) + speech = list( + TRADER_HAIL_GENERIC = "We welcome you to our shop of humorous items. We invite you to partake in the divine experience of being pranked, and pranking someone else.", + TRADER_HAIL_DENY = "We cannot do business with you. We are sorry.", + TRADER_TRADE_COMPLETE = "We thank you for purchasing something. We enjoyed the experience of you doing so and we hope to learn from it.", + TRADER_NO_BLACKLISTED = "We are not allowed to trade for these goods. We are sorry.", + TRADER_NO_GOODS = "We are not allowed to trade for these goods. We are sorry.", + TRADER_NOT_ENOUGH = "We have sufficiently experienced giving away goods for free. We wish to experience getting money in return.", + TRADER_HOW_MUCH = "We believe that is worth " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ".", + TRADER_WHAT_WANT = "We wish only for the experiences you give us, in all else we want", + TRADER_COMPLIMENT_DENY = "You are attempting to compliment us.", + TRADER_COMPLIMENT_ACCEPT = "You are attempting to compliment us.", + TRADER_INSULT_GOOD = "You are attempting to insult us, correct?", + TRADER_INSULT_BAD = "We do not understand.", + TRADER_BRIBE_REFUSAL = "We are sorry, but we cannot accept.", + TRADER_BRIBE_ACCEPT = "We are happy to say that we accept this bribe.", + ) possible_trading_items = list( /obj/item/clothing/mask/gas/clown_hat = TRADER_THIS_TYPE, /obj/item/clothing/mask/gas/mime = TRADER_THIS_TYPE, @@ -113,26 +123,34 @@ /datum/trader/ship/replica_shop name = "Replica Store Owner" - name_language = TRADER_DEFAULT_NAME origin = "Replica Store" - possible_origins = list("Ye-Old Armory", "Knights and Knaves", "The Blacksmith", "Historical Human Apparel and Items", "The Pointy End", "Fight Knight's Knightly Nightly Knight Fights", "Elminster's Fine Steel", "The Arms of King Duordan", "Queen's Edict") - speech = list("hail_generic" = "Greetings, traveler! You've the look of one with a keen hunger for human history. Come in, and learn! Mayhaps even... buy?", - "hail_deny" = "I shan't palaver with a man who thumbs his nose at the annals of history. Goodbye.", - - "trade_complete" = "Thank you, mighty warrior. And remember - these may be replicas, but their edges are honed to razor sharpness!", - "trade_blacklist"= "Nay, we accept only the CURRENCY_SINGULAR. Or sovereigns of the king's mint, of course.", - "trade_not_enough"="Alas, traveler, my fine wares cost more than that.", - "how_much" = "For VALUE CURRENCY, I can part with this finest of goods.", - "what_want" = "I have ever longed for", - - "compliment_deny"= "Oh ho ho! Aren't you quite the jester.", - "compliment_accept"="Why, thank you, traveler! Long have I slaved over the anvil to produce these goods.", - "insult_good" = "Hey, bro, I'm just tryin' to make a living here, okay? The Camelot schtick is part of my brand.", - "insult_bad" = "Man, fuck you, then.", - - "bribe_refusal" = "Alas, traveler - I could stay all eve, but I've an client in waiting, and they are not known for patience.", - "bribe_accept" = "Mayhaps I could set a spell longer, and rest my weary feet.", - ) + possible_origins = list( + "Ye-Old Armory", + "Knights and Knaves", + "The Blacksmith", + "Historical Human Apparel and Items", + "The Pointy End", + "Fight Knight's Knightly Nightly Knight Fights", + "Elminster's Fine Steel", + "The Arms of King Duordan", + "Queen's Edict" + ) + speech = list( + TRADER_HAIL_GENERIC = "Greetings, traveler! You've the look of one with a keen hunger for human history. Come in, and learn! Mayhaps even... buy?", + TRADER_HAIL_DENY = "I shan't palaver with a man who thumbs his nose at the annals of history. Goodbye.", + TRADER_TRADE_COMPLETE = "Thank you, mighty warrior. And remember - these may be replicas, but their edges are honed to razor sharpness!", + TRADER_NO_BLACKLISTED = "Nay, we accept only the " + TRADER_TOKEN_CUR_SINGLE + ". Or sovereigns of the king's mint, of course.", + TRADER_NO_GOODS = "Nay, we accept only the " + TRADER_TOKEN_CUR_SINGLE + ". Or sovereigns of the king's mint, of course.", + TRADER_NOT_ENOUGH = "Alas, traveler, my fine wares cost more than that.", + TRADER_HOW_MUCH = "For " + TRADER_TOKEN_VALUE + " " + TRADER_TOKEN_CURRENCY + ", I can part with this finest of goods.", + TRADER_WHAT_WANT = "I have ever longed for", + TRADER_COMPLIMENT_DENY = "Oh ho ho! Aren't you quite the jester.", + TRADER_COMPLIMENT_ACCEPT = "Why, thank you, traveler! Long have I slaved over the anvil to produce these goods.", + TRADER_INSULT_GOOD = "Hey, bro, I'm just tryin' to make a living here, okay? The Camelot schtick is part of my brand.", + TRADER_INSULT_BAD = "Man, fuck you, then.", + TRADER_BRIBE_REFUSAL = "Alas, traveler - I could stay all eve, but I've an client in waiting, and they are not known for patience.", + TRADER_BRIBE_ACCEPT = "Mayhaps I could set a spell longer, and rest my weary feet." + ) possible_trading_items = list( /obj/item/clothing/head/wizard/magus = TRADER_THIS_TYPE, /obj/item/shield/buckler = TRADER_THIS_TYPE, diff --git a/code/datums/trading/traders/ship.dm b/code/datums/trading/traders/ship.dm index 0e0887e6fa3..79166901a84 100644 --- a/code/datums/trading/traders/ship.dm +++ b/code/datums/trading/traders/ship.dm @@ -1,6 +1,8 @@ //Ships are on a time limit as far as being around goes. //They are ALSO the only ones that can appear after round start /datum/trader/ship + abstract_type = /datum/trader/ship + trade_flags = TRADER_MONEY | TRADER_BRIBABLE var/duration_of_stay = 0 var/typical_duration = 20 //minutes (since trader processes only tick once a minute) @@ -14,11 +16,10 @@ duration_of_stay -= 5 return --duration_of_stay > 0 -/datum/trader/ship/bribe_to_stay_longer(var/amt) - if(prob(-disposition)) - return get_response("bribe_refusal", "How about.... no?") +/datum/trader/ship/is_bribable() + return ..() || prob(-disposition) - var/staylength = round(amt/100) +/datum/trader/ship/is_bribed(var/staylength) duration_of_stay += staylength - . = get_response("bribe_accept", "Sure, I'll stay for TIME more minutes.") - . = replacetext(., "TIME", staylength) \ No newline at end of file + . = get_response(TRADER_BRIBE_ACCEPT, "Sure, I'll stay for " + TRADER_TOKEN_TIME + " more minutes.") + . = replacetext(., TRADER_TOKEN_TIME, staylength) diff --git a/code/datums/trading/traders/unique.dm b/code/datums/trading/traders/unique.dm index b4a4cc110c8..cebfff729ed 100644 --- a/code/datums/trading/traders/unique.dm +++ b/code/datums/trading/traders/unique.dm @@ -1,5 +1,6 @@ /datum/trader/ship/unique - trade_flags = TRADER_WANTED_ONLY|TRADER_GOODS + abstract_type = /datum/trader/ship/unique + trade_flags = TRADER_WANTED_ONLY | TRADER_GOODS | TRADER_BRIBABLE want_multiplier = 5 typical_duration = 40 @@ -23,7 +24,7 @@ return --duration_of_stay > 0 /datum/trader/ship/unique/what_do_you_want() - return get_response("what_want", "I don't want anything!") + return get_response(TRADER_WHAT_WANT, "I don't want anything!") /datum/trader/ship/unique/severance name = "Unknown" @@ -41,22 +42,23 @@ blacklisted_trade_items = null - speech = list("hail_generic" = "H-hello. Can you hear me? G-good... I have... specific needs... I have a lot to t-trade with you in return of course.", - "hail_deny" = "--CONNECTION SEVERED--", - - "trade_complete" = "Hahahahahahaha! Thankyouthankyouthankyou!", - "trade_no_money" = "I d-don't NEED cash.", - "trade_not_enough" = "N-no, no no no. M-more than that... more...", - "trade_found_unwanted" = "I d-don't think you GET what I want, fr- from your offer.", - "how_much" = "Meat. I want meat. The kind they don't serve in the- the mess hall.", - "what_want" = "Long p-pork. Yes... that's what I want...", - - "compliment_deny" = "Your lies won't ch-change what I did.", - "compliment_accept" = "Yes... I suppose you're right.", - "insult_good" = "I... probably deserve that.", - "insult_bad" = "Maybe you should c-come here and say that. You'd be worth s-something then.", - ) - mob_transfer_message = "You are transported to ORIGIN, and with a sickening thud, you fall unconscious, never to wake again." + speech = list( + TRADER_HAIL_GENERIC = "H-hello. Can you hear me? G-good... I have... specific needs... I have a lot to t-trade with you in return of course.", + TRADER_HAIL_DENY = "--CONNECTION SEVERED--", + TRADER_TRADE_COMPLETE = "Hahahahahahaha! Thankyouthankyouthankyou!", + TRADER_NO_MONEY = "I d-don't NEED cash.", + TRADER_NOT_ENOUGH = "N-no, no no no. M-more than that... more...", + TRADER_FOUND_UNWANTED = "I d-don't think you GET what I want, fr- from your offer.", + TRADER_HOW_MUCH = "Meat. I want meat. The kind they don't serve in the- the mess hall.", + TRADER_WHAT_WANT = "Long p-pork. Yes... that's what I want...", + TRADER_COMPLIMENT_DENY = "Your lies won't ch-change what I did.", + TRADER_COMPLIMENT_ACCEPT = "Yes... I suppose you're right.", + TRADER_INSULT_GOOD = "I... probably deserve that.", + TRADER_INSULT_BAD = "Maybe you should c-come here and say that. You'd be worth s-something then.", + TRADER_BRIBE_ACCEPT = "Okay. Fine. But... h-hurry. I can only stay another " + TRADER_TOKEN_TIME + "m-minutes.", + TRADER_BRIBE_REFUSAL = "No! N-no, they're getting closer- I have to, I h-have to go soon." + ) + mob_transfer_message = "You are transported to " + TRADER_TOKEN_ORIGIN + ", and with a sickening thud, you fall unconscious, never to wake again." /datum/trader/ship/unique/rock @@ -72,29 +74,35 @@ ) want_multiplier = 5000 - speech = list("hail_generic" = "Blub am MERCHANT. Blub hunger for things. Boo bring them to blub, yes?", - "hail_deny" = "Blub does not want to speak to boo.", - - "trade_complete" = "Blub likes to trade!", - "trade_no_money" = "Boo try to give Blub paper. Blub does not want paper.", - "trade_not_enough" = "Blub hungry for bore than that.", - "trade_found_unwanted" = "Blub only wants bocks. Give bocks.", - "trade_refuse" = "No, Blub will not do that. Blub wants bocks, yes? Give bocks.", - "how_much" = "Blub wants bocks. Boo give bocks. Blub gives stuff blub found.", - "what_want" = "Blub wants bocks. Big bocks, small bocks. Shiny bocks!", - - "compliment_deny" = "Blub is just MERCHANT. What do boo mean?", - "compliment_accept" = "Boo are a bood berson!", - "insult_good" = "Blub do not understand. Blub thought we were briends.", - "insult_bad" = "Blub feels bad now.", - ) + speech = list( + TRADER_HAIL_GENERIC = "Blub am " + TRADER_TOKEN_MERCHANT + ". Blub hunger for things. Boo bring them to blub, yes?", + TRADER_HAIL_DENY = "Blub does not want to speak to boo.", + TRADER_TRADE_COMPLETE = "Blub likes to trade!", + TRADER_NO_MONEY = "Boo try to give Blub paper. Blub does not want paper.", + TRADER_NOT_ENOUGH = "Blub hungry for bore than that.", + TRADER_NO_BLACKLISTED = "Blub not want that! No!", + TRADER_FOUND_UNWANTED = "Blub only wants bocks. Give bocks.", + TRADER_HOW_MUCH = "Blub wants bocks. Boo give bocks. Blub gives stuff blub found.", + TRADER_WHAT_WANT = "Blub wants bocks. Big bocks, small bocks. Shiny bocks!", + TRADER_COMPLIMENT_DENY = "Blub is just " + TRADER_TOKEN_MERCHANT + ". What do boo mean?", + TRADER_COMPLIMENT_ACCEPT = "Boo are a bood berson!", + TRADER_INSULT_GOOD = "Blub do not understand. Blub thought we were briends.", + TRADER_INSULT_BAD = "Blub feels bad now.", + TRADER_BRIBE_ACCEPT = "Blub will stay for " + TRADER_TOKEN_TIME + " binutes bonger.", + TRADER_BRIBE_REFUSAL = "Blub must go. Blub's beople beed blem." + ) //probably could stick soem Howl references in here but like, eh. Haven't seen it in years. /datum/trader/ship/unique/wizard name = "Sorcerer" origin = "A moving castle" - possible_origins = list("An indistinct location", "Unknown location", "The Diamond Sphere", "Beyond the Veil", "Deadverse") - name_language = TRADER_DEFAULT_NAME + possible_origins = list( + "An indistinct location", + "Unknown location", + "The Diamond Sphere", + "Beyond the Veil", + "Deadverse" + ) possible_wanted_items = list( /mob/living/simple_animal/construct = TRADER_SUBTYPES_ONLY, @@ -118,19 +126,24 @@ /obj/item/staff = TRADER_ALL, ) //Probably see about getting some more wizard based shit - speech = list("hail_generic" = "Hello! Are you here on pleasure or business?", - "hail_Golem" = "Interesting... how incredibly interesting... come! Let us do business!", - "hail_deny" = "I'm sorry, but I REALLY don't want to speak to you.", - - "trade_complete" = "Pleasure doing business with you!", - "trade_no_money" = "Cash? Ha! What's cash to a man like me?", - "trade_not_enough" = "Hm, well I do enjoy what you're offering, I prefer a fair trade.", - "trade_found_unwanted" = "What? I want oddities! Don't you understand?", - "how_much" = "I want dark things, brooding things... things that go bump in the night. Things that bleed wrong, live wrong, are wrong.", - "what_want" = "Have anything from a broodish cult?", - - "compliment_deny" = "Like I haven't heard that one before!", - "compliment_accept" = "Haha! Aren't you nice.", - "insult_good" = "Naughty naughty.", - "insult_bad" = "Now where do you get off talking to me like that?", - ) \ No newline at end of file + speech = list( + TRADER_HAIL_GENERIC = "Hello! Are you here on pleasure or business?", + TRADER_HAIL_DENY = "I'm sorry, but I REALLY don't want to speak to you.", + TRADER_TRADE_COMPLETE = "Pleasure doing business with you!", + TRADER_NO_MONEY = "Cash? Ha! What's cash to a man like me?", + TRADER_NOT_ENOUGH = "Hm, well I do enjoy what you're offering, I prefer a fair trade.", + TRADER_FOUND_UNWANTED = "What? I want oddities! Don't you understand?", + TRADER_HOW_MUCH = "I want dark things, brooding things... things that go bump in the night. Things that bleed wrong, live wrong, are wrong.", + TRADER_WHAT_WANT = "Have anything from a broodish cult?", + TRADER_COMPLIMENT_DENY = "Like I haven't heard that one before!", + TRADER_COMPLIMENT_ACCEPT = "Haha! Aren't you nice.", + TRADER_INSULT_GOOD = "Naughty naughty.", + TRADER_INSULT_BAD = "Now where do you get off talking to me like that?", + TRADER_BRIBE_ACCEPT = "Well, if you're not pulling the knob on my staff, I can stay for another " + TRADER_TOKEN_TIME + " minutes.", + TRADER_BRIBE_REFUSAL = "A wizard does not depart early or late, but precisely when they intend to. No.", + TRADER_NO_BLACKLISTED = "I cannot accept such a thing. No trade." + ) + +/datum/trader/ship/unique/wizard/New() + speech[TRADER_HAIL_START + SPECIES_GOLEM] = "Interesting... how incredibly interesting... come! Let us do business!" + ..() diff --git a/code/datums/trading/traders/weaponry.dm b/code/datums/trading/traders/weaponry.dm index 2f9d25d5c04..2dc50d4c074 100644 --- a/code/datums/trading/traders/weaponry.dm +++ b/code/datums/trading/traders/weaponry.dm @@ -1,22 +1,29 @@ /datum/trader/ship/gunshop name = "Gun Shop Employee" - name_language = TRADER_DEFAULT_NAME origin = "Gun Shop" - possible_origins = list("Rooty Tootie's Point-n-Shooties", "Bang-Bang Shop", "Wild Wild West Shop", "Keleshnikov", "Hunting Depot", "Big Game Hunters") - speech = list("hail_generic" = "Hello, hello! I hope you have your permit. Oh, who are we kidding, you're welcome anyway!", - "hail_deny" = "Store policy dictates that you can fuck off.", - - "trade_complete" = "Thanks for buying your guns from ORIGIN!", - "trade_blacklist" = "We may deal in guns, but that doesn't mean we'll trade for illegal goods...", - "trade_no_goods" = "Cash for guns, thats the deal.", - "trade_not_enough" = "Guns are expensive! Give us more if you REALLY want it.", - "how_much" = "Well, I'd love to give this little beauty to you for VALUE.", - - "compliment_deny" = "If we were in the same room right now, I'd probably punch you.", - "compliment_accept" = "Ha! Good one!", - "insult_good" = "I expected better from you. I suppose in that, I was wrong.", - "insult_bad" = "If I had my gun I'd shoot you!" - ) + possible_origins = list( + "Rooty Tootie's Point-n-Shooties", + "Bang-Bang Shop", + "Wild Wild West Shop", + "Keleshnikov", + "Hunting Depot", + "Big Game Hunters" + ) + speech = list( + TRADER_HAIL_GENERIC = "Hello, hello! I hope you have your permit. Oh, who are we kidding, you're welcome anyway!", + TRADER_HAIL_DENY = "Store policy dictates that you can fuck off.", + TRADER_TRADE_COMPLETE = "Thanks for buying your guns from " + TRADER_TOKEN_ORIGIN + "!", + TRADER_NO_BLACKLISTED = "We may deal in guns, but that doesn't mean we'll trade for illegal goods...", + TRADER_NO_GOODS = "Cash for guns, thats the deal.", + TRADER_NOT_ENOUGH = "Guns are expensive! Give us more if you REALLY want it.", + TRADER_HOW_MUCH = "Well, I'd love to give this little beauty to you for " + TRADER_TOKEN_VALUE + ".", + TRADER_COMPLIMENT_DENY = "If we were in the same room right now, I'd probably punch you.", + TRADER_COMPLIMENT_ACCEPT = "Ha! Good one!", + TRADER_INSULT_GOOD = "I expected better from you. I suppose in that, I was wrong.", + TRADER_INSULT_BAD = "If I had my gun I'd shoot you!", + TRADER_BRIBE_ACCEPT = "For that much scratch, I can stay for another " + TRADER_TOKEN_TIME + " minutes.", + TRADER_BRIBE_REFUSAL = "Look, I've got places to be, I can't hang around shooting the shit." + ) possible_trading_items = list( /obj/item/gun/projectile/pistol/holdout = TRADER_ALL, @@ -32,23 +39,30 @@ /datum/trader/ship/egunshop name = "Energy Gun Shop Employee" - name_language = TRADER_DEFAULT_NAME origin = "EGun Shop" - possible_origins = list("The Emperor's Lasgun Shop", "Future Guns", "Solar Army", "Kiefer's Dependable Electric Arms", "Olympus Kingsport") - speech = list("hail_generic" = "Welcome to the future of warfare! ORIGIN, your one-stop shop for energy weaponry!", - "hail_deny" = "I'm sorry, your communication channel has been blacklisted.", - - "trade_complete" = "Thank you, your purchase has been logged and you have automatically liked our Spacebook page.", - "trade_blacklist" = "I'm sorry, is that a joke?", - "trade_no_goods" = "We deal in cash.", - "trade_not_enough" = "State of the art weaponry costs more than that.", - "how_much" = "All our quality weapons are priceless, but I'd give that to you for VALUE.", + possible_origins = list( + "The Emperor's Lasgun Shop", + "Future Guns", + "Solar Army", + "Kiefer's Dependable Electric Arms", + "Olympus Kingsport" + ) + speech = list( + TRADER_HAIL_GENERIC = "Welcome to the future of warfare! " + TRADER_TOKEN_ORIGIN + ", your one-stop shop for energy weaponry!", + TRADER_HAIL_DENY = "I'm sorry, your communication channel has been blacklisted.", + TRADER_TRADE_COMPLETE = "Thank you, your purchase has been logged and you have automatically liked our Spacebook page.", + TRADER_NO_BLACKLISTED = "I'm sorry, is that a joke?", + TRADER_NO_GOODS = "We deal in cash.", + TRADER_NOT_ENOUGH = "State of the art weaponry costs more than that.", + TRADER_HOW_MUCH = "All our quality weapons are priceless, but I'd give that to you for " + TRADER_TOKEN_VALUE + ".", + TRADER_COMPLIMENT_DENY = "If I was dumber I probably would have believed you.", + TRADER_COMPLIMENT_ACCEPT = "Yes, I am very smart.", + TRADER_INSULT_GOOD = "Energy weapons are TWICE the gun kinetic guns are!", + TRADER_INSULT_BAD = "That's... very mean. I won't think twice about blacklisting your channel, so stop.", + TRADER_BRIBE_ACCEPT = "Look, I'm not supposed to, but I guess I can stay for " + TRADER_TOKEN_TIME + " minutes.", + TRADER_BRIBE_REFUSAL = "Sorry, no can do. I'm on a tight schedule." - "compliment_deny" = "If I was dumber I probably would have believed you.", - "compliment_accept" = "Yes, I am very smart.", - "insult_good" = "Energy weapons are TWICE the gun kinetic guns are!", - "insult_bad" = "That's... very mean. I won't think twice about blacklisting your channel, so stop." - ) + ) possible_trading_items = list( /obj/item/gun/energy/taser = TRADER_THIS_TYPE, @@ -66,20 +80,20 @@ /datum/trader/dogan name = "Dogan" origin = "Dogan's Gun Beacon" - speech = list("hail_generic" = "Hello! This is an automatic recording of me, Mr. Dogan! I hope you like the... GUNS... I've got in store for you today.", - "hail_deny" = "I formally welcome you to... NOT... visit our store!", - - "trade_complete" = "Thank you for... PURCHASING... that quality... ITEM... from me!", - "trade_blacklist" = "Thank you for... that quality... ILLEGAL OFFER THAT I WILL REFUSE... from me!", - "trade_no_goods" = "Thank you for... that quality... OFFER THAT ISN'T MONEY THAT I WILL REFUSE... from me!", - "trade_not_enough" = "Thank you for... that quality... OFFER THAT IS NOT ENOUGH... from me!", - "how_much" = "Thank you for... ASKING ME ABOUT MY PRICES... that quality... ITEM is worth VALUE... from me!", - - "compliment_deny" = "Thank you for... that quality... COMPLIMENT... from me!", - "compliment_accept" = "Thank you for... that quality... COMPLIMENT... from me!", - "insult_good" = "Thank you for... that quality... INSULT... from me!", - "insult_bad" = "Thank you for... that quality... INSULT... from me!" - ) + speech = list( + TRADER_HAIL_GENERIC = "Hello! This is an automatic recording of me, Mr. Dogan! I hope you like the... GUNS... I've got in store for you today.", + TRADER_HAIL_DENY = "I formally welcome you to... NOT... visit our store!", + TRADER_TRADE_COMPLETE = "Thank you for... PURCHASING... that quality... " + TRADER_TOKEN_ITEM + "... from me!", + TRADER_NO_BLACKLISTED = "Thank you for... that quality... ILLEGAL OFFER THAT I WILL REFUSE... from me!", + TRADER_NO_GOODS = "Thank you for... that quality... OFFER THAT ISN'T MONEY THAT I WILL REFUSE... from me!", + TRADER_NOT_ENOUGH = "Thank you for... that quality... OFFER THAT IS NOT ENOUGH... from me!", + TRADER_HOW_MUCH = "Thank you for... ASKING ME ABOUT MY PRICES... that quality... " + TRADER_TOKEN_ITEM + " is worth " + TRADER_TOKEN_VALUE + "... from me!", + TRADER_COMPLIMENT_DENY = "Thank you for... that quality... COMPLIMENT... from me!", + TRADER_COMPLIMENT_ACCEPT = "Thank you for... that quality... COMPLIMENT... from me!", + TRADER_INSULT_GOOD = "Thank you for... that quality... INSULT... from me!", + TRADER_INSULT_BAD = "Thank you for... that quality... INSULT... from me!", + TRADER_BRIBE_REFUSAL = "Your... BLATANT BRIBERY... is... UNNECESSARY!" + ) compliment_increase = 0 insult_drop = 0 diff --git a/code/datums/traits/traits.dm b/code/datums/traits/traits.dm index 2cabd2c4684..dc623ae5fce 100644 --- a/code/datums/traits/traits.dm +++ b/code/datums/traits/traits.dm @@ -16,45 +16,62 @@ /mob/living/proc/GetTraits() SHOULD_NOT_SLEEP(TRUE) RETURN_TYPE(/list) - return traits - -/mob/living/carbon/human/GetTraits() - if(traits) - return traits - return species.traits + var/decl/species/our_species = get_species() + return traits || our_species?.traits /mob/living/proc/SetTrait(trait_type, trait_level) SHOULD_NOT_SLEEP(TRUE) + var/decl/species/our_species = get_species() var/decl/trait/T = GET_DECL(trait_type) if(!T.validate_level(trait_level)) return FALSE - LAZYSET(traits, trait_type, trait_level) - return TRUE - -/mob/living/carbon/human/SetTrait(trait_type, trait_level) - var/decl/trait/T = GET_DECL(trait_type) - if(!T.validate_level(trait_level)) - return FALSE - - if(!traits) // If traits haven't been setup before, check if we need to do so now - var/species_level = species.traits[trait_type] + if(our_species && !traits) // If species traits haven't been setup before, check if we need to do so now + var/species_level = our_species.traits[trait_type] if(species_level == trait_level) // Matched the default species trait level, ignore return TRUE - traits = species.traits.Copy() // The setup is to simply copy the species list of traits + traits = our_species.traits.Copy() // The setup is to simply copy the species list of traits - return ..(trait_type, trait_level) - -/mob/living/proc/RemoveTrait(trait_type) - LAZYREMOVE(traits, trait_type) - -/mob/living/carbon/human/RemoveTrait(trait_type) - // If traits haven't been setup, but we're trying to remove a trait that exists on the species then setup traits - if(!traits && (trait_type in species.traits)) - traits = species.traits.Copy() + LAZYSET(traits, trait_type, trait_level) + return TRUE - ..(trait_type) // Could go through the trouble of nulling the traits list if it's again equal to the species list but eh - traits = traits || list() // But we do ensure that humans don't null their traits list, to avoid copying from species again +/mob/living/proc/RemoveTrait(trait_type, canonize = TRUE) + var/decl/species/our_species = get_species() + // If traits haven't been set up, but we're trying to remove a trait that exists on the species then set up traits + if(!traits && LAZYISIN(our_species?.traits, trait_type)) + traits = our_species.traits.Copy() + if(LAZYLEN(traits)) + LAZYREMOVE(traits, trait_type) + // Check if we can just default back to species traits. + if(canonize) + CanonizeTraits() + +/// Removes a trait unless it exists on the species. +/// If it does exist on the species, we reset it to the species' trait level. +/mob/living/proc/RemoveExtrinsicTrait(trait_type) + var/decl/species/our_species = get_species() + if(!LAZYACCESS(our_species?.traits, trait_type)) + RemoveTrait(trait_type) + else if(our_species?.traits[trait_type] != GetTraitLevel(trait_type)) + SetTrait(trait_type, our_species?.traits[trait_type]) + +/// Sets the traits list to null if it's identical to the species list. +/// Returns TRUE if the list was reset and FALSE otherwise. +/mob/living/proc/CanonizeTraits() + if(!traits) // Already in canonical form. + return FALSE + var/decl/species/our_species = get_species() + if(!our_species) // Doesn't apply without a species. + return FALSE + var/list/missing_traits = traits ^ our_species?.traits + var/list/matched_traits = traits & our_species?.traits + if(LAZYLEN(missing_traits)) + return FALSE + for(var/trait in matched_traits) // inside this loop we know our_species exists and has traits + if(traits[trait] != our_species.traits[trait]) + return FALSE + traits = null + return TRUE /decl/trait abstract_type = /decl/trait diff --git a/code/datums/underwear/underwear.dm b/code/datums/underwear/underwear.dm index 0ef3cb0dde6..a42fcf1a66f 100644 --- a/code/datums/underwear/underwear.dm +++ b/code/datums/underwear/underwear.dm @@ -66,5 +66,5 @@ UW.icon_state = icon_state for(var/datum/gear_tweak/gt in tweaks) - gt.tweak_item(user, UW, metadata && metadata["[gt]"] ? metadata["[gt]"] : gt.get_default()) + gt.tweak_item(user, UW, ((metadata && metadata["[gt]"]) ? metadata["[gt]"] : gt.get_default())) return UW diff --git a/code/datums/vote/gamemode.dm b/code/datums/vote/gamemode.dm index 2b31287946b..bb05d20a73d 100644 --- a/code/datums/vote/gamemode.dm +++ b/code/datums/vote/gamemode.dm @@ -22,7 +22,7 @@ ..() choices += config.votable_modes for (var/F in choices) - var/datum/game_mode/M = gamemode_cache[F] + var/decl/game_mode/M = decls_repository.get_decl_by_id(F, validate_decl_type = FALSE) if(!M) continue display_choices[F] = capitalize(M.name) diff --git a/code/datums/vote/transfer.dm b/code/datums/vote/transfer.dm index 736c14343b1..52de1c72e4c 100644 --- a/code/datums/vote/transfer.dm +++ b/code/datums/vote/transfer.dm @@ -53,7 +53,7 @@ if((. = ..())) return if(config.vote_no_dead_crew_transfer) - return !isliving(user) || ismouse(user) || is_drone(user) + return !isliving(user) || ismouse(user) || isdrone(user) /datum/vote/transfer/check_toggle() return config.allow_vote_restart ? "Allowed" : "Disallowed" diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 921909d2c0a..d8e207e3a19 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -41,7 +41,7 @@ var/global/const/AIRLOCK_WIRE_SPEAKER = 4096 /datum/wires/airlock/CanUse(var/mob/living/L) var/obj/machinery/door/airlock/A = holder - if(!istype(L, /mob/living/silicon)) + if(!issilicon(L)) if(A.isElectrified()) if(A.shock(L, 100)) return 0 diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm index c9ada1658a9..65636924813 100644 --- a/code/datums/wires/camera.dm +++ b/code/datums/wires/camera.dm @@ -40,7 +40,7 @@ var/global/const/CAMERA_WIRE_NOTHING2 = 32 if(CAMERA_WIRE_FOCUS) var/datum/extension/network_device/camera/D = get_extension(holder, /datum/extension/network_device) var/new_range = (mended ? C.long_range : C.short_range) - D.set_view_range(new_range) + D?.set_view_range(new_range) if(CAMERA_WIRE_POWER) C.cut_power = !mended @@ -64,7 +64,7 @@ var/global/const/CAMERA_WIRE_NOTHING2 = 32 if(CAMERA_WIRE_FOCUS) var/datum/extension/network_device/camera/D = get_extension(holder, /datum/extension/network_device) var/new_range = (D.view_range == C.long_range ? C.short_range : C.long_range) - D.set_view_range(new_range) + D?.set_view_range(new_range) if(CAMERA_WIRE_LIGHT) C.light_disabled = !C.light_disabled diff --git a/code/datums/wires/smartfridge.dm b/code/datums/wires/smartfridge.dm index 81949dcddd4..86a00b1217a 100644 --- a/code/datums/wires/smartfridge.dm +++ b/code/datums/wires/smartfridge.dm @@ -17,7 +17,7 @@ var/global/const/SMARTFRIDGE_WIRE_IDSCAN = 4 /datum/wires/smartfridge/CanUse(var/mob/living/L) var/obj/machinery/smartfridge/S = holder - if(!istype(L, /mob/living/silicon)) + if(!issilicon(L)) if(S.seconds_electrified) if(S.shock(L, 100)) return 0 diff --git a/code/datums/wires/suit_cycler.dm b/code/datums/wires/suit_cycler.dm index 0c3ae3a3c5d..ab98f8f934f 100644 --- a/code/datums/wires/suit_cycler.dm +++ b/code/datums/wires/suit_cycler.dm @@ -13,7 +13,7 @@ var/global/const/SUIT_STORAGE_WIRE_LOCKED = 4 /datum/wires/suit_cycler/CanUse(var/mob/living/L) var/obj/machinery/suit_cycler/S = holder - if(!istype(L, /mob/living/silicon)) + if(!issilicon(L)) if(S.electrified) if(S.shock(L, 100)) return 0 diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 6e9c47a6508..9af6ae5230a 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -15,7 +15,7 @@ var/global/const/VENDING_WIRE_IDSCAN = 8 /datum/wires/vending/CanUse(var/mob/living/L) var/obj/machinery/vending/V = holder - if(!istype(L, /mob/living/silicon)) + if(!issilicon(L)) if(V.seconds_electrified) if(V.shock(L, 100)) return 0 diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 17c33b953e3..6a4919f951f 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -131,7 +131,7 @@ return 1 // Get the raw list of potential players. -/decl/special_role/proc/build_candidate_list(datum/game_mode/mode, ghosts_only) +/decl/special_role/proc/build_candidate_list(decl/game_mode/mode, ghosts_only) candidates = list() // Clear. // Prune restricted status. Broke it up for readability. @@ -155,7 +155,7 @@ return candidates // Builds a list of potential antags without actually setting them. Used to test mode viability. -/decl/special_role/proc/get_potential_candidates(var/datum/game_mode/mode, var/ghosts_only) +/decl/special_role/proc/get_potential_candidates(var/decl/game_mode/mode, var/ghosts_only) var/candidates = list() // Keeping broken up for readability @@ -205,7 +205,7 @@ return 0 var/datum/mind/player = pending_antagonists[1] - if(!add_antagonist(player,0,0,0,1,1)) + if(!add_antagonist(player, do_not_announce = TRUE, preserve_appearance = TRUE)) message_admins("Could not auto-spawn a [name], failed to add antagonist.") return 0 @@ -241,7 +241,7 @@ if(player.assigned_special_role) log_debug("[player.key] was selected for [name] by lottery, but they already have a special role.") return 0 - if(!(flags & ANTAG_OVERRIDE_JOB) && (!player.current || istype(player.current, /mob/new_player))) + if(!(flags & ANTAG_OVERRIDE_JOB) && (!player.current || isnewplayer(player.current))) log_debug("[player.key] was selected for [name] by lottery, but they have not joined the game.") return 0 if(GAME_STATE >= RUNLEVEL_GAME && (isghostmind(player) || isnewplayer(player.current)) && !(player in SSticker.antag_pool)) diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm index 9a9febdd271..8ecfb5a6c5b 100644 --- a/code/game/antagonist/antagonist_add.dm +++ b/code/game/antagonist/antagonist_add.dm @@ -22,7 +22,7 @@ /decl/special_role/proc/add_antagonist(var/datum/mind/player, var/ignore_role, var/do_not_equip, var/move_to_spawn, var/do_not_announce, var/preserve_appearance) if(!add_antagonist_mind(player, ignore_role)) - return + return FALSE load_required_map() @@ -40,21 +40,21 @@ if(istype(skill_setter)) skill_setter.initialize_skills(player.current.skillset) if(!do_not_equip) - equip(player.current) + equip_role(player.current) if(player.current) player.current.faction = faction - return 1 + return TRUE /decl/special_role/proc/add_antagonist_mind(var/datum/mind/player, var/ignore_role, var/nonstandard_role_type, var/nonstandard_role_msg) if(!istype(player)) - return 0 + return FALSE if(!player.current) - return 0 + return FALSE if(player in current_antagonists) - return 0 + return FALSE if(!can_become_antag(player, ignore_role)) - return 0 + return FALSE current_antagonists |= player if(faction_verb) @@ -80,7 +80,7 @@ if(nonstandard_role_msg) to_chat(player.current, "[nonstandard_role_msg]") update_icons_added(player) - return 1 + return TRUE /decl/special_role/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted) if(!istype(player)) diff --git a/code/game/antagonist/antagonist_equip.dm b/code/game/antagonist/antagonist_equip.dm index 7284b21584f..4808f235716 100644 --- a/code/game/antagonist/antagonist_equip.dm +++ b/code/game/antagonist/antagonist_equip.dm @@ -1,4 +1,4 @@ -/decl/special_role/proc/equip(var/mob/living/carbon/human/player) +/decl/special_role/proc/equip_role(var/mob/living/carbon/human/player) SHOULD_CALL_PARENT(TRUE) @@ -19,7 +19,7 @@ if(default_outfit) var/decl/hierarchy/outfit/outfit = GET_DECL(default_outfit) - outfit.equip(player) + outfit.equip_outfit(player) if(default_access) var/obj/item/card/id/id = player.get_equipped_item(slot_wear_id_str) @@ -31,7 +31,7 @@ return TRUE -/decl/special_role/proc/unequip(var/mob/living/carbon/human/player) +/decl/special_role/proc/unequip_role(var/mob/living/carbon/human/player) return istype(player) /decl/special_role/proc/equip_rig(var/rig_type, var/mob/living/carbon/human/player) diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index c8a8d7c66cb..6f7cbf938ca 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -1,7 +1,7 @@ /decl/special_role/proc/can_become_antag(var/datum/mind/player, var/ignore_role) if(player.current) - if(isliving(player.current) && player.current.stat) + if(isliving(player.current) && player.current.stat == DEAD) return FALSE if(jobban_isbanned(player.current, name)) return FALSE @@ -28,7 +28,7 @@ for(var/datum/mind/antag in current_antagonists) if(mob_path && !istype(antag.current,mob_path)) continue - if(antag.current.stat==2) + if(antag.current.stat == DEAD) continue return 0 return 1 diff --git a/code/game/antagonist/antagonist_panel.dm b/code/game/antagonist/antagonist_panel.dm index 57e88158677..c3f0c808c7e 100644 --- a/code/game/antagonist/antagonist_panel.dm +++ b/code/game/antagonist/antagonist_panel.dm @@ -45,7 +45,7 @@ dat += "[N.name], " var/atom/disk_loc = N.loc while(!isturf(disk_loc)) - if(istype(disk_loc, /mob)) + if(ismob(disk_loc)) var/mob/M = disk_loc dat += "carried by [M.real_name] " if(istype(disk_loc, /obj)) diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm index 17b83a1342c..454d1c1b2f1 100644 --- a/code/game/antagonist/antagonist_update.dm +++ b/code/game/antagonist/antagonist_update.dm @@ -36,10 +36,10 @@ return var/indicator = (faction_indicator && (other in faction_members)) ? faction_indicator : antag_indicator var/image/I = image('icons/mob/hud.dmi', loc = other.current, icon_state = indicator, layer = ABOVE_HUMAN_LAYER) - if(ishuman(other.current)) - var/mob/living/carbon/human/H = other.current - I.pixel_x = H.bodytype.antaghud_offset_x - I.pixel_y = H.bodytype.antaghud_offset_y + var/decl/bodytype/root_bodytype = other.current.get_bodytype() + if(istype(root_bodytype)) + I.pixel_x = root_bodytype.antaghud_offset_x + I.pixel_y = root_bodytype.antaghud_offset_y return I /decl/special_role/proc/update_all_icons() @@ -81,7 +81,7 @@ if(I.loc == player.current) qdel(I) -/decl/special_role/proc/update_current_antag_max(datum/game_mode/mode) +/decl/special_role/proc/update_current_antag_max(decl/game_mode/mode) cur_max = hard_cap if(type in mode.associated_antags) cur_max = hard_cap_round diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm index 569da9f53ec..b381a6f3fbc 100644 --- a/code/game/antagonist/outsider/mercenary.dm +++ b/code/game/antagonist/outsider/mercenary.dm @@ -27,7 +27,7 @@ global_objectives |= new /datum/objective/nuclear return 1 -/decl/special_role/mercenary/equip(var/mob/living/carbon/human/player) +/decl/special_role/mercenary/equip_role(var/mob/living/carbon/human/player) . = ..() if(.) var/obj/item/radio/uplink/U = new(get_turf(player), player.mind, DEFAULT_TELECRYSTAL_AMOUNT) diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm index 043d70da251..dc90996ea1a 100644 --- a/code/game/antagonist/outsider/ninja.dm +++ b/code/game/antagonist/outsider/ninja.dm @@ -98,7 +98,7 @@ hands = list(/obj/item/modular_computer/pda/ninja) id_type = /obj/item/card/id/syndicate -/decl/special_role/ninja/equip(var/mob/living/carbon/human/player) +/decl/special_role/ninja/equip_role(var/mob/living/carbon/human/player) . = ..() if(.) var/decl/uplink_source/pda/uplink_source = GET_DECL(/decl/uplink_source/pda) diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm index e64d15e9f82..0123b9a0942 100644 --- a/code/game/antagonist/outsider/wizard.dm +++ b/code/game/antagonist/outsider/wizard.dm @@ -64,7 +64,7 @@ wizard.current.real_name = "[pick(global.wizard_first)] [pick(global.wizard_second)]" wizard.current.SetName(wizard.current.real_name) -/decl/special_role/wizard/equip(var/mob/living/carbon/human/wizard_mob) +/decl/special_role/wizard/equip_role(var/mob/living/carbon/human/wizard_mob) default_outfit = pick(decls_repository.get_decl_paths_of_subtype(/decl/hierarchy/outfit/wizard)) . = ..() diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index 3fd5dc284e1..25c20aa16ae 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -69,7 +69,7 @@ sacrifice_target = sacrifice.target global_objectives |= sacrifice -/decl/special_role/cultist/equip(var/mob/living/carbon/human/player) +/decl/special_role/cultist/equip_role(var/mob/living/carbon/human/player) . = ..() if(.) var/obj/item/book/tome/T = new(get_turf(player)) @@ -95,12 +95,12 @@ . = ..() if(.) to_chat(player, "[conversion_blurb]") - if(player.current && !istype(player.current, /mob/living/simple_animal/construct)) + if(player.current && !isconstruct(player.current)) player.current.add_language(/decl/language/cultcommon) /decl/special_role/cultist/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted) . = ..() - if(. && player.current && !istype(player.current, /mob/living/simple_animal/construct)) + if(. && player.current && !isconstruct(player.current)) player.current.remove_language(/decl/language/cultcommon) /decl/special_role/cultist/update_antag_mob(var/datum/mind/player) diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm index b76641b9354..f6ef8f7c3ea 100644 --- a/code/game/antagonist/station/loyalist.dm +++ b/code/game/antagonist/station/loyalist.dm @@ -35,7 +35,7 @@ return global_objectives = list() for(var/mob/living/carbon/human/player in SSmobs.mob_list) - if(!player.mind || player.stat==2 || !(player.mind.assigned_role in SSjobs.titles_by_department(command_department_id))) + if(!player.mind || player.stat == DEAD || !(player.mind.assigned_role in SSjobs.titles_by_department(command_department_id))) continue var/datum/objective/protect/loyal_obj = new loyal_obj.target = player.mind diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index 7dbc740eb29..1269452a0b4 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -43,7 +43,7 @@ survive.owner = player player.objectives |= survive -/decl/special_role/renegade/equip(var/mob/living/carbon/human/player) +/decl/special_role/renegade/equip_role(var/mob/living/carbon/human/player) . = ..() if(.) var/gun_type = pick(spawn_guns) diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm index 398f67cf367..b56b094a7d8 100644 --- a/code/game/antagonist/station/revolutionary.dm +++ b/code/game/antagonist/station/revolutionary.dm @@ -35,14 +35,14 @@ return global_objectives = list() for(var/mob/living/carbon/human/player in SSmobs.mob_list) - if(!player.mind || player.stat==2 || !(player.mind.assigned_role in SSjobs.titles_by_department(command_department_id))) + if(!player.mind || player.stat == DEAD || !(player.mind.assigned_role in SSjobs.titles_by_department(command_department_id))) continue var/datum/objective/rev/rev_obj = new rev_obj.target = player.mind rev_obj.explanation_text = "Assassinate, capture or convert [player.real_name], the [player.mind.assigned_role]." global_objectives += rev_obj -/decl/special_role/revolutionary/equip(var/mob/living/carbon/human/player) +/decl/special_role/revolutionary/equip_role(var/mob/living/carbon/human/player) . = ..() if(.) spawn_uplink(player) diff --git a/code/game/antagonist/station/thrall.dm b/code/game/antagonist/station/thrall.dm index 8a0dc036268..b4745b87126 100644 --- a/code/game/antagonist/station/thrall.dm +++ b/code/game/antagonist/station/thrall.dm @@ -1,28 +1,29 @@ -/decl/special_role/thrall - name = "Thrall" - name_plural = "Thralls" +/decl/special_role/beguiled + name = "Beguiled" + name_plural = "Beguiled" welcome_text = "Your mind is no longer solely your own..." flags = ANTAG_IMPLANT_IMMUNE - var/list/thrall_controllers = list() + var/list/minion_controllers = list() -/decl/special_role/thrall/create_objectives(var/datum/mind/player) - var/mob/living/controller = thrall_controllers["\ref[player]"] +/decl/special_role/beguiled/create_objectives(var/datum/mind/player) + var/mob/living/controller = minion_controllers["\ref[player]"] if(!controller) return // Someone is playing with buttons they shouldn't be. var/datum/objective/obey = new obey.owner = player - obey.explanation_text = "Obey your master, [controller.real_name], in all things." + obey.explanation_text = "You are under [controller.real_name]'s glamour, and must follow their commands." player.objectives |= obey -/decl/special_role/thrall/add_antagonist(var/datum/mind/player, var/ignore_role, var/do_not_equip, var/move_to_spawn, var/do_not_announce, var/preserve_appearance, var/mob/new_controller) +/decl/special_role/beguiled/add_antagonist(var/datum/mind/player, var/ignore_role, var/do_not_equip, var/move_to_spawn, var/do_not_announce, var/preserve_appearance, var/mob/new_controller) if(!new_controller) - return 0 + return FALSE . = ..() - if(.) thrall_controllers["\ref[player]"] = new_controller + if(.) + minion_controllers["\ref[player]"] = new_controller -/decl/special_role/thrall/greet(var/datum/mind/player) +/decl/special_role/beguiled/greet(var/datum/mind/player) . = ..() - var/mob/living/controller = thrall_controllers["\ref[player]"] + var/mob/living/controller = minion_controllers["\ref[player]"] if(controller) - to_chat(player, "Your will has been subjugated by that of [controller.real_name]. Obey them in all things.") + to_chat(player, "You have been ensnared by [controller.real_name]'s glamour. Follow their commands.") diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm index 4b1795ae56c..29b5bcc9722 100644 --- a/code/game/antagonist/station/traitor.dm +++ b/code/game/antagonist/station/traitor.dm @@ -22,7 +22,7 @@ if(!..()) return - if(istype(traitor.current, /mob/living/silicon)) + if(issilicon(traitor.current)) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = traitor kill_objective.find_target() @@ -67,12 +67,37 @@ traitor.objectives += hijack_objective return -/decl/special_role/traitor/equip(var/mob/living/carbon/human/player) +/decl/special_role/traitor/add_antagonist(datum/mind/player, ignore_role, do_not_equip, move_to_spawn, do_not_announce, preserve_appearance) + . = ..() + if(.) + + var/list/dudes = list() + for(var/mob/living/carbon/human/man in global.player_list) + if(man.client) + var/decl/cultural_info/culture = man.get_cultural_value(TAG_FACTION) + if(culture && prob(culture.subversive_potential)) + dudes += man + dudes -= player.current + + if(length(dudes)) + var/mob/living/carbon/human/M = pick(dudes) + to_chat(player.current, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") + player.StoreMemory("Potential Collaborator: [M.real_name]", /decl/memory_options/system) + to_chat(M, "The subversive potential of your faction has been noticed, and you may be contacted for assistance soon...") + + to_chat(player.current, "Your employers provided you with the following information on how to identify possible allies:") + to_chat(player.current, "Code Phrase: [syndicate_code_phrase]") + to_chat(player.current, "Code Response: [syndicate_code_response]") + player.StoreMemory("Code Phrase: [syndicate_code_phrase]", /decl/memory_options/system) + player.StoreMemory("Code Response: [syndicate_code_response]", /decl/memory_options/system) + to_chat(player.current, "Use the code words, preferably in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") + +/decl/special_role/traitor/equip_role(var/mob/living/carbon/human/player) . = ..() - if(istype(player, /mob/living/silicon)) // this needs to be here because ..() returns false if the mob isn't human + if(issilicon(player)) // this needs to be here because ..() returns false if the mob isn't human add_law_zero(player) - if(istype(player, /mob/living/silicon/robot)) + if(isrobot(player)) var/mob/living/silicon/robot/R = player R.SetLockdown(0) R.emagged = 1 // Provides a traitor robot with its module's emag item @@ -83,27 +108,6 @@ else return FALSE - var/list/dudes = list() - for(var/mob/living/carbon/human/man in global.player_list) - if(man.client) - var/decl/cultural_info/culture = man.get_cultural_value(TAG_FACTION) - if(culture && prob(culture.subversive_potential)) - dudes += man - dudes -= player - - if(LAZYLEN(dudes)) - var/mob/living/carbon/human/M = pick(dudes) - to_chat(player, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") - player.StoreMemory("Potential Collaborator: [M.real_name]", /decl/memory_options/system) - to_chat(M, "The subversive potential of your faction has been noticed, and you may be contacted for assistance soon...") - - to_chat(player, "Your employers provided you with the following information on how to identify possible allies:") - to_chat(player, "Code Phrase: [syndicate_code_phrase]") - to_chat(player, "Code Response: [syndicate_code_response]") - player.StoreMemory("Code Phrase: [syndicate_code_phrase]", /decl/memory_options/system) - player.StoreMemory("Code Response: [syndicate_code_response]", /decl/memory_options/system) - to_chat(player, "Use the code words, preferably in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") - /decl/special_role/traitor/proc/spawn_uplink(var/mob/living/carbon/human/traitor_mob) setup_uplink_source(traitor_mob, DEFAULT_TELECRYSTAL_AMOUNT) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 81e2bbce9d9..50538fdcb7c 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -1,3 +1,5 @@ +/// This list of names is here to make sure we don't state our descriptive blurb to a person more than once. +var/global/list/area_blurb_stated_to = list() var/global/list/areas = list() /area @@ -9,7 +11,7 @@ var/global/list/areas = list() plane = DEFAULT_PLANE layer = BASE_AREA_LAYER luminosity = 0 - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE var/proper_name /// Automatically set by SetName and Initialize; cached result of strip_improper(name). var/holomap_color // Color of this area on the holomap. Must be a hex color (as string) or null. @@ -41,6 +43,7 @@ var/global/list/areas = list() var/list/forced_ambience var/sound_env = STANDARD_STATION var/description //A text-based description of what this area is for. + var/area_blurb_category // Used to filter description showing across subareas var/base_turf // The base turf type of the area, which can be used to override the z-level's base turf var/open_turf // The base turf of the area if it has a turf below it in multizi. Overrides turf-specific open type @@ -54,7 +57,6 @@ var/global/list/areas = list() var/list/air_scrub_names = list() var/list/air_vent_info = list() var/list/air_scrub_info = list() - var/list/blurbed_stated_to = list() //This list of names is here to make sure we don't state our descriptive blurb to a person more than once. var/tmp/is_outside = OUTSIDE_NO @@ -65,6 +67,8 @@ var/global/list/areas = list() uid = ++global_uid proper_name = strip_improper(name) luminosity = !dynamic_lighting + if(isnull(area_blurb_category)) + area_blurb_category = type ..() /area/Initialize() @@ -128,6 +132,7 @@ var/global/list/areas = list() T.last_outside_check = OUTSIDE_UNCERTAIN if(T.is_outside == OUTSIDE_AREA && T.is_outside() != old_outside) T.update_weather() + T.update_external_atmos_participation() /turf/proc/update_registrations_on_adjacent_area_change() for(var/obj/machinery/door/firedoor/door in src) @@ -207,7 +212,7 @@ var/global/list/areas = list() if(!fire) fire = 1 //used for firedoor checks update_icon() - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE if(!all_doors) return for(var/obj/machinery/door/firedoor/D in all_doors) @@ -222,7 +227,7 @@ var/global/list/areas = list() if (fire) fire = 0 //used for firedoor checks update_icon() - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE if(!all_doors) return for(var/obj/machinery/door/firedoor/D in all_doors) @@ -249,13 +254,13 @@ var/global/list/areas = list() if (!( party )) party = 1 update_icon() - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE return /area/proc/partyreset() if (party) party = 0 - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE update_icon() for(var/obj/machinery/door/firedoor/D in src) if(!D.blocked) @@ -323,7 +328,7 @@ var/global/list/areas = list() var/global/list/mob/living/forced_ambiance_list = new /area/Entered(A) - if(!istype(A,/mob/living)) + if(!isliving(A)) return var/mob/living/L = A if(!L.lastarea) @@ -347,12 +352,10 @@ var/global/list/mob/living/forced_ambiance_list = new /area/proc/do_area_blurb(var/mob/living/L) if(isnull(description)) return - if(L?.get_preference_value(/datum/client_preference/area_info_blurb) != PREF_YES) return - - if(!(L.ckey in blurbed_stated_to)) - blurbed_stated_to += L.ckey + if(!(L.ckey in global.area_blurb_stated_to[area_blurb_category])) + LAZYADD(global.area_blurb_stated_to[area_blurb_category], L.ckey) to_chat(L, SPAN_NOTICE(FONT_SMALL("[description]"))) /area/proc/play_ambience(var/mob/living/L) @@ -388,7 +391,7 @@ var/global/list/mob/living/forced_ambiance_list = new if(mob.Check_Shoegrip()) return - if(istype(mob,/mob/living/carbon/human/)) + if(ishuman(mob)) var/mob/living/carbon/human/H = mob if(prob(H.skill_fail_chance(SKILL_EVA, 100, SKILL_ADEPT))) if(!MOVING_DELIBERATELY(H)) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 4d78a75bd74..9e219cd6d10 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,6 +1,6 @@ /atom - /// (1 | 2) Determines if this atom is below `1` or above `2` plating. TODO: Use defines. - var/level = 2 + /// (DEFINE) Determines where this atom sits in terms of turf plating. See misc.dm + var/level = LEVEL_ABOVE_PLATING /// (BITFLAG) See flags.dm var/atom_flags = ATOM_FLAG_NO_TEMP_CHANGE /// (FLOAT) The world.time that this atom last bumped another. Used mostly by mobs. @@ -27,8 +27,8 @@ var/was_bloodied /// (COLOR) The color of the blood shown on blood overlays. var/blood_color - /// (1 | 2 | 3) If it shows up under UV light. 0 doesn't, 1 does, 2 is currently glowing due to UV light. TODO: Use defines - var/fluorescent + /// (FALSE|DEFINES) How this atom is interacting with UV light. See misc.dm + var/fluorescent = FALSE /// (LIST) A list of all mobs that are climbing or currently on this atom @@ -97,7 +97,7 @@ - TODO: Also sometimes handles resetting of view itself, probably should be more consistent. */ /atom/proc/check_eye(user) - if (istype(user, /mob/living/silicon/ai)) // WHY + if (isAI(user)) // WHY return 0 return -1 @@ -116,7 +116,7 @@ /// Handle reagents being modified /atom/proc/on_reagent_change() - return + SHOULD_CALL_PARENT(TRUE) /** Handle an atom bumping this atom @@ -331,6 +331,19 @@ SHOULD_CALL_PARENT(FALSE) //Don't call the stub plz return +/** + * Returns the sum of this atoms's reagents plus the combined matter of all its contents. + * Obj adds matter contents. Other overrides may add extra handling for things like material storage. + * Most useful for calculating worth or deconstructing something along with its contents. + */ +/atom/proc/get_contained_matter() + if(length(reagents?.reagent_volumes)) + LAZYINITLIST(.) + for(var/R in reagents.reagent_volumes) + .[R] += FLOOR(REAGENT_VOLUME(reagents, R) / REAGENT_UNITS_PER_MATERIAL_UNIT) + for(var/atom/contained_obj as anything in get_contained_external_atoms()) // machines handle component parts separately + . = MERGE_ASSOCS_WITH_NUM_VALUES(., contained_obj.get_contained_matter()) + /// Return a list of all simulated atoms inside this one. /atom/proc/get_contained_external_atoms() for(var/atom/movable/AM in contents) @@ -471,7 +484,7 @@ SHOULD_CALL_PARENT(TRUE) if(!simulated) return - fluorescent = 0 + fluorescent = FALSE germ_level = 0 blood_color = null if(istype(blood_DNA, /list)) @@ -752,15 +765,6 @@ RETURN_TYPE(/obj/item/radio) return -/** - Get the material cost of this atom. - - - Return: An dictionary where key is the material and value is the amount. -*/ -/atom/proc/building_cost() - RETURN_TYPE(/list) - . = list() - /atom/Topic(href, href_list) var/mob/user = usr if(href_list["look_at_me"] && istype(user)) @@ -855,3 +859,9 @@ /atom/proc/on_defilement() return + +/atom/proc/get_overhead_text_x_offset() + return 0 + +/atom/proc/get_overhead_text_y_offset() + return 0 diff --git a/code/game/atoms_fluids.dm b/code/game/atoms_fluids.dm index fd7a636214f..3211271a2e5 100644 --- a/code/game/atoms_fluids.dm +++ b/code/game/atoms_fluids.dm @@ -2,8 +2,8 @@ return /atom/proc/fluid_act(var/datum/reagents/fluids) - fluids.touch(src) - if(reagents && fluids.total_volume >= FLUID_SHALLOW && ATOM_IS_OPEN_CONTAINER(src)) + SHOULD_CALL_PARENT(TRUE) + if(reagents && fluids?.total_volume >= FLUID_SHALLOW && ATOM_IS_OPEN_CONTAINER(src)) reagents.trans_to_holder(fluids, reagents.total_volume) fluids.trans_to_holder(reagents, min(fluids.total_volume, reagents.maximum_volume)) @@ -32,7 +32,7 @@ if(!istype(T)) return FALSE depth = T.get_fluid_depth() - if(istype(loc, /mob)) + if(ismob(loc)) return depth >= FLUID_SHALLOW if(isturf(loc)) return depth >= 3 diff --git a/code/game/atoms_layering.dm b/code/game/atoms_layering.dm index b150c70fafb..4f37917e6cb 100644 --- a/code/game/atoms_layering.dm +++ b/code/game/atoms_layering.dm @@ -1,5 +1,12 @@ /atom plane = DEFAULT_PLANE + appearance_flags = DEFAULT_APPEARANCE_FLAGS +/atom/movable + appearance_flags = DEFAULT_APPEARANCE_FLAGS | TILE_BOUND // Most AMs are not visibly bigger than a tile. +/image + appearance_flags = DEFAULT_APPEARANCE_FLAGS +/mutable_appearance + appearance_flags = DEFAULT_APPEARANCE_FLAGS // Inherits /image but re docs, subject to change /atom/proc/hud_layerise() plane = HUD_PLANE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index fa8561acc6e..b6bda7218a4 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,6 @@ /atom/movable layer = OBJ_LAYER - appearance_flags = TILE_BOUND | PIXEL_SCALE | LONG_GLIDE + appearance_flags = TILE_BOUND | DEFAULT_APPEARANCE_FLAGS | LONG_GLIDE glide_size = 8 abstract_type = /atom/movable @@ -18,7 +18,7 @@ var/movable_flags var/last_move = null - var/anchored = 0 + var/anchored = FALSE // var/elevation = 2 - not used anywhere var/move_speed = 10 var/l_move_time = 1 @@ -455,5 +455,9 @@ if(simulated && !anchored) step_towards(src, S) +/atom/movable/proc/crossed_mob(var/mob/living/victim) + return + /atom/movable/proc/get_object_size() - return ITEM_SIZE_NORMAL \ No newline at end of file + return ITEM_SIZE_NORMAL + diff --git a/code/game/base_turf.dm b/code/game/base_turf.dm index edb7d1006f7..671213c63e8 100644 --- a/code/game/base_turf.dm +++ b/code/game/base_turf.dm @@ -11,12 +11,30 @@ if(HasBelow(T.z)) if(istype(A) && A.open_turf) return A.open_turf + + // Find the first non-open turf below and use its open_turf_type. + var/z_stack_type = get_open_turf_type(T) + if(z_stack_type) + return z_stack_type + + // Otherwise, default to the open turf type set on the turf being removed. if(T.open_turf_type) return T.open_turf_type if(istype(A) && A.base_turf) return A.base_turf return get_base_turf(T.z) +// Returns the open turf of a Z-stack by finding the nearest non-open turf below. +/proc/get_open_turf_type(var/turf/T) + if(!HasBelow(T.z)) + return + var/turf/below = T + while ((below = GetBelow(below))) + if(!below.is_open() || !HasBelow(below.z)) + if(below.open_turf_type) + return below.open_turf_type + return + /client/proc/set_base_turf() set category = "Debug" set name = "Set Base Turf" diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index d74cf32a3fe..0121e88e2d2 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -59,9 +59,11 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] /datum/dna // READ-ONLY, GETS OVERWRITTEN // DO NOT FUCK WITH THESE OR BYOND WILL EAT YOUR FACE - var/uni_identity="" // Encoded UI - var/struc_enzymes="" // Encoded SE - var/unique_enzymes="" // MD5 of player name + var/uni_identity="" // Encoded UI + var/struc_enzymes="" // Encoded SE + var/unique_enzymes="" // MD5 of mob genetic marker value + + var/fingerprint // Internal dirtiness checks var/dirtyUI=0 @@ -87,6 +89,7 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] clone = ..() clone.lineage = lineage clone.unique_enzymes = unique_enzymes + clone.fingerprint = fingerprint clone.b_type = b_type clone.real_name = real_name clone.species = species || global.using_map.default_species @@ -138,6 +141,9 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1) + fingerprint = character.get_full_print(ignore_blockers = TRUE) + unique_enzymes = character.get_unique_enzymes() + // Hair var/list/hair_types = decls_repository.get_decl_paths_of_subtype(/decl/sprite_accessory/hair) SetUIValueRange(DNA_UI_HAIR_STYLE, hair_types.Find(character.h_style), length(hair_types), 1) @@ -151,7 +157,7 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] if(LAZYLEN(E.markings)) body_markings[E.organ_tag] = E.markings.Copy() - b_type = character.b_type + b_type = character.get_blood_type() UpdateUI() @@ -321,7 +327,6 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] //testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]") SetSEBlock(block,newBlock,defer) - /proc/EncodeDNABlock(var/value) return add_zero2(num2hex(value,1), 3) @@ -352,7 +357,7 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] ResetSE() if(length(unique_enzymes) != 32) - unique_enzymes = md5(character.real_name) + unique_enzymes = md5(num2text(character.original_genetic_seed)) else if(!species) species = global.using_map.default_species @@ -366,5 +371,4 @@ var/global/list/assigned_blocks[DNA_SE_LENGTH] /datum/dna/proc/ready_dna(mob/living/carbon/human/character) ResetUIFrom(character) ResetSE() - unique_enzymes = md5(character.real_name) - global.reg_dna[unique_enzymes] = character.real_name + unique_enzymes = character.get_unique_enzymes() diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index dce004bb25c..48c4da795e0 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -133,62 +133,55 @@ // Simpler. Don't specify UI in order for the mob to use its own. /mob/proc/UpdateAppearance(var/list/UI=null) - if(istype(src, /mob/living/carbon/human)) - if(UI!=null) - src.dna.UI=UI - src.dna.UpdateUI() - dna.check_integrity() - var/mob/living/carbon/human/H = src - H.hair_colour = rgb(dna.GetUIValueRange(DNA_UI_HAIR_R,255), dna.GetUIValueRange(DNA_UI_HAIR_G,255), dna.GetUIValueRange(DNA_UI_HAIR_B,255)) - H.facial_hair_colour = rgb(dna.GetUIValueRange(DNA_UI_BEARD_R,255), dna.GetUIValueRange(DNA_UI_BEARD_G,255), dna.GetUIValueRange(DNA_UI_BEARD_B,255)) - H.skin_colour = rgb(dna.GetUIValueRange(DNA_UI_SKIN_R,255), dna.GetUIValueRange(DNA_UI_SKIN_G,255), dna.GetUIValueRange(DNA_UI_SKIN_B,255)) - H.eye_colour = rgb(dna.GetUIValueRange(DNA_UI_EYES_R,255), dna.GetUIValueRange(DNA_UI_EYES_G,255), dna.GetUIValueRange(DNA_UI_EYES_B,255)) - H.update_eyes() - H.skin_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative. - - // TODO: update DNA gender to not be a bool - use bodytype and pronouns - /* - if(H.gender != NEUTER) - if (dna.GetUIState(DNA_UI_GENDER)) - H.set_gender(FEMALE) + return FALSE + +/mob/living/carbon/human/UpdateAppearance(var/list/UI=null) + + if(UI!=null) + src.dna.UI=UI + src.dna.UpdateUI() + + dna.check_integrity() + + fingerprint = dna.fingerprint + unique_enzymes = dna.unique_enzymes + hair_colour = rgb(dna.GetUIValueRange(DNA_UI_HAIR_R,255), dna.GetUIValueRange(DNA_UI_HAIR_G,255), dna.GetUIValueRange(DNA_UI_HAIR_B,255)) + facial_hair_colour = rgb(dna.GetUIValueRange(DNA_UI_BEARD_R,255), dna.GetUIValueRange(DNA_UI_BEARD_G,255), dna.GetUIValueRange(DNA_UI_BEARD_B,255)) + skin_colour = rgb(dna.GetUIValueRange(DNA_UI_SKIN_R,255), dna.GetUIValueRange(DNA_UI_SKIN_G,255), dna.GetUIValueRange(DNA_UI_SKIN_B,255)) + eye_colour = rgb(dna.GetUIValueRange(DNA_UI_EYES_R,255), dna.GetUIValueRange(DNA_UI_EYES_G,255), dna.GetUIValueRange(DNA_UI_EYES_B,255)) + skin_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative. + + // TODO: update DNA gender to not be a bool - use bodytype and pronouns + //Body markings + for(var/tag in dna.body_markings) + var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(src, tag) + if(E) + var/list/marklist = dna.body_markings[tag] + if(length(marklist)) + E.markings = marklist.Copy() else - H.set_gender(MALE) - */ - - //Body markings - for(var/tag in dna.body_markings) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(H, tag) - if(E) - var/list/marklist = dna.body_markings[tag] - if(length(marklist)) - E.markings = marklist.Copy() - else - LAZYCLEARLIST(E.markings) - - //Base skin and blend - for(var/obj/item/organ/organ in H.get_organs()) - organ.set_dna(H.dna) - - //Hair - var/list/hair_subtypes = decls_repository.get_decl_paths_of_subtype(/decl/sprite_accessory/hair) - var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE, length(hair_subtypes)) - if(hair > 0 && hair <= length(hair_subtypes)) - H.h_style = hair_subtypes[hair] - - //Facial Hair - var/list/beard_subtypes = decls_repository.get_decl_paths_of_subtype(/decl/sprite_accessory/facial_hair) - var/beard = dna.GetUIValueRange(DNA_UI_BEARD_STYLE, length(beard_subtypes)) - if((0 < beard) && (beard <= length(beard_subtypes))) - H.f_style = beard_subtypes[beard] - - H.force_update_limbs() - H.update_body() - H.update_eyes() - H.update_hair() - - return 1 - else - return 0 + LAZYCLEARLIST(E.markings) + + //Base skin and blend + for(var/obj/item/organ/organ in get_organs()) + organ.set_dna(dna) + + //Hair + var/list/hair_subtypes = decls_repository.get_decl_paths_of_subtype(/decl/sprite_accessory/hair) + var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE, length(hair_subtypes)) + if(hair > 0 && hair <= length(hair_subtypes)) + h_style = hair_subtypes[hair] + + //Facial Hair + var/list/beard_subtypes = decls_repository.get_decl_paths_of_subtype(/decl/sprite_accessory/facial_hair) + var/beard = dna.GetUIValueRange(DNA_UI_BEARD_STYLE, length(beard_subtypes)) + if((0 < beard) && (beard <= length(beard_subtypes))) + f_style = beard_subtypes[beard] + + force_update_limbs() + update_hair(update_icons = FALSE) + update_eyes() + return TRUE // Used below, simple injection modifier. /proc/probinj(var/pr, var/inj) diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm index a2ff5594b92..5c809eee420 100644 --- a/code/game/gamemodes/calamity/calamity.dm +++ b/code/game/gamemodes/calamity/calamity.dm @@ -1,16 +1,16 @@ #define ANTAG_TYPE_RATIO 8 -/datum/game_mode/calamity +/decl/game_mode/calamity name = "Calamity" round_description = "This must be a Thursday. You never could get the hang of Thursdays..." extended_round_description = "All hell is about to break loose. Literally every antagonist type may spawn in this round. Hold on tight." - config_tag = "calamity" + uid = "calamity" required_players = 1 votable = 0 event_delay_mod_moderate = 0.5 event_delay_mod_major = 0.75 -/datum/game_mode/calamity/create_antagonists() +/decl/game_mode/calamity/create_antagonists() var/list/antag_candidates = list() var/list/all_antagonist_datums = decls_repository.get_decls_of_subtype(/decl/special_role) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index c10826eba7c..3e973359edd 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -1,8 +1,8 @@ -/datum/game_mode/cult +/decl/game_mode/cult name = "Cult" round_description = "Some crewmembers are attempting to start a cult!" extended_round_description = "There has been an infiltration by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!" - config_tag = "cult" + uid = "cult" required_players = 10 required_enemies = 3 end_on_antag_death = FALSE diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 1c21c09ee7a..28daf9435d2 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -42,9 +42,8 @@ /obj/item/clothing/head/culthood name = "cult hood" desc = "A hood worn by the followers of Nar-Sie." - icon = 'icons/clothing/head/cult.dmi' - flags_inv = HIDEFACE + flags_inv = HIDEFACE | BLOCK_HEAD_HAIR body_parts_covered = SLOT_HEAD armor = list( ARMOR_MELEE = ARMOR_MELEE_RESISTANT, diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index b38ec7d3f95..6d3194a0877 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -1,6 +1,6 @@ /obj/structure/cult - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE icon = 'icons/obj/cult.dmi' /obj/structure/cult/talisman @@ -93,9 +93,8 @@ desc = "You're pretty sure that abyss is staring back." icon = 'icons/obj/cult.dmi' icon_state = "hole" - density = 1 - unacidable = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE var/spawnable = null /obj/effect/gateway/active @@ -126,41 +125,44 @@ new t(src.loc) qdel(src) -/obj/effect/gateway/active/Crossed(var/atom/A) - if(!istype(A, /mob/living)) +/obj/effect/gateway/active/Crossed(var/atom/movable/AM) + if(!isliving(AM)) return - var/mob/living/M = A + var/mob/living/M = AM + if(M.stat == DEAD) + return - if(M.stat != DEAD) - if(M.HasMovementHandler(/datum/movement_handler/mob/transformation)) - return + if(M.HasMovementHandler(/datum/movement_handler/mob/transformation)) + return - M.handle_pre_transformation() + M.handle_pre_transformation() - if(iscultist(M)) return - if(!ishuman(M) && !isrobot(M)) return + if(iscultist(M)) + return + if(!ishuman(M) && !isrobot(M)) + return - M.AddMovementHandler(/datum/movement_handler/mob/transformation) - M.icon = null - M.overlays.len = 0 - M.set_invisibility(101) + M.AddMovementHandler(/datum/movement_handler/mob/transformation) + M.icon = null + M.overlays.len = 0 + M.set_invisibility(INVISIBILITY_ABSTRACT) - if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/Robot = M - if(Robot.mmi) - qdel(Robot.mmi) - else - for(var/obj/item/W in M) - M.drop_from_inventory(W) - if(istype(W, /obj/item/implant)) - qdel(W) - - var/mob/living/new_mob = new /mob/living/simple_animal/corgi(A.loc) - new_mob.a_intent = I_HURT - if(M.mind) - M.mind.transfer_to(new_mob) - else - new_mob.key = M.key + if(isrobot(M)) + var/mob/living/silicon/robot/Robot = M + if(Robot.mmi) + qdel(Robot.mmi) + else + for(var/obj/item/W in M) + M.drop_from_inventory(W) + if(istype(W, /obj/item/implant)) + qdel(W) + + var/mob/living/new_mob = new /mob/living/simple_animal/corgi(AM.loc) + new_mob.a_intent = I_HURT + if(M.mind) + M.mind.transfer_to(new_mob) + else + new_mob.key = M.key - to_chat(new_mob, "Your form morphs into that of a corgi.")//Because we don't have cluwnes + to_chat(new_mob, "Your form morphs into that of a corgi.")//Because we don't have cluwnes diff --git a/code/game/gamemodes/cult/cultify/mob.dm b/code/game/gamemodes/cult/cultify/mob.dm index 60751eaabdd..8c95baa107c 100644 --- a/code/game/gamemodes/cult/cultify/mob.dm +++ b/code/game/gamemodes/cult/cultify/mob.dm @@ -6,7 +6,7 @@ icon = 'icons/mob/mob.dmi' icon_state = "ghost-narsie" cut_overlays() - set_invisibility(0) + set_invisibility(INVISIBILITY_NONE) to_chat(src, SPAN_SINISTER("Even as a non-corporal being, you can feel Nar-Sie's presence altering you. You are now visible to everyone.")) /mob/living/on_defilement() @@ -20,7 +20,7 @@ G.icon = 'icons/mob/mob.dmi' G.icon_state = "ghost-narsie" G.overlays.Cut() - G.set_invisibility(0) + G.set_invisibility(INVISIBILITY_NONE) to_chat(G, "You feel relieved as what's left of your soul finally escapes its prison of flesh.") else dust() diff --git a/code/game/gamemodes/cult/ghosts.dm b/code/game/gamemodes/cult/ghosts.dm index 17de3d70705..28955489c2c 100644 --- a/code/game/gamemodes/cult/ghosts.dm +++ b/code/game/gamemodes/cult/ghosts.dm @@ -282,9 +282,9 @@ to_chat(src, "You are now invisible.") visible_message("It fades from sight...") set_invisibility(INVISIBILITY_OBSERVER) - mouse_opacity = 1 + mouse_opacity = MOUSE_OPACITY_NORMAL else ghost_magic_cd = world.time + 60 SECONDS to_chat(src, "You are now visible.") - set_invisibility(0) - mouse_opacity = 0 // This is so they don't make people invincible to melee attacks by hovering over them + set_invisibility(INVISIBILITY_NONE) + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE // This is so they don't make people invincible to melee attacks by hovering over them diff --git a/code/game/gamemodes/cult/narsie.dm b/code/game/gamemodes/cult/narsie.dm index b1346e2cb1f..90ba89f658a 100644 --- a/code/game/gamemodes/cult/narsie.dm +++ b/code/game/gamemodes/cult/narsie.dm @@ -16,7 +16,6 @@ var/global/list/narsie_list = list() icon = 'icons/obj/narsie.dmi' icon_state = "narsie" anchored = TRUE - unacidable = TRUE pixel_x = -236 pixel_y = -256 plane = ABOVE_LIGHTING_PLANE diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 60e6a5ec29a..41c42b43b72 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,10 +1,9 @@ /obj/effect/rune name = "rune" desc = "A strange collection of symbols drawn in blood." - anchored = 1 + anchored = TRUE icon = 'icons/effects/uristrunes.dmi' icon_state = "blank" - unacidable = 1 layer = RUNE_LAYER var/blood @@ -267,9 +266,8 @@ icon = 'icons/effects/effects.dmi'//TODO: better icon icon_state = "smoke" color = "#ff0000" - anchored = 1 - density = 1 - unacidable = 1 + anchored = TRUE + density = TRUE var/obj/effect/rune/wall/rune var/health var/max_health = 200 @@ -490,7 +488,7 @@ //TODO: other rewards? /* old sac code - left there in case someone wants to salvage it var/worth = 0 - if(istype(H,/mob/living/carbon/human)) + if(ishuman(H)) var/mob/living/carbon/human/lamb = H if(lamb.species.rarity_value > 3) worth = 1 diff --git a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm index ebb26b19070..2c5f9a9ffa7 100644 --- a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm +++ b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm @@ -20,7 +20,7 @@ else create_duplicate(M) for(var/mob/goast in global.ghost_mob_list) - goast.mouse_opacity = 0 //can't let you click that Dave + goast.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE //can't let you click that Dave goast.set_invisibility(SEE_INVISIBLE_LIVING) goast.alpha = 255 old_accessible_z_levels = SSmapping.accessible_z_levels.Copy() @@ -73,7 +73,7 @@ name = "echo" desc = "It's not going to punch you, is it?" var/mob/living/carbon/human/daddy - anchored = 1 + anchored = TRUE var/reality = 0 simulated = 0 @@ -121,10 +121,7 @@ /obj/effect/bluegoast/proc/blueswitch() var/mob/living/carbon/human/H if(ishuman(daddy)) - H = new(get_turf(src), daddy.species.name) - H.dna = daddy.dna.Clone() - H.sync_organ_dna() - H.UpdateAppearance() + H = new(get_turf(src), daddy.species.name, daddy.dna.Clone(), daddy.get_bodytype()) for(var/obj/item/entry in daddy.get_equipped_items(TRUE)) daddy.remove_from_mob(entry) //steals instead of copies so we don't end up with duplicates H.equip_to_appropriate_slot(entry) @@ -144,4 +141,3 @@ color = "#ff9900" alpha = 100 blend_mode = BLEND_SUBTRACT - layer = FULLSCREEN_LAYER \ No newline at end of file diff --git a/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm b/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm index b8c6afdaf28..95caa40a160 100644 --- a/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm +++ b/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm @@ -12,7 +12,7 @@ cinematic.icon_state = "station_intact" cinematic.plane = HUD_PLANE cinematic.layer = HUD_ABOVE_ITEM_LAYER - cinematic.mouse_opacity = 2 + cinematic.mouse_opacity = MOUSE_OPACITY_PRIORITY cinematic.screen_loc = "LEFT+1,BOTTOM" /datum/universal_state/nuclear_explosion/OnEnter() diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm index db3d57b3d51..9b8ef1cd7a8 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm @@ -6,7 +6,6 @@ icon = 'icons/obj/rift.dmi' icon_state = "rift" anchored = TRUE - unacidable = TRUE pixel_x = -236 pixel_y = -256 plane = ABOVE_LIGHTING_PLANE @@ -31,7 +30,7 @@ /obj/effect/wormhole_exit/proc/transit_to_exit(const/atom/A) if(!A.simulated) return FALSE - if (istype(A, /mob/living)) + if (isliving(A)) var/mob/living/L = A if(!length(global.endgame_safespawns)) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm index fb65ab959b8..a3c8c357bd2 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm @@ -114,9 +114,9 @@ var/global/universe_has_ended = 0 /datum/universal_state/supermatter_cascade/proc/PlayerSet() for(var/datum/mind/M in global.player_list) - if(!istype(M.current,/mob/living)) + if(!isliving(M.current)) continue - if(M.current.stat!=2) + if(M.current.stat != DEAD) SET_STATUS_MAX(M.current, STAT_WEAK, 10) M.current.flash_eyes() diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index b4d069c4354..0ebfbd5cabe 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -59,7 +59,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is //AI laws for(var/mob/living/silicon/ai/M in global.living_mob_list_) - if(M.stat != 2 && M.see_in_dark != 0) + if(M.stat != DEAD && M.see_in_dark != 0) var/who2 = pick("ALIENS", "BEARS", "CLOWNS", "XENOS", "PETES", "BOMBS", "FETISHES", "WIZARDS", "SYNDICATE AGENTS", "CENTCOM OFFICERS", "SPACE PIRATES", "TRAITORS", "MONKEYS", "BEES", "CARP", "CRABS", "EELS", "BANDITS", "LIGHTS") var/what2 = pick("BOLTERS", "STAVES", "DICE", "SINGULARITIES", "TOOLBOXES", "NETTLES", "AIRLOCKS", "CLOTHES", "WEAPONS", "MEDKITS", "BOMBS", "CANISTERS", "CHAIRS", "BBQ GRILLS", "ID CARDS", "CAPTAINS") var/what2pref = pick("SOFT", "WARM", "WET", "COLD", "ICY", "SEXY", "UGLY", "CUBAN") diff --git a/code/game/gamemodes/events/black_hole.dm b/code/game/gamemodes/events/black_hole.dm index 5418da178ff..9a4d26c3cba 100644 --- a/code/game/gamemodes/events/black_hole.dm +++ b/code/game/gamemodes/events/black_hole.dm @@ -5,10 +5,9 @@ icon = 'icons/obj/objects.dmi' desc = "FUCK FUCK FUCK AAAHHH!" icon_state = "bhole3" - opacity = 1 - unacidable = 1 - density = 0 - anchored = 1 + opacity = TRUE + density = FALSE + anchored = TRUE /obj/effect/bhole/Initialize() . = ..() @@ -57,9 +56,9 @@ //MOVEMENT if( prob(50) ) - src.anchored = 0 + src.anchored = FALSE step(src,pick(global.alldirs)) - src.anchored = 1 + src.anchored = TRUE /obj/effect/bhole/proc/grav(var/r, var/ex_act_force, var/pull_chance, var/turf_removal_chance) if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index e5c20bd0f53..40706050003 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,7 +1,7 @@ -/datum/game_mode/extended +/decl/game_mode/extended name = "Extended" - config_tag = "extended" + uid = "extended" required_players = 0 round_description = "Just have fun and role-play!" extended_round_description = "There are no antagonists during extended, unless an admin decides to be cheeky. Just play your character, mess around with your job, and have fun." - addantag_allowed = ADDANTAG_ADMIN // No add antag vote allowed on extended, except when manually called by admins. \ No newline at end of file + addantag_allowed = ADDANTAG_ADMIN // No add antag vote allowed on extended, except when manually called by admins. diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e62310f18a7..62299631a4e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,11 +1,12 @@ var/global/antag_add_finished // Used in antag type voting. var/global/list/additional_antag_types = list() -/datum/game_mode +/decl/game_mode + abstract_type = /decl/game_mode + decl_flags = DECL_FLAG_MANDATORY_UID var/name = "invalid" var/round_description = "How did you even vote this in?" var/extended_round_description = "This roundtype should not be spawned, let alone votable. Someone contact a developer and tell them the game's broken again." - var/config_tag = null var/votable = TRUE var/probability = 0 @@ -44,19 +45,15 @@ var/global/list/additional_antag_types = list() null ) -/datum/game_mode/New() - ..() - // Enforce some formatting. - // This will probably break something. +/decl/game_mode/Initialize() name = capitalize(lowertext(name)) - config_tag = lowertext(config_tag) - if(round_autoantag && !length(latejoin_antags)) latejoin_antags = associated_antags.Copy() else if(!round_autoantag && length(latejoin_antags)) round_autoantag = TRUE + . = ..() -/datum/game_mode/Topic(href, href_list[]) +/decl/game_mode/Topic(href, href_list[]) if(..()) return if(href_list["toggle"]) @@ -132,7 +129,7 @@ var/global/list/additional_antag_types = list() if (usr.client && usr.client.holder) usr.client.holder.show_game_mode(usr) -/datum/game_mode/proc/announce() //to be called when round starts +/decl/game_mode/proc/announce() //to be called when round starts to_world("The current game mode is [capitalize(name)]!") if(round_description) to_world("[round_description]") if(round_autoantag) to_world("Antagonists will be added to the round automagically as needed.") @@ -156,7 +153,7 @@ var/global/list/additional_antag_types = list() // startRequirements() // Checks to see if the game can be setup and ran with the current number of players or whatnot. // Returns 0 if the mode can start and a message explaining the reason why it can't otherwise. -/datum/game_mode/proc/startRequirements() +/decl/game_mode/proc/startRequirements() var/playerC = 0 for(var/mob/new_player/player in global.player_list) if((player.client)&&(player.ready)) @@ -189,7 +186,7 @@ var/global/list/additional_antag_types = list() else return 0 -/datum/game_mode/proc/refresh_event_modifiers() +/decl/game_mode/proc/refresh_event_modifiers() if(event_delay_mod_moderate || event_delay_mod_major) SSevent.report_at_round_end = 1 if(event_delay_mod_moderate) @@ -199,7 +196,7 @@ var/global/list/additional_antag_types = list() var/datum/event_container/EMajor = SSevent.event_containers[EVENT_LEVEL_MAJOR] EMajor.delay_modifier = event_delay_mod_major -/datum/game_mode/proc/pre_setup() +/decl/game_mode/proc/pre_setup() for(var/decl/special_role/antag in antag_templates) antag.update_current_antag_max(src) antag.build_candidate_list(src) //compile a list of all eligible candidates @@ -214,8 +211,9 @@ var/global/list/additional_antag_types = list() sortTim(antag_templates_by_initial_spawn_req, /proc/cmp_numeric_asc, TRUE) antag_templates = list() - for(var/template in antag_templates_by_initial_spawn_req) - antag_templates += template + for(var/decl/special_role/antag in antag_templates_by_initial_spawn_req) + antag_templates |= antag + latejoin_antags |= antag.type var/list/valid_templates_per_candidate = list() // number of roles each candidate can satisfy for(var/candidate in all_candidates) @@ -240,7 +238,7 @@ var/global/list/additional_antag_types = list() antag.candidates = shuffle(antag.candidates) // makes selection past initial_spawn_req fairer ///post_setup() -/datum/game_mode/proc/post_setup() +/decl/game_mode/proc/post_setup() next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) @@ -265,8 +263,9 @@ var/global/list/additional_antag_types = list() antag.post_spawn() // Update goals, now that antag status and jobs are both resolved. - for(var/thing in SSticker.minds) - var/datum/mind/mind = thing + for(var/datum/mind/mind as anything in SSticker.minds) + if(!mind.current || !mind.assigned_job) + continue mind.generate_goals(mind.assigned_job, is_spawning=TRUE) mind.current.show_goals() @@ -279,11 +278,11 @@ var/global/list/additional_antag_types = list() SSstatistics.set_field_details("server_ip","[world.internet_address]:[world.port]") return 1 -/datum/game_mode/proc/fail_setup() +/decl/game_mode/proc/fail_setup() for(var/decl/special_role/antag in antag_templates) antag.reset_antag_selection() -/datum/game_mode/proc/announce_ert_disabled() +/decl/game_mode/proc/announce_ert_disabled() if(!ert_disabled) return @@ -321,7 +320,7 @@ var/global/list/additional_antag_types = list() ) command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission") -/datum/game_mode/proc/check_finished() +/decl/game_mode/proc/check_finished() if(SSevac.evacuation_controller?.round_over() || station_was_nuked) return 1 if(end_on_antag_death && antag_templates && antag_templates.len) @@ -336,10 +335,10 @@ var/global/list/additional_antag_types = list() return 1 return 0 -/datum/game_mode/proc/cleanup() //This is called when the round has ended but not the game, if any cleanup would be necessary in that case. +/decl/game_mode/proc/cleanup() //This is called when the round has ended but not the game, if any cleanup would be necessary in that case. return -/datum/game_mode/proc/declare_completion() +/decl/game_mode/proc/declare_completion() set waitfor = FALSE sleep(2) @@ -415,10 +414,10 @@ var/global/list/additional_antag_types = list() return 0 -/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. +/decl/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. return 0 -/datum/game_mode/proc/get_players_for_role(var/antag_type) +/decl/game_mode/proc/get_players_for_role(var/antag_type) var/list/players = list() var/list/candidates = list() @@ -431,7 +430,7 @@ var/global/list/additional_antag_types = list() for(var/mob/player in global.player_list) if(!player.client) continue - if(istype(player, /mob/new_player)) + if(isnewplayer(player)) continue if(!antag_template.name || (antag_template.name in player.client.prefs.be_special_role)) log_debug("[player.key] had [antag_template.name] enabled, so we are drafting them.") @@ -463,16 +462,16 @@ var/global/list/additional_antag_types = list() // required_enemies if the number of people with that role set to yes is less than recomended_enemies, // Less if there are not enough valid players in the game entirely to make required_enemies. -/datum/game_mode/proc/num_players() +/decl/game_mode/proc/num_players() . = 0 for(var/mob/new_player/P in global.player_list) if(P.client && P.ready) . ++ -/datum/game_mode/proc/round_status_topic(href, href_list[]) +/decl/game_mode/proc/round_status_topic(href, href_list[]) return 0 -/datum/game_mode/proc/create_antagonists() +/decl/game_mode/proc/create_antagonists() if(!config.traitor_scaling) antag_scaling_coeff = 0 @@ -494,7 +493,7 @@ var/global/list/additional_antag_types = list() shuffle(antag_templates) //In the case of multiple antag types // Manipulates the end-game cinematic in conjunction with global.cinematic -/datum/game_mode/proc/nuke_act(obj/screen/cinematic_screen, station_missed = 0) +/decl/game_mode/proc/nuke_act(obj/screen/cinematic_screen, station_missed = 0) if(!cinematic_icon_states) return if(station_missed < 2) diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 2ebc4eb8820..802d83c3c00 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -1,14 +1,15 @@ -/datum/game_mode/var/next_spawn = 0 -/datum/game_mode/var/min_autotraitor_delay = 4200 // Approx 7 minutes. -/datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes. +/decl/game_mode + var/next_spawn = 0 + var/min_autotraitor_delay = 7 MINUTES + var/max_autotraitor_delay = 20 MINUTES ///process() ///Called by the gameticker -/datum/game_mode/proc/process() +/decl/game_mode/proc/process() if(shall_process_autoantag()) process_autoantag() -/datum/game_mode/proc/shall_process_autoantag() +/decl/game_mode/proc/shall_process_autoantag() if(!round_autoantag || world.time < next_spawn) return FALSE if(SSevac.evacuation_controller && (SSevac.evacuation_controller.is_evacuating() || SSevac.evacuation_controller.has_evacuated())) @@ -20,16 +21,16 @@ return TRUE //This can be overriden in case a game mode needs to do stuff when a player latejoins -/datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character) +/decl/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character) if(character.mind) character.mind.generate_goals(character.mind.assigned_job, is_spawning=TRUE) character.show_goals() return 0 -/datum/game_mode/proc/handle_offsite_latejoin(var/mob/living/carbon/human/character) +/decl/game_mode/proc/handle_offsite_latejoin(var/mob/living/carbon/human/character) return 0 -/datum/game_mode/proc/process_autoantag() +/decl/game_mode/proc/process_autoantag() message_admins("[uppertext(name)]: Attempting autospawn.") var/list/usable_templates = list() diff --git a/code/game/gamemodes/godmode/form_items/starlight_mobs.dm b/code/game/gamemodes/godmode/form_items/starlight_mobs.dm index 979e3211898..2dbde85f029 100644 --- a/code/game/gamemodes/godmode/form_items/starlight_mobs.dm +++ b/code/game/gamemodes/godmode/form_items/starlight_mobs.dm @@ -1,7 +1,7 @@ /mob/living/starlight_soul name = "soul" desc = "A captured soul." - anchored = 1 + anchored = TRUE meat_type = null meat_amount = 0 diff --git a/code/game/gamemodes/godmode/form_items/starlight_structures.dm b/code/game/gamemodes/godmode/form_items/starlight_structures.dm index 605c2bd8ca1..d98eb249478 100644 --- a/code/game/gamemodes/godmode/form_items/starlight_structures.dm +++ b/code/game/gamemodes/godmode/form_items/starlight_structures.dm @@ -12,7 +12,7 @@ icon = 'icons/obj/singularity.dmi' icon_state = "singularity_s1" power_adjustment = 1 - density = 0 + density = FALSE var/weakref/target_ref var/start_time = 0 var/power_drain = 7 diff --git a/code/game/gamemodes/godmode/god_structures.dm b/code/game/gamemodes/godmode/god_structures.dm index 273392f75a5..f40e5bb4597 100644 --- a/code/game/gamemodes/godmode/god_structures.dm +++ b/code/game/gamemodes/godmode/god_structures.dm @@ -18,8 +18,8 @@ /obj/structure/deity icon = 'icons/obj/cult.dmi' maxhealth = 10 - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE icon_state = "tomealtar" is_spawnable_type = FALSE // will usually runtime without a linked god diff --git a/code/game/gamemodes/godmode/god_trap.dm b/code/game/gamemodes/godmode/god_trap.dm index bb919ad3d43..323b3bf2e15 100644 --- a/code/game/gamemodes/godmode/god_trap.dm +++ b/code/game/gamemodes/godmode/god_trap.dm @@ -1,5 +1,5 @@ /obj/structure/deity/trap - density = 0 + density = FALSE health = 1 var/triggered = 0 @@ -24,7 +24,7 @@ return /obj/structure/deity/trap/proc/trigger(var/atom/entered, var/atom/movable/enterer) - if(triggered > world.time || !istype(enterer, /mob/living)) + if(triggered > world.time || !isliving(enterer)) return triggered = world.time + 30 SECONDS \ No newline at end of file diff --git a/code/game/gamemodes/godmode/godmode.dm b/code/game/gamemodes/godmode/godmode.dm index a450a7cd2b6..9bf79d8ca87 100644 --- a/code/game/gamemodes/godmode/godmode.dm +++ b/code/game/gamemodes/godmode/godmode.dm @@ -1,12 +1,12 @@ -/datum/game_mode/godmode +/decl/game_mode/godmode name = "Deity" round_description = "An otherworldly beast has turned its attention to you and your fellow cremembers." extended_round_description = "The station has been infiltrated by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!" - config_tag = "god" + uid = "god" required_players = 10 required_enemies = 3 end_on_antag_death = FALSE associated_antags = list( - /decl/special_role/deity, + /decl/special_role/deity, /decl/special_role/godcultist ) \ No newline at end of file diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index f11138c4060..c2bedd494d5 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -1,10 +1,10 @@ /* -(VOX) HEIST ROUNDTYPE +HEIST ROUNDTYPE */ -/datum/game_mode/heist +/decl/game_mode/heist name = "Heist" - config_tag = "heist" + uid = "heist" required_players = 12 required_enemies = 3 round_description = "An unidentified drive signature has slipped into close sensor range and is approaching!" diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index 00d60dbf8cd..828322db8c9 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -2,11 +2,11 @@ #define METEOR_FAILSAFE_THRESHOLD 45 MINUTES // Failsafe that guarantees Severity will be at least 15 when the round hits this time. // In general, a PVE oriented game mode. A middle ground between Extended and actual antagonist based rounds. -/datum/game_mode/meteor +/decl/game_mode/meteor name = "Meteor" round_description = "You are about to enter an asteroid belt!" extended_round_description = "We are on an unavoidable collision course with an asteroid field. You have only a moment to prepare before you are barraged by dust and meteors. As if it was not enough, all kinds of negative events seem to happen more frequently. Good luck." - config_tag = "meteor" + uid = "meteor" required_players = 15 // Definitely not good for low-pop votable = 1 shuttle_delay = 2 @@ -29,33 +29,33 @@ event_delay_mod_major = 0.3 /decl/vv_set_handler/meteor_severity_handler - handled_type = /datum/game_mode/meteor + handled_type = /decl/game_mode/meteor handled_vars = list( - "meteor_severity" = /datum/game_mode/meteor/proc/set_meteor_severity, - "meteor_wave_delay" = /datum/game_mode/meteor/proc/set_meteor_wave_delay + "meteor_severity" = /decl/game_mode/meteor/proc/set_meteor_severity, + "meteor_wave_delay" = /decl/game_mode/meteor/proc/set_meteor_wave_delay ) -/datum/game_mode/meteor/proc/set_meteor_severity(value) +/decl/game_mode/meteor/proc/set_meteor_severity(value) meteor_severity = clamp(value, 0, maximal_severity) -/datum/game_mode/meteor/proc/set_meteor_wave_delay(value) +/decl/game_mode/meteor/proc/set_meteor_wave_delay(value) meteor_wave_delay = max(10 SECONDS, value) -/datum/game_mode/meteor/VV_static() +/decl/game_mode/meteor/VV_static() return ..() + "maximal_severity" -/datum/game_mode/meteor/post_setup() +/decl/game_mode/meteor/post_setup() ..() alert_title = "Automated Beacon AB-[rand(10, 99)]" alert_text = "This is an automatic warning. Your facility: [global.using_map.full_name] is on a collision course with a nearby asteroid belt. Estimated time until impact is: [meteor_grace_period / 1200] MINUTES. Please perform necessary actions to secure your ship or station from the threat. Have a nice day." start_text = "This is an automatic warning. Your facility: [global.using_map.full_name] has entered an asteroid belt. Estimated time until you leave the belt is: [rand(20,30)] HOURS and [rand(1, 59)] MINUTES. For your safety, please consider changing course or using protective equipment. Have a nice day." next_wave = round_duration_in_ticks + meteor_grace_period -/datum/game_mode/meteor/proc/on_meteor_warn() +/decl/game_mode/meteor/proc/on_meteor_warn() alert_sent = 1 command_announcement.Announce(alert_text, alert_title) -/datum/game_mode/meteor/proc/on_enter_field() +/decl/game_mode/meteor/proc/on_enter_field() alert_sent = 2 command_announcement.Announce(start_text, alert_title) for(var/obj/machinery/shield_diffuser/SD in SSmachines.machinery) @@ -70,7 +70,7 @@ T.add_overlay(image('icons/obj/overmap.dmi', "meteor[rand(1,4)]")) next_wave = round_duration_in_ticks + meteor_wave_delay -/datum/game_mode/meteor/process() +/decl/game_mode/meteor/process() // Send an alert halfway through the round. if((round_duration_in_ticks >= (next_wave / 2)) && !alert_sent) on_meteor_warn() @@ -94,7 +94,7 @@ if(send_admin_broadcasts) log_and_message_admins("Meteor: Wave fired. Escalation: [escalated ? "Yes" : "No"]. Severity: [meteor_severity]/[maximal_severity]") -/datum/game_mode/meteor/proc/get_meteor_types() +/decl/game_mode/meteor/proc/get_meteor_types() switch(meteor_severity) if(1 to 9) return meteors_dust diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 2f99480f8aa..3289a214b08 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -129,8 +129,8 @@ var/global/list/meteors_cataclysm = list(\ desc = "You should probably run instead of gawking at this." icon = 'icons/obj/meteor.dmi' icon_state = "small" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE var/hits = 4 var/hitpwr = 2 //Level of ex_act to be called on hit. var/dest diff --git a/code/game/gamemodes/mixed/crossfire.dm b/code/game/gamemodes/mixed/crossfire.dm index 041f78e5ea3..f031d36a780 100644 --- a/code/game/gamemodes/mixed/crossfire.dm +++ b/code/game/gamemodes/mixed/crossfire.dm @@ -1,8 +1,8 @@ -/datum/game_mode/crossfire +/decl/game_mode/crossfire name = "Mercenary & Heist" round_description = "Mercenaries and raiders are preparing for a nice visit..." extended_round_description = "Nothing can possibly go wrong with lots of people and lots of guns, right?" - config_tag = "crossfire" + uid = "crossfire" required_players = 25 required_enemies = 6 end_on_antag_death = FALSE diff --git a/code/game/gamemodes/mixed/siege.dm b/code/game/gamemodes/mixed/siege.dm index 6fa8fb621b8..1e84f5dbcc5 100644 --- a/code/game/gamemodes/mixed/siege.dm +++ b/code/game/gamemodes/mixed/siege.dm @@ -1,6 +1,6 @@ -/datum/game_mode/siege +/decl/game_mode/siege name = "Mercenary & Revolution" - config_tag = "siege" + uid = "siege" round_description = "Getting stuck between a rock and a hard place, maybe the nice visitors can help with your internal security problem?" extended_round_description = "GENERAL QUARTERS! OH GOD WE GAVE THE REVOLUTIONARIES GUNS!" required_players = 20 diff --git a/code/game/gamemodes/mixed/spyvspy.dm b/code/game/gamemodes/mixed/spyvspy.dm index 06e6ddd6dcc..f0f9d638cf1 100644 --- a/code/game/gamemodes/mixed/spyvspy.dm +++ b/code/game/gamemodes/mixed/spyvspy.dm @@ -1,8 +1,8 @@ -/datum/game_mode/spyvspy +/decl/game_mode/spyvspy name = "Spy v. Spy" round_description = "There are traitorous forces at play, but some crew have resolved to stop them by any means necessary!" extended_round_description = "Traitors and renegades both spawn during this mode." - config_tag = "spyvspy" + uid = "spyvspy" required_players = 4 required_enemies = 4 end_on_antag_death = FALSE diff --git a/code/game/gamemodes/mixed/uprising.dm b/code/game/gamemodes/mixed/uprising.dm index 6109afbb42f..3200ee883e9 100644 --- a/code/game/gamemodes/mixed/uprising.dm +++ b/code/game/gamemodes/mixed/uprising.dm @@ -1,8 +1,8 @@ -/datum/game_mode/uprising +/decl/game_mode/uprising name = "Cult & Revolution" round_description = "Some crewmembers are attempting to start a revolution while a cult plots in the shadows!" extended_round_description = "Cultists and revolutionaries spawn in this round." - config_tag = "uprising" + uid = "uprising" required_players = 20 required_enemies = 6 end_on_antag_death = FALSE diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index 0358b59aea9..1e281e66f5e 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -1,8 +1,8 @@ -/datum/game_mode/ninja +/decl/game_mode/ninja name = "Ninja" round_description = "An agent of the Spider Clan is on board!" extended_round_description = "A heavily armed, high-tech covert infiltrator is on board pursuing their mysterious goals." - config_tag = "ninja" + uid = "ninja" required_players = 5 required_enemies = 1 end_on_antag_death = FALSE diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 652840ba536..663767d11c0 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -4,11 +4,11 @@ var/global/list/nuke_disks = list() -/datum/game_mode/nuclear +/decl/game_mode/nuclear name = "Mercenary" round_description = "A mercenary strike force is approaching!" extended_round_description = "A heavily armed merc team is approaching in their warship; whatever their goal is, it can't be good for the crew." - config_tag = "mercenary" + uid = "mercenary" required_players = 15 required_enemies = 1 end_on_antag_death = FALSE @@ -22,13 +22,13 @@ var/global/list/nuke_disks = list() ) //checks if L has a nuke disk on their person -/datum/game_mode/nuclear/proc/check_mob(mob/living/L) +/decl/game_mode/nuclear/proc/check_mob(mob/living/L) for(var/obj/item/disk/nuclear/N in nuke_disks) if(N.storage_depth(L) >= 0) return TRUE return FALSE -/datum/game_mode/nuclear/declare_completion() +/decl/game_mode/nuclear/declare_completion() var/decl/special_role/merc = GET_DECL(/decl/special_role/mercenary) if(config.objectives_disabled == CONFIG_OBJECTIVE_NONE || (merc && !merc.global_objectives.len)) ..() diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index bdf00ce7247..cbd16ae38a8 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -1,6 +1,6 @@ -/datum/game_mode/revolution +/decl/game_mode/revolution name = "Revolution" - config_tag = "revolution" + uid = "revolution" round_description = "Some crewmembers are attempting to start a revolution!" extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders." required_players = 4 diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 9203ffcf94b..b87bc25b101 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,8 +1,8 @@ -/datum/game_mode/traitor +/decl/game_mode/traitor name = "traitor" round_description = "There is a foreign agent or traitor onboard. Do not let the traitor succeed!" extended_round_description = "Some members of the crew have been suborned, and are acting to meet a secret and traitorous goals of their own." - config_tag = "traitor" + uid = "traitor" required_players = 0 required_enemies = 1 associated_antags = list(/decl/special_role/traitor) diff --git a/code/game/gamemodes/wizard/servant_items/champion.dm b/code/game/gamemodes/wizard/servant_items/champion.dm index 53cb1b5cf8c..ace80ee8685 100644 --- a/code/game/gamemodes/wizard/servant_items/champion.dm +++ b/code/game/gamemodes/wizard/servant_items/champion.dm @@ -42,7 +42,7 @@ /obj/item/clothing/shoes/jackboots/medievalboots name = "leather boots" desc = "Old-fashioned leather boots. Probably not something you want to get kicked with." - material = /decl/material/solid/leather + material = /decl/material/solid/organic/leather force = 5 armor = list( ARMOR_MELEE = ARMOR_MELEE_RESISTANT, diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index b2fbdc10822..4e1d0b54e6c 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,8 +1,8 @@ -/datum/game_mode/wizard +/decl/game_mode/wizard name = "Wizard" round_description = "There is a SPACE WIZARD onboard. You can't let the magician achieve their objectives!" extended_round_description = "A powerful space wizard has made their way on board. They have a wide variety of powers and spells available to them that makes your own simple moral self tremble with fear and excitement. Ultimately, their purpose is unknown. However, it is up to you and your crew to decide if their powers can be used for good or if their arrival foreshadows devastation." - config_tag = "wizard" + uid = "wizard" required_players = 5 required_enemies = 1 end_on_antag_death = FALSE diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 525cd14da71..014baac33a1 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -17,14 +17,43 @@ if(id) . = id.GetAccess() -/atom/movable/proc/GetIdCard() - var/list/cards = GetIdCards() - return LAZYACCESS(cards, LAZYLEN(cards)) - -/atom/movable/proc/GetIdCards() +/atom/movable/proc/GetIdCard(list/exceptions, prefer_held = TRUE) + RETURN_TYPE(/obj/item/card/id) + . = GetIdCards(exceptions) + return LAZYACCESS(., LAZYLEN(.)) + +// Duplicated logic, because it's short enough to not bother splitting out. +// Quite gross logic sorry, did not want to work out a proper sorting method :( +// The logic behind this sorting is that we should prefer ID cards as such: +// - held cards, because they are very easily shifted dropped etc +// - equipped cards, because they can also be removed, albeit slower +// - any remaining cards, because at time of writing they are implanted and +// can't be removed easily at all. +/mob/GetIdCard(list/exceptions, prefer_held = TRUE) + RETURN_TYPE(/obj/item/card/id) + // Get candidate cards, return similar to parent if we don't care + . = GetIdCards(exceptions) + var/card_count = length(.) + if(card_count <= 0) + return null + if(!prefer_held || card_count == 1) + return .[card_count] + // Move ID to the end of the list. + var/obj/item/id = get_equipped_item(slot_wear_id_str) + if(id) + . -= id + . += id + // Move held items to the end of the list (prefer them over equipped ID) + for(var/obj/item/card in get_held_items()) + if(card in .) + . -= card + . += card + return .[length(.)] + +/atom/movable/proc/GetIdCards(list/exceptions) var/datum/extension/access_provider/our_provider = get_extension(src, /datum/extension/access_provider) if(our_provider) - LAZYDISTINCTADD(., our_provider.GetIdCards()) + LAZYDISTINCTADD(., our_provider.GetIdCards(exceptions)) /atom/movable/proc/check_access(atom/movable/A) return check_access_list(A ? A.GetAccess() : list()) @@ -210,56 +239,6 @@ var/global/list/priv_region_access "Emergency Response Team", "Emergency Response Team Leader") -/mob/observer/ghost - var/static/obj/item/card/id/all_access/ghost_all_access - -/mob/observer/ghost/GetIdCards() - . = ..() - if (!is_admin(src)) - return . - - if (!ghost_all_access) - ghost_all_access = new() - LAZYDISTINCTADD(., ghost_all_access) - -/mob/living/bot/GetIdCards() - . = ..() - if(istype(botcard)) - LAZYDISTINCTADD(., botcard) - -// Gets the ID card of a mob, but will not check types in the exceptions list -/mob/living/carbon/human/GetIdCard(exceptions = null) - return LAZYACCESS(GetIdCards(exceptions), 1) - -/mob/living/carbon/human/GetIdCards(exceptions = null) - . = ..() - var/list/candidates = get_held_items() - var/id = get_equipped_item(slot_wear_id_str) - if(id) - LAZYDISTINCTADD(candidates, id) - for(var/atom/movable/candidate in candidates) - if(!candidate || is_type_in_list(candidate, exceptions)) - continue - var/list/obj/item/card/id/id_cards = candidate.GetIdCards() - if(LAZYLEN(id_cards)) - LAZYDISTINCTADD(., id_cards) - -/mob/living/carbon/human/GetAccess(var/union = TRUE) - . = ..(union) - -/mob/living/silicon/GetIdCards() - . = ..() - if(stat || (ckey && !client)) - return // Unconscious, dead or once possessed but now client-less silicons are not considered to have id access. - if(istype(idcard)) - LAZYDISTINCTADD(., idcard) - -/proc/FindNameFromID(var/mob/M, var/missing_id_name = "Unknown") - var/obj/item/card/id/C = M.GetIdCard() - if(C) - return C.registered_name - return missing_id_name - /proc/get_all_job_icons() //For all existing HUD icons return SSjobs.titles_to_datums + list("Prisoner") @@ -270,13 +249,13 @@ var/global/list/priv_region_access var/job_icons = get_all_job_icons() if(I.assignment in job_icons) //Check if the job has a hud icon return I.assignment - if(I.rank in job_icons) - return I.rank + if(I.position in job_icons) + return I.position var/centcom = get_all_centcom_jobs() if(I.assignment in centcom) return "Centcom" - if(I.rank in centcom) + if(I.position in centcom) return "Centcom" else return diff --git a/code/game/jobs/job/_job.dm b/code/game/jobs/job/_job.dm index 4222150aeea..2931c501d3b 100644 --- a/code/game/jobs/job/_job.dm +++ b/code/game/jobs/job/_job.dm @@ -9,7 +9,7 @@ var/current_positions = 0 // How many players have this job var/availablity_chance = 100 // Percentage chance job is available each round var/guestbanned = FALSE // If set to 1 this job will be unavalible to guests - var/must_fill = FALSE // If set to 1 this job will be have priority over other job preferences. Do not reccommend on jobs with more that one position. + var/must_fill = FALSE // If set to 1 this job will be have priority over other job preferences. Do not recommend on jobs with more than one position. var/not_random_selectable = FALSE // If set to 1 this job will not be selected when a player asks for a random job. var/description // If set, returns a static description. To add dynamic text, overwrite this proc, call parent aka . = ..() and then . += "extra text" on the line after that. var/list/event_categories // A set of tags used to check jobs for suitability for things like random event selection. @@ -85,26 +85,15 @@ /datum/job/dd_SortValue() return title -/datum/job/proc/equip(var/mob/living/carbon/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) - +/datum/job/proc/equip_job(var/mob/living/carbon/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) if (required_language) H.add_language(required_language) H.set_default_language(required_language) - H.add_language(/decl/language/human/common) H.set_default_language(/decl/language/human/common) var/decl/hierarchy/outfit/outfit = get_outfit(H, alt_title, branch, grade) - if(outfit) . = outfit.equip(H, title, alt_title) - - if(!QDELETED(H)) - var/obj/item/card/id/id = H.GetIdCard() - if(id) - id.rank = title - id.assignment = id.rank - id.access |= get_access() - if(!id.detail_color) - id.detail_color = selection_color - id.update_icon() + if(outfit) + return outfit.equip_outfit(H, alt_title || title, job = src, rank = grade) /datum/job/proc/get_outfit(var/mob/living/carbon/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) if(alt_title && alt_titles) @@ -174,13 +163,12 @@ var/decl/hierarchy/outfit/outfit = get_outfit(H, alt_title, branch, grade) if(!outfit) return FALSE - . = outfit.equip(H, title, alt_title, OUTFIT_ADJUSTMENT_SKIP_POST_EQUIP|OUTFIT_ADJUSTMENT_SKIP_ID_PDA|additional_skips) + . = outfit.equip_outfit(H, alt_title || title, equip_adjustments = (OUTFIT_ADJUSTMENT_SKIP_POST_EQUIP|OUTFIT_ADJUSTMENT_SKIP_ID_PDA|additional_skips), job = src, rank = grade) /datum/job/proc/get_access() if(minimal_access.len && (!config || config.jobs_have_minimal_access)) return minimal_access?.Copy() - else - return access?.Copy() + return access?.Copy() //If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 /datum/job/proc/player_old_enough(client/C) @@ -451,13 +439,13 @@ spawnpos = null if(!spawnpos) // Step through all spawnpoints and pick first appropriate for job - for(var/decl/spawnpoint/candidate as anything in global.using_map.allowed_spawns) + for(var/decl/spawnpoint/candidate as anything in global.using_map.allowed_latejoin_spawns) if(candidate?.check_job_spawning(src)) spawnpos = candidate break return spawnpos -/datum/job/proc/post_equip_rank(var/mob/person, var/alt_title) +/datum/job/proc/post_equip_job_title(var/mob/person, var/alt_title, var/rank) if(is_semi_antagonist && person.mind) var/decl/special_role/provocateur/provocateurs = GET_DECL(/decl/special_role/provocateur) provocateurs.add_antagonist(person.mind) diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index e542861cd2e..771dc6e7423 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -8,7 +8,7 @@ var/global/list/whitelist = list() return 1 /proc/load_whitelist() - whitelist = file2list(WHITELISTFILE, FALSE) + whitelist = file2list(WHITELISTFILE) if(!length(whitelist)) whitelist = null diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm index 9648d1ab6e4..38c32161aeb 100644 --- a/code/game/machinery/Beacon.dm +++ b/code/game/machinery/Beacon.dm @@ -3,8 +3,8 @@ icon_state = "floor_beaconf" name = "tracking beacon" desc = "A device that uses zero-point energy to create a permanent tracking beacon." - level = 1 // underfloor - anchored = 1 + level = LEVEL_BELOW_PLATING + anchored = TRUE idle_power_usage = 0 var/obj/item/radio/beacon/beacon @@ -12,7 +12,7 @@ . = ..() var/turf/T = get_turf(src) beacon = new /obj/item/radio/beacon(T) - beacon.invisibility = INVISIBILITY_MAXIMUM + beacon.set_invisibility(INVISIBILITY_MAXIMUM) hide(!T.is_plating()) diff --git a/code/game/machinery/CableLayer.dm b/code/game/machinery/CableLayer.dm index 8fb51a9348a..049eea19da1 100644 --- a/code/game/machinery/CableLayer.dm +++ b/code/game/machinery/CableLayer.dm @@ -2,7 +2,7 @@ name = "automatic cable layer" icon = 'icons/obj/machines/pipe_dispenser.dmi' icon_state = "pipe_d" - density = 1 + density = TRUE interact_offline = TRUE var/obj/structure/cable/last_piece var/obj/item/stack/cable_coil/cable diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 706e8e01c61..f06b1cd5057 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -3,8 +3,8 @@ desc = "Used for advanced medical procedures." icon = 'icons/obj/surgery.dmi' icon_state = "table2-idle" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE throwpass = 1 idle_power_usage = 1 active_power_usage = 5 @@ -94,7 +94,7 @@ icon_state = "table2-idle" if(ishuman(victim)) var/mob/living/carbon/human/H = victim - if(H.pulse()) + if(H.get_pulse()) icon_state = "table2-active" /obj/machinery/optable/Process() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 19b3b6c4358..f78d4e0d926 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -60,7 +60,7 @@ var/decl/material/reagent = GET_DECL(rid) for(var/banned_type in banned_chem_types) if(istype(reagent, banned_type)) - to_chat(user, SPAN_WARNING("Automatic safety checking indicates the present of a prohibited substance in this canister.")) + to_chat(user, SPAN_WARNING("Automatic safety checking indicates the presence of a prohibited substance in this canister.")) return FALSE var/mob/M = canister.loc if(istype(M) && !M.try_unequip(canister, src)) @@ -79,6 +79,16 @@ to_chat(user, SPAN_NOTICE("You remove \the [canister] from \the [src].")) return TRUE +/obj/machinery/sleeper/proc/eject_all_reagent_canisters() + for(var/obj/item/canister in loaded_canisters) + canister.dropInto(loc) + LAZYCLEARLIST(loaded_canisters) + +/obj/machinery/sleeper/dismantle() + eject_all_reagent_canisters() + remove_beaker() + return ..() + /obj/machinery/sleeper/get_contained_external_atoms() . = ..() LAZYREMOVE(., loaded_canisters) @@ -112,35 +122,47 @@ else to_chat(user, SPAN_NOTICE("There are no chemical canisters loaded.")) +/obj/machinery/sleeper/proc/has_room_in_beaker() + return beaker && beaker.reagents.total_volume < beaker.reagents.maximum_volume + /obj/machinery/sleeper/Process() if(stat & (NOPOWER|BROKEN)) return - if(filtering > 0) - if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - var/pumped = LAZYLEN(occupant.reagents?.reagent_volumes) - if(pumped) - occupant.reagents.trans_to_obj(beaker, pump_speed * pumped) - occupant.vessel.trans_to_obj(beaker, pumped + 1) + if(!istype(occupant)) + if(filtering) + toggle_filter() + if(pump) + toggle_pump() + if(lavage) + toggle_lavage() + return + + if(filtering) + if(has_room_in_beaker()) + var/trans_volume = LAZYLEN(occupant.reagents?.reagent_volumes) + if(trans_volume) + occupant.reagents.trans_to_obj(beaker, pump_speed * trans_volume) + occupant.vessel.trans_to_obj(beaker, trans_volume + 1) else toggle_filter() - if(pump > 0) - if(beaker && istype(occupant)) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - var/datum/reagents/ingested = occupant.get_ingested_reagents() - if(ingested) - var/trans_amt = LAZYLEN(ingested.reagent_volumes) - if(trans_amt) - ingested.trans_to_obj(beaker, pump_speed * trans_amt) + + if(pump) + if(has_room_in_beaker()) + var/datum/reagents/ingested = occupant.get_ingested_reagents() + if(ingested) + var/trans_volume = LAZYLEN(ingested.reagent_volumes) + if(trans_volume) + ingested.trans_to_obj(beaker, pump_speed * trans_volume) else toggle_pump() + if(lavage) - if(beaker?.reagents) - if (beaker.reagents.total_volume < beaker.reagents.maximum_volume) - var/datum/reagents/inhaled = occupant.get_inhaled_reagents() + if(has_room_in_beaker()) + var/datum/reagents/inhaled = occupant.get_inhaled_reagents() + if(inhaled) var/trans_volume = LAZYLEN(inhaled?.reagent_volumes) - if(inhaled && trans_volume) + if(trans_volume) inhaled.trans_to_obj(beaker, pump_speed * trans_volume) else toggle_lavage() diff --git a/code/game/machinery/_machines_base/machinery.dm b/code/game/machinery/_machines_base/machinery.dm index a8c7a4badf0..70f7aeca353 100644 --- a/code/game/machinery/_machines_base/machinery.dm +++ b/code/game/machinery/_machines_base/machinery.dm @@ -400,7 +400,7 @@ Class Procs: /obj/machinery/CouldUseTopic(var/mob/user) ..() - if(clicksound && istype(user, /mob/living/carbon)) + if(clicksound && iscarbon(user)) playsound(src, clicksound, clickvol) /obj/machinery/proc/display_parts(mob/user) @@ -444,7 +444,7 @@ Class Procs: // This is really pretty crap and should be overridden for specific machines. /obj/machinery/fluid_act(var/datum/reagents/fluids) ..() - if(!(stat & (NOPOWER|BROKEN)) && !waterproof && (fluids.total_volume > FLUID_DEEP)) + if(!QDELETED(src) && !(stat & (NOPOWER|BROKEN)) && !waterproof && (fluids?.total_volume > FLUID_DEEP)) explosion_act(3) /obj/machinery/Move() @@ -460,15 +460,6 @@ Class Procs: if(battery && (!functional_only || battery.is_functional())) return battery.get_cell() -/obj/machinery/building_cost() - . = ..() - var/list/component_types = types_of_component(/obj/item/stock_parts) - for(var/path in component_types) - var/obj/item/stock_parts/part = get_component_of_type(path) - var/list/part_costs = part.building_cost() - for(var/key in part_costs) - .[key] += part_costs[key] * component_types[path] - /obj/machinery/emag_act(remaining_charges, mob/user, emag_source) . = ..() for(var/obj/item/stock_parts/access_lock/lock in get_all_components_of_type(/obj/item/stock_parts/access_lock)) @@ -489,8 +480,12 @@ Class Procs: // This only includes external atoms by default, so we need to add components back. /obj/machinery/get_contained_matter() . = ..() - for(var/obj/component in component_parts) - . = MERGE_ASSOCS_WITH_NUM_VALUES(., component.get_contained_matter()) + var/list/component_types = types_of_component(/obj/item/stock_parts) + for(var/path in component_types) + for(var/obj/item/stock_parts/part in get_all_components_of_type(path)) + var/list/part_costs = part.get_contained_matter() + for(var/key in part_costs) + .[key] += part_costs[key] * component_types[path] /obj/machinery/proc/get_auto_access() var/area/A = get_area(src) @@ -502,4 +497,11 @@ Class Procs: ///Handles updating stock parts and internal id tag when changing it to something else /obj/machinery/proc/set_id_tag(var/new_id_tag) id_tag = new_id_tag - //#TODO: Add handling for components, when we're sure it will work for any kind of machinery. Some machines do not use the same id_tag on receiver and transmitters for example. \ No newline at end of file + //#TODO: Add handling for components, when we're sure it will work for any kind of machinery. Some machines do not use the same id_tag on receiver and transmitters for example. + +// Make sure that mapped subtypes get the right codex entry. +/obj/machinery/get_codex_value() + return base_type || ..() + +/obj/machinery/solvent_can_melt(var/solvent_power = MAT_SOLVENT_STRONG) + return FALSE diff --git a/code/game/machinery/_machines_base/machinery_damage.dm b/code/game/machinery/_machines_base/machinery_damage.dm index a8e43425260..8c7953186f9 100644 --- a/code/game/machinery/_machines_base/machinery_damage.dm +++ b/code/game/machinery/_machines_base/machinery_damage.dm @@ -30,8 +30,11 @@ // And lastly hit the circuitboard victim = get_component_of_type(/obj/item/stock_parts/circuitboard) - if(victim) - victim.take_damage(amount, damtype) + if(victim?.can_take_damage() && victim.is_functional()) + amount -= victim.take_damage(amount, damtype) + + if(amount && (damtype == BRUTE || damtype == BURN)) + dismantle() /obj/machinery/proc/get_damageable_component(var/damage_type) var/list/victims = shuffle(component_parts) diff --git a/code/game/machinery/_machines_base/stock_parts/building_material.dm b/code/game/machinery/_machines_base/stock_parts/building_material.dm index 14aa1aea81d..615a39b9a85 100644 --- a/code/game/machinery/_machines_base/stock_parts/building_material.dm +++ b/code/game/machinery/_machines_base/stock_parts/building_material.dm @@ -33,23 +33,32 @@ new_material.forceMove(null) // amount will cap the amount given in a stack, but may return less than amount specified. -/obj/item/stock_parts/building_material/proc/remove_material(material_type, amount) +/obj/item/stock_parts/building_material/proc/remove_material(material_type, amount, force_destination) if(ispath(material_type, /obj/item/stack)) for(var/obj/item/stack/stack in materials) if(stack.stack_merge_type == material_type) var/stack_amount = stack.get_amount() if(stack_amount <= amount) materials -= stack - stack.dropInto(loc) + if(force_destination) + stack.forceMove(force_destination) + else + stack.dropInto(loc) amount -= stack_amount return stack var/obj/item/stack/new_stack = stack.split(amount) - new_stack.dropInto(loc) + if(force_destination) + new_stack.forceMove(force_destination) + else + new_stack.dropInto(loc) return new_stack for(var/obj/item/item in materials) if(istype(item, material_type)) materials -= item - item.dropInto(loc) + if(force_destination) + item.forceMove(force_destination) + else + item.dropInto(loc) return item /obj/item/stock_parts/building_material/on_uninstall(var/obj/machinery/machine) @@ -58,9 +67,9 @@ materials = null ..() -/obj/item/stock_parts/building_material/building_cost() +/obj/item/stock_parts/building_material/get_contained_matter() . = ..() for(var/obj/item/thing in materials) - var/list/costs = thing.building_cost() + var/list/costs = thing.get_contained_matter() for(var/key in costs) - .[key] += costs[key] \ No newline at end of file + .[key] += costs[key] diff --git a/code/game/machinery/_machines_base/stock_parts/card_reader.dm b/code/game/machinery/_machines_base/stock_parts/card_reader.dm index f3ee37f8c8c..fb8b1fe8d34 100644 --- a/code/game/machinery/_machines_base/stock_parts/card_reader.dm +++ b/code/game/machinery/_machines_base/stock_parts/card_reader.dm @@ -7,7 +7,7 @@ desc = "A RFID card reader for various authentication or data sharing usages." icon = 'icons/obj/items/stock_parts/modular_components.dmi' icon_state = "cardreader" - material = /decl/material/solid/plastic + material = /decl/material/solid/organic/plastic matter = list( /decl/material/solid/metal/steel = MATTER_AMOUNT_TRACE, /decl/material/solid/metal/copper = MATTER_AMOUNT_TRACE, diff --git a/code/game/machinery/_machines_base/stock_parts/disk_reader.dm b/code/game/machinery/_machines_base/stock_parts/disk_reader.dm index 1a0ce05bd05..eb6a5b8fe72 100644 --- a/code/game/machinery/_machines_base/stock_parts/disk_reader.dm +++ b/code/game/machinery/_machines_base/stock_parts/disk_reader.dm @@ -7,7 +7,7 @@ desc = "A floppy disk drive for installation in most machines. Able to read most floppy disks." icon = 'icons/obj/items/stock_parts/modular_components.dmi' icon_state = "floppy_drive" - material = /decl/material/solid/plastic + material = /decl/material/solid/organic/plastic matter = list( /decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY, /decl/material/solid/metal/copper = MATTER_AMOUNT_REINFORCEMENT, diff --git a/code/game/machinery/_machines_base/stock_parts/money_printer.dm b/code/game/machinery/_machines_base/stock_parts/money_printer.dm index 8be3830fce5..f48e3c060b8 100644 --- a/code/game/machinery/_machines_base/stock_parts/money_printer.dm +++ b/code/game/machinery/_machines_base/stock_parts/money_printer.dm @@ -2,7 +2,7 @@ name = "cryptographic micro-printer" desc = "A micro-printer capable of scanning, recycling, and printing cryptographically secured bank notes on ultra thin plastic." icon_state = "printer" - material = /decl/material/solid/plastic + material = /decl/material/solid/organic/plastic matter = list( /decl/material/solid/fiberglass = MATTER_AMOUNT_REINFORCEMENT, /decl/material/solid/silicon = MATTER_AMOUNT_REINFORCEMENT @@ -19,7 +19,7 @@ /obj/item/stock_parts/computer/money_printer/attackby(obj/item/W, mob/user) . = ..() - if(istype(W, /obj/item/stack/material) && W.get_material_type() == /decl/material/solid/plastic) + if(istype(W, /obj/item/stack/material) && W.get_material_type() == /decl/material/solid/organic/plastic) var/obj/item/stack/material/stack = W stored_plastic += SHEET_MATERIAL_AMOUNT * stack.amount @@ -29,7 +29,7 @@ if(IS_SCREWDRIVER(W) && !istype(loc, /obj/machinery)) to_chat(user, "You pry out the plastic reserves of \the [src].") - SSmaterials.create_object(/decl/material/solid/plastic, get_turf(src), round(stored_plastic / SHEET_MATERIAL_AMOUNT)) + SSmaterials.create_object(/decl/material/solid/organic/plastic, get_turf(src), round(stored_plastic / SHEET_MATERIAL_AMOUNT)) stored_plastic = 0 if(istype(W, /obj/item/cash)) @@ -41,7 +41,7 @@ return var/obj/item/cash/receiving = W var/decl/currency/receiving_currency = GET_DECL(receiving.currency) - if(receiving_currency.material != /decl/material/solid/plastic) + if(receiving_currency.material != /decl/material/solid/organic/plastic) to_chat(user, SPAN_WARNING("\The [src] cannot accept cash of this currency!")) return @@ -62,7 +62,7 @@ return FALSE // TODO: Support for non-plastic currencies var/decl/currency/printed_currency = GET_DECL(currency_type) - if(printed_currency.material != /decl/material/solid/plastic) + if(printed_currency.material != /decl/material/solid/organic/plastic) return FALSE return (stored_plastic >= amount*max(1, round(SHEET_MATERIAL_AMOUNT/10))) diff --git a/code/game/machinery/_machines_base/stock_parts/power/battery.dm b/code/game/machinery/_machines_base/stock_parts/power/battery.dm index fda2c356b7d..b1ac9b50f09 100644 --- a/code/game/machinery/_machines_base/stock_parts/power/battery.dm +++ b/code/game/machinery/_machines_base/stock_parts/power/battery.dm @@ -136,10 +136,9 @@ /obj/item/stock_parts/power/battery/on_refresh(var/obj/machinery/machine) if(machine && !cell) var/obj/item/stock_parts/building_material/mat = machine.get_component_of_type(/obj/item/stock_parts/building_material) - var/obj/item/cell/cell = mat && mat.remove_material(/obj/item/cell, 1) + var/obj/item/cell/cell = mat && mat.remove_material(/obj/item/cell, 1, src) if(cell) add_cell(machine, cell) - cell.forceMove(src) charge_rate = initial(charge_rate) charge_rate *= 1 + 0.5 * machine.total_component_rating_of_type(/obj/item/stock_parts/capacitor) @@ -183,7 +182,7 @@ return ..() /obj/item/stock_parts/power/battery/attack_hand(mob/user) - if(cell && istype(loc, /obj/machinery) && user.check_dexterity(DEXTERITY_GRIP)) + if(cell && istype(loc, /obj/machinery) && user.check_dexterity(DEXTERITY_HOLD_ITEM)) user.put_in_hands(cell) extract_cell(user) return TRUE @@ -226,7 +225,7 @@ material = /decl/material/solid/metal/steel matter = list( /decl/material/solid/metal/aluminium = MATTER_AMOUNT_REINFORCEMENT, - /decl/material/solid/plastic = MATTER_AMOUNT_TRACE + /decl/material/solid/organic/plastic = MATTER_AMOUNT_TRACE ) /obj/item/stock_parts/power/battery/buildable/turbo/get_lore_info() @@ -241,7 +240,7 @@ material = /decl/material/solid/metal/steel matter = list( /decl/material/solid/metal/aluminium = MATTER_AMOUNT_REINFORCEMENT, - /decl/material/solid/plastic = MATTER_AMOUNT_TRACE + /decl/material/solid/organic/plastic = MATTER_AMOUNT_TRACE ) /obj/item/stock_parts/power/battery/buildable/responsive/get_lore_info() diff --git a/code/game/machinery/_machines_base/stock_parts/power/terminal.dm b/code/game/machinery/_machines_base/stock_parts/power/terminal.dm index f982ee7f31c..8372665d500 100644 --- a/code/game/machinery/_machines_base/stock_parts/power/terminal.dm +++ b/code/game/machinery/_machines_base/stock_parts/power/terminal.dm @@ -180,7 +180,7 @@ expected_part_type = /obj/item/stock_parts/power/terminal /decl/stock_part_preset/terminal_setup/apply(obj/machinery/machine, var/obj/item/stock_parts/power/terminal/part) - if(isturf(machine.loc)) + if(isturf(machine.loc) && machine.anchored) part.make_terminal(machine) //Offset terminals towards the owner's facing direction diff --git a/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm b/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm index 67d06b18aec..3ea9f96f1fa 100644 --- a/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm +++ b/code/game/machinery/_machines_base/stock_parts/radio/transmitter.dm @@ -4,6 +4,9 @@ icon_state = "transmitter" var/range = 60 // Limits transmit range var/latency = 2 // Delay between event and transmission; doesn't apply to transmit on tick + #ifdef UNIT_TEST + latency = 0 // this can slow down testing and cause random inconsistent failures + #endif var/buffer /obj/item/stock_parts/radio/transmitter/proc/queue_transmit(list/data) @@ -11,7 +14,10 @@ return if(!buffer) buffer = data - addtimer(CALLBACK(src, .proc/transmit), latency) + if(latency) + addtimer(CALLBACK(src, .proc/transmit), latency) + else + transmit() else buffer |= data diff --git a/code/game/machinery/_machines_base/stock_parts/stock_parts_interface.dm b/code/game/machinery/_machines_base/stock_parts/stock_parts_interface.dm index d43c4bbf012..22b01cce5db 100644 --- a/code/game/machinery/_machines_base/stock_parts/stock_parts_interface.dm +++ b/code/game/machinery/_machines_base/stock_parts/stock_parts_interface.dm @@ -23,7 +23,7 @@ desc = "A standard part required by many machines to recieve user input." icon_state = "input" origin_tech = "{'materials':1}" - material = /decl/material/solid/plastic + material = /decl/material/solid/organic/plastic base_type = /obj/item/stock_parts/keyboard part_flags = PART_FLAG_HAND_REMOVE w_class = ITEM_SIZE_TINY @@ -33,4 +33,3 @@ ..() if(is_functional()) machine.set_noinput(FALSE) - \ No newline at end of file diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index fb0e422cbed..d09354e7bd3 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -2,7 +2,7 @@ name = "\improper AI Liquid Dispenser" icon = 'icons/obj/items/device/motion_detector.dmi' icon_state = "motion0" - anchored = 1.0 + anchored = TRUE idle_power_usage = 10 var/uses = 20 var/disabled = 1 @@ -26,7 +26,7 @@ /obj/machinery/ai_slipper/attackby(obj/item/W, mob/user) if(stat & (NOPOWER|BROKEN)) return - if (istype(user, /mob/living/silicon)) + if (issilicon(user)) return attack_ai(user) else // trying to unlock the interface if(allowed(user)) @@ -52,7 +52,7 @@ return var/t = "AI Liquid Dispenser ([area.proper_name])
" - if(src.locked && (!istype(user, /mob/living/silicon))) + if(src.locked && (!issilicon(user))) t += "(Swipe ID card to unlock control panel.)
" else t += text("Dispenser [] - []?
\n", src.disabled?"deactivated":"activated", src, src.disabled?"Enable":"Disable") diff --git a/code/game/machinery/air_sensor.dm b/code/game/machinery/air_sensor.dm index e7daf84e268..aa53b70818e 100644 --- a/code/game/machinery/air_sensor.dm +++ b/code/game/machinery/air_sensor.dm @@ -11,7 +11,7 @@ public_variables = list( /decl/public_access/public_variable/gas, /decl/public_access/public_variable/pressure, - /decl/public_access/public_variable/temperature + /decl/public_access/public_variable/temperature ) stock_part_presets = list(/decl/stock_part_preset/radio/basic_transmitter/air_sensor = 1) use_power = POWER_USE_IDLE @@ -47,7 +47,7 @@ return . = list() for(var/gas in air_sample.gas) - var/decl/material/mat = GET_DECL(gas) + var/decl/material/mat = GET_DECL(gas) var/gaspercent = round(air_sample.gas[gas]*100/total_moles,0.01) var/gas_list = list("symbol" = mat.gas_symbol_html, "percent" = gaspercent) . += list(gas_list) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 374f7131c46..5a82cc55e3a 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -47,7 +47,7 @@ name = BASE_ALARM_NAME icon = 'icons/obj/monitors.dmi' icon_state = "alarm0" - anchored = 1 + anchored = TRUE idle_power_usage = 80 active_power_usage = 1000 //For heating/cooling rooms. 1000 joules equates to about 1 degree every 2 seconds for a single tile of air. power_channel = ENVIRON @@ -941,7 +941,7 @@ FIRE ALARM var/d2 var/decl/security_state/security_state = GET_DECL(global.using_map.security_state) - if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon)) + if (ishuman(user) || issilicon(user) || isobserver(user)) A = A.loc if (A.fire) @@ -1051,7 +1051,7 @@ FIRE ALARM ASSERT(isarea(A)) var/d1 var/d2 - if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) + if (ishuman(user) || isAI(user)) if (A.party) d1 = text("No Party :(", src) diff --git a/code/game/machinery/atmoalter/_atmos_connection.dm b/code/game/machinery/atmoalter/_atmos_connection.dm new file mode 100644 index 00000000000..32abc3ea478 --- /dev/null +++ b/code/game/machinery/atmoalter/_atmos_connection.dm @@ -0,0 +1,92 @@ +// Extension for allowing an atom to be connected to an atmospherics connector port. +/datum/extension/atmospherics_connection + expected_type = /atom/movable + base_type = /datum/extension/atmospherics_connection + + var/toggle_anchor // Whether to toggle anchor holder on connect/disconnect + var/obj/machinery/atmospherics/portables_connector/connected_port + + var/datum/gas_mixture/merged_mixture + +/datum/extension/atmospherics_connection/New(datum/holder, _toggle_anchor, _merged_mixture) + . = ..() + toggle_anchor = _toggle_anchor + merged_mixture = _merged_mixture + +/datum/extension/atmospherics_connection/Destroy() + merged_mixture = null + disconnect() + . = ..() + +/datum/extension/atmospherics_connection/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) + //Make sure not already connected to something else + if(connected_port || !new_port || new_port.connected_device) + return FALSE + + var/atom/movable/movable_holder = holder + + //Make sure are close enough for a valid connection + if(new_port.loc != movable_holder.loc) + return FALSE + + //Perform the connection + connected_port = new_port + connected_port.connected_device = holder + connected_port.on = 1 //Activate port updates + + if(toggle_anchor) + movable_holder.anchored = TRUE //Prevent movement + + //Actually enforce the air sharing + var/datum/pipe_network/network = connected_port.return_network(holder) + + if(network && !network.gases.Find(merged_mixture)) + network.gases += merged_mixture + network.update = 1 + + return TRUE + +/datum/extension/atmospherics_connection/proc/disconnect() + if(!connected_port) + return FALSE + + var/datum/pipe_network/network = connected_port.return_network(holder) + if(network) + network.gases -= merged_mixture + + var/atom/movable/movable_holder = holder + + if(toggle_anchor) + movable_holder.anchored = FALSE + + connected_port.connected_device = null + connected_port = null + + return TRUE + +/datum/extension/atmospherics_connection/proc/update_connected_network() + if(!connected_port) + return + + var/datum/pipe_network/network = connected_port.return_network(holder) + if(network) + network.update = 1 + +/datum/extension/atmospherics_connection/proc/update_merged_mixture(datum/gas_mixture/new_mixture) + if(merged_mixture == new_mixture) + return TRUE + + if(!connected_port) + return FALSE + + var/datum/pipe_network/network = connected_port.return_network(holder) + + if(!network) + return FALSE + + network.gases.Remove(merged_mixture) + if(!network.gases.Find(new_mixture)) + network.gases += new_mixture + + network.update = 1 + return TRUE \ No newline at end of file diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 882ae584215..fc10ef624ba 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -2,7 +2,7 @@ name = "\improper Canister: \[CAUTION\]" icon = 'icons/obj/atmos.dmi' icon_state = "yellow" - density = 1 + density = TRUE var/health = 100.0 obj_flags = OBJ_FLAG_CONDUCTIBLE w_class = ITEM_SIZE_GARGANTUAN @@ -117,7 +117,7 @@ update_flag = 0 if(holding) update_flag |= 1 - if(connected_port) + if(get_port()) update_flag |= 2 var/tank_pressure = return_pressure() @@ -268,7 +268,7 @@ update_flag healthcheck() /obj/machinery/portable_atmospherics/canister/attackby(var/obj/item/W, var/mob/user) - if(istype(user, /mob/living/silicon/robot) && istype(W, /obj/item/tank/jetpack)) + if(isrobot(user) && istype(W, /obj/item/tank/jetpack)) var/obj/item/tank/jetpack/pack = W var/datum/gas_mixture/thejetpack = pack.air_contents if(!thejetpack) @@ -298,7 +298,7 @@ update_flag var/data[0] data["name"] = name data["canLabel"] = can_label ? 1 : 0 - data["portConnected"] = connected_port ? 1 : 0 + data["portConnected"] = get_port() ? 1 : 0 data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) data["releasePressure"] = round(release_pressure ? release_pressure : 0) data["minReleasePressure"] = round(0.1 ATM) diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index b2ba91ecd8e..45aa2558c24 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/meter.dmi' icon_state = "meterX" var/atom/target = null //A pipe for the base type - anchored = 1.0 + anchored = TRUE power_channel = ENVIRON idle_power_usage = 15 @@ -81,7 +81,7 @@ /obj/machinery/meter/examine(mob/user, distance) . = ..() - if(distance > 3 && !(istype(user, /mob/living/silicon/ai) || isghost(user))) + if(distance > 3 && !(isAI(user) || isghost(user))) to_chat(user, "You are too far away to read it.") else if(stat & (NOPOWER|BROKEN)) diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index 696585a9fbd..a046dde2a97 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -5,7 +5,6 @@ atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE var/datum/gas_mixture/air_contents = new - var/obj/machinery/atmospherics/portables_connector/connected_port var/obj/item/tank/holding var/volume = 0 var/destroyed = 0 @@ -22,6 +21,10 @@ ..() air_contents.volume = volume air_contents.temperature = T20C + + + set_extension(src, /datum/extension/atmospherics_connection, TRUE, air_contents) + return INITIALIZE_HINT_LATELOAD /obj/machinery/portable_atmospherics/Destroy() @@ -32,12 +35,13 @@ /obj/machinery/portable_atmospherics/LateInitialize() var/obj/machinery/atmospherics/portables_connector/port = locate() in loc if(port) - connect(port) - update_icon() + var/datum/extension/atmospherics_connection/connection = get_extension(src, /datum/extension/atmospherics_connection) + if(connection) + connection.connect(port) + update_icon() /obj/machinery/portable_atmospherics/Process() - if(!connected_port) //only react when pipe_network will ont it do it for you - //Allow for reactions + if(get_port()) // Only react when pipe_network will not do it for you air_contents.react() else update_icon() @@ -53,52 +57,24 @@ /obj/machinery/portable_atmospherics/on_update_icon() return null -/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) - //Make sure not already connected to something else - if(connected_port || !new_port || new_port.connected_device) - return 0 - - //Make sure are close enough for a valid connection - if(new_port.loc != loc) - return 0 +/obj/machinery/portable_atmospherics/proc/get_port() + var/datum/extension/atmospherics_connection/connection = get_extension(src, /datum/extension/atmospherics_connection) - //Perform the connection - connected_port = new_port - connected_port.connected_device = src - connected_port.on = 1 //Activate port updates + return connection?.connected_port - anchored = 1 //Prevent movement - - //Actually enforce the air sharing - var/datum/pipe_network/network = connected_port.return_network(src) - if(network && !network.gases.Find(air_contents)) - network.gases += air_contents - network.update = 1 +/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) + var/datum/extension/atmospherics_connection/connection = get_extension(src, /datum/extension/atmospherics_connection) - return 1 + return connection?.connect(new_port) /obj/machinery/portable_atmospherics/proc/disconnect() - if(!connected_port) - return 0 - - var/datum/pipe_network/network = connected_port.return_network(src) - if(network) - network.gases -= air_contents - - anchored = 0 + var/datum/extension/atmospherics_connection/connection = get_extension(src, /datum/extension/atmospherics_connection) - connected_port.connected_device = null - connected_port = null - - return 1 + return connection?.disconnect() /obj/machinery/portable_atmospherics/proc/update_connected_network() - if(!connected_port) - return - - var/datum/pipe_network/network = connected_port.return_network(src) - if (network) - network.update = 1 + var/datum/extension/atmospherics_connection/connection = get_extension(src, /datum/extension/atmospherics_connection) + connection?.update_connected_network() /obj/machinery/portable_atmospherics/attackby(var/obj/item/W, var/mob/user) if ((istype(W, /obj/item/tank) && !( src.destroyed ))) @@ -111,8 +87,7 @@ return else if(IS_WRENCH(W) && !panel_open) - if(connected_port) - disconnect() + if(disconnect()) to_chat(user, "You disconnect \the [src] from the port.") update_icon() return diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index 0f6231de021..97fb22a99b3 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -3,7 +3,7 @@ icon = 'icons/obj/atmos.dmi' icon_state = "psiphon:0" - density = 1 + density = TRUE w_class = ITEM_SIZE_NORMAL base_type = /obj/machinery/portable_atmospherics/powered/pump atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE @@ -40,7 +40,7 @@ if(holding) overlays += "siphon-open" - if(connected_port) + if(get_port()) overlays += "siphon-connector" /obj/machinery/portable_atmospherics/powered/pump/emp_act(severity) @@ -112,7 +112,7 @@ /obj/machinery/portable_atmospherics/powered/pump/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1) var/list/data[0] var/obj/item/cell/cell = get_cell() - data["portConnected"] = connected_port ? 1 : 0 + data["portConnected"] = get_port() ? 1 : 0 data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) data["targetpressure"] = round(target_pressure) data["pump_dir"] = direction_out diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 49ab66a4e1b..cd1ca3705e9 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -3,7 +3,7 @@ icon = 'icons/obj/atmos.dmi' icon_state = "pscrubber:0" - density = 1 + density = TRUE w_class = ITEM_SIZE_NORMAL base_type = /obj/machinery/portable_atmospherics/powered/scrubber atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE @@ -49,7 +49,7 @@ if(holding) overlays += "scrubber-open" - if(connected_port) + if(get_port()) overlays += "scrubber-connector" /obj/machinery/portable_atmospherics/powered/scrubber/Process() @@ -95,7 +95,7 @@ /obj/machinery/portable_atmospherics/powered/scrubber/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1) var/list/data[0] var/obj/item/cell/cell = get_cell() - data["portConnected"] = connected_port ? 1 : 0 + data["portConnected"] = get_port() ? 1 : 0 data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) data["rate"] = round(volume_rate) data["minrate"] = round(minrate) @@ -148,9 +148,9 @@ //Huge scrubber /obj/machinery/portable_atmospherics/powered/scrubber/huge - name = "Huge Air Scrubber" + name = "huge air scrubber" icon_state = "scrubber:0" - anchored = 1 + anchored = TRUE volume = 50000 volume_rate = 5000 base_type = /obj/machinery/portable_atmospherics/powered/scrubber/huge @@ -200,7 +200,7 @@ /obj/machinery/portable_atmospherics/powered/scrubber/huge/stationary - name = "Stationary Air Scrubber" + name = "stationary air scrubber" base_type = /obj/machinery/portable_atmospherics/powered/scrubber/huge/stationary /obj/machinery/portable_atmospherics/powered/scrubber/huge/stationary/attackby(var/obj/item/I, var/mob/user) diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index dabbf6cfa12..a4210bcb185 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -9,8 +9,8 @@ desc = "" icon = 'icons/obj/biogenerator.dmi' icon_state = "biogen-stand" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE idle_power_usage = 40 base_type = /obj/machinery/biogenerator construct_state = /decl/machine_construction/default/panel_closed @@ -59,6 +59,7 @@ . = ..() /obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well. + ..() update_icon() /obj/machinery/biogenerator/on_update_icon() diff --git a/code/game/machinery/bodyscanner.dm b/code/game/machinery/bodyscanner.dm index 23d02f7359f..b236e2d5bd3 100644 --- a/code/game/machinery/bodyscanner.dm +++ b/code/game/machinery/bodyscanner.dm @@ -5,8 +5,8 @@ name = "Body Scanner" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "body_scanner_0" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE idle_power_usage = 60 active_power_usage = 10000 //10 kW. It's a big all-body scanner. construct_state = /decl/machine_construction/default/panel_closed diff --git a/code/game/machinery/bodyscanner_console.dm b/code/game/machinery/bodyscanner_console.dm index 397fc05db08..f6aa9afebe7 100644 --- a/code/game/machinery/bodyscanner_console.dm +++ b/code/game/machinery/bodyscanner_console.dm @@ -4,12 +4,11 @@ name = "Body Scanner Console" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "body_scannerconsole" - density = 0 - anchored = 1 + density = FALSE + anchored = TRUE construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null stat_immune = 0 - var/list/display_tags = list() var/list/connected_displays = list() var/list/data = list() @@ -36,7 +35,7 @@ /obj/machinery/body_scanconsole/proc/FindDisplays() for(var/obj/machinery/body_scan_display/D in SSmachines.machinery) - if(D.tag in display_tags) + if(D.id_tag == connected.id_tag) connected_displays += D events_repository.register(/decl/observ/destroyed, D, src, .proc/remove_display) return !!connected_displays.len @@ -107,7 +106,7 @@ to_chat(user, "[html_icon(src)]Error: No scan stored.") return TOPIC_REFRESH var/list/scan = data["scan"] - new /obj/item/paper/bodyscan(loc, "Printout error.", "Body scan report - [stored_scan_subject]", scan.Copy()) + new /obj/item/paper/bodyscan(loc, null, "Printout error.", "Body scan report - [stored_scan_subject]", scan.Copy()) return TOPIC_REFRESH if(href_list["push"]) diff --git a/code/game/machinery/bodyscanner_display.dm b/code/game/machinery/bodyscanner_display.dm index 0643635724e..e70446dc677 100644 --- a/code/game/machinery/bodyscanner_display.dm +++ b/code/game/machinery/bodyscanner_display.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/modular_computers/modular_telescreen.dmi' icon_state = "telescreen" anchored = TRUE - density = 0 + density = FALSE idle_power_usage = 75 active_power_usage = 300 construct_state = /decl/machine_construction/default/panel_closed @@ -19,18 +19,25 @@ /obj/machinery/body_scan_display/proc/add_new_scan(var/list/scan) bodyscans += list(scan.Copy()) updateUsrDialog() + queue_icon_update() /obj/machinery/body_scan_display/on_update_icon() . = ..() cut_overlays() if(!(stat & (BROKEN|NOPOWER))) - add_overlay("operating") + if (selected != 0) + add_overlay("operating") + else if (bodyscans.len > 0) + add_overlay("menu") + else + add_overlay("standby") /obj/machinery/body_scan_display/OnTopic(mob/user, href_list) if(href_list["view"]) var/selection = text2num(href_list["view"]) if(is_valid_index(selection, bodyscans)) selected = selection + queue_icon_update() return TOPIC_REFRESH return TOPIC_HANDLED if(href_list["delete"]) @@ -39,6 +46,7 @@ return TOPIC_HANDLED if(selected == selection) selected = 0 + queue_icon_update() else if(selected > selection) selected-- bodyscans -= list(bodyscans[selection]) diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 850dc4bb7a6..97c7529dcfe 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -3,7 +3,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "launcherbtt" desc = "A remote control switch for something." - anchored = 1 + anchored = TRUE obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED layer = ABOVE_WINDOW_LAYER power_channel = ENVIRON @@ -47,8 +47,7 @@ /obj/machinery/button/interface_interact(user) if(!CanInteract(user, DefaultTopicState())) return FALSE - if(istype(user, /mob/living/carbon)) - playsound(src, "button", 60) + playsound(src, "button", 60) activate(user) return TRUE diff --git a/code/game/machinery/camera/_camera_device.dm b/code/game/machinery/camera/_camera_device.dm index aba5e522a61..6fa7a539f25 100644 --- a/code/game/machinery/camera/_camera_device.dm +++ b/code/game/machinery/camera/_camera_device.dm @@ -12,7 +12,7 @@ var/xray_enabled = FALSE has_commands = TRUE -/datum/extension/network_device/camera/New(datum/holder, n_id, n_key, c_type, autojoin, list/preset_channels, camera_name, camnet_enabled = TRUE, req_connection = TRUE) +/datum/extension/network_device/camera/New(datum/holder, n_id, n_key, r_type, autojoin, list/preset_channels, camera_name, camnet_enabled = TRUE, req_connection = TRUE) if(length(preset_channels)) channels = preset_channels.Copy() . = ..() @@ -22,6 +22,7 @@ display_name = camera_name /datum/extension/network_device/camera/post_construction() + . = ..() if(cameranet_enabled) cameranet.add_source(holder) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 1c568833574..04426a9e287 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -7,7 +7,7 @@ idle_power_usage = 5 active_power_usage = 10 layer = CAMERA_LAYER - anchored = 1 + anchored = TRUE movable_flags = MOVABLE_FLAG_PROXMOVE obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED directional_offset = "{'SOUTH':{'y':21}, 'EAST':{'x':-10}, 'WEST':{'x':10}}" @@ -86,13 +86,12 @@ if(!c_tag) var/area/A = get_area(src) if(isturf(loc) && A) - for(var/obj/machinery/camera/C in A) - if(C == src) continue - if(C.number) - number = max(number, C.number+1) - c_tag = "[A.proper_name][number == 1 ? "" : " #[number]"]" - if(!c_tag) // Add a default c_tag in case the camera has been placed in an invalid location or inside another object. - c_tag = "Security Camera - [random_id(/obj/machinery/camera, 100,999)]" + var/suffix = uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, "c_tag [A.proper_name]", 1) // unlike sequential_id, starts at 1 instead of 100 + if(suffix == 1) + suffix = null + c_tag = "[A.proper_name][suffix ? " [suffix]" : null]" + // Add a default c_tag in case the camera has been placed in an invalid location or inside another object. + c_tag ||= "Security Camera - [random_id(/obj/machinery/camera, 100,999)]" invalidateCameraCache() set_extension(src, /datum/extension/network_device/camera, null, null, null, TRUE, preset_channels, c_tag, cameranet_enabled, requires_connection) @@ -131,7 +130,7 @@ /obj/machinery/camera/proc/newTarget(var/mob/target) if (!motion_sensor) return FALSE - if (istype(target, /mob/living/silicon/ai)) + if (isAI(target)) return FALSE if (detectTime == 0) detectTime = world.time // start the clock @@ -192,7 +191,7 @@ if (istype(AM, /obj)) var/obj/O = AM if (O.throwforce >= src.toughness) - visible_message("[src] was hit by [O].") + visible_message(SPAN_WARNING("[src] was hit by [O]!")) take_damage(O.throwforce) /obj/machinery/camera/physical_attack_hand(mob/living/carbon/human/user) @@ -200,7 +199,7 @@ return if(user.species.can_shred(user)) user.do_attack_animation(src) - visible_message("\The [user] slashes at [src]!") + visible_message(SPAN_WARNING("\The [user] slashes at [src]!")) playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) add_hiddenprint(user) take_damage(25) @@ -220,11 +219,11 @@ /obj/machinery/camera/proc/add_channels(var/list/channels) var/datum/extension/network_device/camera/D = get_extension(src, /datum/extension/network_device) - D.add_channels(channels) + D?.add_channels(channels) /obj/machinery/camera/proc/remove_channels(var/list/channels) var/datum/extension/network_device/camera/D = get_extension(src, /datum/extension/network_device) - D.remove_channels(channels) + D?.remove_channels(channels) /obj/machinery/camera/set_broken(new_state, cause) . = ..() @@ -241,7 +240,7 @@ if (status != newstatus && (!cut_power || status == TRUE)) status = newstatus // The only way for AI to reactivate cameras are malf abilities, this gives them different messages. - if(istype(user, /mob/living/silicon/ai)) + if(isAI(user)) user = null if(status) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 62bf538ecfe..30ee583beec 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -1,32 +1,31 @@ /obj/machinery/camera/network/engineering preset_channels = list(CAMERA_CAMERA_CHANNEL_ENGINEERING) - initial_access = list(access_engine) + req_access = list(access_engine) /obj/machinery/camera/network/ert preset_channels = list(CAMERA_CHANNEL_ERT) cameranet_enabled = FALSE - initial_access = list(access_engine) + req_access = list(access_engine) /obj/machinery/camera/network/medbay preset_channels = list(CAMERA_CHANNEL_MEDICAL) - initial_access = list(access_medical) - + req_access = list(access_medical) /obj/machinery/camera/network/mercenary preset_channels = list(CAMERA_CHANNEL_MERCENARY) cameranet_enabled = FALSE - initial_access = list(access_mercenary) + req_access = list(access_mercenary) /obj/machinery/camera/network/mining preset_channels = list(CAMERA_CHANNEL_MINE) - initial_access = list(access_mining) + req_access = list(access_mining) /obj/machinery/camera/network/research preset_channels = list(CAMERA_CHANNEL_RESEARCH) - initial_access = list(access_research) + req_access = list(access_research) /obj/machinery/camera/network/security preset_channels = list(CAMERA_CHANNEL_SECURITY) - initial_access = list(access_security) + req_access = list(access_security) /obj/machinery/camera/network/television preset_channels = list(CAMERA_CHANNEL_TELEVISION) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index c22453cc8cf..ea4513468bd 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -9,7 +9,7 @@ return !(T && isPlayerLevel(T.z)) /mob/living/silicon/ai/proc/get_camera_list() - if(src.stat == 2) + if(src.stat == DEAD) return var/list/T = list() @@ -98,7 +98,7 @@ var/list/cameras = list() /mob/living/silicon/ai/proc/trackable_mobs() - if(usr.stat == 2) + if(usr.stat == DEAD) return list() var/datum/trackable/TB = new() @@ -115,7 +115,7 @@ else TB.names.Add(name) TB.namecounts[name] = 1 - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) TB.humans[name] = M else TB.others[name] = M @@ -129,7 +129,7 @@ set name = "Follow With Camera" set desc = "Select who you would like to track." - if(src.stat == 2) + if(src.stat == DEAD) to_chat(src, "You can't follow [target_name] with cameras because you are dead!") return if(!target_name) diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 8de3f6262a3..ed265488c05 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -3,7 +3,7 @@ desc = "A much more powerful version of the standard recharger that is specially designed for charging power cells." icon = 'icons/obj/power.dmi' icon_state = "ccharger0" - anchored = 1 + anchored = TRUE idle_power_usage = 5 power_channel = EQUIP var/chargelevel = -1 diff --git a/code/game/machinery/commsrelay.dm b/code/game/machinery/commsrelay.dm index aea515878ea..5573f9df902 100644 --- a/code/game/machinery/commsrelay.dm +++ b/code/game/machinery/commsrelay.dm @@ -3,8 +3,8 @@ desc = "This machine creates a microscopic wormhole between here and a suitable target, allowing for FTL communication." icon = 'icons/obj/machines/tcomms/bs_relay.dmi' icon_state = "bspacerelay" - anchored = 1 - density = 1 + anchored = TRUE + density = TRUE idle_power_usage = 15000 construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index a732ce9e243..6ae35fa9752 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -2,8 +2,8 @@ /obj/machinery/computer/operating name = "patient monitoring console" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE icon_keyboard = "med_key" icon_screen = "crew" var/mob/living/carbon/human/victim = null @@ -23,7 +23,7 @@ /obj/machinery/computer/operating/interact(mob/user) if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) - if (!istype(user, /mob/living/silicon)) + if (!issilicon(user)) user.unset_machine() close_browser(user, "window=op") return diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index d4b6e05f3fe..3fa89eef553 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -1,8 +1,8 @@ var/global/list/empty_playable_ai_cores = list() /obj/structure/aicore - density = 1 - anchored = 0 + density = TRUE + anchored = FALSE name = "\improper AI core" icon = 'icons/mob/AI.dmi' icon_state = "0" @@ -150,7 +150,7 @@ var/global/list/empty_playable_ai_cores = list() if(!B) to_chat(user, SPAN_WARNING("Sticking an empty [P] into the frame would sort of defeat the purpose.")) return - if(B.stat == 2) + if(B.stat == DEAD) to_chat(user, SPAN_WARNING("Sticking a dead [P] into the frame would sort of defeat the purpose.")) return if(jobban_isbanned(B, "AI")) @@ -201,7 +201,7 @@ var/global/list/deactivated_ai_cores = list() name = "inactive AI" icon = 'icons/mob/AI.dmi' icon_state = "ai-empty" - anchored = 1 + anchored = TRUE tool_interaction_flags = (TOOL_INTERACTION_ANCHOR | TOOL_INTERACTION_DECONSTRUCT) /obj/structure/aicore/deactivated/Initialize() @@ -215,7 +215,7 @@ var/global/list/deactivated_ai_cores = list() /obj/structure/aicore/deactivated/proc/load_ai(var/mob/living/silicon/ai/transfer, var/obj/item/aicard/card, var/mob/user) - if(!istype(transfer) || locate(/mob/living/silicon/ai) in src) + if(!isAI(transfer) || locate(/mob/living/silicon/ai) in src) return transfer.aiRestorePowerRoutine = 0 diff --git a/code/game/machinery/computer/arcade_orion.dm b/code/game/machinery/computer/arcade_orion.dm index 54de20448b6..93b47f19f05 100644 --- a/code/game/machinery/computer/arcade_orion.dm +++ b/code/game/machinery/computer/arcade_orion.dm @@ -4,7 +4,7 @@ ////////////////////////// //Orion Trail Events -#define ORION_TRAIL_RAIDERS "Vox Raiders" +#define ORION_TRAIL_RAIDERS "Space Pirates" #define ORION_TRAIL_FLUX "Interstellar Flux" #define ORION_TRAIL_ILLNESS "Illness" #define ORION_TRAIL_BREAKDOWN "Breakdown" @@ -318,7 +318,7 @@ else event_info = "You couldn't fight them off!
" if(prob(10*settlers.len)) - remove_settler(null, "was kidnapped by the Vox!") + remove_settler(null, "was kidnapped by the pirates!") change_resource(null,-1) change_resource(null,-0.5) if(ORION_TRAIL_DERELICT) @@ -399,7 +399,7 @@ /obj/machinery/computer/arcade/orion_trail/proc/emag_effect(var/event) switch(event) if(ORION_TRAIL_RAIDERS) - if(istype(usr,/mob/living/carbon)) + if(iscarbon(usr)) var/mob/living/carbon/M = usr if(prob(50)) to_chat(usr, "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?") @@ -410,7 +410,7 @@ else to_chat(usr, "The sounds of battle fill your ears...") if(ORION_TRAIL_ILLNESS) - if(istype(usr,/mob/living/carbon/human)) + if(ishuman(usr)) var/mob/living/carbon/human/M = usr to_chat(M, "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.") M.vomit() @@ -421,7 +421,7 @@ var/mob/living/M = usr M.adjustBruteLoss(10) if(ORION_TRAIL_FLUX) - if(istype(usr,/mob/living/carbon) && prob(75)) + if(iscarbon(usr) && prob(75)) var/mob/living/carbon/M = usr SET_STATUS_MAX(M, STAT_WEAK, 3) src.visible_message("A sudden gust of powerful wind slams \the [M] into the floor!", "You hear a large fwooshing sound, followed by a bang.") @@ -473,10 +473,10 @@ /obj/item/orion_ship name = "model settler ship" desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..." - icon = 'icons/obj/toy.dmi' + icon = 'icons/obj/toy/toy.dmi' icon_state = "ship" w_class = ITEM_SIZE_SMALL - material = /decl/material/solid/plastic + material = /decl/material/solid/organic/plastic matter = list( /decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY, /decl/material/solid/metal/copper = MATTER_AMOUNT_REINFORCEMENT, diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 72e54fe197f..ec09704fe94 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -8,20 +8,21 @@ icon_keyboard = "generic_key" icon_screen = "comm_logs" light_color = "#00b000" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE initial_access = list(list(access_engine_equip, access_atmospherics)) var/list/monitored_alarm_ids = null var/datum/nano_module/atmos_control/atmos_control base_type = /obj/machinery/computer/atmoscontrol +// TODO: replace this with a modular computer at some point /obj/machinery/computer/atmoscontrol/laptop - name = "Atmospherics Laptop" + name = "atmospherics laptop" desc = "A cheap laptop." icon_state = "laptop" icon_keyboard = "laptop_key" icon_screen = "atmoslaptop" - density = 0 + density = FALSE /obj/machinery/computer/atmoscontrol/interface_interact(user) ui_interact(user) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 4745a0ca0cb..5a6e4780c71 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -4,7 +4,6 @@ name = "computer frame" icon = 'icons/obj/items/stock_parts/stock_parts.dmi' icon_state = "unwired" - obj_flags = OBJ_FLAG_ROTATABLE expected_machine_type = "computer" /obj/machinery/constructable_frame/computerframe/on_update_icon() diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 6e5cce85337..dad1d1f750f 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -2,8 +2,8 @@ name = "computer console" icon = 'icons/obj/computer.dmi' icon_state = "computer" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE idle_power_usage = 300 active_power_usage = 300 construct_state = /decl/machine_construction/default/panel_closed/computer @@ -24,9 +24,6 @@ overlay_layer = layer update_icon() -/obj/machinery/computer/get_codex_value() - return "computer" - /obj/machinery/computer/emp_act(severity) if(prob(20/severity)) set_broken(TRUE) ..() diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm index a260d1e6e3a..7419b982914 100644 --- a/code/game/machinery/computer/guestpass.dm +++ b/code/game/machinery/computer/guestpass.dm @@ -50,7 +50,7 @@ icon_state = "guest" icon_keyboard = null icon_screen = "pass" - density = 0 + density = FALSE var/obj/item/card/id/giver var/list/accesses = list() @@ -91,7 +91,7 @@ if(giver) data["giver"] = !!giver - data["giver_name"] = giver.rank || giver.assignment + data["giver_name"] = giver.position || giver.assignment data["giv_name"] = giv_name var/list/giver_access = list() diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 78f17a16b4e..858df3d35e4 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -122,13 +122,13 @@ dat += "
[++i]. Set Custom Key
" else dat += "

Please authenticate with the server in order to show additional options." - if((istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) && (user.mind.assigned_special_role && user.mind.original == user)) + if((isAI(user) || isrobot(user)) && (user.mind.assigned_special_role && user.mind.original == user)) //Malf/Traitor AIs can bruteforce into the system to gain the Key. dat += "
*&@#. Bruteforce Key
" //Hacking screen. if(2) - if(istype(user, /mob/living/silicon/ai) || istype(user, /mob/living/silicon/robot)) + if(isAI(user) || isrobot(user)) dat += "Brute-forcing for server key.
It will take 20 seconds for every character that the password has." dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time." else @@ -285,7 +285,7 @@ //Hack the Console to get the password if (href_list["hack"]) - if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && usr.mind.assigned_special_role && usr.mind.original == usr) + if((isAI(usr) || isrobot(usr)) && usr.mind.assigned_special_role && usr.mind.original == usr) src.hacking = 1 src.screen = 2 update_icon() diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 0ea594d7e82..524f6a35889 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -68,7 +68,7 @@ return TOPIC_HANDLED // Antag AI checks - if(!istype(user, /mob/living/silicon/ai) || !(user.mind.assigned_special_role && user.mind.original == user)) + if(!isAI(user) || !(user.mind.assigned_special_role && user.mind.original == user)) to_chat(user, "Access Denied") return TOPIC_HANDLED @@ -110,7 +110,7 @@ for(var/mob/living/silicon/robot/R in global.silicon_mob_list) // Ignore drones - if(is_drone(R)) + if(isdrone(R)) continue // Ignore antagonistic cyborgs if(R.scrambledcodes) @@ -145,7 +145,7 @@ robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None" robot["hackable"] = 0 // Antag AIs know whether linked cyborgs are hacked or not. - if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.assigned_special_role && operator.mind.original == operator)) + if(operator && isAI(operator) && (R.connected_ai == operator) && (operator.mind.assigned_special_role && operator.mind.original == operator)) robot["hacked"] = R.emagged ? 1 : 0 robot["hackable"] = R.emagged? 0 : 1 robots.Add(list(robot)) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 0ab6191ec8c..e58b243c5dc 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -1,8 +1,6 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - //Circuit boards are in /code/game/objects/items/weapons/circuitboards/machinery/ - -/obj/machinery/constructable_frame //Made into a seperate type to make future revisions easier. +///Made into a seperate type to make future revisions easier. +/obj/machinery/constructable_frame name = "machine frame" icon = 'icons/obj/items/stock_parts/stock_parts.dmi' icon_state = "box_0" @@ -11,9 +9,10 @@ use_power = POWER_USE_OFF uncreated_component_parts = null construct_state = /decl/machine_construction/frame/unwrenched + obj_flags = OBJ_FLAG_ROTATABLE + atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE var/obj/item/stock_parts/circuitboard/circuit = null var/expected_machine_type - atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE /obj/machinery/constructable_frame/state_transition(decl/machine_construction/new_state) . = ..() diff --git a/code/game/machinery/cracker.dm b/code/game/machinery/cracker.dm index 689aef65288..0037f028edb 100644 --- a/code/game/machinery/cracker.dm +++ b/code/game/machinery/cracker.dm @@ -3,8 +3,8 @@ desc = "An integrated catalytic water cracking system used to break H2O down into H and O." icon = 'icons/obj/machines/cracker.dmi' icon_state = "cracker" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE waterproof = TRUE volume = 5000 use_power = POWER_USE_IDLE diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 331a8fbb367..65a10708027 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -13,7 +13,7 @@ desc = "An interface between crew and the cryogenic storage oversight systems." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "cellconsole" - density = 0 + density = FALSE interact_offline = 1 obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED directional_offset = "{'NORTH':{'y':-24}, 'SOUTH':{'y':32}, 'EAST':{'x':-24}, 'WEST':{'x':24}}" @@ -133,7 +133,7 @@ desc = "A bewildering tangle of machinery and pipes." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "cryo_rear" - anchored = 1 + anchored = TRUE dir = WEST //Cryopods themselves. @@ -142,8 +142,8 @@ desc = "A man-sized pod for entering suspended animation." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "body_scanner_0" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE dir = WEST var/base_icon_state = "body_scanner_0" @@ -189,7 +189,7 @@ icon_state = "redpod0" base_icon_state = "redpod0" occupied_icon_state = "redpod1" - var/launched = 0 + var/launched = FALSE var/datum/gas_mixture/airtank /obj/machinery/cryopod/lifepod/Initialize() @@ -203,7 +203,7 @@ return airtank /obj/machinery/cryopod/lifepod/proc/launch() - launched = 1 + launched = TRUE for(var/d in global.cardinal) var/turf/T = get_step(src,d) var/obj/machinery/door/blast/B = locate() in T @@ -212,13 +212,17 @@ break var/newz - if(prob(10)) + if(prob(90)) var/list/possible_locations var/obj/effect/overmap/visitable/O = global.overmap_sectors[num2text(z)] if(istype(O)) for(var/obj/effect/overmap/visitable/OO in range(O,2)) if((OO.sector_flags & OVERMAP_SECTOR_IN_SPACE) || istype(OO,/obj/effect/overmap/visitable/sector/planetoid)) - LAZYDISTINCTADD(possible_locations, text2num(level)) + // Don't try to escape to the place we just launched from + if(OO == O) + continue + var/datum/level_data/data = OO.get_topmost_level_data() + LAZYDISTINCTADD(possible_locations, text2num(data.level_z)) if(length(possible_locations)) newz = pick(possible_locations) if(!newz) @@ -454,7 +458,7 @@ set name = "Eject Pod" set category = "Object" set src in oview(1) - if(usr.stat != 0) + if(usr.stat != CONSCIOUS) return icon_state = base_icon_state @@ -477,7 +481,7 @@ set category = "Object" set src in oview(1) - if(usr.stat != 0 || !check_occupant_allowed(usr)) + if(usr.stat != CONSCIOUS || !check_occupant_allowed(usr)) return if(src.occupant) @@ -550,8 +554,8 @@ desc = "Whoever was inside isn't going to wake up now. It looks like you could pry it open with a crowbar." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "broken_cryo" - anchored = 1 - density = 1 + anchored = TRUE + density = TRUE var/closed = 1 var/busy = 0 var/remains_type = /obj/item/remains/human diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 8ce9d2e0f03..7e1f90e854e 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -9,8 +9,8 @@ name = "deployable barrier" desc = "A deployable barrier. Swipe your ID card to lock/unlock it." icon = 'icons/obj/objects.dmi' - anchored = 0.0 - density = 1 + anchored = FALSE + density = TRUE icon_state = "barrier0" var/health = 100.0 var/maxhealth = 100.0 @@ -57,7 +57,6 @@ src.health -= W.force * 0.75 if(BRUTE) src.health -= W.force * 0.5 - else if (src.health <= 0) src.explode() ..() @@ -91,7 +90,7 @@ /obj/machinery/deployable/barrier/physically_destroyed(skip_qdel) SSmaterials.create_object(/decl/material/solid/metal/steel, get_turf(src), 1, /obj/item/stack/material/rods) . = ..() - + /obj/machinery/deployable/barrier/proc/explode() visible_message("[src] blows apart!") spark_at(src, cardinal_only = TRUE) diff --git a/code/game/machinery/doors/_door.dm b/code/game/machinery/doors/_door.dm index 0247544b7fa..60fd6d4c053 100644 --- a/code/game/machinery/doors/_door.dm +++ b/code/game/machinery/doors/_door.dm @@ -6,9 +6,9 @@ desc = "It opens and closes." icon = 'icons/obj/doors/Doorint.dmi' icon_state = "door1" - anchored = 1 - opacity = 1 - density = 1 + anchored = TRUE + opacity = TRUE + density = TRUE layer = CLOSED_DOOR_LAYER interact_offline = TRUE construct_state = /decl/machine_construction/default/panel_closed/door @@ -52,7 +52,7 @@ var/set_dir_on_update = TRUE /obj/machinery/door/proc/can_operate(var/mob/user) - . = istype(user) && !user.restrained() && (!issmall(user) || ishuman(user) || issilicon(user) || istype(user, /mob/living/bot)) + . = istype(user) && !user.restrained() && (!issmall(user) || ishuman(user) || issilicon(user) || isbot(user)) /obj/machinery/door/attack_generic(var/mob/user, var/damage, var/attack_verb, var/environment_smash) if(environment_smash >= 1) @@ -521,8 +521,8 @@ success = 1 else for(var/obj/O in T) - for(var/b_type in blend_objects) - if( istype(O, b_type)) + for(var/blend_type in blend_objects) + if( istype(O, blend_type)) success = 1 if(success) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 768110ea59f..790e7a1a30e 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -91,9 +91,6 @@ var/global/list/airlock_overlays = list() /obj/machinery/door/airlock/proc/get_window_material() return GET_DECL(window_material) -/obj/machinery/door/airlock/get_codex_value() - return "airlock" - /obj/machinery/door/airlock/Process() if(main_power_lost_until > 0 && world.time >= main_power_lost_until) regainMainPower() @@ -295,9 +292,9 @@ About the new airlock wires panel: /obj/machinery/door/airlock/on_update_icon(state=0, override=0) if(set_dir_on_update) - if(connections & (NORTH|SOUTH)) - set_dir(WEST) - else + if(connections & (NORTH|SOUTH) == (NORTH|SOUTH)) + set_dir(EAST) + else if (connections & (EAST|WEST) == (EAST|WEST)) set_dir(SOUTH) switch(state) @@ -546,7 +543,7 @@ About the new airlock wires panel: return ..() /obj/machinery/door/airlock/physical_attack_hand(mob/user) - if(!istype(usr, /mob/living/silicon)) + if(!issilicon(usr)) if(src.isElectrified()) if(src.shock(user, 100)) return TRUE @@ -727,7 +724,7 @@ About the new airlock wires panel: update_icon() return TRUE - if(!istype(user, /mob/living/silicon)) + if(!issilicon(user)) if(src.isElectrified()) if(src.shock(user, 75)) return TRUE @@ -801,7 +798,7 @@ About the new airlock wires panel: return TRUE - else if((stat & (BROKEN|NOPOWER)) && istype(user, /mob/living/simple_animal)) + else if((stat & (BROKEN|NOPOWER)) && isanimal(user)) var/mob/living/simple_animal/A = user var/obj/item/I = A.get_natural_weapon() if(I?.force >= 10) @@ -869,7 +866,7 @@ About the new airlock wires panel: if(moved) spark_at(da, amount=5, cardinal_only = TRUE) else - da.anchored = 1 + da.anchored = TRUE da.state = 1 da.created_name = name da.update_icon() diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index c0ac2ac4d92..eea3bf99a74 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -235,7 +235,7 @@ var/obj/structure/door_assembly/da = ..() . = da - da.anchored = 1 + da.anchored = TRUE da.state = 1 da.created_name = name da.update_icon() diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index ef9ca949ae3..f0f98def655 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -19,8 +19,8 @@ icon_state = "frame" desc = "A remote control for a door." initial_access = list(access_brig) - anchored = 1.0 // can't pick it up - density = 0 // can walk through it. + anchored = TRUE // can't pick it up + density = FALSE // can walk through it. var/releasetime = 0 // when world.timeofday reaches it - release the prisoner var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing var/picture_state // icon_state of alert picture, if not displaying text/numbers diff --git a/code/game/machinery/doors/double.dm b/code/game/machinery/doors/double.dm index 394893adcc6..deade476b6b 100644 --- a/code/game/machinery/doors/double.dm +++ b/code/game/machinery/doors/double.dm @@ -19,7 +19,6 @@ appearance_flags = 0 opacity = TRUE width = 2 - set_dir_on_update = FALSE /obj/machinery/door/airlock/double/update_connections(var/propagate = 0) var/dirs = 0 @@ -42,8 +41,8 @@ success = 1 else for(var/obj/O in T) - for(var/b_type in blend_objects) - if( istype(O, b_type)) + for(var/blend_type in blend_objects) + if( istype(O, blend_type)) success = 1 if(success) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 70faf531e85..eecf6644ddc 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -17,8 +17,8 @@ icon_state = "open" initial_access = list(list(access_atmospherics, access_engine_equip)) autoset_access = FALSE - opacity = 0 - density = 0 + opacity = FALSE + density = FALSE layer = BELOW_DOOR_LAYER open_layer = BELOW_DOOR_LAYER closed_layer = ABOVE_WINDOW_LAYER diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index b7d4763ef1d..b0130013ea7 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -12,11 +12,12 @@ stat_immune = NOSCREEN | NOINPUT | NOPOWER uncreated_component_parts = null atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CHECKS_BORDER - opacity = 0 + opacity = FALSE explosion_resistance = 5 pry_mod = 0.5 base_type = /obj/machinery/door/window frame_type = /obj/structure/windoor_assembly + set_dir_on_update = FALSE // these can properly face all 4 directions! don't force us into just 2! var/base_state = "left" /obj/machinery/door/window/get_auto_access() @@ -138,7 +139,7 @@ return /obj/machinery/door/window/physical_attack_hand(mob/user) - if(istype(user,/mob/living/carbon/human)) + if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) diff --git a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm index 4f9b4783cac..0da24e61151 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm @@ -6,7 +6,6 @@ icon_state = "airlock_control_off" layer = ABOVE_OBJ_LAYER obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED - unacidable = TRUE base_type = /obj/machinery/dummy_airlock_controller construct_state = /decl/machine_construction/wall_frame/panel_closed frame_type = /obj/item/frame/button/airlock_controller diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 0842b5de998..7e98869a6c5 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -1,6 +1,6 @@ /obj/machinery/embedded_controller name = "Embedded Controller" - anchored = 1 + anchored = TRUE idle_power_usage = 10 layer = ABOVE_WINDOW_LAYER clicksound = "button" @@ -50,7 +50,6 @@ icon_state = "airlock_control_off" power_channel = ENVIRON density = FALSE - unacidable = TRUE obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED construct_state = /decl/machine_construction/wall_frame/panel_closed frame_type = /obj/item/frame/button/airlock_controller diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 28296257736..a39a573c195 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -12,7 +12,7 @@ var/last_flash = 0 //Don't want it getting spammed like regular flashes var/strength = 10 //How weakened targets are when flashed. var/base_state = "mflash" - anchored = 1 + anchored = TRUE idle_power_usage = 2 movable_flags = MOVABLE_FLAG_PROXMOVE @@ -78,12 +78,14 @@ flash_time = round(H.getFlashMod() * flash_time) if(flash_time <= 0) return - var/obj/item/organ/internal/E = GET_INTERNAL_ORGAN(H, H.species.vision_organ) - if(E && E.is_bruised() && prob(E.damage + 50)) - H.flash_eyes() - E.damage += rand(1, 5) - - if(!O.blinded) + var/vision_organ = H.get_bodytype()?.vision_organ + if(vision_organ) + var/obj/item/organ/internal/E = GET_INTERNAL_ORGAN(H, vision_organ) + if(E && E.is_bruised() && prob(E.damage + 50)) + H.flash_eyes() + E.damage += rand(1, 5) + + if(!O.is_blind()) do_flash(O, flash_time) /obj/machinery/flasher/proc/do_flash(var/mob/living/victim, var/flash_time) @@ -107,15 +109,15 @@ icon_state = "pflash1" icon = 'icons/obj/machines/flash_portable.dmi' strength = 8 - anchored = 0 + anchored = FALSE base_state = "pflash" - density = 1 + density = TRUE /obj/machinery/flasher/portable/HasProximity(atom/movable/AM) . = ..() if(!. || !anchored || disable || last_flash && world.time < last_flash + 150) return - if(istype(AM, /mob/living/carbon)) + if(iscarbon(AM)) var/mob/living/carbon/M = AM if(!MOVING_DELIBERATELY(M)) flash() diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 9934e156d3f..ee1f8948409 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -2,7 +2,7 @@ name = "emergency floodlight" icon = 'icons/obj/machines/floodlight.dmi' icon_state = "flood00" - density = 1 + density = TRUE obj_flags = OBJ_FLAG_ROTATABLE construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null diff --git a/code/game/machinery/floor_light.dm b/code/game/machinery/floor_light.dm index 9a8f9cb8926..ae9bc63c9a6 100644 --- a/code/game/machinery/floor_light.dm +++ b/code/game/machinery/floor_light.dm @@ -6,7 +6,7 @@ var/global/list/floor_light_cache = list() icon_state = "base" desc = "A backlit floor panel." layer = ABOVE_TILE_LAYER - anchored = 0 + anchored = FALSE use_power = POWER_USE_ACTIVE idle_power_usage = 2 active_power_usage = 20 @@ -23,7 +23,7 @@ var/global/list/floor_light_cache = list() var/default_light_color = "#ffffff" /obj/machinery/floor_light/prebuilt - anchored = 1 + anchored = TRUE /obj/machinery/floor_light/Initialize() . = ..() diff --git a/code/game/machinery/floorlayer.dm b/code/game/machinery/floorlayer.dm index a70327390df..5b224487cce 100644 --- a/code/game/machinery/floorlayer.dm +++ b/code/game/machinery/floorlayer.dm @@ -3,7 +3,7 @@ name = "automatic floor layer" icon = 'icons/obj/machines/pipe_dispenser.dmi' icon_state = "pipe_d" - density = 1 + density = TRUE interact_offline = TRUE var/turf/old_turf var/on = 0 diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 9b211dbfce8..bcb38a699ea 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -30,17 +30,17 @@ Possible to do for anyone motivated enough: #define AREA_BASED 6 var/global/const/HOLOPAD_MODE = RANGE_BASED +var/global/list/holopads = list() /obj/machinery/hologram/holopad name = "\improper holopad" desc = "It's a floor-mounted device for projecting holographic images." icon = 'icons/obj/machines/holopad.dmi' icon_state = "holopad-B0" - layer = ABOVE_TILE_LAYER + idle_power_usage = 5 var/power_per_hologram = 500 //per usage per hologram - idle_power_usage = 5 var/list/mob/living/silicon/ai/masters = new() //List of AIs that use the holopad var/last_request = 0 //to prevent request spam. ~Carn @@ -58,10 +58,24 @@ var/global/const/HOLOPAD_MODE = RANGE_BASED var/allow_ai = TRUE var/static/list/reachable_overmaps = list(OVERMAP_ID_SPACE) + var/holopad_id + /obj/machinery/hologram/holopad/Initialize() . = ..() - var/area/A = get_area(src) - desc = "It's a floor-mounted device for projecting holographic images. Its ID is '[A.proper_name]'" + + // Null ID means we want to use our area name. + global.holopads += src + if(isnull(holopad_id)) + var/area/A = get_area(src) + holopad_id = A?.proper_name || "Unknown" + + // For overmap sites, always tag the sector name so we have a unique discriminator for long range calls. + var/obj/effect/overmap/visitable/sector = global.overmap_sectors[num2text(z)] + if(sector) + holopad_id = "[sector.name] - [holopad_id]" + + // Update our desc. + desc = "It's a floor-mounted device for projecting holographic images. Its ID is '[holopad_id]'" /obj/machinery/hologram/holopad/interface_interact(var/mob/living/carbon/human/user) //Carn: Hologram requests. if(!CanInteract(user, DefaultTopicState())) @@ -92,12 +106,11 @@ var/global/const/HOLOPAD_MODE = RANGE_BASED if(last_request + 200 < world.time) //don't spam the AI with requests you jerk! last_request = world.time to_chat(user, "You request an AI's presence.") - var/area/area = get_area(src) for(var/mob/living/silicon/ai/AI in global.living_mob_list_) if(!AI.client) continue if (holopadType != HOLOPAD_LONG_RANGE && !SSmapping.are_connected_levels(AI.z, src.z)) continue - to_chat(AI, "Your presence is requested at \the [area.proper_name].") + to_chat(AI, "Your presence is requested at \the [holopad_id].") else to_chat(user, "A request for AI presence was already sent recently.") if("Holocomms") @@ -116,11 +129,10 @@ var/global/const/HOLOPAD_MODE = RANGE_BASED zlevels_long |= O.map_z for(var/obj/machinery/hologram/holopad/H in SSmachines.machinery) if (H.operable()) - var/area/A = get_area(H) if(H.z in zlevels) - holopadlist["[A.proper_name]"] = H //Define a list and fill it with the area of every holopad in the world + holopadlist["[H.holopad_id]"] = H //Define a list and fill it with the area of every holopad in the world if (H.holopadType == HOLOPAD_LONG_RANGE && (H.z in zlevels_long)) - holopadlist["[A.proper_name]"] = H + holopadlist["[H.holopad_id]"] = H holopadlist = sortTim(holopadlist, /proc/cmp_text_asc) var/temppad = input(user, "Which holopad would you like to contact?", "holopad list") as null|anything in holopadlist targetpad = holopadlist["[temppad]"] @@ -143,10 +155,8 @@ var/global/const/HOLOPAD_MODE = RANGE_BASED targetpad.incoming_connection = 1 playsound(targetpad.loc, 'sound/machines/chime.ogg', 25, 5) targetpad.icon_state = "[targetpad.base_icon]1" - var/area/our_area = get_area(src) - var/area/target_area = get_area(targetpad) - targetpad.audible_message("\The [src] announces, \"Incoming communications request from [our_area.proper_name].\"") - to_chat(user, "Trying to establish a connection to the holopad in [target_area.proper_name]... Please await confirmation from recipient.") + targetpad.audible_message("\The [src] announces, \"Incoming communications request from [holopad_id].\"") + to_chat(user, "Trying to establish a connection to the holopad in [targetpad.holopad_id]... Please await confirmation from recipient.") /obj/machinery/hologram/holopad/proc/take_call(mob/living/carbon/user) @@ -155,9 +165,7 @@ var/global/const/HOLOPAD_MODE = RANGE_BASED caller_id.reset_view(src) if(!masters[caller_id])//If there is no hologram, possibly make one. activate_holocall(caller_id) - var/area/source_area = get_area(sourcepad) - var/area/our_area = get_area(src) - log_admin("[key_name(caller_id)] just established a holopad connection from [source_area.proper_name] to [our_area.proper_name]") + log_admin("[key_name(caller_id)] just established a holopad connection from [sourcepad.holopad_id] to [holopad_id]") /obj/machinery/hologram/holopad/proc/end_call(mob/user) if(!caller_id) @@ -289,9 +297,9 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(A) if(A.holo_icon_malf == TRUE) hologram.overlays += icon("icons/effects/effects.dmi", "malf-scanline") - hologram.mouse_opacity = 0//So you can't click on it. + hologram.mouse_opacity = MOUSE_OPACITY_UNCLICKABLE//So you can't click on it. hologram.layer = ABOVE_HUMAN_LAYER //Above all the other objects/mobs. Or the vast majority of them. - hologram.anchored = 1//So space wind cannot drag it. + hologram.anchored = TRUE//So space wind cannot drag it. if(caller_id) hologram.SetName("[caller_id.name] (Hologram)") hologram.forceMove(get_step(src,1)) @@ -381,12 +389,13 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ */ /obj/machinery/hologram - anchored = 1 + anchored = TRUE idle_power_usage = 5 active_power_usage = 100 //Destruction procs. /obj/machinery/hologram/holopad/Destroy() + global.holopads -= src for (var/mob/living/master in masters) clear_holo(master) return ..() diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm index d0553a4de1a..61011c1e5b3 100644 --- a/code/game/machinery/holosign.dm +++ b/code/game/machinery/holosign.dm @@ -7,7 +7,7 @@ layer = ABOVE_DOOR_LAYER idle_power_usage = 2 active_power_usage = 70 - anchored = 1 + anchored = TRUE obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED directional_offset = "{'NORTH':{'y':-32}, 'SOUTH':{'y':32}, 'EAST':{'x':32}, 'WEST':{'x':-32}}" var/lit = 0 diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index acb30b36144..09a65b80873 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/machines/igniter.dmi' icon_state = "igniter1" var/on = 0 - anchored = 1 + anchored = TRUE idle_power_usage = 20 active_power_usage = 1000 @@ -90,7 +90,7 @@ var/last_spark = 0 var/base_state = "migniter" obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED - anchored = 1 + anchored = TRUE idle_power_usage = 20 active_power_usage = 1000 diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index b8965659703..51e67f598eb 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -4,8 +4,8 @@ icon = 'icons/obj/jukebox_new.dmi' icon_state = "jukebox3-nopower" var/state_base = "jukebox3" - anchored = 1 - density = 1 + anchored = TRUE + density = TRUE power_channel = EQUIP idle_power_usage = 10 active_power_usage = 100 @@ -122,7 +122,7 @@ /obj/machinery/media/jukebox/proc/emag_play() playsound(loc, 'sound/items/AirHorn.ogg', 100, 1) for(var/mob/living/carbon/M in ohearers(6, src)) - if(istype(M, /mob/living/carbon/human)) + if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.get_sound_volume_multiplier() < 0.2) continue diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm index dc3128b80ce..8b6d0a7b74a 100644 --- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm +++ b/code/game/machinery/kitchen/cooking_machines/_cooker.dm @@ -8,8 +8,8 @@ name = "cooker" desc = "You shouldn't be seeing this!" icon = 'icons/obj/cooking_machines.dmi' - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE idle_power_usage = 5 construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm b/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm index 7f279bd0561..0fa404f0f5e 100644 --- a/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm +++ b/code/game/machinery/kitchen/cooking_machines/_cooker_output.dm @@ -6,6 +6,7 @@ nutriment_amt = 5 bitesize = 2 filling_color = COLOR_BROWN + abstract_type = /obj/item/chems/food/variable /obj/item/chems/food/variable/Initialize() . = ..() diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 90501335331..0350d3a4998 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -4,8 +4,8 @@ desc = "The name isn't descriptive enough?" icon = 'icons/obj/kitchen.dmi' icon_state = "grinder" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE initial_access = list(list(access_kitchen, access_morgue)) construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null @@ -105,11 +105,11 @@ to_chat(user, "\The [src] is locked and running, wait for it to finish.") return - if(!(istype(victim, /mob/living/carbon)) && !(istype(victim, /mob/living/simple_animal)) ) + if(!iscarbon(victim) && !isanimal(victim)) to_chat(user, "This is not suitable for \the [src]!") return - if(istype(victim,/mob/living/carbon/human) && !emagged) + if(ishuman(victim) && !emagged) to_chat(user, "\The [src] safety guard is engaged!") return @@ -134,7 +134,7 @@ set name = "Empty Gibber" set src in oview(1) - if (usr.stat != 0) + if (usr.stat != CONSCIOUS) return src.go_out() add_fingerprint(usr) @@ -181,7 +181,7 @@ var/mob/living/carbon/C = occupant slab_nutrition = C.nutrition / 15 - if(istype(occupant, /mob/living/carbon/human)) + if(ishuman(occupant)) slab_name = occupant.real_name // Small mobs don't give as much nutrition. diff --git a/code/game/machinery/kitchen/icecream.dm b/code/game/machinery/kitchen/icecream.dm index 503a64ce407..7a223bb40b5 100644 --- a/code/game/machinery/kitchen/icecream.dm +++ b/code/game/machinery/kitchen/icecream.dm @@ -14,9 +14,9 @@ desc = "A heavy metal container used to produce and store ice cream." icon = 'icons/obj/kitchen.dmi' icon_state = "icecream_vat" - density = 1 - anchored = 0 - atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_REACT | ATOM_FLAG_OPEN_CONTAINER + density = TRUE + anchored = FALSE + atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_CHEM_CHANGE | ATOM_FLAG_OPEN_CONTAINER idle_power_usage = 100 var/list/product_types = list() diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index 5cd607e3440..65f98e8a90d 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -3,11 +3,11 @@ icon = 'icons/obj/kitchen.dmi' icon_state = "mw" layer = BELOW_OBJ_LAYER - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE idle_power_usage = 5 active_power_usage = 100 - atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_REACT | ATOM_FLAG_OPEN_CONTAINER + atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_CHEM_CHANGE | ATOM_FLAG_OPEN_CONTAINER construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null stat_immune = 0 @@ -350,7 +350,7 @@ SSnano.update_uis(src) /obj/machinery/microwave/on_reagent_change() - . = ..() + ..() if(!operating) SSnano.update_uis(src) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index a723a04cac4..8aae9fabfd8 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -6,11 +6,11 @@ icon = 'icons/obj/vending.dmi' icon_state = "fridge_sci" layer = BELOW_OBJ_LAYER - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE idle_power_usage = 5 active_power_usage = 100 - atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_REACT + atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_NO_CHEM_CHANGE obj_flags = OBJ_FLAG_ANCHORABLE | OBJ_FLAG_ROTATABLE atmos_canpass = CANPASS_NEVER required_interaction_dexterity = DEXTERITY_SIMPLE_MACHINES @@ -71,11 +71,11 @@ initial_access = list(list(access_medical, access_chemistry)) /obj/machinery/smartfridge/secure/medbay/accept_check(var/obj/item/O) - if(istype(O,/obj/item/chems/glass/)) + if(istype(O,/obj/item/chems/glass)) return 1 - if(istype(O,/obj/item/storage/pill_bottle/)) + if(istype(O,/obj/item/storage/pill_bottle)) return 1 - if(istype(O,/obj/item/chems/pill/)) + if(istype(O,/obj/item/chems/pill)) return 1 return 0 @@ -121,7 +121,7 @@ var/obj/item/chems/food/S = O return !!S.dried_type else if(istype(O, /obj/item/stack/material)) - return istype(O.material, /decl/material/solid/skin) + return istype(O.material, /decl/material/solid/organic/skin) return 0 /obj/machinery/smartfridge/drying_rack/Process() @@ -163,9 +163,9 @@ else if(istype(thing, /obj/item/stack/material)) var/obj/item/stack/material/skin = thing - if(!istype(skin.material, /decl/material/solid/skin)) + if(!istype(skin.material, /decl/material/solid/organic/skin)) continue - var/decl/material/solid/skin/skin_mat = skin.material + var/decl/material/solid/organic/skin/skin_mat = skin.material if(!skin_mat.tans_to) continue for(var/atom/item_to_stock in SSmaterials.create_object(skin_mat.tans_to, get_turf(src), skin.amount)) diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 32778f69086..f574381e6c5 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -7,7 +7,7 @@ icon = 'icons/obj/power.dmi' icon_state = "light0" obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED - anchored = 1.0 + anchored = TRUE idle_power_usage = 20 power_channel = LIGHT required_interaction_dexterity = DEXTERITY_SIMPLE_MACHINES diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index a335f7b58cf..e7aa1f660e4 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -12,9 +12,9 @@ var/global/list/magnetic_modules = list() icon_state = "floor_magnet-f" name = "Electromagnetic Generator" desc = "A device that uses powernet to create points of magnetic energy." - level = 1 // underfloor + level = LEVEL_BELOW_PLATING layer = ABOVE_WIRE_LAYER - anchored = 1 + anchored = TRUE idle_power_usage = 50 var/freq = 1449 // radio frequency @@ -169,7 +169,7 @@ var/global/list/magnetic_modules = list() step_towards(M, center) for(var/mob/living/silicon/S in orange(magnetic_field, center)) - if(istype(S, /mob/living/silicon/ai)) continue + if(isAI(S)) continue step_towards(S, center) use_power_oneoff(electricity_level * 5) @@ -187,8 +187,8 @@ var/global/list/magnetic_modules = list() name = "magnetic control console" icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! icon_state = "airlock_control_off" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE idle_power_usage = 45 var/frequency = 1449 var/code = 0 diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 15e226a2b10..6c3161ce09b 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -5,7 +5,7 @@ desc = "Shoots things into space." icon = 'icons/obj/machines/massdriver.dmi' icon_state = "mass_driver" - anchored = 1.0 + anchored = TRUE idle_power_usage = 2 active_power_usage = 50 diff --git a/code/game/machinery/mech_recharger.dm b/code/game/machinery/mech_recharger.dm index 8a8a988ff97..1738984bce3 100644 --- a/code/game/machinery/mech_recharger.dm +++ b/code/game/machinery/mech_recharger.dm @@ -3,9 +3,9 @@ desc = "A exosuit recharger, built into the floor." icon = 'icons/mecha/mech_bay.dmi' icon_state = "recharge_floor" - density = 0 + density = FALSE layer = ABOVE_TILE_LAYER - anchored = 1 + anchored = TRUE idle_power_usage = 200 // Some electronics, passive drain. active_power_usage = 60 KILOWATTS // When charging base_type = /obj/machinery/mech_recharger @@ -18,14 +18,15 @@ var/repair_power_usage = 10 KILOWATTS // Per 1 HP of health. var/repair = 0 -/obj/machinery/mech_recharger/Crossed(var/mob/living/exosuit/M) +/obj/machinery/mech_recharger/Crossed(atom/movable/AM) . = ..() - if(istype(M) && charging != M) - start_charging(M) + if(istype(AM, /mob/living/exosuit) && charging != AM) + start_charging(AM) -/obj/machinery/mech_recharger/Uncrossed(var/mob/living/exosuit/M) +/obj/machinery/mech_recharger/Uncrossed(atom/movable/AM) . = ..() - if(M == charging) + var/mob/living/exosuit/M = AM + if(istype(M) && M == charging) stop_charging() /obj/machinery/mech_recharger/RefreshParts() diff --git a/code/game/machinery/message_server.dm b/code/game/machinery/message_server.dm index 126a8116a7e..f9b935ff75e 100644 --- a/code/game/machinery/message_server.dm +++ b/code/game/machinery/message_server.dm @@ -42,8 +42,8 @@ var/global/list/message_servers = list() name = "messaging server" icon = 'icons/obj/machines/tcomms/message_server.dmi' icon_state = "message_server" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE idle_power_usage = 10 active_power_usage = 100 diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 90f596e716a..c216f24a31a 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -5,9 +5,9 @@ var/global/list/navbeacons = list() icon_state = "navbeacon0-f" name = "navigation beacon" desc = "A radio beacon used for bot navigation." - level = 1 + level = LEVEL_BELOW_PLATING layer = ABOVE_WIRE_LAYER - anchored = 1 + anchored = TRUE var/open = 0 // true if cover is open var/locked = 1 // true if controls are locked @@ -113,7 +113,7 @@ Transponder Codes: