diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 4fbdebf6f1..31f0233b23 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -24,6 +24,7 @@ #define IS_TAJARA 5 #define IS_XENOS 6 #define IS_TESHARI 7 +#define IS_SLIME 8 #define CE_STABLE "stable" // Inaprovaline #define CE_ANTIBIOTIC "antibiotic" // Spaceacilin diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 09931cb622..152e22a11a 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -9,6 +9,7 @@ #define CUT "cut" #define BRUISE "bruise" +#define PIERCE "pierce" #define STUN "stun" #define WEAKEN "weaken" diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 98ad3b28ca..8bac7f560c 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -136,9 +136,15 @@ #define INCAPACITATION_RESTRAINED 1 #define INCAPACITATION_BUCKLED_PARTIALLY 2 #define INCAPACITATION_BUCKLED_FULLY 4 +#define INCAPACITATION_STUNNED 8 +#define INCAPACITATION_FORCELYING 16 //needs a better name - represents being knocked down BUT still conscious. +#define INCAPACITATION_KNOCKOUT 32 + #define INCAPACITATION_DEFAULT (INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY) -#define INCAPACITATION_ALL (INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_PARTIALLY|INCAPACITATION_BUCKLED_FULLY) +#define INCAPACITATION_KNOCKDOWN (INCAPACITATION_KNOCKOUT|INCAPACITATION_FORCELYING) +#define INCAPACITATION_DISABLED (INCAPACITATION_KNOCKDOWN|INCAPACITATION_STUNNED) +#define INCAPACITATION_ALL (~INCAPACITATION_NONE) // Bodyparts and organs. #define O_MOUTH "mouth" diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index 2dec4406a4..27fc17055c 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -8,9 +8,9 @@ // unused: 0x8000 - higher than this will overflow // Species spawn flags -#define IS_WHITELISTED 0x1 // Must be whitelisted to play. -#define CAN_JOIN 0x2 // Species is selectable in chargen. -#define IS_RESTRICTED 0x4 // Is not a core/normally playable species. (castes, mutantraces) +#define SPECIES_IS_WHITELISTED 0x1 // Must be whitelisted to play. +#define SPECIES_IS_RESTRICTED 0x2 // Is not a core/normally playable species. (castes, mutantraces) +#define SPECIES_CAN_JOIN 0x4 // Species is selectable in chargen. // Species appearance flags #define HAS_SKIN_TONE 0x1 // Skin tone selectable in chargen. (0-255) @@ -19,6 +19,7 @@ #define HAS_UNDERWEAR 0x8 // Underwear is drawn onto the mob icon. #define HAS_EYE_COLOR 0x10 // Eye colour selectable in chargen. (RGB) #define HAS_HAIR_COLOR 0x20 // Hair colour selectable in chargen. (RGB) +#define RADIATION_GLOWS 0x40 // Radiation causes this character to glow. // Languages. #define LANGUAGE_SOL_COMMON "Sol Common" @@ -29,6 +30,7 @@ #define LANGUAGE_ROOTSPEAK "Rootspeak" #define LANGUAGE_TRADEBAND "Tradeband" #define LANGUAGE_GUTTER "Gutter" +#define LANGUAGE_SCHECHI "Schechi" // Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 9c0d80e5eb..f00e97d484 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -194,16 +194,22 @@ var/global/list/string_slot_flags = list( language_keys[lowertext(L.key)] = L var/rkey = 0 - paths = typesof(/datum/species)-/datum/species + paths = typesof(/datum/species) for(var/T in paths) + rkey++ - var/datum/species/S = new T + + var/datum/species/S = T + if(!initial(S.name)) + continue + + S = new T S.race_key = rkey //Used in mob icon caching. all_species[S.name] = S - if(!(S.spawn_flags & IS_RESTRICTED)) + if(!(S.spawn_flags & SPECIES_IS_RESTRICTED)) playable_species += S.name - if(S.spawn_flags & IS_WHITELISTED) + if(S.spawn_flags & SPECIES_IS_WHITELISTED) whitelisted_species += S.name //Posters diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index c0a0cac8b3..ac07b8d075 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -92,7 +92,7 @@ if (powerlevel > 0 && !istype(A, /mob/living/carbon/slime)) if(ishuman(M)) var/mob/living/carbon/human/H = M - stunprob *= H.species.siemens_coefficient + stunprob *= max(H.species.siemens_coefficient,0) switch(power * 10) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 4f211b930e..cc603aa2df 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -26,11 +26,11 @@ var/dat = {" @@ -258,8 +258,9 @@ preview_icon.Blend(E.get_icon(), ICON_OVERLAY) //Tail - if(H.species.tail) - temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[H.species.tail]_s") + var/use_species_tail = H.species.get_tail(H) + if(use_species_tail) + temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[use_species_tail]_s") preview_icon.Blend(temp, ICON_OVERLAY) // Skin tone diff --git a/code/game/gamemodes/changeling/absorbed_dna.dm b/code/game/gamemodes/changeling/absorbed_dna.dm index 2527f90697..bdf243b412 100644 --- a/code/game/gamemodes/changeling/absorbed_dna.dm +++ b/code/game/gamemodes/changeling/absorbed_dna.dm @@ -3,10 +3,12 @@ var/datum/dna/dna var/speciesName var/list/languages + var/identifying_gender -/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages) +/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender) ..() name = newName dna = newDNA speciesName = newSpecies languages = newLanguages + identifying_gender = newIdentifying_Gender \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 7e6563ca4b..ae5ede1566 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -85,7 +85,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/mob/living/carbon/human/H = src if(istype(H)) - var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages) + var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages, H.identifying_gender) absorbDNA(newDNA) return 1 diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 793b3a42ea..0eec3ed213 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -39,6 +39,7 @@ H.b_type = "AB+" //For some reason we have two blood types on the mob. for(var/flavor in H.flavor_texts) //Nulls out flavor text, so we don't keep our previous mob's flavor. flavor = null + H.identifying_gender = chosen_dna.identifying_gender src.real_name = chosen_dna.name src.flavor_text = "" src.UpdateAppearance() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index f67e28bb1a..2aa1d2b024 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -201,7 +201,6 @@ var/global/list/additional_antag_types = list() display_roundstart_logout_report() spawn (rand(waittime_l, waittime_h)) - send_intercept() spawn(rand(100,150)) announce_ert_disabled() @@ -373,56 +372,6 @@ var/global/list/additional_antag_types = list() /datum/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/send_intercept() - - var/intercepttext = "Cent. Com. Update Requested status information:
" - intercepttext += " In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with subversive elements:
" - - var/list/disregard_roles = list() - for(var/antag_type in all_antag_types) - var/datum/antagonist/antag = all_antag_types[antag_type] - if(antag.flags & ANTAG_SUSPICIOUS) - disregard_roles |= antag.role_text - - var/list/suspects = list() - for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) - - // NT relation option - var/special_role = man.mind.special_role - var/datum/antagonist/special_role_data = get_antag_data(special_role) - - if (special_role in disregard_roles) - continue - else if(man.client.prefs.nanotrasen_relation == COMPANY_OPPOSED && prob(50) || \ - man.client.prefs.nanotrasen_relation == COMPANY_SKEPTICAL && prob(20)) - suspects += man - // Antags - else if(special_role_data && prob(special_role_data.suspicion_chance)) - suspects += man - - // Some poor people who were just in the wrong place at the wrong time.. - else if(prob(10)) - suspects += man - - for(var/mob/M in suspects) - if(player_is_antag(M.mind, only_offstation_roles = 1)) - continue - switch(rand(1, 100)) - if(1 to 50) - intercepttext += "Someone with the job of [M.mind.assigned_role]
" - else - intercepttext += "[M.name], the [M.mind.assigned_role]
" - - for (var/obj/machinery/computer/communications/comm in machines) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Status Summary" - intercept.info = intercepttext - - comm.messagetitle.Add("Cent. Com. Status Summary") - comm.messagetext.Add(intercepttext) - world << sound('sound/AI/commandreport.ogg') - /datum/game_mode/proc/get_players_for_role(var/role, var/antag_id) var/list/players = list() var/list/candidates = list() diff --git a/code/game/gamemodes/mixed/visitors.dm b/code/game/gamemodes/mixed/visitors.dm index e9a5919819..853e5039d4 100644 --- a/code/game/gamemodes/mixed/visitors.dm +++ b/code/game/gamemodes/mixed/visitors.dm @@ -3,8 +3,8 @@ round_description = "A space wizard and a ninja have invaded the station!" extended_round_description = "A ninja and wizard spawn during this round." config_tag = "visitors" - required_players = 6 - required_players_secret = 6 + required_players = 8 + required_players_secret = 8 required_enemies = 2 end_on_antag_death = 0 antag_tags = list(MODE_WIZARD, MODE_NINJA) diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index d71412dc8a..480c69d27f 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -10,7 +10,7 @@ only hope this unknown assassin isn't here for you." config_tag = "ninja" required_players = 1 - required_players_secret = 8 + required_players_secret = 6 required_enemies = 1 end_on_antag_death = 0 antag_tags = list(MODE_NINJA) \ No newline at end of file diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 0cc48203c5..9da98075f3 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -4,7 +4,7 @@ extended_round_description = "A powerful entity capable of manipulating the elements around him, most commonly referred to as a 'wizard', has infiltrated the station. 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 the destruction of the entire station." config_tag = "wizard" required_players = 1 - required_players_secret = 8 + required_players_secret = 6 required_enemies = 1 end_on_antag_death = 0 antag_tags = list(MODE_WIZARD) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index ddcbb9cc2c..fd0996e2bc 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -4,12 +4,14 @@ /datum/data/vending_product var/product_name = "generic" // Display name for the product var/product_path = null - var/amount = 0 // Amount held in the vending machine - var/price = 0 // Price to buy one - var/display_color = null // Display color for vending machine listing + var/amount = 0 // The original amount held in the vending machine + var/list/instances + var/price = 0 // Price to buy one + var/display_color = null // Display color for vending machine listing var/category = CAT_NORMAL // CAT_HIDDEN for contraband, CAT_COIN for premium + var/vending_machine // The vending machine we belong to -/datum/data/vending_product/New(var/path, var/name = null, var/amount = 1, var/price = 0, var/color = null, var/category = CAT_NORMAL) +/datum/data/vending_product/New(var/vending_machine, var/path, var/name = null, var/amount = 1, var/price = 0, var/color = null, var/category = CAT_NORMAL) ..() src.product_path = path @@ -24,6 +26,43 @@ src.price = price src.display_color = color src.category = category + src.vending_machine = vending_machine + +/datum/data/vending_product/Destroy() + vending_machine = null + if(instances) + for(var/product in instances) + qdel(product) + instances.Cut() + . = ..() + +/datum/data/vending_product/proc/get_amount() + return instances ? instances.len : amount + +/datum/data/vending_product/proc/add_product(var/atom/movable/product) + if(product.type != product_path) + return 0 + init_products() + product.forceMove(vending_machine) + instances += product + +/datum/data/vending_product/proc/get_product(var/product_location) + if(!get_amount() || !product_location) + return + init_products() + + var/atom/movable/product = instances[instances.len] // Remove the last added product + instances -= product + product.forceMove(product_location) + return product + +/datum/data/vending_product/proc/init_products() + if(instances) + return + instances = list() + for(var/i = 1 to amount) + var/new_product = new product_path(vending_machine) + instances += new_product /** * A vending machine @@ -130,7 +169,7 @@ var/category = current_list[2] for(var/entry in current_list[1]) - var/datum/data/vending_product/product = new/datum/data/vending_product(entry) + var/datum/data/vending_product/product = new/datum/data/vending_product(src, entry) product.price = (entry in src.prices) ? src.prices[entry] : 0 product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1 @@ -143,6 +182,9 @@ wires = null qdel(coin) coin = null + for(var/datum/data/vending_product/R in product_records) + qdel(R) + product_records = null return ..() /obj/machinery/vending/ex_act(severity) @@ -214,7 +256,7 @@ return else if(istype(W, /obj/item/weapon/coin) && premium.len > 0) user.drop_item() - W.loc = src + W.forceMove(src) coin = W categories |= CAT_COIN user << "You insert \the [W] into \the [src]." @@ -410,7 +452,7 @@ "name" = I.product_name, "price" = I.price, "color" = I.display_color, - "amount" = I.amount))) + "amount" = I.get_amount()))) data["products"] = listed_products @@ -440,10 +482,10 @@ usr << "There is no coin in this machine." return - coin.loc = src.loc + coin.forceMove(src.loc) if(!usr.get_active_hand()) usr.put_in_hands(coin) - usr << "You remove the [coin] from the [src]" + usr << "You remove \the [coin] from \the [src]" coin = null categories &= ~CAT_COIN @@ -504,13 +546,13 @@ else user << "You weren't able to pull the coin out fast enough, the machine ate it, string and all." qdel(coin) + coin = null categories &= ~CAT_COIN else qdel(coin) + coin = null categories &= ~CAT_COIN - R.amount-- - if(((src.last_reply + (src.vend_delay + 200)) <= world.time) && src.vend_reply) spawn(0) src.speak(src.vend_reply) @@ -520,16 +562,31 @@ if (src.icon_vend) //Show the vending animation if needed flick(src.icon_vend,src) spawn(src.vend_delay) - new R.product_path(get_turf(src)) + R.get_product(get_turf(src)) + if(prob(1)) + sleep(3) + if(R.get_product(get_turf(src))) + src.visible_message("\The [src] clunks as it vends an additional item.") + src.status_message = "" src.status_error = 0 src.vend_ready = 1 currently_vending = null nanomanager.update_uis(src) -/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user) - user << "You insert \the [src] in the product receptor." - R.amount++ + +/** + * Add item to the machine + * + * Checks if item is vendable in this machine should be performed before + * calling. W is the item being inserted, R is the associated vending_product entry. + */ +/obj/machinery/vending/proc/stock(obj/item/weapon/W, var/datum/data/vending_product/R, var/mob/user) + if(!user.unEquip(W)) + return + + user << "You insert \the [W] in the product receptor." + R.add_product(W) nanomanager.update_uis(src) @@ -579,15 +636,8 @@ //Oh no we're malfunctioning! Dump out some product and break. /obj/machinery/vending/proc/malfunction() for(var/datum/data/vending_product/R in src.product_records) - if (R.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = R.product_path - if (!dump_path) - continue - - while(R.amount>0) - new dump_path(src.loc) - R.amount-- + while(R.get_amount()>0) + R.get_product(loc) break stat |= BROKEN @@ -602,20 +652,15 @@ return 0 for(var/datum/data/vending_product/R in src.product_records) - if (R.amount <= 0) //Try to use a record that actually has something to dump. + throw_item = R.get_product(loc) + if (!throw_item) continue - var/dump_path = R.product_path - if (!dump_path) - continue - - R.amount-- - throw_item = new dump_path(src.loc) break if (!throw_item) return 0 spawn(0) throw_item.throw_at(target, 16, 3, src) - src.visible_message("[src] launches [throw_item.name] at [target.name]!") + src.visible_message("\The [src] launches \a [throw_item] at \the [target]!") return 1 /* @@ -643,7 +688,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "dispenser" product_paths = "/obj/item/weapon/tank/oxygen;/obj/item/weapon/tank/phoron;/obj/item/weapon/tank/emergency_oxygen;/obj/item/weapon/tank/emergency_oxygen/engi;/obj/item/clothing/mask/breath" - product_amounts = "10;10;10;5;25" + productamounts = "10;10;10;5;25" vend_delay = 0 */ @@ -869,7 +914,7 @@ for(var/entry in current_list[1]) var/obj/item/seeds/S = new entry(src) var/name = S.name - var/datum/data/vending_product/product = new/datum/data/vending_product(entry, name) + var/datum/data/vending_product/product = new/datum/data/vending_product(src, entry, name) product.price = (entry in src.prices) ? src.prices[entry] : 0 product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1 @@ -929,8 +974,10 @@ icon_deny = "tool-deny" //req_access = list(access_maint_tunnels) //Maintenance access products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/weapon/crowbar = 5,/obj/item/weapon/weldingtool = 3,/obj/item/weapon/wirecutters = 5, - /obj/item/weapon/wrench = 5,/obj/item/device/analyzer = 5,/obj/item/device/t_scanner = 5,/obj/item/weapon/screwdriver = 5) - contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2) + /obj/item/weapon/wrench = 5,/obj/item/device/analyzer = 5,/obj/item/device/t_scanner = 5,/obj/item/weapon/screwdriver = 5, + /obj/item/device/flashlight/glowstick = 3, /obj/item/device/flashlight/glowstick/red = 3, /obj/item/device/flashlight/glowstick/blue = 3, + /obj/item/device/flashlight/glowstick/orange =3, /obj/item/device/flashlight/glowstick/yellow = 3) + contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2, ) premium = list(/obj/item/clothing/gloves/yellow = 1) /obj/machinery/vending/engivend diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index c7f90e9746..83ac8851dd 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -199,7 +199,7 @@ src.force = on_damage src.damtype = "fire" processing_objects += src - + /obj/item/device/flashlight/flare/proc/ignite() //Used for flare launchers. on = !on update_icon() @@ -208,6 +208,76 @@ processing_objects += src return 1 +//Glowsticks + +/obj/item/device/flashlight/glowstick + name = "green glowstick" + desc = "A green military-grade glowstick." + w_class = 2.0 + brightness_on = 4 + light_power = 2 + light_color = "#49F37C" + icon_state = "glowstick" + item_state = "glowstick" + var/fuel = 0 + +/obj/item/device/flashlight/glowstick/New() + fuel = rand(1600, 2000) + ..() + +/obj/item/device/flashlight/glowstick/process() + fuel = max(fuel - 1, 0) + if(!fuel || !on) + turn_off() + if(!fuel) + src.icon_state = "[initial(icon_state)]-empty" + processing_objects -= src + +/obj/item/device/flashlight/glowstick/proc/turn_off() + on = 0 + update_icon() + +/obj/item/device/flashlight/glowstick/attack_self(mob/user) + + if(!fuel) + user << "The glowstick has already been turned on." + return + if(on) + return + + . = ..() + if(.) + user.visible_message("[user] cracks and shakes the glowstick.", "You crack and shake the glowstick, turning it on!") + processing_objects += src + +/obj/item/device/flashlight/glowstick/red + name = "red glowstick" + desc = "A red military-grade glowstick." + light_color = "#FC0F29" + icon_state = "glowstick_red" + item_state = "glowstick_red" + +/obj/item/device/flashlight/glowstick/blue + name = "blue glowstick" + desc = "A blue military-grade glowstick." + light_color = "#599DFF" + icon_state = "glowstick_blue" + item_state = "glowstick_blue" + +/obj/item/device/flashlight/glowstick/orange + name = "orange glowstick" + desc = "A orange military-grade glowstick." + light_color = "#FA7C0B" + icon_state = "glowstick_orange" + item_state = "glowstick_orange" + +/obj/item/device/flashlight/glowstick/yellow + name = "yellow glowstick" + desc = "A yellow military-grade glowstick." + light_color = "#FEF923" + icon_state = "glowstick_yellow" + item_state = "glowstick_yellow" + /obj/item/device/flashlight/slime gender = PLURAL name = "glowing slime extract" diff --git a/code/game/objects/items/devices/uplink_items.dm b/code/game/objects/items/devices/uplink_items.dm index f9ec0f32dd..bc9666990b 100644 --- a/code/game/objects/items/devices/uplink_items.dm +++ b/code/game/objects/items/devices/uplink_items.dm @@ -446,10 +446,6 @@ datum/uplink_item/dd_SortValue() item_cost = 20 path = /obj/item/weapon/circuitboard/teleporter -/datum/uplink_item/item/tools/teleporter/New() - ..() - antag_roles = list(MODE_MERCENARY) - /datum/uplink_item/item/tools/money name = "Operations Funding" item_cost = 3 @@ -632,7 +628,6 @@ datum/uplink_item/dd_SortValue() /datum/uplink_item/item/badassery/surplus/New() ..() - antag_roles = list(MODE_MERCENARY) desc = "A crate containing [item_worth] telecrystal\s worth of surplus leftovers." /datum/uplink_item/item/badassery/surplus/get_goods(var/obj/item/device/uplink/U, var/loc) @@ -681,7 +676,6 @@ var/image/default_abstract_uplink_icon ..() name = "[command_name()] Update Announcement" desc = "Causes a falsified [command_name()] Update. Triggers immediately after supplying additional data." - antag_roles = list(MODE_MERCENARY) /datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args) command_announcement.Announce(args.["message"], args.["title"]) @@ -692,10 +686,6 @@ var/image/default_abstract_uplink_icon desc = "Creates a fake crew arrival announcement as well as fake crew records, using your current appearance (including held items!) and worn id card. Trigger with care!" item_cost = 4 -/datum/uplink_item/abstract/announcements/fake_crew_arrival/New() - ..() - antag_roles = list(MODE_MERCENARY) - /datum/uplink_item/abstract/announcements/fake_crew_arrival/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args) if(!user) return 0 diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 451b2c41af..c55fd587c0 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -2,8 +2,8 @@ name = "medical pack" singular_name = "medical pack" icon = 'icons/obj/items.dmi' - amount = 5 - max_amount = 5 + amount = 10 + max_amount = 10 w_class = 2 throw_speed = 4 throw_range = 20 @@ -65,24 +65,43 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open == 0) - if(!affecting.bandage()) + if(affecting.is_bandaged()) user << "The wounds on [M]'s [affecting.name] have already been bandaged." return 1 else + user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ + "You start treating [M]'s [affecting.name]." ) + var/used = 0 for (var/datum/wound/W in affecting.wounds) if (W.internal) continue + if(W.bandaged) + continue + if(used == amount) + break + if(!do_mob(user, M, W.damage/5)) + user << "You must stand still to bandage wounds." + break + if (W.current_stage <= W.max_bleeding_stage) - user.visible_message("\The [user] bandages [W.desc] on [M]'s [affecting.name].", \ - "You bandage [W.desc] on [M]'s [affecting.name]." ) + user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \ + "You bandage \a [W.desc] on [M]'s [affecting.name]." ) //H.add_side_effect("Itch") - else if (istype(W,/datum/wound/bruise)) - user.visible_message("\The [user] places a bruise patch over [W.desc] on [M]'s [affecting.name].", \ - "You place a bruise patch over [W.desc] on [M]'s [affecting.name]." ) + else if (W.damage_type == BRUISE) + user.visible_message("\The [user] places a bruise patch over \a [W.desc] on [M]'s [affecting.name].", \ + "You place a bruise patch over \a [W.desc] on [M]'s [affecting.name]." ) else - user.visible_message("\The [user] places a bandaid over [W.desc] on [M]'s [affecting.name].", \ - "You place a bandaid over [W.desc] on [M]'s [affecting.name]." ) - use(1) + user.visible_message("\The [user] places a bandaid over \a [W.desc] on [M]'s [affecting.name].", \ + "You place a bandaid over \a [W.desc] on [M]'s [affecting.name]." ) + W.bandage() + used++ + affecting.update_damages() + if(used == amount) + if(affecting.is_bandaged()) + user << "\The [src] is used up." + else + user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + use(used) else if (can_operate(H)) //Checks if mob is lying down on table for surgery if (do_surgery(H,user,src)) @@ -108,13 +127,19 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open == 0) - if(!affecting.salve()) + if(affecting.is_salved()) user << "The wounds on [M]'s [affecting.name] have already been salved." return 1 else - user.visible_message("[user] salves wounds on [M]'s [affecting.name].", \ - "You salve wounds on [M]'s [affecting.name]." ) + user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ + "You start salving the wounds on [M]'s [affecting.name]." ) + if(!do_mob(user, M, 10)) + user << "You must stand still to salve wounds." + return 1 + user.visible_message("[user] salved wounds on [M]'s [affecting.name].", \ + "You salved wounds on [M]'s [affecting.name]." ) use(1) + affecting.salve() else if (can_operate(H)) //Checks if mob is lying down on table for surgery if (do_surgery(H,user,src)) @@ -127,7 +152,7 @@ singular_name = "advanced trauma kit" desc = "An advanced trauma kit for severe injuries." icon_state = "traumakit" - heal_brute = 12 + heal_brute = 0 origin_tech = list(TECH_BIO = 1) /obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) @@ -139,29 +164,43 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open == 0) - var/bandaged = affecting.bandage() - var/disinfected = affecting.disinfect() - - if(!(bandaged || disinfected)) + if(affecting.is_bandaged() && affecting.is_disinfected()) user << "The wounds on [M]'s [affecting.name] have already been treated." return 1 else + user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ + "You start treating [M]'s [affecting.name]." ) + var/used = 0 for (var/datum/wound/W in affecting.wounds) if (W.internal) continue + if (W.bandaged && W.disinfected) + continue + if(used == amount) + break + if(!do_mob(user, M, W.damage/5)) + user << "You must stand still to bandage wounds." + break if (W.current_stage <= W.max_bleeding_stage) - user.visible_message("\The [user] cleans [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \ - "You clean and seal [W.desc] on [M]'s [affecting.name]." ) - //H.add_side_effect("Itch") - else if (istype(W,/datum/wound/bruise)) - user.visible_message("\The [user] places a medical patch over [W.desc] on [M]'s [affecting.name].", \ - "You place a medical patch over [W.desc] on [M]'s [affecting.name]." ) + user.visible_message("\The [user] cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \ + "You clean and seal \a [W.desc] on [M]'s [affecting.name]." ) + else if (W.damage_type == BRUISE) + user.visible_message("\The [user] places a medical patch over \a [W.desc] on [M]'s [affecting.name].", \ + "You place a medical patch over \a [W.desc] on [M]'s [affecting.name]." ) else - user.visible_message("\The [user] smears some bioglue over [W.desc] on [M]'s [affecting.name].", \ - "You smear some bioglue over [W.desc] on [M]'s [affecting.name]." ) - if (bandaged) - affecting.heal_damage(heal_brute,0) - use(1) + user.visible_message("\The [user] smears some bioglue over \a [W.desc] on [M]'s [affecting.name].", \ + "You smear some bioglue over \a [W.desc] on [M]'s [affecting.name]." ) + W.bandage() + W.disinfect() + W.heal_damage(heal_brute) + used++ + affecting.update_damages() + if(used == amount) + if(affecting.is_bandaged()) + user << "\The [src] is used up." + else + user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + use(used) else if (can_operate(H)) //Checks if mob is lying down on table for surgery if (do_surgery(H,user,src)) @@ -174,7 +213,7 @@ singular_name = "advanced burn kit" desc = "An advanced treatment kit for severe burns." icon_state = "burnkit" - heal_burn = 12 + heal_burn = 0 origin_tech = list(TECH_BIO = 1) @@ -187,14 +226,20 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open == 0) - if(!affecting.salve()) + if(affecting.is_salved()) user << "The wounds on [M]'s [affecting.name] have already been salved." return 1 else + user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ + "You start salving the wounds on [M]'s [affecting.name]." ) + if(!do_mob(user, M, 10)) + user << "You must stand still to salve wounds." + return 1 user.visible_message( "[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.", \ "You cover wounds on [M]'s [affecting.name] with regenerative membrane." ) affecting.heal_damage(0,heal_burn) use(1) + affecting.salve() else if (can_operate(H)) //Checks if mob is lying down on table for surgery if (do_surgery(H,user,src)) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 17e9d35ab9..6d1a2eaa3d 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -68,6 +68,7 @@ icon_state = "emag" item_state = "card-id" origin_tech = list(TECH_MAGNET = 2, TECH_ILLEGAL = 2) + var/default_uses = 10 var/uses = 10 /obj/item/weapon/card/emag/resolve_attackby(atom/A, mob/user) @@ -87,6 +88,12 @@ qdel(src) return 1 +/obj/item/weapon/card/emag/attackby(obj/item/O as obj, mob/user as mob) + if(istype(O, /obj/item/device/telecrystal)) + src.uses += default_uses/2 //Adds half the default amount of uses which is more than you get per TC when buying, as to balance the utility of having multiple emags vs one heavily usable one + usr << "You add \the [O] to \the [src]. Increasing the uses of \the [src] to [uses]." + qdel(O) + /obj/item/weapon/card/id name = "identification card" diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 867dada6d9..9c103a8ed2 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -143,7 +143,8 @@ user << "You begin adding the plating..." - if(!do_after(user,40) || !S.use(2)) + var/amount_to_use = reinf_material ? 1 : 2 + if(!do_after(user,40) || !S.use(amount_to_use)) return 1 //once we've gotten this far don't call parent attackby() if(anchored) @@ -167,7 +168,7 @@ user << "\The [src] is already reinforced." return 0 - if(S.get_amount() < 2) + if(S.get_amount() < 1) user << "There isn't enough material here to reinforce the girder." return 0 @@ -177,7 +178,7 @@ return 0 user << "Now reinforcing..." - if (!do_after(user,40) || !S.use(2)) + if (!do_after(user,40) || !S.use(1)) return 1 //don't call parent attackby() past this point user << "You added reinforcement!" diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index bd95b7f594..369f42fc38 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -69,7 +69,7 @@ var/list/flooring_types name = "carpet" icon_base = "bcarpet" build_type = null - flags = TURF_HAS_EDGES + flags = TURF_HAS_EDGES | TURF_HAS_CORNERS | TURF_REMOVE_CROWBAR | TURF_CAN_BURN /decl/flooring/tiling name = "floor" @@ -186,7 +186,7 @@ var/list/flooring_types icon = 'icons/turf/flooring/circuit.dmi' icon_base = "bcircuit" build_type = null - flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK + flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR can_paint = 1 /decl/flooring/reinforced/circuit/green diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 23ffac6465..ffc2297d02 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -217,8 +217,7 @@ if (istype(W, /obj/item/weapon/wirecutters)) playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) construction_stage = 5 - new /obj/item/stack/rods( src ) - user << "You cut the outer grille." + user << "You cut through the outer grille." update_icon() return if(5) @@ -229,16 +228,13 @@ return construction_stage = 4 update_icon() - user << "You remove the support lines." + user << "You unscrew the support lines." + return + else if (istype(W, /obj/item/weapon/wirecutters)) + construction_stage = 6 + user << "You mend the outer grille." + update_icon() return - else if( istype(W, /obj/item/stack/rods) ) - var/obj/item/stack/O = W - if(O.get_amount()>0) - O.use(1) - construction_stage = 6 - update_icon() - user << "You replace the outer grille." - return if(4) var/cut_cover if(istype(W,/obj/item/weapon/weldingtool)) @@ -261,6 +257,15 @@ update_icon() user << "You press firmly on the cover, dislodging it." return + else if (istype(W, /obj/item/weapon/screwdriver)) + user << "You begin screwing down the support lines." + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) + if(!do_after(user,40) || !istype(src, /turf/simulated/wall) || construction_stage != 4) + return + construction_stage = 5 + update_icon() + user << "You screw down the support lines." + return if(3) if (istype(W, /obj/item/weapon/crowbar)) user << "You struggle to pry off the cover." @@ -299,8 +304,7 @@ return construction_stage = 0 update_icon() - new /obj/item/stack/rods(src) - user << "The support rods drop out as you cut them loose from the frame." + user << "The slice through the support rods." return if(0) if(istype(W, /obj/item/weapon/crowbar)) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 16235a72fc..db48305926 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -162,7 +162,8 @@ reinf_material.place_dismantled_girder(src, reinf_material) else material.place_dismantled_girder(src) - material.place_dismantled_product(src,devastated) + if(!devastated) + material.place_dismantled_product(src) for(var/obj/O in src.contents) //Eject contents! if(istype(O,/obj/structure/sign/poster)) diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 17899026a0..ef9b419d97 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -540,9 +540,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "

" dat += "Language: [current_species.language]
" dat += "" - if(current_species.spawn_flags & CAN_JOIN) + if(current_species.spawn_flags & SPECIES_CAN_JOIN) dat += "
Often present on human stations." - if(current_species.spawn_flags & IS_WHITELISTED) + if(current_species.spawn_flags & SPECIES_IS_WHITELISTED) dat += "
Whitelist restricted." if(!current_species.has_organ[O_HEART]) dat += "
Does not have a circulatory system." @@ -570,9 +570,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O var/restricted = 0 if(config.usealienwhitelist) //If we're using the whitelist, make sure to check it! - if(!(current_species.spawn_flags & CAN_JOIN)) + if(!(current_species.spawn_flags & SPECIES_CAN_JOIN)) restricted = 2 - else if((current_species.spawn_flags & IS_WHITELISTED) && !is_alien_whitelisted(preference_mob(),current_species)) + else if((current_species.spawn_flags & SPECIES_IS_WHITELISTED) && !is_alien_whitelisted(preference_mob(),current_species)) restricted = 1 if(restricted) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index a9f52a0d2b..f99f77a59a 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -116,6 +116,7 @@ datum/preferences var/communicator_visibility = 0 var/datum/category_collection/player_setup_collection/player_setup + var/datum/browser/panel /datum/preferences/New(client/C) player_setup = new(src) @@ -383,7 +384,11 @@ datum/preferences dat += "
" dat += "" - user << browse(dat, "window=saves;size=300x390") + //user << browse(dat, "window=saves;size=300x390") + panel = new(user, "Character Slots", "Character Slots", 300, 390, src) + panel.set_content(dat) + panel.open() /datum/preferences/proc/close_load_dialog(mob/user) - user << browse(null, "window=saves") \ No newline at end of file + //user << browse(null, "window=saves") + panel.close() \ No newline at end of file diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 88ef03dda2..8c6fd55c69 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -337,11 +337,11 @@ overlays |= light_overlay_cache["[light_overlay]_icon"] // Generate and cache the on-mob icon, which is used in update_inv_head(). - var/cache_key = "[light_overlay][H ? "_[H.species.get_bodytype()]" : ""]" + var/cache_key = "[light_overlay][H ? "_[H.species.get_bodytype(H)]" : ""]" if(!light_overlay_cache[cache_key]) var/use_icon = 'icons/mob/light_overlays.dmi' - if(H && sprite_sheets[H.species.get_bodytype()]) - use_icon = sprite_sheets[H.species.get_bodytype()] + if(H && sprite_sheets[H.species.get_bodytype(H)]) + use_icon = sprite_sheets[H.species.get_bodytype(H)] light_overlay_cache[cache_key] = image("icon" = use_icon, "icon_state" = "[light_overlay]") if(H) @@ -535,8 +535,8 @@ var/icon/under_icon if(icon_override) under_icon = icon_override - else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype()]) - under_icon = sprite_sheets[H.species.get_bodytype()] + else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype(H)]) + under_icon = sprite_sheets[H.species.get_bodytype(H)] else if(item_icons && item_icons[slot_w_uniform_str]) under_icon = item_icons[slot_w_uniform_str] else @@ -558,8 +558,8 @@ var/icon/under_icon if(icon_override) under_icon = icon_override - else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype()]) - under_icon = sprite_sheets[H.species.get_bodytype()] + else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype(H)]) + under_icon = sprite_sheets[H.species.get_bodytype(H)] else if(item_icons && item_icons[slot_w_uniform_str]) under_icon = item_icons[slot_w_uniform_str] else diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index ba50f29cf5..26d7de9082 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -472,8 +472,8 @@ var/species_icon = 'icons/mob/rig_back.dmi' // Since setting mob_icon will override the species checks in // update_inv_wear_suit(), handle species checks here. - if(wearer && sprite_sheets && sprite_sheets[wearer.species.get_bodytype()]) - species_icon = sprite_sheets[wearer.species.get_bodytype()] + if(wearer && sprite_sheets && sprite_sheets[wearer.species.get_bodytype(wearer)]) + species_icon = sprite_sheets[wearer.species.get_bodytype(wearer)] mob_icon = image("icon" = species_icon, "icon_state" = "[icon_state]") if(installed_modules.len) diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 70f69be834..920b751117 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -195,9 +195,8 @@ var/list/name_to_material // General wall debris product placement. // Not particularly necessary aside from snowflakey cult girders. -/material/proc/place_dismantled_product(var/turf/target,var/is_devastated) - for(var/x=1;x<(is_devastated?2:3);x++) - place_sheet(target) +/material/proc/place_dismantled_product(var/turf/target) + place_sheet(target) // Debris product. Used ALL THE TIME. /material/proc/place_sheet(var/turf/target) diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index ac63e4e582..dc8dbccb01 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -138,7 +138,7 @@ var/list/holder_mob_icon_cache = list() var/skin_colour = rgb(owner.r_skin, owner.g_skin, owner.b_skin) var/hair_colour = rgb(owner.r_hair, owner.g_hair, owner.b_hair) var/eye_colour = rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes) - var/species_name = lowertext(owner.species.get_bodytype()) + var/species_name = lowertext(owner.species.get_bodytype(owner)) for(var/cache_entry in generate_for_slots) var/cache_key = "[owner.species]-[cache_entry]-[skin_colour]-[hair_colour]" diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 823ac808ec..c3813000bb 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -143,13 +143,13 @@ var/datum/species/current_species = all_species[current_species_name] if(check_whitelist && config.usealienwhitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it! - if(!(current_species.spawn_flags & CAN_JOIN)) + if(!(current_species.spawn_flags & SPECIES_CAN_JOIN)) continue if(whitelist.len && !(current_species_name in whitelist)) continue if(blacklist.len && (current_species_name in blacklist)) continue - if((current_species.spawn_flags & IS_WHITELISTED) && !is_alien_whitelisted(src, current_species_name)) + if((current_species.spawn_flags & SPECIES_IS_WHITELISTED) && !is_alien_whitelisted(src, current_species_name)) continue valid_species += current_species_name @@ -158,9 +158,9 @@ /mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1) - var/use_species = species.get_bodytype() + var/use_species = species.get_bodytype(src) var/obj/item/organ/external/head/H = get_organ(BP_HEAD) - if(H) use_species = H.species.get_bodytype() + if(H) use_species = H.species.get_bodytype(src) var/list/valid_hairstyles = new() for(var/hairstyle in hair_styles_list) @@ -180,9 +180,9 @@ /mob/living/carbon/human/proc/generate_valid_facial_hairstyles() - var/use_species = species.get_bodytype() + var/use_species = species.get_bodytype(src) var/obj/item/organ/external/head/H = get_organ(BP_HEAD) - if(H) use_species = H.species.get_bodytype() + if(H) use_species = H.species.get_bodytype(src) var/list/valid_facial_hairstyles = new() for(var/facialhairstyle in facial_hair_styles_list) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 00d02651b7..f9f423de68 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -51,7 +51,12 @@ msg += ", [use_gender]!" else if(species.name != "Human") - msg += ", \a [species.name]!" + msg += ", \a [species.get_examine_name()]!" + + var/extra_species_text = species.get_additional_examine_text(src) + if(extra_species_text) + msg += "[extra_species_text]
" + msg += "
" //uniform diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0c11ada074..56482186b4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -326,11 +326,19 @@ //Removed the horrible safety parameter. It was only being used by ninja code anyways. //Now checks siemens_coefficient of the affected area by default /mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null) + if(status_flags & GODMODE) return 0 //godmode if (!def_zone) def_zone = pick("l_hand", "r_hand") + if(species.siemens_coefficient == -1) + if(stored_shock_by_ref["\ref[src]"]) + stored_shock_by_ref["\ref[src]"] += shock_damage + else + stored_shock_by_ref["\ref[src]"] = shock_damage + return + var/obj/item/organ/external/affected_organ = get_organ(check_zone(def_zone)) var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1c09c04c70..cfb5058c0a 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -92,7 +92,7 @@ emp_act if (!def_zone) return 1.0 - var/siemens_coefficient = species.siemens_coefficient + var/siemens_coefficient = max(species.siemens_coefficient,0) var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? for(var/obj/item/clothing/C in clothing_items) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 1114979ffe..61540e990f 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -241,7 +241,13 @@ radiation = Clamp(radiation,0,100) - if (radiation) + if(!radiation) + if(species.appearance_flags & RADIATION_GLOWS) + set_light(0) + else + if(species.appearance_flags & RADIATION_GLOWS) + set_light(max(1,min(10,radiation/10)), max(1,min(20,radiation/20)), species.get_flesh_colour(src)) + // END DOGSHIT SNOWFLAKE var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in internal_organs if(rad_organ && !rad_organ.is_broken()) diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index ba7d4d1d0a..58a967c809 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -19,7 +19,7 @@ death_message = "dissolves into ash..." flags = NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT - spawn_flags = IS_RESTRICTED + spawn_flags = SPECIES_IS_RESTRICTED genders = list(NEUTER) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index e9c63918c5..25a8149e48 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -21,10 +21,12 @@ var/prone_icon // If set, draws this from icobase when mob is prone. var/blood_color = "#A10808" // Red. var/flesh_color = "#FFC896" // Pink. - var/base_color // Used by changelings. Should also be used for icon previes.. + var/base_color // Used by changelings. Should also be used for icon previews. + var/tail // Name of tail state in species effects icon file. var/tail_animation // If set, the icon to obtain tail animation states from. var/tail_hair + var/race_key = 0 // Used for mob icon cache string. var/icon/icon_template // Used for mob icon generation for non-32x32 species. var/mob_size = MOB_MEDIUM @@ -175,71 +177,9 @@ inherent_verbs = list() inherent_verbs |= /mob/living/carbon/human/proc/regurgitate -/datum/species/proc/get_station_variant() - return name - -/datum/species/proc/get_bodytype() - return name - -/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H) - return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message) - -/datum/species/proc/get_death_message(var/mob/living/carbon/human/H) - if(config.show_human_death_message) - return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message) - else - return "no message" - -/datum/species/proc/get_ssd(var/mob/living/carbon/human/H) - return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd) - -/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H) - return ((H && H.isSynthetic()) ? SYNTH_BLOOD_COLOUR : blood_color) - -/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H) - return ((H && H.isSynthetic()) ? 1 : virus_immune) - -/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H) - return ((H && H.isSynthetic()) ? SYNTH_FLESH_COLOUR : flesh_color) - -/datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type) - - if(!prob(5)) - return - - var/covered = 0 // Basic coverage can help. - for(var/obj/item/clothing/clothes in H) - if(H.item_is_in_hands(clothes)) - continue - if((clothes.body_parts_covered & UPPER_TORSO) && (clothes.body_parts_covered & LOWER_TORSO)) - covered = 1 - break - - switch(msg_type) - if("cold") - if(!covered) - H << "[pick(cold_discomfort_strings)]" - if("heat") - if(covered) - H << "[pick(heat_discomfort_strings)]" - /datum/species/proc/sanitize_name(var/name) return sanitizeName(name) -/datum/species/proc/get_random_name(var/gender) - if(!name_language) - if(gender == FEMALE) - return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) - else - return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - - var/datum/language/species_language = all_languages[name_language] - if(!species_language) - species_language = all_languages[default_language] - if(!species_language) - return "unknown" - return species_language.get_random_name(gender) - /datum/species/proc/equip_survival_gear(var/mob/living/carbon/human/H,var/extendedtank = 1) if(H.backbag == 1) if (extendedtank) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) @@ -351,6 +291,3 @@ // Called in life() when the mob has no client. /datum/species/proc/handle_npc(var/mob/living/carbon/human/H) return - -/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H) - return vision_flags diff --git a/code/modules/mob/living/carbon/human/species/species_attack.dm b/code/modules/mob/living/carbon/human/species/species_attack.dm index cd4ca21e00..018dbafa84 100644 --- a/code/modules/mob/living/carbon/human/species/species_attack.dm +++ b/code/modules/mob/living/carbon/human/species/species_attack.dm @@ -67,9 +67,9 @@ attack_noun = list("body") damage = 2 -/datum/unarmed_attack/slime_glomp/apply_effects() - //Todo, maybe have a chance of causing an electrical shock? - return +/datum/unarmed_attack/slime_glomp/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone) + ..() + user.apply_stored_shock_to(target) /datum/unarmed_attack/stomp/weak attack_verb = list("jumped on") diff --git a/code/modules/mob/living/carbon/human/species/species_getters.dm b/code/modules/mob/living/carbon/human/species/species_getters.dm new file mode 100644 index 0000000000..625d555943 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/species_getters.dm @@ -0,0 +1,97 @@ +/datum/species/proc/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H) + return list() + +/datum/species/proc/get_additional_examine_text(var/mob/living/carbon/human/H) + return + +/datum/species/proc/get_tail(var/mob/living/carbon/human/H) + return tail + +/datum/species/proc/get_tail_animation(var/mob/living/carbon/human/H) + return tail_animation + +/datum/species/proc/get_tail_hair(var/mob/living/carbon/human/H) + return tail_hair + +/datum/species/proc/get_blood_mask(var/mob/living/carbon/human/H) + return blood_mask + +/datum/species/proc/get_damage_overlays(var/mob/living/carbon/human/H) + return damage_overlays + +/datum/species/proc/get_damage_mask(var/mob/living/carbon/human/H) + return damage_mask + +/datum/species/proc/get_examine_name(var/mob/living/carbon/human/H) + return name + +/datum/species/proc/get_icobase(var/mob/living/carbon/human/H, var/get_deform) + return (get_deform ? deform : icobase) + +/datum/species/proc/get_station_variant() + return name + +/datum/species/proc/get_race_key(var/mob/living/carbon/human/H) + return race_key + +/datum/species/proc/get_bodytype(var/mob/living/carbon/human/H) + return name + +/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message) + +/datum/species/proc/get_death_message(var/mob/living/carbon/human/H) + if(config.show_human_death_message) + return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message) + else + return "no message" + +/datum/species/proc/get_ssd(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd) + +/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? SYNTH_BLOOD_COLOUR : blood_color) + +/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? 1 : virus_immune) + +/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? SYNTH_FLESH_COLOUR : flesh_color) + +/datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type) + + if(!prob(5)) + return + + var/covered = 0 // Basic coverage can help. + for(var/obj/item/clothing/clothes in H) + if(H.item_is_in_hands(clothes)) + continue + if((clothes.body_parts_covered & UPPER_TORSO) && (clothes.body_parts_covered & LOWER_TORSO)) + covered = 1 + break + + switch(msg_type) + if("cold") + if(!covered) + H << "[pick(cold_discomfort_strings)]" + if("heat") + if(covered) + H << "[pick(heat_discomfort_strings)]" + +/datum/species/proc/get_random_name(var/gender) + if(!name_language) + if(gender == FEMALE) + return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) + else + return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) + + var/datum/language/species_language = all_languages[name_language] + if(!species_language) + species_language = all_languages[default_language] + if(!species_language) + return "unknown" + return species_language.get_random_name(gender) + +/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H) + return vision_flags diff --git a/code/modules/mob/living/carbon/human/species/species_helpers.dm b/code/modules/mob/living/carbon/human/species/species_helpers.dm new file mode 100644 index 0000000000..3152312f1c --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/species_helpers.dm @@ -0,0 +1,6 @@ +var/list/stored_shock_by_ref = list() + +/mob/living/proc/apply_stored_shock_to(var/mob/living/target) + if(stored_shock_by_ref["\ref[src]"]) + target.electrocute_act(stored_shock_by_ref["\ref[src]"]*0.9, src) + stored_shock_by_ref["\ref[src]"] = 0 diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm new file mode 100644 index 0000000000..293df93215 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -0,0 +1,187 @@ +// This is something of an intermediary species used for species that +// need to emulate the appearance of another race. Currently it is only +// used for slimes but it may be useful for changelings later. +var/list/wrapped_species_by_ref = list() + +/datum/species/shapeshifter + + inherent_verbs = list( + /mob/living/carbon/human/proc/shapeshifter_select_shape, + /mob/living/carbon/human/proc/shapeshifter_select_hair, + /mob/living/carbon/human/proc/shapeshifter_select_gender + ) + + var/list/valid_transform_species = list() + var/monochromatic + var/default_form = "Human" + +/datum/species/shapeshifter/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H) + return valid_transform_species + +/datum/species/shapeshifter/get_icobase(var/mob/living/carbon/human/H, var/get_deform) + if(!H) return ..(null, get_deform) + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_icobase(H, get_deform) + +/datum/species/shapeshifter/get_race_key(var/mob/living/carbon/human/H) + return "[..()]-[wrapped_species_by_ref["\ref[H]"]]" + +/datum/species/shapeshifter/get_bodytype(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_bodytype(H) + +/datum/species/shapeshifter/get_blood_mask(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_blood_mask(H) + +/datum/species/shapeshifter/get_damage_mask(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_damage_mask(H) + +/datum/species/shapeshifter/get_damage_overlays(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_damage_overlays(H) + +/datum/species/shapeshifter/get_tail(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_tail(H) + +/datum/species/shapeshifter/get_tail_animation(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_tail_animation(H) + +/datum/species/shapeshifter/get_tail_hair(var/mob/living/carbon/human/H) + if(!H) return ..() + var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]] + return S.get_tail_hair(H) + +/datum/species/shapeshifter/handle_post_spawn(var/mob/living/carbon/human/H) + ..() + wrapped_species_by_ref["\ref[H]"] = default_form + if(monochromatic) + H.r_hair = H.r_skin + H.g_hair = H.g_skin + H.b_hair = H.b_skin + H.r_facial = H.r_skin + H.g_facial = H.g_skin + H.b_facial = H.b_skin + + for(var/obj/item/organ/external/E in H.organs) + E.sync_colour_to_human(H) + +// Verbs follow. +/mob/living/carbon/human/proc/shapeshifter_select_hair() + + set name = "Select Hair" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 10 + + var/list/valid_hairstyles = list() + var/list/valid_facialhairstyles = list() + for(var/hairstyle in hair_styles_list) + var/datum/sprite_accessory/S = hair_styles_list[hairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if(!(species.get_bodytype(src) in S.species_allowed)) + continue + valid_hairstyles += hairstyle + for(var/facialhairstyle in facial_hair_styles_list) + var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if(!(species.get_bodytype(src) in S.species_allowed)) + continue + valid_facialhairstyles += facialhairstyle + + + visible_message("\The [src]'s form contorts subtly.") + if(valid_hairstyles.len) + var/new_hair = input("Select a hairstyle.", "Shapeshifter Hair") as null|anything in valid_hairstyles + change_hair(new_hair ? new_hair : "Bald") + if(valid_facialhairstyles.len) + var/new_hair = input("Select a facial hair style.", "Shapeshifter Hair") as null|anything in valid_facialhairstyles + change_facial_hair(new_hair ? new_hair : "Shaved") + +/mob/living/carbon/human/proc/shapeshifter_select_gender() + + set name = "Select Gender" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 50 + + var/new_gender = input("Please select a gender.", "Shapeshifter Gender") as null|anything in list(FEMALE, MALE, NEUTER, PLURAL) + if(!new_gender) + return + + visible_message("\The [src]'s form contorts subtly.") + change_gender(new_gender) + +/mob/living/carbon/human/proc/shapeshifter_select_shape() + + set name = "Select Body Shape" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 50 + + var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + if(!new_species || !all_species[new_species] || wrapped_species_by_ref["\ref[src]"] == new_species) + return + + wrapped_species_by_ref["\ref[src]"] = new_species + visible_message("\The [src] shifts and contorts, taking the form of \a [new_species]!") + regenerate_icons() + +/mob/living/carbon/human/proc/shapeshifter_select_colour() + + set name = "Select Body Colour" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 50 + + var/new_skin = input("Please select a new body color.", "Shapeshifter Colour") as color + if(!new_skin) + return + shapeshifter_set_colour(new_skin) + +/mob/living/carbon/human/proc/shapeshifter_set_colour(var/new_skin) + + r_skin = hex2num(copytext(new_skin, 2, 4)) + g_skin = hex2num(copytext(new_skin, 4, 6)) + b_skin = hex2num(copytext(new_skin, 6, 8)) + + var/datum/species/shapeshifter/S = species + if(S.monochromatic) + r_hair = r_skin + g_hair = g_skin + b_hair = b_skin + r_facial = r_skin + g_facial = g_skin + b_facial = b_skin + + for(var/obj/item/organ/external/E in organs) + E.sync_colour_to_human(src) + + regenerate_icons() diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index 83d5f6f8f0..bccafdde14 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -8,7 +8,7 @@ language = "Sol Common" //todo? unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch) flags = NO_PAIN | NO_SCAN | NO_POISON | NO_MINOR_CUT - spawn_flags = IS_RESTRICTED + spawn_flags = SPECIES_IS_RESTRICTED siemens_coefficient = 0 breath_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm index 85890f4de6..6074934cec 100644 --- a/code/modules/mob/living/carbon/human/species/station/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm @@ -30,7 +30,7 @@ brute_mod = 1.5 burn_mod = 1.5 - spawn_flags = IS_RESTRICTED + spawn_flags = SPECIES_IS_RESTRICTED bump_flag = MONKEY swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm new file mode 100644 index 0000000000..2ada0dd7c7 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -0,0 +1,188 @@ +var/datum/species/shapeshifter/promethean/prometheans + +// Species definition follows. +/datum/species/shapeshifter/promethean + + name = "Promethean" + name_plural = "Prometheans" + blurb = "What has Science done?" + show_ssd = "totally quiescent" + death_message = "rapidly loses cohesion, splattering across the ground..." + knockout_message = "collapses inwards, forming a disordered puddle of goo." + remains_type = /obj/effect/decal/cleanable/ash + + blood_color = "#05FF9B" + flesh_color = "#05FFFB" + + hunger_factor = DEFAULT_HUNGER_FACTOR //todo + reagent_tag = IS_SLIME + mob_size = MOB_SMALL + bump_flag = SLIME + swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL + push_flags = MONKEY|SLIME|SIMPLE_ANIMAL + flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT + appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | RADIATION_GLOWS + spawn_flags = SPECIES_IS_RESTRICTED + + breath_type = null + poison_type = null + + gluttonous = 2 + virus_immune = 1 + blood_volume = 600 + min_age = 1 + max_age = 5 + brute_mod = 0.5 + burn_mod = 2 + oxy_mod = 0 + total_health = 120 + + cold_level_1 = 260 + cold_level_2 = 200 + cold_level_3 = 120 + + heat_level_1 = 360 + heat_level_2 = 400 + heat_level_3 = 1000 + + body_temperature = 310.15 + + siemens_coefficient = -1 + rarity_value = 5 + + unarmed_types = list(/datum/unarmed_attack/slime_glomp) + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime) // Slime core. + has_limbs = list( + BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/slime), + BP_GROIN = list("path" = /obj/item/organ/external/groin/unbreakable/slime), + BP_HEAD = list("path" = /obj/item/organ/external/head/unbreakable/slime), + BP_L_ARM = list("path" = /obj/item/organ/external/arm/unbreakable/slime), + BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/unbreakable/slime), + BP_L_LEG = list("path" = /obj/item/organ/external/leg/unbreakable/slime), + BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/unbreakable/slime), + BP_L_HAND = list("path" = /obj/item/organ/external/hand/unbreakable/slime), + BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/unbreakable/slime), + BP_L_FOOT = list("path" = /obj/item/organ/external/foot/unbreakable/slime), + BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/unbreakable/slime) + ) + heat_discomfort_strings = list("You feel too warm.") + cold_discomfort_strings = list("You feel too cool.") + + inherent_verbs = list( + /mob/living/carbon/human/proc/shapeshifter_select_shape, + /mob/living/carbon/human/proc/shapeshifter_select_colour, + /mob/living/carbon/human/proc/shapeshifter_select_hair, + /mob/living/carbon/human/proc/shapeshifter_select_gender + ) + + valid_transform_species = list("Human", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey") + monochromatic = 1 + + var/heal_rate = 5 // Temp. Regen per tick. + +/datum/species/shapeshifter/promethean/New() + ..() + prometheans = src + +/datum/species/shapeshifter/promethean/equip_survival_gear(var/mob/living/carbon/human/H) + var/boxtype = pick(typesof(/obj/item/weapon/storage/toolbox/lunchbox)) + var/obj/item/weapon/storage/toolbox/lunchbox/L = new boxtype(get_turf(H)) + var/mob/living/simple_animal/mouse/mouse = new (L) + var/obj/item/weapon/holder/holder = new (L) + mouse.forceMove(holder) + holder.sync(mouse) + if(H.backbag == 1) + H.equip_to_slot_or_del(L, slot_r_hand) + else + H.equip_to_slot_or_del(L, slot_in_backpack) + +/datum/species/shapeshifter/promethean/hug(var/mob/living/carbon/human/H,var/mob/living/target) + + var/t_him = "them" + switch(target.gender) + if(MALE) + t_him = "him" + if(FEMALE) + t_him = "her" + + H.visible_message("\The [H] glomps [target] to make [t_him] feel better!", \ + "You glomps [target] to make [t_him] feel better!") + H.apply_stored_shock_to(target) + +/datum/species/shapeshifter/promethean/handle_death(var/mob/living/carbon/human/H) + spawn(1) + if(H) + H.gib() + +/datum/species/shapeshifter/promethean/handle_environment_special(var/mob/living/carbon/human/H) + + var/turf/T = H.loc + if(istype(T)) + var/obj/effect/decal/cleanable/C = locate() in T + if(C) + qdel(C) + //TODO: gain nutriment + + // Regenerate limbs and heal damage if we have any. Copied from Bay xenos code. + + // Theoretically the only internal organ a slime will have + // is the slime core. but we might as well be thorough. + for(var/obj/item/organ/I in H.internal_organs) + if(I.damage > 0) + I.damage = max(I.damage - heal_rate, 0) + if (prob(5)) + H << "You feel a soothing sensation within your [I.name]..." + return 1 + + // Replace completely missing limbs. + for(var/limb_type in has_limbs) + var/obj/item/organ/external/E = H.organs_by_name[limb_type] + if(E && (E.is_stump() || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED)))) + E.removed() + qdel(E) + E = null + if(!E) + var/list/organ_data = has_limbs[limb_type] + var/limb_path = organ_data["path"] + var/obj/item/organ/O = new limb_path(H) + organ_data["descriptor"] = O.name + H << "You feel a slithering sensation as your [O.name] reforms." + H.update_body() + return 1 + + // Heal remaining damage. + if (H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss()) + H.adjustBruteLoss(-heal_rate) + H.adjustFireLoss(-heal_rate) + H.adjustOxyLoss(-heal_rate) + H.adjustToxLoss(-heal_rate) + return 1 + +/datum/species/shapeshifter/promethean/get_blood_colour(var/mob/living/carbon/human/H) + return (H ? rgb(H.r_skin, H.g_skin, H.b_skin) : ..()) + +/datum/species/shapeshifter/promethean/get_flesh_colour(var/mob/living/carbon/human/H) + return (H ? rgb(H.r_skin, H.g_skin, H.b_skin) : ..()) + +/datum/species/shapeshifter/promethean/get_additional_examine_text(var/mob/living/carbon/human/H) + + if(!stored_shock_by_ref["\ref[H]"]) + return + + var/t_she = "She is" + if(H.gender == MALE) + t_she = "He is" + else if(H.gender == PLURAL) + t_she = "They are" + else if(H.gender == NEUTER) + t_she = "It is" + + switch(stored_shock_by_ref["\ref[H]"]) + if(1 to 10) + return "[t_she] flickering gently with a little electrical activity." + if(11 to 20) + return "[t_she] glowing gently with moderate levels of electrical activity.\n" + if(21 to 35) + return "[t_she] glowing brightly with high levels of electrical activity." + if(35 to INFINITY) + return "[t_she] radiating massive levels of electrical activity!" diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 2f931a38f7..27541c2773 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -36,7 +36,7 @@ blood_volume = 400 hunger_factor = 0.2 - spawn_flags = CAN_JOIN | IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR bump_flag = MONKEY swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL diff --git a/code/modules/mob/living/carbon/human/species/station/slime.dm b/code/modules/mob/living/carbon/human/species/station/slime.dm deleted file mode 100644 index 769b1a2f35..0000000000 --- a/code/modules/mob/living/carbon/human/species/station/slime.dm +++ /dev/null @@ -1,52 +0,0 @@ -/datum/species/slime - name = "Slime" - name_plural = "slimes" - mob_size = MOB_SMALL - - icobase = 'icons/mob/human_races/r_slime.dmi' - deform = 'icons/mob/human_races/r_slime.dmi' - - language = null //todo? - unarmed_types = list(/datum/unarmed_attack/slime_glomp) - flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT - spawn_flags = IS_RESTRICTED - siemens_coefficient = 3 //conductive - darksight = 3 - - blood_color = "#05FF9B" - flesh_color = "#05FFFB" - - remains_type = /obj/effect/decal/cleanable/ash - death_message = "rapidly loses cohesion, splattering across the ground..." - - has_organ = list( - "brain" = /obj/item/organ/internal/brain/slime - ) - - breath_type = null - poison_type = null - - bump_flag = SLIME - swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL - push_flags = MONKEY|SLIME|SIMPLE_ANIMAL - - has_limbs = list( - BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable), - BP_GROIN = list("path" = /obj/item/organ/external/groin/unbreakable), - BP_HEAD = list("path" = /obj/item/organ/external/head/unbreakable), - BP_L_ARM = list("path" = /obj/item/organ/external/arm/unbreakable), - BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/unbreakable), - BP_L_LEG = list("path" = /obj/item/organ/external/leg/unbreakable), - BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/unbreakable), - BP_L_HAND = list("path" = /obj/item/organ/external/hand/unbreakable), - BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/unbreakable), - BP_L_FOOT = list("path" = /obj/item/organ/external/foot/unbreakable), - BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/unbreakable) - ) - - genders = list(NEUTER) - -/datum/species/slime/handle_death(var/mob/living/carbon/human/H) - spawn(1) - if(H) - H.gib() diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index d3e3a314bc..246b684ca4 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -14,10 +14,10 @@ min_age = 17 max_age = 110 - spawn_flags = CAN_JOIN + spawn_flags = SPECIES_CAN_JOIN appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR -/datum/species/human/get_bodytype() +/datum/species/human/get_bodytype(var/mob/living/carbon/human/H) return "Human" /datum/species/unathi @@ -54,7 +54,7 @@ heat_level_2 = 480 //Default 400 heat_level_3 = 1100 //Default 1000 - spawn_flags = CAN_JOIN | IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR flesh_color = "#34AF10" @@ -116,7 +116,7 @@ primitive_form = "Farwa" - spawn_flags = CAN_JOIN | IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR flesh_color = "#AFA59E" @@ -155,7 +155,7 @@ min_age = 19 max_age = 80 - spawn_flags = CAN_JOIN | IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR flesh_color = "#8CD7A3" @@ -246,7 +246,7 @@ body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not flags = NO_SCAN | IS_PLANT | NO_PAIN | NO_SLIP | NO_MINOR_CUT - spawn_flags = CAN_JOIN | IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED blood_color = "#004400" flesh_color = "#907E4A" diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 22329cf2be..b313ae0d8a 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -174,9 +174,6 @@ var/global/list/damage_icon_parts = list() for(var/obj/item/organ/external/O in organs) if(O.is_stump()) continue - //if(O.status & ORGAN_DESTROYED) damage_appearance += "d" //what is this? - //else - // damage_appearance += O.damage_state damage_appearance += O.damage_state if(damage_appearance == previous_damage_appearance) @@ -194,15 +191,14 @@ var/global/list/damage_icon_parts = list() if(O.is_stump()) continue - O.update_icon() if(O.damage_state == "00") continue var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]" + var/cache_index = "[O.damage_state]/[O.icon_name]/[species.get_blood_colour(src)]/[species.get_bodytype(src)]" if(damage_icon_parts[cache_index] == null) - DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human - DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels - DI.Blend(species.blood_color, ICON_MULTIPLY) + DI = new /icon(species.get_damage_overlays(src), O.damage_state) // the damage icon for whole human + DI.Blend(new /icon(species.get_damage_mask(src), O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels + DI.Blend(species.get_blood_colour(src), ICON_MULTIPLY) damage_icon_parts[cache_index] = DI else DI = damage_icon_parts[cache_index] @@ -236,7 +232,7 @@ var/global/list/damage_icon_parts = list() if(gender == FEMALE) g = "female" - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]" + var/icon_key = "[species.get_race_key(src)][g][s_tone][r_skin][g_skin][b_skin]" if(lip_style) icon_key += "[lip_style]" else @@ -258,7 +254,7 @@ var/global/list/damage_icon_parts = list() else icon_key += "1" if(part) - icon_key += "[part.species.race_key]" + icon_key += "[part.species.get_race_key(part.owner)]" icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" if(part.s_col && part.s_col.len >= 3) @@ -357,7 +353,7 @@ var/global/list/damage_icon_parts = list() if(f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (src.species.get_bodytype() in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (src.species.get_bodytype(src) in facial_hair_style.species_allowed)) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) @@ -366,7 +362,7 @@ var/global/list/damage_icon_parts = list() if(h_style && !(head && (head.flags_inv & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style && (src.species.get_bodytype() in hair_style.species_allowed)) + if(hair_style && (src.species.get_bodytype(src) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) @@ -378,6 +374,8 @@ var/global/list/damage_icon_parts = list() if (ears_s) face_standing.Blend(ears_s, ICON_OVERLAY) // VOREStation Edit - END + if(head_organ.nonsolid) + face_standing += rgb(,,,120) overlays_standing[HAIR_LAYER] = image(face_standing) @@ -470,8 +468,8 @@ var/global/list/damage_icon_parts = list() var/icon/under_icon if(w_uniform.icon_override) under_icon = w_uniform.icon_override - else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.get_bodytype()]) - under_icon = w_uniform.sprite_sheets[species.get_bodytype()] + else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.get_bodytype(src)]) + under_icon = w_uniform.sprite_sheets[species.get_bodytype(src)] else if(w_uniform.item_icons && w_uniform.item_icons[slot_w_uniform_str]) under_icon = w_uniform.item_icons[slot_w_uniform_str] else @@ -492,7 +490,7 @@ var/global/list/damage_icon_parts = list() //apply blood overlay if(w_uniform.blood_DNA) - var/image/bloodsies = image(icon = species.blood_mask, icon_state = "uniformblood") + var/image/bloodsies = image(icon = species.get_blood_mask(src), icon_state = "uniformblood") bloodsies.color = w_uniform.blood_color standing.overlays += bloodsies @@ -516,8 +514,8 @@ var/global/list/damage_icon_parts = list() var/image/standing if(wear_id.icon_override) standing = image("icon" = wear_id.icon_override, "icon_state" = "[icon_state]") - else if(wear_id.sprite_sheets && wear_id.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = wear_id.sprite_sheets[species.get_bodytype()], "icon_state" = "[icon_state]") + else if(wear_id.sprite_sheets && wear_id.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = wear_id.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[icon_state]") else standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") overlays_standing[ID_LAYER] = standing @@ -539,13 +537,13 @@ var/global/list/damage_icon_parts = list() var/image/standing if(gloves.icon_override) standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]") - else if(gloves.sprite_sheets && gloves.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = gloves.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_state]") + else if(gloves.sprite_sheets && gloves.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = gloves.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_state]") else standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]") if(gloves.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "bloodyhands") bloodsies.color = gloves.blood_color standing.overlays += bloodsies gloves.screen_loc = ui_gloves @@ -553,7 +551,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[GLOVES_LAYER] = standing else if(blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "bloodyhands") bloodsies.color = hand_blood_color overlays_standing[GLOVES_LAYER] = bloodsies else @@ -566,8 +564,8 @@ var/global/list/damage_icon_parts = list() if(glasses.icon_override) overlays_standing[GLASSES_LAYER] = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") - else if(glasses.sprite_sheets && glasses.sprite_sheets[species.get_bodytype()]) - overlays_standing[GLASSES_LAYER]= image("icon" = glasses.sprite_sheets[species.get_bodytype()], "icon_state" = "[glasses.icon_state]") + else if(glasses.sprite_sheets && glasses.sprite_sheets[species.get_bodytype(src)]) + overlays_standing[GLASSES_LAYER]= image("icon" = glasses.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[glasses.icon_state]") else overlays_standing[GLASSES_LAYER]= image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") @@ -588,9 +586,9 @@ var/global/list/damage_icon_parts = list() if(l_ear.icon_override) t_type = "[t_type]_l" overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]") - else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.get_bodytype()]) + else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.get_bodytype(src)]) t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") @@ -600,9 +598,9 @@ var/global/list/damage_icon_parts = list() if(r_ear.icon_override) t_type = "[t_type]_r" overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]") - else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.get_bodytype()]) + else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.get_bodytype(src)]) t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") @@ -616,20 +614,20 @@ var/global/list/damage_icon_parts = list() var/image/standing if(shoes.icon_override) standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]") - else if(shoes.sprite_sheets && shoes.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = shoes.sprite_sheets[species.get_bodytype()], "icon_state" = "[shoes.icon_state]") + else if(shoes.sprite_sheets && shoes.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = shoes.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[shoes.icon_state]") else standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]") if(shoes.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color standing.overlays += bloodsies standing.color = shoes.color overlays_standing[SHOES_LAYER] = standing else if(feet_blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") bloodsies.color = feet_blood_color overlays_standing[SHOES_LAYER] = bloodsies else @@ -655,8 +653,8 @@ var/global/list/damage_icon_parts = list() var/t_icon if(head.icon_override) t_icon = head.icon_override - else if(head.sprite_sheets && head.sprite_sheets[species.get_bodytype()]) - t_icon = head.sprite_sheets[species.get_bodytype()] + else if(head.sprite_sheets && head.sprite_sheets[species.get_bodytype(src)]) + t_icon = head.sprite_sheets[species.get_bodytype(src)] else if(head.item_icons && (slot_head_str in head.item_icons)) t_icon = head.item_icons[slot_head_str] @@ -681,13 +679,13 @@ var/global/list/damage_icon_parts = list() var/image/standing = image(icon = t_icon, icon_state = t_state) if(head.blood_DNA) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "helmetblood") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "helmetblood") bloodsies.color = head.blood_color standing.overlays += bloodsies if(istype(head,/obj/item/clothing/head)) var/obj/item/clothing/head/hat = head - var/cache_key = "[hat.light_overlay]_[species.get_bodytype()]" + var/cache_key = "[hat.light_overlay]_[species.get_bodytype(src)]" if(hat.on && light_overlay_cache[cache_key]) standing.overlays |= light_overlay_cache[cache_key] @@ -707,8 +705,8 @@ var/global/list/damage_icon_parts = list() if(belt.icon_override) standing.icon = belt.icon_override - else if(belt.sprite_sheets && belt.sprite_sheets[species.get_bodytype()]) - standing.icon = belt.sprite_sheets[species.get_bodytype()] + else if(belt.sprite_sheets && belt.sprite_sheets[species.get_bodytype(src)]) + standing.icon = belt.sprite_sheets[species.get_bodytype(src)] else standing.icon = 'icons/mob/belt.dmi' @@ -745,7 +743,7 @@ var/global/list/damage_icon_parts = list() var/t_icon = INV_SUIT_DEF_ICON if(wear_suit.icon_override) t_icon = wear_suit.icon_override - else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.get_bodytype()]) + else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.get_bodytype(src)]) t_icon = wear_suit.sprite_sheets[species.name] else if(wear_suit.item_icons && wear_suit.item_icons[slot_wear_suit_str]) t_icon = wear_suit.item_icons[slot_wear_suit_str] @@ -761,7 +759,7 @@ var/global/list/damage_icon_parts = list() if(wear_suit.blood_DNA) var/obj/item/clothing/suit/S = wear_suit if(istype(S)) //You can put non-suits in your suit slot (diona nymphs etc). - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "[S.blood_overlay_type]blood") bloodsies.color = wear_suit.blood_color standing.overlays += bloodsies @@ -790,14 +788,14 @@ var/global/list/damage_icon_parts = list() var/image/standing if(wear_mask.icon_override) standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state]") - else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype()], "icon_state" = "[wear_mask.icon_state]") + else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[wear_mask.icon_state]") else standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") standing.color = wear_mask.color if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA ) - var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood") + var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color standing.overlays += bloodsies overlays_standing[FACEMASK_LAYER] = standing @@ -818,8 +816,8 @@ var/global/list/damage_icon_parts = list() //If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc. var/obj/item/weapon/rig/rig = back overlay_icon = rig.mob_icon - else if(back.sprite_sheets && back.sprite_sheets[species.get_bodytype()]) - overlay_icon = back.sprite_sheets[species.get_bodytype()] + else if(back.sprite_sheets && back.sprite_sheets[species.get_bodytype(src)]) + overlay_icon = back.sprite_sheets[species.get_bodytype(src)] else if(back.item_icons && (slot_back_str in back.item_icons)) overlay_icon = back.item_icons[slot_back_str] else @@ -863,8 +861,8 @@ var/global/list/damage_icon_parts = list() var/image/standing if(handcuffed.icon_override) standing = image("icon" = handcuffed.icon_override, "icon_state" = "handcuff1") - else if(handcuffed.sprite_sheets && handcuffed.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = handcuffed.sprite_sheets[species.get_bodytype()], "icon_state" = "handcuff1") + else if(handcuffed.sprite_sheets && handcuffed.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = handcuffed.sprite_sheets[species.get_bodytype(src)], "icon_state" = "handcuff1") else standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") overlays_standing[HANDCUFF_LAYER] = standing @@ -879,8 +877,8 @@ var/global/list/damage_icon_parts = list() var/image/standing if(legcuffed.icon_override) standing = image("icon" = legcuffed.icon_override, "icon_state" = "legcuff1") - else if(legcuffed.sprite_sheets && legcuffed.sprite_sheets[species.get_bodytype()]) - standing = image("icon" = legcuffed.sprite_sheets[species.get_bodytype()], "icon_state" = "legcuff1") + else if(legcuffed.sprite_sheets && legcuffed.sprite_sheets[species.get_bodytype(src)]) + standing = image("icon" = legcuffed.sprite_sheets[species.get_bodytype(src)], "icon_state" = "legcuff1") else standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") overlays_standing[LEGCUFF_LAYER] = standing @@ -977,24 +975,29 @@ var/global/list/damage_icon_parts = list() return // VOREStation Edit - END - if(species.tail && !(wear_suit && wear_suit.flags_inv & HIDETAIL)) + var/species_tail = species.get_tail(src) + + if(species_tail && !(wear_suit && wear_suit.flags_inv & HIDETAIL)) var/icon/tail_s = get_tail_icon() - overlays_standing[TAIL_LAYER] = image(tail_s, icon_state = "[species.tail]_s") + overlays_standing[TAIL_LAYER] = image(tail_s, icon_state = "[species_tail]_s") animate_tail_reset(0) if(update_icons) update_icons() /mob/living/carbon/human/proc/get_tail_icon() - var/icon_key = "[species.race_key][r_skin][g_skin][b_skin][r_hair][g_hair][b_hair]" + var/icon_key = "[species.get_race_key(src)][r_skin][g_skin][b_skin][r_hair][g_hair][b_hair]" var/icon/tail_icon = tail_icon_cache[icon_key] if(!tail_icon) //generate a new one - tail_icon = new/icon(icon = (species.tail_animation? species.tail_animation : 'icons/effects/species.dmi')) + var/species_tail_anim = species.get_tail_animation(src) + if(!species_tail_anim) species_tail_anim = 'icons/effects/species.dmi' + tail_icon = new/icon(species_tail_anim) tail_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) // The following will not work with animated tails. - if(species.tail_hair) - var/icon/hair_icon = icon('icons/effects/species.dmi', "[species.tail]_[species.tail_hair]") + var/use_species_tail = species.get_tail_hair(src) + if(use_species_tail) + var/icon/hair_icon = icon('icons/effects/species.dmi', "[species.get_tail(src)]_[use_species_tail]") hair_icon.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) tail_icon.Blend(hair_icon, ICON_OVERLAY) tail_icon_cache[icon_key] = tail_icon @@ -1005,7 +1008,7 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/proc/set_tail_state(var/t_state) var/image/tail_overlay = overlays_standing[TAIL_LAYER] - if(tail_overlay && species.tail_animation) + if(tail_overlay && species.get_tail_animation(src)) tail_overlay.icon_state = t_state return tail_overlay return null @@ -1013,7 +1016,7 @@ var/global/list/damage_icon_parts = list() //Not really once, since BYOND can't do that. //Update this if the ability to flick() images or make looping animation start at the first frame is ever added. /mob/living/carbon/human/proc/animate_tail_once(var/update_icons=1) - var/t_state = "[species.tail]_once" + var/t_state = "[species.get_tail(src)]_once" var/image/tail_overlay = overlays_standing[TAIL_LAYER] if(tail_overlay && tail_overlay.icon_state == t_state) @@ -1030,29 +1033,28 @@ var/global/list/damage_icon_parts = list() update_icons() /mob/living/carbon/human/proc/animate_tail_start(var/update_icons=1) - set_tail_state("[species.tail]_slow[rand(0,9)]") + set_tail_state("[species.get_tail(src)]_slow[rand(0,9)]") if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_fast(var/update_icons=1) - set_tail_state("[species.tail]_loop[rand(0,9)]") + set_tail_state("[species.get_tail(src)]_loop[rand(0,9)]") if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_reset(var/update_icons=1) if(stat != DEAD) - set_tail_state("[species.tail]_idle[rand(0,9)]") + set_tail_state("[species.get_tail(src)]_idle[rand(0,9)]") else - set_tail_state("[species.tail]_static") - + set_tail_state("[species.get_tail(src)]_static") if(update_icons) update_icons() /mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1) - set_tail_state("[species.tail]_static") + set_tail_state("[species.get_tail(src)]_static") if(update_icons) update_icons() diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 7db2bcf5c8..69ddb59038 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -217,7 +217,7 @@ if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men var/mob/living/carbon/human/H = L - if(H.species.name == "Slime") + if(H.species.name == "Promethean") continue if(!L.canmove) // Only one slime can latch on at a time. diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 42ba1968f5..0c81845e2c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -579,7 +579,7 @@ default behaviour is: set name = "Resist" set category = "IC" - if(!stat && canClick()) + if(!incapacitated(INCAPACITATION_KNOCKOUT) && canClick()) setClickCooldown(20) resist_grab() if(!weakened) @@ -646,7 +646,9 @@ default behaviour is: if(GRAB_PASSIVE) qdel(G) if(GRAB_AGGRESSIVE) - if(prob(60)) //same chance of breaking the grab as disarm + //Not standing up makes it much harder to break, so it is easier to cuff someone who is down without forcing them into unconsciousness. + //Otherwise, it's the same chance of breaking the grab as disarm. + if(incapacitated(INCAPACITATION_KNOCKDOWN)? prob(15) : prob(60)) visible_message("[src] has broken free of [G.assailant]'s grip!") qdel(G) if(GRAB_NECK) @@ -877,7 +879,7 @@ default behaviour is: else if(istype(buckled, /obj/vehicle)) var/obj/vehicle/V = buckled - if(cannot_stand()) + if(is_physically_disabled()) lying = 0 canmove = 1 pixel_y = V.mob_offset_y - 5 @@ -895,18 +897,13 @@ default behaviour is: anchored = 0 canmove = 1 - else if(cannot_stand()) - lying = 1 - canmove = 0 - else if(stunned) - canmove = 0 else if(captured) anchored = 1 canmove = 0 lying = 0 else - lying = 0 - canmove = 1 + lying = incapacitated(INCAPACITATION_KNOCKDOWN) + canmove = !incapacitated(INCAPACITATION_DISABLED) if(lying) density = 0 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ee45284925..9cbe7e1221 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -151,11 +151,13 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c add_language("Galactic Common", 1) add_language("Sol Common", 0) add_language("Sinta'unathi", 0) + add_language("Siik'maas", 0) add_language("Siik'tajr", 0) add_language("Skrellian", 0) add_language("Tradeband", 1) add_language("Gutter", 0) add_language("Encoded Audio Language", 1) + add_language("Schechi", 0) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 6f0b3d81bd..7d2848f9bf 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -75,7 +75,7 @@ /datum/robot_component/armour name = "armour plating" external_type = /obj/item/robot_parts/robot_component/armour - max_damage = 60 + max_damage = 90 // ACTUATOR diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 69371109ec..e6c7546e09 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -23,7 +23,7 @@ var/global/list/robot_modules = list( var/hide_on_manifest = 0 var/channels = list() var/networks = list() - var/languages = list(LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, LANGUAGE_SIIK_TAJR = 0, LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0) + var/languages = list(LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, LANGUAGE_SIIK_TAJR = 0, LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_SCHECHI = 0) var/sprites = list() var/can_be_pushed = 1 var/no_slip = 0 @@ -479,11 +479,12 @@ var/global/list/robot_modules = list( LANGUAGE_SOL_COMMON = 1, LANGUAGE_UNATHI = 1, LANGUAGE_SIIK_MAAS = 1, - LANGUAGE_SIIK_TAJR = 0, + LANGUAGE_SIIK_TAJR = 1, LANGUAGE_SKRELLIAN = 1, LANGUAGE_ROOTSPEAK = 1, LANGUAGE_TRADEBAND = 1, - LANGUAGE_GUTTER = 1 + LANGUAGE_GUTTER = 1, + LANGUAGE_SCHECHI = 1 ) /obj/item/weapon/robot_module/clerical/butler @@ -623,9 +624,12 @@ var/global/list/robot_modules = list( LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, + LANGUAGE_SIIK_MAAS = 0, LANGUAGE_SIIK_TAJR = 0, LANGUAGE_SKRELLIAN = 0, - LANGUAGE_GUTTER = 1 + LANGUAGE_ROOTSPEAK = 0, + LANGUAGE_GUTTER = 1, + LANGUAGE_SCHECHI = 0 ) sprites = list( "Dread" = "securityrobot", diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 9b60baaa9c..f649648592 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -159,8 +159,20 @@ return UNBUCKLED return restrained() ? FULLY_BUCKLED : PARTIALLY_BUCKLED +/mob/proc/is_physically_disabled() + return incapacitated(INCAPACITATION_DISABLED) + +/mob/proc/cannot_stand() + return incapacitated(INCAPACITATION_KNOCKDOWN) + /mob/proc/incapacitated(var/incapacitation_flags = INCAPACITATION_DEFAULT) - if (stat || paralysis || stunned || weakened || resting || sleeping || (status_flags & FAKEDEATH)) + if ((incapacitation_flags & INCAPACITATION_STUNNED) && stunned) + return 1 + + if ((incapacitation_flags & INCAPACITATION_FORCELYING) && (weakened || resting)) + return 1 + + if ((incapacitation_flags & INCAPACITATION_KNOCKOUT) && (stat || paralysis || sleeping || (status_flags & FAKEDEATH))) return 1 if((incapacitation_flags & INCAPACITATION_RESTRAINED) && restrained()) @@ -688,9 +700,6 @@ /mob/proc/can_stand_overridden() return 0 -/mob/proc/cannot_stand() - return incapacitated(INCAPACITATION_DEFAULT & (~INCAPACITATION_RESTRAINED)) - //Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. /mob/proc/update_canmove() return canmove diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 7b7f994e8f..f814ac2b23 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -152,7 +152,7 @@ var/voice_name = "unidentifiable voice" var/faction = "neutral" //Used for checking whether hostile simple animals will attack you, possibly more stuff later - var/captured = 0 //Functionally, should give the same effect as being buckled into a chair when true. + var/captured = 0 //Functionally, should give the same effect as being buckled into a chair when true. Only used by energy nets, TODO replace with buckling //Generic list for proc holders. Only way I can see to enable certain verbs/procs. Should be modified if needed. var/proc_holder_list[] = list()//Right now unused. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index f660da3c25..ae89a67366 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -175,7 +175,7 @@ return 0 var/datum/species/S = all_species[client.prefs.species] - if(!(S.spawn_flags & CAN_JOIN)) + if(!(S.spawn_flags & SPECIES_CAN_JOIN)) src << alert("Your current species, [client.prefs.species], is not available for play on the station.") return 0 @@ -460,11 +460,13 @@ return new_character /mob/new_player/proc/ViewManifest() - var/dat = "" - dat += "

Show Crew Manifest

" + var/dat = "
" dat += data_core.get_manifest(OOC = 1) - src << browse(dat, "window=manifest;size=370x420;can_close=1") + //src << browse(dat, "window=manifest;size=370x420;can_close=1") + var/datum/browser/popup = new(src, "Crew Manifest", "Crew Manifest", 370, 420, src) + popup.set_content(dat) + popup.open() /mob/new_player/Move() return 0 @@ -480,7 +482,7 @@ /mob/new_player/proc/is_species_whitelisted(datum/species/S) if(!S) return 1 - return is_alien_whitelisted(src, S.name) || !config.usealienwhitelist || !(S.spawn_flags & IS_WHITELISTED) + return is_alien_whitelisted(src, S.name) || !config.usealienwhitelist || !(S.spawn_flags & SPECIES_IS_WHITELISTED) /mob/new_player/get_species() var/datum/species/chosen_species diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index cebd834a24..28d054b377 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -26,6 +26,7 @@ var/last_dam = -1 // used in healing/processing calculations. // Appearance vars. + var/nonsolid // Snowflake warning, reee. Used for slime limbs. var/icon_name = null // Icon state base. var/body_part = null // Part flag var/icon_position = 0 // Used in mob overlay layering calculations. @@ -199,11 +200,11 @@ /obj/item/organ/external/replaced(var/mob/living/carbon/human/target) owner = target + forceMove(owner) if(istype(owner)) owner.organs_by_name[organ_tag] = src owner.organs |= src for(var/obj/item/organ/organ in src) - organ.loc = owner organ.replaced(owner,src) if(parent_organ) @@ -212,6 +213,12 @@ if(!parent.children) parent.children = list() parent.children.Add(src) + //Remove all stump wounds since limb is not missing anymore + for(var/datum/wound/lost_limb/W in parent.wounds) + parent.wounds -= W + qdel(W) + break + parent.update_damages() /**************************************************** DAMAGE PROCS @@ -249,7 +256,10 @@ if(is_damageable(brute + burn) || !config.limbs_can_break) if(brute) if(can_cut) - createwound( CUT, brute ) + if(sharp && !edge) + createwound( PIERCE, brute ) + else + createwound( CUT, brute ) else createwound( BRUISE, brute ) if(burn) @@ -263,7 +273,10 @@ if (brute > 0) //Inflict all burte damage we can if(can_cut) - createwound( CUT, min(brute,can_inflict) ) + if(sharp && !edge) + createwound( PIERCE, min(brute,can_inflict) ) + else + createwound( CUT, min(brute,can_inflict) ) else createwound( BRUISE, min(brute,can_inflict) ) var/temp = can_inflict @@ -326,10 +339,10 @@ break // heal brute damage - if(W.damage_type == CUT || W.damage_type == BRUISE) - brute = W.heal_damage(brute) - else if(W.damage_type == BURN) + if(W.damage_type == BURN) burn = W.heal_damage(burn) + else + brute = W.heal_damage(brute) if(internal) status &= ~ORGAN_BROKEN @@ -653,10 +666,10 @@ Note that amputating the affected organ does in fact remove the infection from t //update damage counts for(var/datum/wound/W in wounds) if(!W.internal) //so IB doesn't count towards crit/paincrit - if(W.damage_type == CUT || W.damage_type == BRUISE) - brute_dam += W.damage - else if(W.damage_type == BURN) + if(W.damage_type == BURN) burn_dam += W.damage + else + brute_dam += W.damage if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && H.should_have_organ(O_HEART))) W.bleed_timer-- @@ -719,6 +732,9 @@ Note that amputating the affected organ does in fact remove the infection from t if(cannot_amputate || !owner) return + if(disintegrate == DROPLIMB_EDGE && nonsolid) + disintegrate = DROPLIMB_BLUNT //splut + switch(disintegrate) if(DROPLIMB_EDGE) if(!clean) @@ -747,10 +763,13 @@ Note that amputating the affected organ does in fact remove the infection from t var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed(). var/obj/item/organ/external/parent_organ = parent + + var/use_flesh_colour = species.get_flesh_colour(owner) + var/use_blood_colour = species.get_blood_colour(owner) + removed(null, ignore_children) victim.traumatic_shock += 60 - wounds.Cut() if(parent_organ) var/datum/wound/lost_limb/W = new (src, disintegrate, clean) if(clean) @@ -795,10 +814,8 @@ Note that amputating the affected organ does in fact remove the infection from t else gore = new /obj/effect/decal/cleanable/blood/gibs(get_turf(victim)) if(species) - if(species.get_flesh_colour()) - gore.fleshcolor = species.get_flesh_colour() - if(species.get_blood_colour()) - gore.basecolor = species.get_blood_colour() + gore.fleshcolor = use_flesh_colour + gore.basecolor = use_blood_colour gore.update_icon() gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) @@ -840,15 +857,46 @@ Note that amputating the affected organ does in fact remove the infection from t "\The [holder.legcuffed.name] falls off you.") holder.drop_from_inventory(holder.legcuffed) +// checks if all wounds on the organ are bandaged +/obj/item/organ/external/proc/is_bandaged() + for(var/datum/wound/W in wounds) + if(W.internal) continue + if(!W.bandaged) + return 0 + return 1 + +// checks if all wounds on the organ are salved +/obj/item/organ/external/proc/is_salved() + for(var/datum/wound/W in wounds) + if(W.internal) continue + if(!W.salved) + return 0 + return 1 + +// checks if all wounds on the organ are disinfected +/obj/item/organ/external/proc/is_disinfected() + for(var/datum/wound/W in wounds) + if(W.internal) continue + if(!W.disinfected) + return 0 + return 1 + /obj/item/organ/external/proc/bandage() var/rval = 0 - src.status &= ~ORGAN_BLEEDING + status &= ~ORGAN_BLEEDING for(var/datum/wound/W in wounds) if(W.internal) continue rval |= !W.bandaged W.bandaged = 1 return rval +/obj/item/organ/external/proc/salve() + var/rval = 0 + for(var/datum/wound/W in wounds) + rval |= !W.salved + W.salved = 1 + return rval + /obj/item/organ/external/proc/disinfect() var/rval = 0 for(var/datum/wound/W in wounds) @@ -867,13 +915,6 @@ Note that amputating the affected organ does in fact remove the infection from t W.clamped = 1 return rval -/obj/item/organ/external/proc/salve() - var/rval = 0 - for(var/datum/wound/W in wounds) - rval |= !W.salved - W.salved = 1 - return rval - /obj/item/organ/external/proc/fracture() if(status & ORGAN_ROBOT) return //ORGAN_BROKEN doesn't have the same meaning for robot limbs diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index ffcb3f32e1..21e1e337b8 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -71,7 +71,7 @@ var/global/list/limb_icon_cache = list() if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype() in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype(owner) in facial_hair_style.species_allowed)) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) @@ -79,7 +79,7 @@ var/global/list/limb_icon_cache = list() if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && (species.get_bodytype() in hair_style.species_allowed)) + if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_ADD) @@ -113,36 +113,47 @@ var/global/list/limb_icon_cache = list() else if (status & ORGAN_ROBOT) mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]") else - if (status & ORGAN_MUTATED) - mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]") - else - mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]") - - if(status & ORGAN_DEAD) - mob_icon.ColorTone(rgb(10,50,0)) - mob_icon.SetIntensity(0.7) - - if(!isnull(s_tone)) - if(s_tone >= 0) - mob_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) - else - mob_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) - else if(s_col && s_col.len >= 3) - mob_icon.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) + mob_icon = new /icon(species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") + apply_colouration(mob_icon) if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" if(!limb_icon_cache[cache_key]) - var/icon/I = icon(species.icobase, "[icon_name]_[body_hair]") + var/icon/I = icon(species.get_icobase(owner), "[icon_name]_[body_hair]") I.Blend(rgb(h_col[1],h_col[2],h_col[3]), ICON_ADD) limb_icon_cache[cache_key] = I mob_icon.Blend(limb_icon_cache[cache_key], ICON_OVERLAY) dir = EAST icon = mob_icon - return mob_icon +/obj/item/organ/external/proc/apply_colouration(var/icon/applying) + + if(nonsolid) + applying.MapColors("#4D4D4D","#969696","#1C1C1C", "#000000") + if(species && species.get_bodytype(owner) != "Human") + applying.SetIntensity(1.5) // Unathi, Taj and Skrell have -very- dark base icons. + else + applying.SetIntensity(0.7) + + else if(status & ORGAN_DEAD) + applying.ColorTone(rgb(10,50,0)) + applying.SetIntensity(0.7) + + if(!isnull(s_tone)) + if(s_tone >= 0) + applying.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + applying.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + else if(s_col && s_col.len >= 3) + applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) + + // Translucency. + if(nonsolid) applying += rgb(,,,180) // SO INTUITIVE TY BYOND + + return applying + // new damage icon system // adjusted to set damage_state to brute/burn code only (without r_name0 as before) /obj/item/organ/external/update_icon() diff --git a/code/modules/organs/subtypes/unbreakable.dm b/code/modules/organs/subtypes/unbreakable.dm index 137249e747..9492d330e1 100644 --- a/code/modules/organs/subtypes/unbreakable.dm +++ b/code/modules/organs/subtypes/unbreakable.dm @@ -1,4 +1,3 @@ -// Slime limbs. /obj/item/organ/external/chest/unbreakable cannot_break = 1 dislocated = -1 @@ -42,3 +41,48 @@ /obj/item/organ/external/head/unbreakable cannot_break = 1 dislocated = -1 + +// Slime limbs. +/obj/item/organ/external/chest/unbreakable/slime + nonsolid = 1 + max_damage = 50 + +/obj/item/organ/external/groin/unbreakable/slime + nonsolid = 1 + max_damage = 30 + +/obj/item/organ/external/arm/unbreakable/slime + nonsolid = 1 + max_damage = 15 + +/obj/item/organ/external/arm/right/unbreakable/slime + nonsolid = 1 + max_damage = 15 + +/obj/item/organ/external/leg/unbreakable/slime + nonsolid = 1 + max_damage = 15 + +/obj/item/organ/external/leg/right/unbreakable/slime + nonsolid = 1 + max_damage = 15 + +/obj/item/organ/external/foot/unbreakable/slime + nonsolid = 1 + max_damage = 5 + +/obj/item/organ/external/foot/right/unbreakable/slime + nonsolid = 1 + max_damage = 5 + +/obj/item/organ/external/hand/unbreakable/slime + nonsolid = 1 + max_damage = 5 + +/obj/item/organ/external/hand/right/unbreakable/slime + nonsolid = 1 + max_damage = 5 + +/obj/item/organ/external/head/unbreakable/slime + nonsolid = 1 + max_damage = 15 diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index 850f5114c0..3cf3ecb239 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -38,7 +38,7 @@ var/internal = 0 // maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented. var/max_bleeding_stage = 0 - // one of CUT, BRUISE, BURN + // one of CUT, PIERCE, BRUISE, BURN var/damage_type = CUT // whether this wound needs a bandage/salve to heal at all // the maximum amount of damage that this wound can have and still autoheal @@ -140,6 +140,15 @@ return 0 + proc/bandage() + bandaged = 1 + + proc/salve() + salved = 1 + + proc/disinfect() + disinfected = 1 + // heal the given amount of damage, and if the given amount of damage was more // than what needed to be healed, return how much heal was left // set @heals_internal to also heal internal organ damage @@ -202,7 +211,7 @@ if (wound_damage() <= 30 && bleed_timer <= 0) return 0 //Bleed timer has run out. Wounds with more than 30 damage don't stop bleeding on their own. - return (damage_type == BRUISE && wound_damage() >= 20 || damage_type == CUT && wound_damage() >= 5) + return 1 /** WOUND DEFINITIONS **/ @@ -226,6 +235,18 @@ return /datum/wound/cut/deep if(0 to 15) return /datum/wound/cut/small + if(PIERCE) + switch(damage) + if(60 to INFINITY) + return /datum/wound/puncture/massive + if(50 to 60) + return /datum/wound/puncture/gaping_big + if(30 to 50) + return /datum/wound/puncture/gaping + if(15 to 30) + return /datum/wound/puncture/flesh + if(0 to 15) + return /datum/wound/puncture/small if(BRUISE) return /datum/wound/bruise if(BURN) @@ -243,6 +264,9 @@ return null //no wound /** CUTS **/ +/datum/wound/cut/bleeding() + return ..() || wound_damage() >= 5 + /datum/wound/cut/small // link wound descriptions to amounts of damage // Minor cuts have max_bleeding_stage set to the stage that bears the wound type's name. @@ -276,7 +300,43 @@ datum/wound/cut/massive stages = list("massive wound" = 70, "massive healing wound" = 50, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0) damage_type = CUT +/** PUNCTURES **/ +/datum/wound/puncture/can_worsen(damage_type, damage) + return 0 +/datum/wound/puncture/can_merge(var/datum/wound/other) + return 0 +/datum/wound/puncture/bleeding() + return ..() || wound_damage() >= 5 + +/datum/wound/puncture/small + max_bleeding_stage = 2 + stages = list("puncture" = 5, "healing puncture" = 2, "small scab" = 0) + damage_type = PIERCE + +/datum/wound/puncture/flesh + max_bleeding_stage = 2 + stages = list("puncture wound" = 15, "blood soaked clot" = 5, "large scab" = 2, "small round scar" = 0) + damage_type = PIERCE + +/datum/wound/puncture/gaping + max_bleeding_stage = 3 + stages = list("gaping hole" = 30, "large blood soaked clot" = 15, "blood soaked clot" = 10, "small angry scar" = 5, "small round scar" = 0) + damage_type = PIERCE + +/datum/wound/puncture/gaping_big + max_bleeding_stage = 3 + stages = list("big gaping hole" = 50, "healing gaping hole" = 20, "large blood soaked clot" = 15, "large angry scar" = 10, "large round scar" = 0) + damage_type = PIERCE + +datum/wound/puncture/massive + max_bleeding_stage = 3 + stages = list("massive wound" = 60, "massive healing wound" = 30, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0) + damage_type = PIERCE + /** BRUISES **/ +/datum/wound/bruise/bleeding() + return ..() || wound_damage() >= 20 + /datum/wound/bruise stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30, "moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5) @@ -285,6 +345,11 @@ datum/wound/cut/massive damage_type = BRUISE /** BURNS **/ +/datum/wound/burn + max_bleeding_stage = 0 +/datum/wound/burn/bleeding() + return 0 + /datum/wound/burn/moderate stages = list("ripped burn" = 10, "moderate burn" = 5, "healing moderate burn" = 2, "fresh skin" = 0) damage_type = BURN @@ -318,15 +383,15 @@ datum/wound/cut/massive /datum/wound/lost_limb/New(var/obj/item/organ/external/lost_limb, var/losstype, var/clean) var/damage_amt = lost_limb.max_damage if(clean) damage_amt /= 2 - + switch(losstype) if(DROPLIMB_EDGE, DROPLIMB_BLUNT) damage_type = CUT max_bleeding_stage = 3 //clotted stump and above can bleed. stages = list( "ripped stump" = damage_amt*1.3, - "bloody stump" = damage_amt, - "clotted stump" = damage_amt*0.5, + "bloody stump" = damage_amt, + "clotted stump" = damage_amt*0.5, "scarred stump" = 0 ) if(DROPLIMB_BURN) @@ -337,7 +402,7 @@ datum/wound/cut/massive "scarred stump" = damage_amt*0.5, "scarred stump" = 0 ) - + ..(damage_amt) /datum/wound/lost_limb/can_merge(var/datum/wound/other) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 540e5a3367..4f34cd7eff 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -344,7 +344,7 @@ PN.trigger_warning(5) if(istype(M,/mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(H.species.siemens_coefficient == 0) + if(H.species.siemens_coefficient <= 0) return if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index 98817fede3..ab134d3406 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -13,12 +13,12 @@ firemodes = list( list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost=null), list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost=null), - list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=400), + list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=null, charge_cost=100), ) /obj/item/weapon/gun/energy/pulse_rifle/mounted self_recharge = 1 - use_external_power = 1 + use_external_power = 1 /obj/item/weapon/gun/energy/pulse_rifle/destroyer name = "pulse destroyer" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index 8a6d50ab29..0022026a67 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -476,9 +476,11 @@ /datum/reagent/slimetoxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species.name != "Slime") + if(H.species.name != "Promethean") M << "Your flesh rapidly mutates!" - H.set_species("Slime") + H.set_species("Promethean") + H.shapeshifter_set_colour("#05FF9B") + H.verbs -= /mob/living/carbon/human/proc/shapeshifter_select_colour /datum/reagent/aslimetoxin name = "Advanced Mutation Toxin" diff --git a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm index 63a467dcfd..9141efbc1e 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm @@ -8,6 +8,7 @@ volume = 30 unacidable = 1 //glass center_of_mass = list("x"=16, "y"=10) + matter = list("glass" = 500) on_reagent_change() /*if(reagents.reagent_list.len > 1 ) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index aee13ede83..eadd4db655 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -32,7 +32,6 @@ "You have attached [target]'s [E.name] to the [E.amputation_point].") user.drop_from_inventory(E) E.replaced(target) - E.loc = target target.update_body() target.updatehealth() target.UpdateDamageIcon() diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index cc56b311b5..e582d1222f 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -110,7 +110,6 @@ proc/do_surgery(mob/living/carbon/M, mob/living/user, obj/item/tool) if (user.a_intent == I_HELP) user << "You can't see any useful way to use [tool] on [M]." - return 1 return 0 proc/sort_surgeries() diff --git a/html/changelogs/Yoshax - carpetfix.yml b/html/changelogs/Yoshax - carpetfix.yml new file mode 100644 index 0000000000..c295d9a0d2 --- /dev/null +++ b/html/changelogs/Yoshax - carpetfix.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Yoshax + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Processing strata floor can now be pried up with a crowbar." + - bugfix: "Blue carpet can now also be removed with a crowbar, and has had it's ability to burn and have corners restored." diff --git a/html/changelogs/Yoshax - featuresandfixes.txt b/html/changelogs/Yoshax - featuresandfixes.txt new file mode 100644 index 0000000000..14389bfc92 --- /dev/null +++ b/html/changelogs/Yoshax - featuresandfixes.txt @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Yoshax + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Doubles the maximum length of records and names to 6144 & 52, resptively. Also increases book nelngth to 12288. (All numbers are in charatcers.) + - bugfix: "Makes various services in the antag uplink purchasable once again. This includes the fake crew arrival." + - bugifx: "Neckgrabs will no longer force people to the ground. In addition, weakened people can no longer resist." + - rscadd: "All vending machines now have a small chance of vending an additional item." + diff --git a/icons/mob/items/lefthand.dmi b/icons/mob/items/lefthand.dmi index f8d3c1c23f..b3f56e6ab3 100644 Binary files a/icons/mob/items/lefthand.dmi and b/icons/mob/items/lefthand.dmi differ diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi index 265df7a2ad..cc0895827a 100644 Binary files a/icons/mob/items/righthand.dmi and b/icons/mob/items/righthand.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index 72c63543ab..a2239630b8 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 8ceefe32cb..2fa64c7ade 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/forensics.dmi b/icons/obj/forensics.dmi index 63225c3012..f91d974309 100644 Binary files a/icons/obj/forensics.dmi and b/icons/obj/forensics.dmi differ diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi index c5f91d2ab2..5b453fbfb4 100644 Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 90ec35d3cf..9520d6fa1b 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1010,7 +1010,6 @@ #include "code\modules\client\preference_setup\global\02_settings.dm" #include "code\modules\client\preference_setup\global\03_pai.dm" #include "code\modules\client\preference_setup\global\04_communicators.dm" -#include "code\modules\client\preference_setup\global\05_ooc.dm" #include "code\modules\client\preference_setup\global\setting_datums.dm" #include "code\modules\client\preference_setup\loadout\gear_tweaks.dm" #include "code\modules\client\preference_setup\loadout\loadout.dm" @@ -1383,13 +1382,16 @@ #include "code\modules\mob\living\carbon\human\whisper.dm" #include "code\modules\mob\living\carbon\human\species\species.dm" #include "code\modules\mob\living\carbon\human\species\species_attack.dm" +#include "code\modules\mob\living\carbon\human\species\species_getters.dm" +#include "code\modules\mob\living\carbon\human\species\species_helpers.dm" #include "code\modules\mob\living\carbon\human\species\species_hud.dm" #include "code\modules\mob\living\carbon\human\species\species_vr.dm" +#include "code\modules\mob\living\carbon\human\species\species_shapeshift.dm" #include "code\modules\mob\living\carbon\human\species\outsider\shadow.dm" #include "code\modules\mob\living\carbon\human\species\station\golem.dm" #include "code\modules\mob\living\carbon\human\species\station\monkey.dm" +#include "code\modules\mob\living\carbon\human\species\station\prometheans.dm" #include "code\modules\mob\living\carbon\human\species\station\seromi.dm" -#include "code\modules\mob\living\carbon\human\species\station\slime.dm" #include "code\modules\mob\living\carbon\human\species\station\station.dm" #include "code\modules\mob\living\carbon\human\species\station\station_vr.dm" #include "code\modules\mob\living\carbon\metroid\death.dm"
NameRankActivity