diff --git a/aurorastation.dme b/aurorastation.dme index 71d6e4eed9b..123e989018f 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -422,6 +422,7 @@ #include "code\game\antagonist\outsider\commando.dm" #include "code\game\antagonist\outsider\deathsquad.dm" #include "code\game\antagonist\outsider\ert.dm" +#include "code\game\antagonist\outsider\loner.dm" #include "code\game\antagonist\outsider\mercenary.dm" #include "code\game\antagonist\outsider\ninja.dm" #include "code\game\antagonist\outsider\raider.dm" @@ -528,6 +529,7 @@ #include "code\game\gamemodes\events\holidays\Other.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\heist\heist.dm" +#include "code\game\gamemodes\loner\loner.dm" #include "code\game\gamemodes\malfunction\malf_hardware.dm" #include "code\game\gamemodes\malfunction\malf_research.dm" #include "code\game\gamemodes\malfunction\malf_research_ability.dm" @@ -2254,6 +2256,9 @@ #include "code\modules\modular_computers\NTNet\NTNet.dm" #include "code\modules\modular_computers\NTNet\NTNet_relay.dm" #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" +#include "code\modules\modular_computers\NTNet\NTNRC\message.dm" +#include "code\modules\modular_computers\NTNet\NTNRC\ntnrc.dm" +#include "code\modules\modular_computers\NTNet\NTNRC\user.dm" #include "code\modules\multiz\_stubs.dm" #include "code\modules\multiz\basic.dm" #include "code\modules\multiz\hoist.dm" diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index 45db04ff5e6..8c9c892aac1 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -46,6 +46,7 @@ #define MODE_RAIDER_MAGE "raider mage" #define MODE_RAIDER "raider" #define MODE_BURGLAR "burglar" +#define MODE_LONER "loner" #define MODE_WIZARD "wizard" #define MODE_CHANGELING "changeling" #define MODE_CULTIST "cultist" diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 158c23b2784..418b2fe81d0 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -201,6 +201,7 @@ #define PROGRAM_ALL_REGULAR (PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_WRISTBOUND | PROGRAM_TELESCREEN) #define PROGRAM_ALL_HANDHELD (PROGRAM_TABLET | PROGRAM_WRISTBOUND) +#define PROGRAM_STATE_DISABLED -1 #define PROGRAM_STATE_KILLED 0 #define PROGRAM_STATE_BACKGROUND 1 #define PROGRAM_STATE_ACTIVE 2 diff --git a/code/datums/outfits/outfit_antag.dm b/code/datums/outfits/outfit_antag.dm index f0149f82987..4236f868f52 100644 --- a/code/datums/outfits/outfit_antag.dm +++ b/code/datums/outfits/outfit_antag.dm @@ -166,6 +166,21 @@ if(!H.shoes) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots/toeless(H), slot_shoes) +/datum/outfit/admin/syndicate/mercenary/loner + name = "Loner" + + head = /obj/item/clothing/head/helmet/space/psi_amp/lesser + l_ear = /obj/item/device/radio/headset/syndicate + r_pocket = /obj/item/device/special_uplink/burglar + + backpack_contents = list( + /obj/item/storage/box/syndie_kit/space = 1, + /obj/item/gun/projectile/shotgun/foldable = 1, + /obj/item/device/multitool/hacktool = 1 + ) + + id_access = "Lone Operative" + /datum/outfit/admin/syndicate/raider name = "Raider" allow_backbag_choice = FALSE diff --git a/code/game/antagonist/outsider/loner.dm b/code/game/antagonist/outsider/loner.dm new file mode 100644 index 00000000000..f45f5f7ed61 --- /dev/null +++ b/code/game/antagonist/outsider/loner.dm @@ -0,0 +1,46 @@ +var/datum/antagonist/loner/loners + +/datum/antagonist/loner + id = MODE_LONER + role_text = "Loner" + role_text_plural = "Loners" + bantype = "loner" + antag_indicator = "loner" + landmark_id = "lonerspawn" + welcome_text = "You are a Loner, someone underequipped to deal with the station. You will probably not survive for the whole round, so don't sweat it if you die!
\ + You are equipped with a lesser cerebro-enhancer, which allows you to unlock your psionic potential. Use it in-hand to choose your boosted faculty, then install it on your head." + flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE + antaghud_indicator = "hudloner" + required_age = 7 + + hard_cap = 1 + hard_cap_round = 1 + initial_spawn_req = 1 + initial_spawn_target = 1 + + faction = "syndicate" + + id_type = /obj/item/card/id/syndicate + +/datum/antagonist/loner/New() + ..() + loners = src + +/datum/antagonist/loner/equip(var/mob/living/carbon/human/player) + if(!..()) + return FALSE + + for(var/obj/item/I in player) + if(istype(I, /obj/item/implant)) + continue + player.drop_from_inventory(I) + if(I.loc != player) + qdel(I) + + player.preEquipOutfit(/datum/outfit/admin/syndicate/mercenary/loner, FALSE) + player.equipOutfit(/datum/outfit/admin/syndicate/mercenary/loner, FALSE) + player.force_update_limbs() + player.update_eyes() + player.regenerate_icons() + + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/changeling/implements/powers/suck.dm b/code/game/gamemodes/changeling/implements/powers/suck.dm index 13073500df7..86dc3298611 100644 --- a/code/game/gamemodes/changeling/implements/powers/suck.dm +++ b/code/game/gamemodes/changeling/implements/powers/suck.dm @@ -80,7 +80,7 @@ var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.get_cloning_variant(), T.languages) absorbDNA(newDNA) - var/datum/changeling/changeling_check = T.mind.antag_datums[MODE_CHANGELING] + var/datum/changeling/changeling_check = T.get_antag_datum(MODE_CHANGELING) if(changeling_check) if(changeling_check.absorbed_dna) for(var/datum/absorbed_dna/dna_data in changeling_check.absorbed_dna) //steal all their loot diff --git a/code/game/gamemodes/loner/loner.dm b/code/game/gamemodes/loner/loner.dm new file mode 100644 index 00000000000..000e294e451 --- /dev/null +++ b/code/game/gamemodes/loner/loner.dm @@ -0,0 +1,10 @@ +/datum/game_mode/loner + name = "loner" + config_tag = "loner" + max_players = 8 + required_enemies = 1 + required_players = 5 + round_description = "Does anyone else hear a whistling noise...?" + extended_round_description = "A lone operative with a very large brain plans on dropping in and paying the crew a visit." + end_on_antag_death = FALSE + antag_tags = list(MODE_LONER) \ No newline at end of file diff --git a/code/game/gamemodes/vampire/vampire_helpers.dm b/code/game/gamemodes/vampire/vampire_helpers.dm index edb506a962d..b0e9063d1fd 100644 --- a/code/game/gamemodes/vampire/vampire_helpers.dm +++ b/code/game/gamemodes/vampire/vampire_helpers.dm @@ -205,7 +205,7 @@ /mob/living/carbon/human/vampire_start_frenzy() . = ..() if(.) - update_body() + update_body(force_base_icon = TRUE) /mob/proc/vampire_stop_frenzy(var/force_stop = 0) var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE] @@ -232,7 +232,7 @@ /mob/living/carbon/human/vampire_stop_frenzy() . = ..() if(.) - update_body() + update_body(force_base_icon = TRUE) // Removes all vampire powers. /mob/proc/remove_vampire_powers() diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index f23e47551a8..b2699ae90ef 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -803,7 +803,7 @@ for(var/mob/living/carbon/human/T in view(5)) if(T == src) continue - if(!vampire_can_affect_target(T, 0, 1)) + if(!vampire_can_affect_target(T, 0, 1, affect_ipc = FALSE)) //Will only affect IPCs at full power. continue if(!T.client) continue diff --git a/code/game/jobs/faction/zavodskoi.dm b/code/game/jobs/faction/zavodskoi.dm index 61266dd33e0..08916d54e5c 100644 --- a/code/game/jobs/faction/zavodskoi.dm +++ b/code/game/jobs/faction/zavodskoi.dm @@ -114,6 +114,6 @@ backpack_contents = list( /obj/item/device/camera = 1, - /obj/item/gun/energy/pistol = 1, + /obj/item/gun/projectile/pistol = 1, /obj/item/stamp/zavodskoi = 1 ) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 6001ee141ad..64feea0c671 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -126,7 +126,7 @@ var/const/NO_EMAG_ACT = -50 var/assignment = null //can be alt title or the actual job var/rank = null //actual job var/dorm = 0 // determines if this ID has claimed a dorm already - var/chat_registered = FALSE // registration for NTNET chat + var/datum/ntnet_user/chat_user /obj/item/card/id/Destroy() mob = null @@ -151,6 +151,8 @@ var/const/NO_EMAG_ACT = -50 /obj/item/card/id/proc/update_name() name = "ID Card ([src.registered_name] ([src.assignment]))" + if(istype(chat_user)) + chat_user.username = chat_user.generateUsernameIdCard(src) /obj/item/card/id/proc/set_id_photo(var/mob/M) front = getFlatIcon(M, SOUTH) @@ -334,6 +336,11 @@ var/const/NO_EMAG_ACT = -50 wear_over_suit = !wear_over_suit mob_icon_update() +/obj/item/card/id/proc/InitializeChatUser() + if(!istype(chat_user)) + chat_user = new() + chat_user.username = chat_user.generateUsernameIdCard(src) + /obj/item/card/id/silver icon_state = "silver" item_state = "silver_id" diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 677262337da..40fdcac0842 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -415,11 +415,27 @@ /obj/item/storage/belt/fannypack name = "leather fannypack" desc = "A dorky fannypack for keeping small items in." + icon = 'icons/clothing/belts/fannypacks.dmi' icon_state = "fannypack_leather" item_state = "fannypack_leather" max_w_class = ITEMSIZE_SMALL + contained_sprite = TRUE storage_slots = null max_storage_space = 8 + var/flipped = FALSE + +/obj/item/storage/belt/fannypack/verb/ToggleFanny() + set name = "Adjust Fannypack" + set category = "Object" + set src in usr + + if(use_check_and_message(usr)) + return 0 + + flipped = !flipped + item_state = "[initial(icon_state)][flipped ? "_flipped" : ""]" + to_chat(usr, "You flip the belt [flipped ? "behind you" : "infront of you"].") + update_icon() /obj/item/storage/belt/fannypack/component name = "component pouch" diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index e3b83955d9e..455d035466d 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -165,6 +165,11 @@ if(!G.wrapped) user_unbuckle_mob(user) + else if(istype(W, /obj/item/disk)) + user.drop_from_inventory(W, get_turf(src)) + W.pixel_x = 10 //make sure they reach the pillow + W.pixel_y = -6 + else if(!istype(W, /obj/item/bedsheet)) ..() diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index 93f66c9ac77..3f2a41ec738 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -131,7 +131,7 @@ // get_debug_type displays this else if(istext(value)) debug_type = null // it's kinda annoying here; we can tell the type by the quotes - vtext = "\"[value]\"" + vtext = "\"[html_encode(value)]\"" else if(isicon(value)) vtext = "[value]" else if(isfile(value)) diff --git a/code/modules/cciaa/cciaa_items.dm b/code/modules/cciaa/cciaa_items.dm index 7ecca775bcf..bc9356fbf75 100644 --- a/code/modules/cciaa/cciaa_items.dm +++ b/code/modules/cciaa/cciaa_items.dm @@ -255,11 +255,13 @@ sLogFile << "Recorder paused at: [get_time()]" to_chat(usr, "The device beeps and flashes \"Recording paused\".") paused = TRUE + icon_state = "taperecorderpause" else sLogFile << "Recorder resumed at: [get_time()]" sLogFile << "--------------------------------" to_chat(usr, "The device beeps and flashes \"Recording resumed\".") paused = FALSE + icon_state = "taperecorderrecording" return /obj/item/device/taperecorder/cciaa/attack_self(mob/user) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a505bf27922..4e34c335659 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1014,13 +1014,13 @@ rolled_down = !rolled_down if(rolled_down) body_parts_covered &= LOWER_TORSO|LEGS|FEET - if(contained_sprite) + if(contained_sprite || !LAZYLEN(item_state_slots)) item_state = "[initial(item_state)]_d" else item_state_slots[slot_w_uniform_str] = "[worn_state]_d" else body_parts_covered = initial(body_parts_covered) - if(contained_sprite) + if(contained_sprite || !LAZYLEN(item_state_slots)) item_state = initial(item_state) else item_state_slots[slot_w_uniform_str] = "[worn_state]" @@ -1044,14 +1044,14 @@ rolled_sleeves = !rolled_sleeves if(rolled_sleeves) body_parts_covered &= ~(ARMS|HANDS) - if(contained_sprite) + if(contained_sprite || !LAZYLEN(item_state_slots)) item_state = "[initial(item_state)]_r" else item_state_slots[slot_w_uniform_str] = "[worn_state]_r" to_chat(usr, SPAN_NOTICE("You roll up your [src]'s sleeves.")) else body_parts_covered = initial(body_parts_covered) - if(contained_sprite) + if(contained_sprite || !LAZYLEN(item_state_slots)) item_state = initial(item_state) else item_state_slots[slot_w_uniform_str] = "[worn_state]" diff --git a/code/modules/clothing/shoes/jobs.dm b/code/modules/clothing/shoes/jobs.dm index 5ab8419d8d6..f9542fd32d5 100644 --- a/code/modules/clothing/shoes/jobs.dm +++ b/code/modules/clothing/shoes/jobs.dm @@ -28,9 +28,6 @@ desc = "Taller synthleather boots with an artificial shine." icon_state = "kneeboots" item_state = "kneeboots" - -/obj/item/clothing/shoes/jackboots/knee/handle_movement(var/turf/walking, var/running) - trip_up(walking, running) /obj/item/clothing/shoes/jackboots/thigh name = "thigh-length black boots" @@ -38,9 +35,6 @@ icon_state = "thighboots" item_state = "thighboots" -/obj/item/clothing/shoes/jackboots/thigh/handle_movement(var/turf/walking, var/running) - trip_up(walking, running) - /obj/item/clothing/shoes/jackboots/toeless name = "toe-less black boots" desc = "Modified pair of boots, particularly friendly to those species whose toes hold claws." diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm index 0cedee0eebd..b43b6227190 100644 --- a/code/modules/clothing/under/accessories/badges.dm +++ b/code/modules/clothing/under/accessories/badges.dm @@ -210,7 +210,7 @@ /obj/item/clothing/accessory/badge/dia name = "\improper DIA badge" - desc = "This badge marks the holder of an investigative agent." + desc = "This badge marks the holder as an investigative agent." icon_state = "diabadge" overlay_state = "diabadge" badge_string = "Corporate Investigator" diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index d0c32b8be01..9867e5b610b 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -1,4 +1,3 @@ - /datum/event/vent_clog announceWhen = 1 startWhen = 5 @@ -6,31 +5,47 @@ var/interval = 2 var/list/vents = list() var/list/gunk = list( - /datum/reagent/water, - /datum/reagent/carbon, - /datum/reagent/nutriment/flour, - /datum/reagent/spacecleaner, - /datum/reagent/nutriment, - /datum/reagent/capsaicin/condensed, - /datum/reagent/mindbreaker, - /datum/reagent/lube, - /datum/reagent/paint, - /datum/reagent/paint, - /datum/reagent/drink/banana, - /datum/reagent/space_drugs, - /datum/reagent/water/holywater, - /datum/reagent/drink/hot_coco, - /datum/reagent/hyperzine, - /datum/reagent/paint, - /datum/reagent/luminol, - /datum/reagent/fuel, - /datum/reagent/blood, - /datum/reagent/sterilizine, - /datum/reagent/verunol, - /datum/reagent/toxin/fertilizer/monoammoniumphosphate + /datum/reagent/water = 10, + /datum/reagent/carbon = 5, + /datum/reagent/nutriment/flour = 8, + /datum/reagent/spacecleaner = 6, + /datum/reagent/nutriment = 6, + /datum/reagent/capsaicin/condensed = 2, + /datum/reagent/mindbreaker = 0.5, + /datum/reagent/lube = 4, + /datum/reagent/paint = 3, + /datum/reagent/drink/banana = 3, + /datum/reagent/space_drugs = 3, + /datum/reagent/water/holywater = 1, + /datum/reagent/drink/hot_coco = 3, + /datum/reagent/hyperzine = 0.75, + /datum/reagent/luminol = 2, + /datum/reagent/fuel = 3, + /datum/reagent/blood = 2, + /datum/reagent/sterilizine = 3, + /datum/reagent/verunol = 3, + /datum/reagent/toxin/fertilizer/monoammoniumphosphate = 1, + /datum/reagent/saline = 2, + /datum/reagent/mental/kokoreed = 0.5, + /datum/reagent/mental/vaam = 0.5, + /datum/reagent/toxin/tobacco = 3, + /datum/reagent/stone_dust = 0.5, + /datum/reagent/crayon_dust = 1, + /datum/reagent/alcohol/butanol = 2, + /datum/reagent/alcohol/ethanol = 2, + /datum/reagent/sugar = 2, + /datum/reagent/drink/coffee = 4, + /datum/reagent/wulumunusha = 0.25, + /datum/reagent/nutriment/virusfood = 2, + /datum/reagent/sodiumchloride = 2, + /datum/reagent/drink/zorasoda/venomgrass = 1, + /datum/reagent/nutriment/protein/egg = 2, + /datum/reagent/serotrotium = 1, + /datum/reagent/psilocybin = 0.5, + /datum/reagent/toxin/spectrocybin = 0.1 ) var/list/gunk_data = list( - /datum/reagent/paint = list("#FE191A", "FDFE7D") + /datum/reagent/paint = list("#FE191A", "#AAAA79", "#5F89E6", "#6CDB38", "#B474B6", "#F0DD34") ) @@ -51,11 +66,11 @@ var/obj/machinery/atmospherics/unary/vent_scrubber/vent = pick_n_take(vents) if(vent && vent.loc && !vent.is_welded()) - - var/datum/reagents/R = new/datum/reagents(35) + var/datum/reagent/chem = pickweight(gunk) + var/reagent_amount = rand(2,5) * 5 //10 to 25 units + var/datum/reagents/R = new/datum/reagents(reagent_amount) R.my_atom = vent - var/chem = pick(gunk) - R.add_reagent(chem, 35, pick(gunk_data[chem])) + R.add_reagent(chem, reagent_amount, pick(gunk_data[chem])) var/datum/effect/effect/system/smoke_spread/chem/smoke = new smoke.show_log = 0 // This displays a log on creation @@ -67,4 +82,4 @@ /datum/event/vent_clog/announce() - command_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert", new_sound = 'sound/AI/scrubbers.ogg') + command_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert", new_sound = 'sound/AI/scrubbers.ogg') \ No newline at end of file diff --git a/code/modules/ghostroles/spawner/base.dm b/code/modules/ghostroles/spawner/base.dm index 08d182d3f82..cd40b8ec4b8 100644 --- a/code/modules/ghostroles/spawner/base.dm +++ b/code/modules/ghostroles/spawner/base.dm @@ -181,6 +181,9 @@ //Proc to enable the ghostspawner /datum/ghostspawner/proc/enable() + if((max_count - count) <= 0) + to_chat(usr, "The ghostspawner can not be enabled - No slots available") + return if(usr) log_and_message_admins("has enabled the ghostspawner [src.name]") enabled = TRUE diff --git a/code/modules/mob/abstract/new_player/sprite_accessories.dm b/code/modules/mob/abstract/new_player/sprite_accessories.dm index 4b2b770ee5c..f8efc9df6ac 100644 --- a/code/modules/mob/abstract/new_player/sprite_accessories.dm +++ b/code/modules/mob/abstract/new_player/sprite_accessories.dm @@ -2862,7 +2862,7 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Scalp Ports)" icon_state = "aug_scalpports" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) vertex_left name = "Augment (Scalp Port, Vertex Left)" @@ -2884,7 +2884,7 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Scalp Ports Diode)" icon_state = "aug_scalpportsdiode" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) vertex_left name = "Augment (Scalp Port Diode, Vertex Left )" @@ -2906,7 +2906,7 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Backside Left, Head)" icon_state = "aug_backside_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) side_diode name = "Augment (Backside Left Diode, Head)" @@ -2916,7 +2916,7 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Backside Right, Head)" icon_state = "aug_backside_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) side_diode name = "Augment (Backside Right Diode, Head)" @@ -2926,19 +2926,19 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Deunan, Side Left)" icon_state = "aug_sidedeunan_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_side_deunan_right name = "Augment (Deunan, Side Right)" icon_state = "aug_sidedeunan_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_side_kuze_left name = "Augment (Kuze, Side Left)" icon_state = "aug_sidekuze_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) side_diode name = "Augment (Kuze Diode, Side Left)" @@ -2948,7 +2948,7 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Kuze, Side Right)" icon_state = "aug_sidekuze_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) side_diode name = "Augment (Kuze Diode, Side Right)" @@ -2958,43 +2958,43 @@ Follow by example and make good judgement based on length which list to include name = "Augment (Kinzie, Side Left)" icon_state = "aug_sidekinzie_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_side_kinzie_right name = "Augment (Kinzie, Side Right)" icon_state = "aug_sidekinzie_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_side_shelly_left name = "Augment (Shelly, Side Left)" icon_state = "aug_sideshelly_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_side_shelly_right name = "Augment (Shelly, Side Right)" icon_state = "aug_sideshelly_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) aug_chestports name = "Augment (Chest Ports)" icon_state = "aug_chestports" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") aug_abdomenports name = "Augment (Abdomen Ports)" icon_state = "aug_abdomenports" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") backstripe name = "Back Stripe" icon_state = "backstripe" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) spinemarks name = "Back Stripe Marks" @@ -3004,7 +3004,7 @@ Follow by example and make good judgement based on length which list to include name = "Color Bands (All)" icon_state = "bands" body_parts = list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_GROIN, BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/diona, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) chest name = "Color Bands (Torso)" @@ -3047,7 +3047,7 @@ Follow by example and make good judgement based on length which list to include name = "Color Bands (Left Foot)" icon_state = "bandshuman" body_parts = list(BP_L_FOOT) - species_allowed = list(/datum/species/human, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell) right_foot name = "Color Bands (Right Foot)" @@ -3058,7 +3058,7 @@ Follow by example and make good judgement based on length which list to include name = "Color Bands (Right Foot)" icon_state = "bandshuman" body_parts = list(BP_R_FOOT) - species_allowed = list(/datum/species/human, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell) bandsface name = "Color Bands (Face)" @@ -3070,241 +3070,241 @@ Follow by example and make good judgement based on length which list to include name = "Color Bands (Face)" icon_state = "bandshumanface" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell) bindi name = "Bindi" icon_state = "bindi" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) blush name = "Blush" icon_state= "blush" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) cheekspot_left name = "Cheek Spot (Left Cheek)" icon_state = "cheekspot_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) cheekspot_right name = "Cheek Spot (Right Cheek)" icon_state = "cheekspot_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) cheshire_left name = "Cheshire (Left Cheek)" icon_state = "cheshire_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) cheshire_right name = "Cheshire (Right Cheek)" icon_state = "cheshire_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) crow_left name = "Crow Mark (Left Eye)" icon_state = "crow_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) crow_right name = "Crow Mark (Right Eye)" icon_state = "crow_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) ear_left name = "Ear Cover (Left)" icon_state = "ear_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell) ear_right name = "Ear Cover (Right)" icon_state = "ear_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell) eyestripe name = "Eye Stripe" icon_state = "eyestripe" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) eyecorner_left name = "Eye Corner Left" icon_state = "eyecorner_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) eyecorner_right name = "Eye Corner Right" icon_state = "eyecorner_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) eyelash_left name = "Eyelash Left" icon_state = "eyelash_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) eyelash_right name = "Eyelash Right" icon_state = "eyelash_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) lips name = "Lips" icon_state = "lips" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) lipcorner_left name = "Lip Corner Left" icon_state = "lipcorner_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) lipcorner_right name = "Lip Corner Right" icon_state = "lipcorner_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) lowercheek_left name = "Lower Cheek Left" icon_state = "lowercheek_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) lowercheek_left name = "Lower Cheek Right" icon_state = "lowercheek_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) neck name = "Neck Cover" icon_state = "neck" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) neckthick name = "Neck Cover (Thick)" icon_state = "neckthick" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) nosestripe name = "Nose Stripe" icon_state = "nosestripe" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") nosetape name = "Nose Tape" icon_state = "nosetape" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, "Vaurca") scratch_abdomen_left name = "Scratch, Abdomen Left" icon_state = "scratch_abdomen_l" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") scratch_abdomen_right name = "Scratch, Abdomen Right" icon_state = "scratch_abdomen_r" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") scratch_abdomen_small_left name = "Scratch, Abdomen Small Left" icon_state = "scratch_abdomensmall_l" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") scratch_abdomen_small_right name = "Scratch, Abdomen Small Right" icon_state = "scratch_abdomensmall_r" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") scratch_back name = "Scratch, Back" icon_state = "scratch_back" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, "Vaurca") scratch_chest_left name = "Scratch, Chest (Left)" icon_state = "scratch_chest_l" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) scratch_chest_right name = "Scratch, Chest (Right)" icon_state = "scratch_chest_r" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_belly name = "Tattoo (Belly)" icon_state = "tat_belly" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_campbell_leftarm name = "Tattoo (Campbell, Left Arm)" icon_state = "tat_campbell" body_parts = list(BP_L_ARM) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_campbell_rightarm name = "Tattoo (Campbell, Right Arm)" icon_state = "tat_campbell" body_parts= list(BP_R_ARM) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_campbell_leftleg name = "Tattoo (Campbell, Left Leg)" icon_state = "tat_campbell" body_parts= list(BP_L_LEG) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_campbell_rightleg name = "Tattoo (Campbell, Right Leg)" icon_state = "tat_campbell" body_parts= list(BP_R_LEG) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_forrest_left name = "Tattoo (Forrest, Left Eye)" icon_state = "tat_forrest_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_forrest_right name = "Tattoo (Forrest, Right Eye)" icon_state = "tat_forrest_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_hive name = "Tattoo (Hive, Back)" icon_state = "tat_hive" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_heart name = "Tattoo (Heart, Chest)" @@ -3316,97 +3316,97 @@ Follow by example and make good judgement based on length which list to include name = "Tattoo (Heart, Lower Back)" icon_state = "tat_heartback" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell) tat_hunter_left name = "Tattoo (Hunter, Left Eye)" icon_state = "tat_hunter_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_hunter_right name = "Tattoo (Hunter, Right Eye)" icon_state = "tat_hunter_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_jaeger_left name = "Tattoo (Jaeger, Left Eye)" icon_state = "tat_jaeger_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_jaeger_right name = "Tattoo (Jaeger, Right Eye)" icon_state = "tat_jaeger_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_kater_left name = "Tattoo (Kater, Left Eye)" icon_state = "tat_kater_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_kater_right name = "Tattoo (Kater, Right Eye)" icon_state = "tat_kater_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_lujan_left name = "Tattoo (Lujan, Left Eye)" icon_state = "tat_lujan_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_lujan_right name = "Tattoo (Lujan, Right Eye)" icon_state = "tat_lujan_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_natasha_left name = "Tattoo (Natasha, Left Eye)" icon_state = "tat_natasha_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_natasha_right name = "Tattoo (Natasha, Right Eye)" icon_state = "tat_natasha_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_nightling name = "Tattoo (Nightling, Back)" icon_state = "tat_nightling" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_silverburgh_left name = "Tattoo (Silverburgh, Left Leg)" icon_state = "tat_silverburgh" body_parts = list(BP_L_LEG) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_silverburgh_right name = "Tattoo (Silverburgh, Right Leg)" icon_state = "tat_silverburgh" body_parts = list(BP_R_LEG) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_tamoko name = "Tattoo (Ta Moko, Face)" icon_state = "tat_tamoko" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell) tat_tiger name = "Tattoo (Tiger Stripes, All)" icon_state = "tat_tiger" body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) chest name = "Tattoo (Tiger Stripes, Chest)" @@ -3452,25 +3452,25 @@ Follow by example and make good judgement based on length which list to include name = "Tattoo (Toshi, Left Eye)" icon_state = "tat_toshi_l" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_toshi_right name = "Tattoo (Volgin, Right Eye)" icon_state = "tat_toshi_r" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tat_wings_back name = "Tattoo (Wings, Lower Back)" icon_state = "tat_wingsback" body_parts = list(BP_CHEST) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell) tigerhead name = "Tiger Stripes (Head, Minor)" icon_state = "tigerhead" body_parts = list(BP_HEAD) - species_allowed = list(/datum/species/human, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) + species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi) tiger_stripes name = "Tiger Stripes (Tajara)" diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index ef7dc248d5f..2c2fffaace5 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -259,4 +259,11 @@ return species.icon_y_offset /mob/living/carbon/human/proc/protected_from_sound() - return (l_ear?.item_flags & SOUNDPROTECTION) || (r_ear?.item_flags & SOUNDPROTECTION) || (head?.item_flags & SOUNDPROTECTION) \ No newline at end of file + return (l_ear?.item_flags & SOUNDPROTECTION) || (r_ear?.item_flags & SOUNDPROTECTION) || (head?.item_flags & SOUNDPROTECTION) + +/mob/living/carbon/human/get_antag_datum(var/antag_role) + if(!mind) + return + var/datum/D = mind.antag_datums[antag_role] + if(D) + return D \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 3707988d441..49f471ba389 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -255,7 +255,7 @@ There are several things that need to be remembered: . += M //BASE MOB SPRITE -/mob/living/carbon/human/proc/update_body(var/update_icons=1) +/mob/living/carbon/human/proc/update_body(var/update_icons=1, var/force_base_icon = FALSE) if (QDELING(src)) return @@ -263,7 +263,6 @@ There are several things that need to be remembered: var/husk = (HUSK in mutations) var/fat = (FAT in mutations) - var/hulk = (HULK in mutations) var/skeleton = (SKELETON in mutations) var/g = (gender == FEMALE ? "f" : "m") @@ -278,12 +277,12 @@ There are several things that need to be remembered: qdel(stand_icon) stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - var/is_frenzied = FALSE + var/is_frenzied = "nofrenzy" if(mind) var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE] if(vampire && (vampire.status & VAMP_FRENZIED)) - is_frenzied = TRUE - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin][lip_style || "nolips"][!!husk][!!fat][!!hulk][!!skeleton][is_frenzied]" + is_frenzied = "frenzy" + var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin][lip_style || "nolips"][!!husk][!!fat][!!skeleton][is_frenzied]" var/obj/item/organ/internal/eyes/eyes = get_eyes() if(eyes) icon_key += "[rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3])]" @@ -298,7 +297,7 @@ There are several things that need to be remembered: icon_key += SSicon_cache.get_organ_shortcode(part) var/icon/base_icon = SSicon_cache.human_icon_cache[icon_key] - if (!base_icon) // Icon ain't in the cache, so generate it. + if (!base_icon || force_base_icon) // Icon ain't in the cache, so generate it. //BEGIN CACHED ICON GENERATION. var/obj/item/organ/external/chest = get_organ(BP_CHEST) base_icon = chest.get_icon(skeleton) @@ -326,6 +325,7 @@ There are several things that need to be remembered: else base_icon.Blend(temp, ICON_OVERLAY) + part.cut_additional_images(src) var/list/add_images = part.get_additional_images(src) if(add_images) add_overlay(add_images, TRUE) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index ea1114046b8..a90be690727 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -95,6 +95,10 @@ /mob/living/silicon/proc/SetName(pickedName as text) real_name = pickedName name = real_name + if(istype(id_card)) + if(!istype(id_card.chat_user)) + id_card.InitializeChatUser() + id_card.chat_user.username = real_name /mob/living/silicon/proc/show_laws() return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 875f0bfb69b..780d11b83a7 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -635,7 +635,7 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) set name = "Make Sound" set category = "Abilities" - if((usr && usr.stat == DEAD) || !make_sound) + if(stat || !make_sound) //Can't make noise if there's no noise or if you're unconscious/dead return if(usr && !sound_time) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index e489734dd9d..408bd4424bf 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1210,4 +1210,7 @@ proc/is_blind(A) disabilities &= ~NEARSIGHTED /mob/proc/remove_deaf() - sdisabilities &= ~DEAF \ No newline at end of file + sdisabilities &= ~DEAF + +/mob/proc/get_antag_datum(var/antag_role) + return \ No newline at end of file diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm index 692451011d5..ead8bf1b721 100644 --- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm +++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm @@ -2,9 +2,9 @@ var/global/ntnrc_uid = 0 /datum/ntnet_conversation var/id var/title = "Untitled Conversation" - var/datum/computer_file/program/chatclient/operator // "Administrator" of this channel. Creator starts as channel's operator, + var/datum/ntnet_user/operator // "Administrator" of this channel. Creator starts as channel's operator, var/list/messages = list() - var/list/clients = list() + var/list/users = list() var/direct = FALSE var/password @@ -19,25 +19,32 @@ var/global/ntnrc_uid = 0 operator = "NanoTrasen Information Technology Division" // assign a fake operator ..() -/datum/ntnet_conversation/proc/add_message(var/message, var/username, var/mob/user, var/reply_ref) - log_ntirc("[user.client.ckey]/([username]) : [message]", ckey=key_name(user), conversation=title) +/datum/ntnet_conversation/proc/process_message(var/datum/ntnet_message/message, var/update_ui = TRUE) + var/admin_log = message.format_admin_log() + if (admin_log) + log_ntirc("[message.user.client.ckey]/([message.nuser.username]): [admin_log]", ckey=key_name(message.user), conversation=title) - for(var/datum/computer_file/program/chatclient/C in clients) - if(C.program_state > PROGRAM_STATE_KILLED) - C.computer.output_message("([get_title(C)]) [username]: [message] (Reply)", 0) - if(!C.silent && C.username != username && C.program_state == PROGRAM_STATE_BACKGROUND) - playsound(C.computer, 'sound/machines/twobeep.ogg', 50, 1) - C.computer.output_message("*[C.ringtone]*") - else if(C.username == username) - ntnet_global.add_log(message, C.computer.network_card, TRUE) + for(var/datum/ntnet_user/U in users) + for(var/datum/computer_file/program/chat_client/Cl in U.clients) + var/notification_text = message.format_chat_notification(src, Cl) + if(notification_text && Cl.can_receive_notification(message.client)) + Cl.computer.output_message(notification_text, 0) + if(message.play_sound) + Cl.play_notification_sound(message.client) - message = "[worldtime2text()] [username]: [message]" - messages.Add(message) - trim_message_list() + var/ntnet_log = message.format_ntnet_log(src) + if(ntnet_log) + ntnet_global.add_log(ntnet_log, message.client.computer.network_card, TRUE) -/datum/ntnet_conversation/proc/add_status_message(var/message) - messages.Add("[worldtime2text()] -!- [message]") - trim_message_list() + var/chat_log = message.format_chat_log(src) + if(chat_log) + messages.Add(chat_log) + trim_message_list() + + if(update_ui) + for(var/datum/ntnet_user/U in users) + for(var/datum/computer_file/program/chat_client/Cl) + SSvueui.check_uis_for_change(Cl) /datum/ntnet_conversation/proc/trim_message_list() if(messages.len <= 50) @@ -47,89 +54,119 @@ var/global/ntnrc_uid = 0 if(messages.len <= 50) return -/datum/ntnet_conversation/proc/add_client(var/datum/computer_file/program/chatclient/C) - if(!istype(C)) - return - if (C in clients) - return - clients.Add(C) - // No operator, so we assume the channel was empty. Assign this user as operator. - if(!operator) - changeop(C) - for(var/datum/computer_file/program/chatclient/CC in clients) - if(CC.program_state > PROGRAM_STATE_KILLED && CC != C) - if(!direct) - CC.computer.output_message(FONT_SMALL("([get_title(CC)]) [C.username] has entered the chat."), 0) +/// EXTERNAL PROCs -/datum/ntnet_conversation/proc/begin_direct(var/datum/computer_file/program/chatclient/CA, var/datum/computer_file/program/chatclient/CB) - if(!istype(CA) || !istype(CB)) - return - direct = TRUE - clients.Add(CA) - clients.Add(CB) - - add_status_message("[CA.username] has opened direct conversation.") - if(CB.program_state > PROGRAM_STATE_KILLED) - CB.computer.output_message(FONT_SMALL("([get_title(CB)]) [CA.username] has opened direct conversation with you."), 0) - -/datum/ntnet_conversation/proc/remove_client(var/datum/computer_file/program/chatclient/C) - if(!istype(C) || !(C in clients)) - return - clients.Remove(C) - - // Channel operator left, pick new operator - if(C == operator) - operator = null - if(clients.len) - var/datum/computer_file/program/chatclient/newop = pick(clients) - changeop(newop) - - for(var/datum/computer_file/program/chatclient/CC in clients) - if(CC.program_state > PROGRAM_STATE_KILLED && CC != C) - CC.computer.output_message(FONT_SMALL("([get_title(CC)]) [C.username] has left the chat."), 0) - - -/datum/ntnet_conversation/proc/changeop(var/datum/computer_file/program/chatclient/newop) - if(istype(newop)) - operator = newop - add_status_message("Channel operator status transferred to [newop.username].") - -/datum/ntnet_conversation/proc/change_title(var/newtitle, var/datum/computer_file/program/chatclient/client) - if(operator != client) - return 0 // Not Authorised - - add_status_message("[client.username] has changed channel title from [get_title(client)] to [newtitle]") - - for(var/datum/computer_file/program/chatclient/C in clients) - if(C.program_state > PROGRAM_STATE_KILLED && C != client) - C.computer.output_message(FONT_SMALL("([get_title(C)]) [client.username] has changed the channel title to [newtitle]."), 0) - title = newtitle - -/datum/ntnet_conversation/proc/get_title(var/datum/computer_file/program/chatclient/cl = null) +/datum/ntnet_conversation/proc/get_title(var/datum/computer_file/program/chat_client/cl = null) if(direct) var/names = list() - for(var/datum/computer_file/program/chatclient/C in clients) - names += C.username - if(cl) - names -= cl.username + for(var/datum/ntnet_user/U in users) + names += U.username + if(istype(cl) && istype(cl.my_user)) + names -= cl.my_user.username return "\[DM] [english_list(names)]" else return title -/datum/ntnet_conversation/proc/get_dead_title() - if(direct) - var/names = list() - for(var/datum/computer_file/program/chatclient/C in clients) - names += C.username - return "\[DM] [english_list(names)]" - else - return title - -/datum/ntnet_conversation/proc/can_see(var/datum/computer_file/program/chatclient/cl) - if(cl in clients) - return TRUE +/datum/ntnet_conversation/proc/can_see(var/datum/computer_file/program/chat_client/cl) if(cl.netadmin_mode) return TRUE + if(istype(cl.my_user)) + if(cl.my_user in users) + return TRUE + else + for(var/datum/ntnet_user/user in users) + if(cl in user.clients) + return TRUE if(!direct) return TRUE return FALSE + +/datum/ntnet_conversation/proc/can_interact(var/datum/computer_file/program/chat_client/cl) + if(cl.netadmin_mode) + return TRUE + if(istype(cl.my_user)) + if(cl.my_user in users) + return TRUE + else + for(var/datum/ntnet_user/user in users) + if(cl in user.clients) + return TRUE + return FALSE + +/datum/ntnet_conversation/proc/can_manage(var/datum/computer_file/program/chat_client/cl) + if(cl.netadmin_mode) + return TRUE + if(cl.my_user == operator) + return TRUE + return FALSE + +/datum/ntnet_conversation/proc/cl_send(var/datum/computer_file/program/chat_client/Cl, var/message, var/mob/user) + if(!istype(Cl) || !can_interact(Cl)) + return + var/datum/ntnet_message/message/msg = new(Cl) + msg.message = message + msg.user = user + process_message(msg) + +/datum/ntnet_conversation/proc/cl_join(var/datum/computer_file/program/chat_client/Cl) + if(!istype(Cl) || !can_see(Cl) || direct) + return + var/datum/ntnet_message/join/msg = new(Cl) + Cl.my_user.channels.Add(src) + users.Add(Cl.my_user) + if(!operator) + operator = Cl.my_user + var/datum/ntnet_message/new_op/msg2 = new(Cl) + process_message(msg, FALSE) + process_message(msg2) + return + process_message(msg) + +/datum/ntnet_conversation/proc/cl_leave(var/datum/computer_file/program/chat_client/Cl) + if(!istype(Cl) || !istype(Cl.my_user) || !(Cl.my_user in users) || !can_interact(Cl) || direct) + return + var/datum/ntnet_message/leave/msg = new(Cl) + Cl.my_user.channels.Remove(src) + users.Remove(Cl.my_user) + if(operator == Cl.my_user) + if(users.len) + operator = pick(users) + var/datum/ntnet_message/new_op/msg2 = new() + msg2.nuser = operator + process_message(msg, FALSE) + process_message(msg2) + return + process_message(msg) + +/datum/ntnet_conversation/proc/cl_change_title(var/datum/computer_file/program/chat_client/Cl, var/newTitle) + if(!istype(Cl) || !istype(Cl.my_user) || !can_manage(Cl) || direct) + return + var/datum/ntnet_message/new_title/msg = new(Cl) + msg.title = newTitle + process_message(msg) + title = newTitle + +/datum/ntnet_conversation/proc/cl_set_password(var/datum/computer_file/program/chat_client/Cl, var/newPassword) + if(!istype(Cl) || !istype(Cl.my_user) || !can_manage(Cl) || direct) + return + if(newPassword) + password = newPassword + else + password = FALSE + +/datum/ntnet_conversation/proc/cl_kick(var/datum/computer_file/program/chat_client/Cl, var/datum/ntnet_user/target) + if(!istype(Cl) || !istype(Cl.my_user) || !can_manage(Cl) || !(target in users) || direct) + return + var/datum/ntnet_message/kick/msg = new(Cl) + msg.target = target + target.channels.Remove(src) + users.Remove(target) + if(operator == target) + if(users.len) + operator = pick(users) + var/datum/ntnet_message/new_op/msg2 = new() + msg2.nuser = operator + process_message(msg, FALSE) + process_message(msg2) + return + process_message(msg) \ No newline at end of file diff --git a/code/modules/modular_computers/NTNet/NTNRC/message.dm b/code/modules/modular_computers/NTNet/NTNRC/message.dm new file mode 100644 index 00000000000..e4e24aa1c89 --- /dev/null +++ b/code/modules/modular_computers/NTNet/NTNRC/message.dm @@ -0,0 +1,96 @@ +// Container for all essesal state for NTRC message while it's proccessed +/datum/ntnet_message + var/mob/user + var/datum/computer_file/program/chat_client/client + var/datum/ntnet_user/nuser + var/play_sound = FALSE + +/datum/ntnet_message/New(var/datum/computer_file/program/chat_client/Pr = null, var/mob/user = null) + if(user) + src.user = user + if(Pr) + client = Pr + nuser = Pr.my_user + +// Should be sanitized +/datum/ntnet_message/proc/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + return FALSE + +/datum/ntnet_message/proc/format_admin_log(var/datum/ntnet_conversation/Conv) + return FALSE + +// Should be sanitized +/datum/ntnet_message/proc/format_ntnet_log(var/datum/ntnet_conversation/Conv) + return FALSE + +/datum/ntnet_message/proc/format_chat_log(var/datum/ntnet_conversation/Conv) + return FALSE + + + +/datum/ntnet_message/message + play_sound = TRUE + var/message = "" + +/datum/ntnet_message/message/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = "([sanitize(Conv.get_title(Cl))]) [nuser.username]: [sanitize(message)] (Reply)" + +/datum/ntnet_message/message/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] [nuser.username]: [message]" + +/datum/ntnet_message/message/format_admin_log(var/datum/ntnet_conversation/Conv) + . = message + +/datum/ntnet_message/message/format_ntnet_log(var/datum/ntnet_conversation/Conv) + . = "[sanitize(Conv.get_title())] [nuser.username]: [sanitize(message)]" + + + +/datum/ntnet_message/join/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = FONT_SMALL("([sanitize(Conv.get_title(Cl))]) [nuser.username] has entered the chat.") + +/datum/ntnet_message/join/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has entered the chat." + + + +/datum/ntnet_message/leave/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = FONT_SMALL("([sanitize(Conv.get_title(Cl))]) [nuser.username] has left the chat.") + +/datum/ntnet_message/leave/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has left the chat." + + + +/datum/ntnet_message/new_op/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has become operator." + + + +/datum/ntnet_message/new_title + var/title = "" + +/datum/ntnet_message/new_title/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has changed channel title from [Conv.get_title()] to [title]" + +/datum/ntnet_message/new_title/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = FONT_SMALL("([sanitize(Conv.get_title(Cl))]) [nuser.username] has changed the channel title to [sanitize(title)].") + + + +/datum/ntnet_message/kick + var/datum/ntnet_user/target + +/datum/ntnet_message/kick/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has kicked [target.username] from conversation." + +/datum/ntnet_message/kick/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = FONT_SMALL("([sanitize(Conv.get_title(Cl))]) [nuser.username] has kicked [target.username] from conversation.") + + + +/datum/ntnet_message/direct/format_chat_log(var/datum/ntnet_conversation/Conv) + . = "[worldtime2text()] -!- [nuser.username] has opened direct conversation." + +/datum/ntnet_message/direct/format_chat_notification(var/datum/ntnet_conversation/Conv, var/datum/computer_file/program/chat_client/Cl) + . = FONT_SMALL("([sanitize(Conv.get_title(Cl))]) [nuser.username] has opened direct conversation with you.") \ No newline at end of file diff --git a/code/modules/modular_computers/NTNet/NTNRC/ntnrc.dm b/code/modules/modular_computers/NTNet/NTNRC/ntnrc.dm new file mode 100644 index 00000000000..db6cd0148ba --- /dev/null +++ b/code/modules/modular_computers/NTNet/NTNRC/ntnrc.dm @@ -0,0 +1,28 @@ +/datum/ntnet + var/list/chat_channels = list() + var/list/chat_clients = list() + var/list/chat_users = list() + +/datum/ntnet/proc/begin_conversation(var/datum/computer_file/program/chat_client/Cl, var/title) + if(!istype(Cl) || !istype(Cl.my_user)) + return + + var/datum/ntnet_conversation/Conv = new(title) + Conv.cl_join(Cl) + + return Conv + +/datum/ntnet/proc/begin_direct(var/datum/computer_file/program/chat_client/Cl, var/datum/ntnet_user/target) + if(!istype(Cl) || !istype(Cl.my_user) || !istype(target) || istype(Cl.my_user.dm_channels[target], /datum/ntnet_conversation)) + return + + var/datum/ntnet_conversation/Conv = new() + Conv.direct = TRUE + Conv.users.Add(Cl.my_user) + Conv.users.Add(target) + + target.dm_channels[Cl.my_user] = Conv + Cl.my_user.dm_channels[target] = Conv + + var/datum/ntnet_message/direct/msg = new(Cl) + Conv.process_message(msg) \ No newline at end of file diff --git a/code/modules/modular_computers/NTNet/NTNRC/user.dm b/code/modules/modular_computers/NTNet/NTNRC/user.dm new file mode 100644 index 00000000000..feb79715bec --- /dev/null +++ b/code/modules/modular_computers/NTNet/NTNRC/user.dm @@ -0,0 +1,21 @@ +/datum/ntnet_user + var/username + var/list/channels = list() + var/list/dm_channels = list() + var/list/clients = list() + +/datum/ntnet_user/New() + . = ..() + ntnet_global.chat_users.Add(src) + +/datum/ntnet_user/Destroy(force) + . = ..() + ntnet_global.chat_users.Remove(src) + +/datum/ntnet_user/proc/generateUsernameIdCard(var/obj/item/card/id/card) + if(!card) + return "Unknown" + return "[card.registered_name] ([card.assignment])" + +/datum/ntnet_user/proc/generateUsernameSilicon(var/mob/living/silicon/silicon) + return silicon.name diff --git a/code/modules/modular_computers/NTNet/NTNet.dm b/code/modules/modular_computers/NTNet/NTNet.dm index f1d53a06b57..e61f97b3d46 100644 --- a/code/modules/modular_computers/NTNet/NTNet.dm +++ b/code/modules/modular_computers/NTNet/NTNet.dm @@ -11,8 +11,6 @@ var/global/datum/ntnet/ntnet_global = new() var/list/available_software = list() var/list/available_software_presets = list() var/list/available_news = list() - var/list/chat_channels = list() - var/list/chat_clients = list() var/list/fileservers = list() var/list/datum/ntnet_account/users = list() // Amount of logs the system tries to keep in memory. Keep below 999 to prevent byond from acting weirdly. diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm index c858e406e36..837b35e2889 100644 --- a/code/modules/modular_computers/computers/modular_computer/core.dm +++ b/code/modules/modular_computers/computers/modular_computer/core.dm @@ -98,7 +98,6 @@ /obj/item/modular_computer/Destroy() kill_program(TRUE) if(registered_id) - registered_id.chat_registered = FALSE registered_id = null for(var/obj/item/computer_hardware/CH in src.get_all_components()) uninstall_component(null, CH) @@ -197,7 +196,7 @@ if(network_card) return network_card.get_signal(specific_action) else - return 0 + return FALSE /obj/item/modular_computer/proc/add_log(var/text) if(!get_ntnet_status()) @@ -366,6 +365,7 @@ /obj/item/modular_computer/proc/enable_service(service, mob/user, var/datum/computer_file/program/S = null) + . = FALSE if(!S) S = hard_drive?.find_file_by_name(service) @@ -382,9 +382,11 @@ return // Start service - if(S.service_activate()) + if(S.service_enable()) enabled_services += S S.service_state = PROGRAM_STATE_ACTIVE + return TRUE + /obj/item/modular_computer/proc/disable_service(service, mob/user, var/datum/computer_file/program/S = null) @@ -399,8 +401,8 @@ enabled_services -= S // Stop service - S.service_deactivate() - S.service_state = PROGRAM_STATE_KILLED + S.service_disable() + S.service_state = PROGRAM_STATE_DISABLED /obj/item/modular_computer/proc/output_message(var/message, var/message_range) message_range += message_output_range @@ -434,12 +436,13 @@ if(!istype(id)) output_error("No ID card found!") return FALSE - if(id.chat_registered) - output_error("This card is already registered to another account!") - return FALSE - id.chat_registered = TRUE registered_id = id + + if(hard_drive) + for(var/datum/computer_file/program/P in hard_drive.stored_files) + P.event_registered() + output_notice("Registration successful!") playsound(get_turf(src), 'sound/machines/ping.ogg', 10, 0) return registered_id @@ -448,12 +451,11 @@ if(!registered_id) return FALSE - registered_id.chat_registered = FALSE - registered_id = null - if(hard_drive) - var/datum/computer_file/program/P = hard_drive.find_file_by_name("ntnrc_client") - P.event_unregistered() + for(var/datum/computer_file/program/P in hard_drive.stored_files) + P.event_unregistered() + + registered_id = null output_message(SPAN_NOTICE("\The [src] beeps: \"Successfully unregistered ID!\"")) playsound(get_turf(src), 'sound/machines/ping.ogg', 20, 0) @@ -476,7 +478,6 @@ return TRUE /obj/item/modular_computer/proc/silence_notifications() - for (var/datum/computer_file/program/P in hard_drive.stored_files) - if (istype(P)) - P.event_silentmode() silent = !silent + for (var/datum/computer_file/program/P in hard_drive.stored_files) + P.event_silentmode() diff --git a/code/modules/modular_computers/computers/modular_computer/power.dm b/code/modules/modular_computers/computers/modular_computer/power.dm index 183ad33294e..97ee8674215 100644 --- a/code/modules/modular_computers/computers/modular_computer/power.dm +++ b/code/modules/modular_computers/computers/modular_computer/power.dm @@ -3,8 +3,9 @@ visible_message(SPAN_WARNING("\The [src]'s screen flickers briefly and then goes dark.")) if(active_program) active_program.event_powerfailure(FALSE) - for(var/datum/computer_file/program/PRG in idle_threads) - PRG.event_powerfailure(TRUE) + for(var/datum/computer_file/program/PRG in hard_drive.stored_files) + if(PRG != active_program) + PRG.event_powerfailure(TRUE) shutdown_computer(FALSE) power_has_failed = TRUE update_icon() diff --git a/code/modules/modular_computers/computers/modular_computer/variables.dm b/code/modules/modular_computers/computers/modular_computer/variables.dm index 6810fc99494..9b79adeab84 100644 --- a/code/modules/modular_computers/computers/modular_computer/variables.dm +++ b/code/modules/modular_computers/computers/modular_computer/variables.dm @@ -4,6 +4,7 @@ name = "Modular Computer" desc = "A modular computer. You shouldn't see this." + var/lexical_name = "computer" var/enabled = FALSE // Whether the computer is turned on. var/screen_on = TRUE // Whether the computer is active/opened/it's screen is on. var/working = TRUE // Whether the computer is working. diff --git a/code/modules/modular_computers/computers/subtypes/dev_handheld.dm b/code/modules/modular_computers/computers/subtypes/dev_handheld.dm index 0ffe87b34c6..4cb40032295 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_handheld.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_handheld.dm @@ -1,5 +1,6 @@ /obj/item/modular_computer/handheld name = "tablet computer" + lexical_name = "tablet" desc = "A portable device for your needs on the go." desc_info = "To deploy the charging cable on this device, either drag and drop it over a nearby APC, or click on the APC with the computer in hand." icon = 'icons/obj/modular_tablet.dmi' diff --git a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm index 38df46a87b7..0090c80e083 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm @@ -1,6 +1,7 @@ /obj/item/modular_computer/laptop anchored = TRUE name = "laptop computer" + lexical_name = "laptop" desc = "A portable computer." desc_info = "You can alt-click the laptop while it's set down on surface to open it up and work with it. Left clicking while it is open will allow you to operate it." hardware_flag = PROGRAM_LAPTOP diff --git a/code/modules/modular_computers/computers/subtypes/dev_pda.dm b/code/modules/modular_computers/computers/subtypes/dev_pda.dm index 00c61b358e7..12369654393 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_pda.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_pda.dm @@ -1,5 +1,6 @@ /obj/item/modular_computer/handheld/pda name = "PDA" + lexical_name = "tablet" desc = "The latest in portable microcomputer solutions from Thinktronic Systems, LTD." icon = 'icons/obj/pda.dmi' icon_state = "pda" diff --git a/code/modules/modular_computers/computers/subtypes/dev_silicon.dm b/code/modules/modular_computers/computers/subtypes/dev_silicon.dm index 1ea422ac828..6767be11604 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_silicon.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_silicon.dm @@ -53,7 +53,7 @@ /obj/item/modular_computer/silicon/install_default_programs() hard_drive.store_file(new /datum/computer_file/program/filemanager(src)) hard_drive.store_file(new /datum/computer_file/program/ntnetdownload(src)) - hard_drive.store_file(new /datum/computer_file/program/chatclient(src)) + hard_drive.store_file(new /datum/computer_file/program/chat_client(src)) hard_drive.remove_file(hard_drive.find_file_by_name("clientmanager")) addtimer(CALLBACK(src, .proc/register_chat), 1 SECOND) @@ -62,24 +62,6 @@ enable_computer(null, TRUE) // passing null because we don't want the UI to open minimize_program() -/obj/item/modular_computer/silicon/verb/send_pda_message() - set category = "AI IM" - set name = "Send Direct Message" - set src in usr - if (usr.stat == DEAD) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - var/datum/computer_file/program/chatclient/CL = hard_drive.find_file_by_name("ntnrc_client") - if(!istype(CL)) - output_error("Chat client not installed!") - return - else if(CL.program_state == PROGRAM_STATE_KILLED) - run_program("ntnrc_client") - - CL.direct_message() - if(CL.channel) - CL.add_message(CL.send_message()) - /obj/item/modular_computer/silicon/robot/drone/install_default_programs() hard_drive.store_file(new /datum/computer_file/program/filemanager(src)) hard_drive.store_file(new /datum/computer_file/program/ntnetdownload(src)) diff --git a/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm b/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm index fffd01dd33c..f7c25243ea5 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm @@ -1,5 +1,6 @@ /obj/item/modular_computer/handheld/wristbound name = "wristbound computer" + lexical_name = "wristbound" desc = "A portable wristbound device for your needs on the go. Quite comfortable." desc_fluff = "A NanoTrasen design, this wristbound computer allows the user to quickly and safely access critical info, without taking their hands out of the equation." icon = 'icons/obj/modular_wristbound.dmi' diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 62c64e649fe..e3b727ea8df 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -24,7 +24,7 @@ var/computer_emagged = FALSE // Set to TRUE if computer that's running us was emagged. Computer updates this every Process() tick var/ui_header // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /nano/images/status_icons. Be careful not to use too large images! var/color = "#FFFFFF" // The color of light the computer should emit when this program is open. - var/service_state = PROGRAM_STATE_KILLED // PROGRAM_STATE_KILLED or PROGRAM_STATE_ACTIVE - specifies whether this program's service is running. + var/service_state = PROGRAM_STATE_DISABLED // PROGRAM_STATE_KILLED or PROGRAM_STATE_ACTIVE - specifies whether this program's service is running. var/silent = FALSE /datum/computer_file/program/New(var/obj/item/modular_computer/comp) @@ -196,27 +196,6 @@ if(computer) return computer.get_header_data() -// This is performed on program startup. May be overriden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure. -// When implementing new program based device, use this to run the program. -/datum/computer_file/program/proc/run_program(var/mob/user) - if(can_run(user, 1) || !requires_access_to_run) - if(nanomodule_path) - NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src) - if(requires_ntnet && network_destination) - generate_network_log("Connection opened to [network_destination].") - program_state = PROGRAM_STATE_ACTIVE - return TRUE - return FALSE - -// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. -/datum/computer_file/program/proc/kill_program(var/forced = 0) - program_state = PROGRAM_STATE_KILLED - if(network_destination) - generate_network_log("Connection to [network_destination] closed.") - if(NM) - qdel(NM) - NM = null - return TRUE // This is called every tick when the program is enabled. Ensure you do parent call if you override it. If parent returns 1 continue with UI initialisation. // It returns 0 if it can't run or if NanoModule was used instead. I suggest using NanoModules where applicable. @@ -248,18 +227,9 @@ else return -1 -// Is called when program service is being activated -// Returns 1 if service startup was sucessfull -/datum/computer_file/program/proc/service_activate() - return FALSE - -// Is called when program service is being deactivated -/datum/computer_file/program/proc/service_deactivate() - return - /datum/computer_file/program/proc/message_dead(var/message) for(var/mob/M in player_list) if(M.stat == DEAD && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS)) if(isnewplayer(M)) continue - to_chat(M, message) + to_chat(M, message) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm index 8172ddcb299..a0d469ae79b 100644 --- a/code/modules/modular_computers/file_system/program_events.dm +++ b/code/modules/modular_computers/file_system/program_events.dm @@ -1,6 +1,47 @@ // Events are sent to the program by the computer. // Always include a parent call when overriding an event. +// This is performed on program startup. May be overriden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure. +// When implementing new program based device, use this to run the program. +/datum/computer_file/program/proc/run_program(var/mob/user) + if(can_run(user, 1) || !requires_access_to_run) + if(nanomodule_path) + NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src) + if(requires_ntnet && network_destination) + generate_network_log("Connection opened to [network_destination].") + program_state = PROGRAM_STATE_ACTIVE + return TRUE + return FALSE + +// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. +/datum/computer_file/program/proc/kill_program(var/forced = 0) + program_state = PROGRAM_STATE_KILLED + if(network_destination) + generate_network_log("Connection to [network_destination] closed.") + if(NM) + qdel(NM) + NM = null + return TRUE + +// Is called when program service is being activated +// Returns 1 if service startup was sucessfull +/datum/computer_file/program/proc/service_activate() + return FALSE + +// Is called when program service is being deactivated +/datum/computer_file/program/proc/service_deactivate() + return + +// Is called when program service is being activated for first time. +/datum/computer_file/program/proc/service_enable() + return service_activate() + +// Is called when program service is being deactivated without +/datum/computer_file/program/proc/service_disable() + return service_deactivate() + +/// SECOND ORDER EVENTS + // Called when the ID card is removed from computer. ID is removed AFTER this proc. /datum/computer_file/program/proc/event_idremoved(var/background) return @@ -9,12 +50,17 @@ return // Called when an ID is unregistered from the device. -/datum/computer_file/program/proc/event_unregistered(var/background) +/datum/computer_file/program/proc/event_unregistered() + return + +// Called when an ID is unregistered from the device. +/datum/computer_file/program/proc/event_registered() return // Called when the computer fails due to power loss. Override when program wants to specifically react to power loss. /datum/computer_file/program/proc/event_powerfailure(var/background) - kill_program(TRUE) + if(program_state > PROGRAM_STATE_KILLED) + kill_program(TRUE) // Called when the network connectivity fails. Computer does necessary checks and only calls this when requires_ntnet_feature and similar variables are not met. /datum/computer_file/program/proc/event_networkfailure(var/background) diff --git a/code/modules/modular_computers/file_system/programs/app_presets.dm b/code/modules/modular_computers/file_system/programs/app_presets.dm index b5b771662ea..5cc1792e079 100644 --- a/code/modules/modular_computers/file_system/programs/app_presets.dm +++ b/code/modules/modular_computers/file_system/programs/app_presets.dm @@ -32,7 +32,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/power_monitor(comp), new /datum/computer_file/program/alarm_monitor(comp), @@ -56,7 +56,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/power_monitor(comp), new /datum/computer_file/program/alarm_monitor(comp), @@ -81,7 +81,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/comm(comp, FALSE), new /datum/computer_file/program/game/sudoku(comp), @@ -108,7 +108,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/suit_sensors(comp), new /datum/computer_file/program/records/medical(comp), @@ -130,7 +130,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/comm(comp, FALSE), new /datum/computer_file/program/suit_sensors(comp), @@ -155,7 +155,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/ntnetmonitor(comp), new /datum/computer_file/program/aidiag(comp), @@ -178,7 +178,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/ntnetmonitor(comp), new /datum/computer_file/program/aidiag(comp), @@ -201,7 +201,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/comm(comp, FALSE), new /datum/computer_file/program/ntnetmonitor(comp), @@ -225,7 +225,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/card_mod(comp), new /datum/computer_file/program/comm(comp, FALSE), @@ -246,7 +246,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/civilian/cargocontrol(comp), new /datum/computer_file/program/card_mod(comp), @@ -269,7 +269,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/card_mod(comp), new /datum/computer_file/program/comm(comp, FALSE), new /datum/computer_file/program/camera_monitor(comp), @@ -317,7 +317,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/camera_monitor(comp), new /datum/computer_file/program/comm(comp), @@ -341,7 +341,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/camera_monitor(comp), new /datum/computer_file/program/comm(comp), @@ -367,7 +367,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/camera_monitor(comp), new /datum/computer_file/program/digitalwarrant(comp), new /datum/computer_file/program/penal_mechs(comp), @@ -391,7 +391,7 @@ new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/filemanager(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/comm(comp, FALSE), new /datum/computer_file/program/camera_monitor(comp), @@ -415,7 +415,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/game/arcade(comp), new /datum/computer_file/program/game/sudoku(comp), @@ -435,7 +435,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/civilian/janitor(comp), new /datum/computer_file/program/game/arcade(comp), @@ -468,7 +468,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargocontrol(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/civilian/cargodelivery(comp), @@ -488,7 +488,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargodelivery(comp), new /datum/computer_file/program/ntsl2_interpreter(comp) ) @@ -506,7 +506,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/game/sudoku(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/records/employment(comp), @@ -525,7 +525,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/newsbrowser(comp), new /datum/computer_file/program/manifest(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/civilian/cargoorder(comp), new /datum/computer_file/program/camera_monitor(comp), new /datum/computer_file/program/alarm_monitor(comp), @@ -594,7 +594,7 @@ new /datum/computer_file/program/filemanager(comp), new /datum/computer_file/program/manifest(comp), new /datum/computer_file/program/newsbrowser(comp), - new /datum/computer_file/program/chatclient(comp), + new /datum/computer_file/program/chat_client(comp), new /datum/computer_file/program/merchant(comp) ) return _prg_list diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index c1bf676e2c3..a4bac57b0a4 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -1,381 +1,253 @@ -/datum/computer_file/program/chatclient +/datum/computer_file/program/chat_client filename = "ntnrc_client" filedesc = "Chat Client" program_icon_state = "command" - extended_desc = "This program allows communication over the NTNRC network." + extended_desc = "This program allows communication over the NTRC network." size = 2 requires_ntnet = TRUE requires_ntnet_feature = NTNET_COMMUNICATION - network_destination = "NTNRC server" - ui_header = "ntnrc_idle.gif" + program_type = PROGRAM_TYPE_ALL + network_destination = "NTRC server" available_on_ntnet = TRUE - nanomodule_path = /datum/nano_module/program/computer_chatclient color = LIGHT_COLOR_GREEN silent = FALSE - var/last_message // Used to generate the toolbar icon - var/username - var/datum/ntnet_conversation/channel - var/operator_mode = FALSE // Channel operator mode + var/datum/ntnet_user/my_user var/netadmin_mode = FALSE // Administrator mode (invisible to other users + bypasses passwords) - var/set_offline = FALSE // appear "invisible" - var/list/directmessagechannels = list() + var/set_offline = FALSE // appear "invisible" var/ringtone = "beep" var/syndi_auth = FALSE -/datum/computer_file/program/chatclient/New(var/obj/item/modular_computer/comp) - ..(comp) - if(!comp) - return -/datum/computer_file/program/chatclient/Destroy() - ntnet_global.chat_clients -= src +/datum/computer_file/program/chat_client/Destroy() return ..() -/datum/computer_file/program/chatclient/Topic(href, href_list) +/datum/computer_file/program/chat_client/proc/can_receive_notification(var/datum/computer_file/program/chat_client/from) + return ((program_state > PROGRAM_STATE_KILLED || service_state > PROGRAM_STATE_KILLED) && from != src && get_signal(NTNET_COMMUNICATION)) + +/datum/computer_file/program/chat_client/proc/play_notification_sound(var/datum/computer_file/program/chat_client/from) + if(!silent && src != from && program_state == PROGRAM_STATE_BACKGROUND) + playsound(computer, 'sound/machines/twobeep.ogg', 50, 1) + computer.output_message("[icon2html(computer, world)] *[ringtone]*", 2) + +/datum/computer_file/program/chat_client/Topic(href, href_list) if(..()) return TRUE - - if(href_list["PRG_toggleringer"]) - . = TRUE - silent = !silent - - if(href_list["PRG_setringtone"]) - . = TRUE - var/t = input(usr, "Please enter new ringtone", filedesc, ringtone) as text|null - if(!usr.Adjacent(computer) || !t) - return + + if(href_list["ringtone"]) + var/newRingtone = href_list["ringtone"] var/obj/item/device/uplink/hidden/H = computer.hidden_uplink - if(istype(H) && H.check_trigger(usr, lowertext(t), lowertext(H.pda_code))) + if(istype(H) && H.check_trigger(usr, lowertext(newRingtone), lowertext(H.pda_code))) to_chat(usr, SPAN_NOTICE("\The [computer] softly beeps.")) syndi_auth = TRUE - SSnanoui.close_uis(NM) + SSvueui.close_uis(src) else - t = sanitize(t, 20) - ringtone = t - - if(href_list["PRG_speak"]) - . = TRUE - add_message(send_message()) - - if(href_list["Reply"]) - . = TRUE - var/datum/ntnet_conversation/C = locate(href_list["Reply"]) in ntnet_global.chat_channels - if(!istype(C)) - to_chat(usr, SPAN_WARNING("The target channel couldn't be found and has likely been deleted!")) - return - var/message = send_message() - if(!(C in ntnet_global.chat_channels)) - to_chat(usr, SPAN_WARNING("The target channel couldn't be found and has likely been deleted!")) - return - add_message(message, C) - - if(href_list["PRG_joinchannel"]) - . = TRUE - var/datum/ntnet_conversation/C - for(var/datum/ntnet_conversation/chan in ntnet_global.chat_channels) - if(chan.id == text2num(href_list["PRG_joinchannel"])) - C = chan - break - - if(!C) - return TRUE - - if(netadmin_mode) - channel = C // Bypasses normal leave/join and passwords. Technically makes the user invisible to others. - return TRUE - - if(C.password) - var/mob/living/user = usr - var/password = sanitize(input(user, "Access Denied. Enter password:")) - if(C?.password == password) - C.add_client(src) - channel = C - return TRUE - C.add_client(src) - message_dead(FONT_SMALL("([C.get_dead_title()]) A new client ([username]) has entered the chat.")) - channel = C - if(href_list["PRG_leavechannel"]) - . = TRUE - if(channel && !channel.direct) - channel.remove_client(src) - message_dead(FONT_SMALL(FONT_SMALL("([channel.get_dead_title()]) A client ([username]) has left the chat."))) - channel = null - if(href_list["PRG_backtomain"]) - . = TRUE - channel = null - if(href_list["PRG_newchannel"]) - . = TRUE + newRingtone = sanitize(newRingtone, 20) + ringtone = newRingtone + SSvueui.check_uis_for_change(src) + + // User only commands + if(!istype(my_user)) + return + // Following actions require signal + if(!get_signal(NTNET_COMMUNICATION)) + return + + if(href_list["send"]) var/mob/living/user = usr - var/channel_title = sanitize(input(user, "Enter channel name or leave blank to cancel:")) - if(!channel_title) - return - var/datum/ntnet_conversation/C = new /datum/ntnet_conversation(channel_title) - C.add_client(src) - C.operator = src - channel = C - message_dead(FONT_SMALL("([channel.get_dead_title()]) A new channel has been made by [username].")) - if(href_list["PRG_toggleadmin"]) - . = TRUE + var/datum/ntnet_conversation/conv = locate(href_list["send"]["target"]) + var/message = href_list["send"]["message"] + if(istype(conv) && message) + if(ishuman(user)) + user.visible_message("[SPAN_BOLD("\The [user]")] taps on [user.get_pronoun("his")] [computer.lexical_name]'s screen.") + conv.cl_send(src, message, user) + if(href_list["join"]) + var/datum/ntnet_conversation/conv = locate(href_list["join"]["target"]) + var/password = href_list["join"]["password"] + if(istype(conv)) + if(conv.password) + if(conv.password == password) + conv.cl_join(src) + else + // How do I alert of password invalid? + else + conv.cl_join(src) + if(href_list["leave"]) + var/datum/ntnet_conversation/conv = locate(href_list["leave"]) + if(istype(conv)) + conv.cl_leave(src) + SSvueui.check_uis_for_change(src) + if(href_list["kick"]) + var/datum/ntnet_conversation/conv = locate(href_list["kick"]["target"]) + var/datum/ntnet_user/tUser = locate(href_list["kick"]["user"]) + if(istype(conv) && istype(tUser)) + conv.cl_kick(src, tUser) + if(href_list["set_password"]) + var/datum/ntnet_conversation/conv = locate(href_list["set_password"]["target"]) + var/password = href_list["set_password"]["password"] + if(istype(conv)) + conv.cl_set_password(src, password) + if(href_list["change_title"]) + var/datum/ntnet_conversation/conv = locate(href_list["change_title"]["target"]) + var/newTitle = href_list["change_title"]["title"] + if(istype(conv)) + conv.cl_change_title(src, newTitle) + if(href_list["new_channel"]) + ntnet_global.begin_conversation(src, sanitize(href_list["new_channel"])) + if(href_list["delete"]) + var/datum/ntnet_conversation/conv = locate(href_list["delete"]) + if(istype(conv) && conv.can_manage(src)) + ntnet_global.chat_channels.Remove(conv) + qdel(conv) + SSvueui.check_uis_for_change(src) + if(href_list["direct"]) + var/datum/ntnet_user/tUser = locate(href_list["direct"]) + ntnet_global.begin_direct(src, tUser) + + if(href_list["toggleadmin"]) if(netadmin_mode) netadmin_mode = FALSE - if(channel) - channel.remove_client(src) // We shouldn't be in channel's user list, but just in case... - channel = null - return TRUE - var/mob/living/user = usr - if(can_run(usr, 1, access_network)) - if(channel) - var/response = alert(user, "Really engage admin-mode? You will be disconnected from your current channel!", "NTNRC Admin mode", "Yes", "No") - if(response == "Yes") - if(channel) - channel.remove_client(src) - channel = null - else - return - netadmin_mode = TRUE - if(href_list["PRG_changename"]) - . = TRUE - var/mob/living/user = usr - var/new_name = sanitize(input(user, "Enter new nickname or leave blank to cancel:")) - if(!new_name) - return TRUE - var/comp_name = ckey(new_name) - for(var/cl in ntnet_global.chat_clients) - var/datum/computer_file/program/chatclient/C = cl - if(ckey(C.username) == comp_name || comp_name == "cancel") - alert(user, "This nickname is already taken.") - return TRUE - for(var/datum/ntnet_conversation/channel in ntnet_global.chat_channels) - if(src in channel.clients) - channel.add_status_message("[username] is now known as [new_name].") - username = new_name - if(href_list["PRG_savelog"]) - . = TRUE - if(!channel) - return - var/mob/living/user = usr - var/logname = input(user, "Enter desired logfile name (.log) or leave blank to cancel:") - if(!logname || !channel) - return TRUE - var/datum/computer_file/data/logfile = new /datum/computer_file/data/logfile() - // Now we will generate HTML-compliant file that can actually be viewed/printed. - logfile.filename = logname - logfile.stored_data = "\[b\]Logfile dump from NTNRC channel [channel.title]\[/b\]\[BR\]" - for(var/logstring in channel.messages) - logfile.stored_data += "[logstring]\[BR\]" - logfile.stored_data += "\[b\]Logfile dump completed.\[/b\]" - logfile.calculate_size() - if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(logfile)) - if(!computer) - // This program shouldn't even be runnable without computer. - crash_with("Var computer is null!") - return TRUE - if(!computer.hard_drive) - computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.") - else // In 99.9% cases this will mean our HDD is full - computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.") - if(href_list["PRG_renamechannel"]) - . = TRUE - if(!operator_mode || !channel) - return TRUE - var/mob/living/user = usr - var/newname = sanitize(input(user, "Enter new channel name or leave blank to cancel:")) - if(!newname || !channel) - return - channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.") - channel.title = newname - if(href_list["PRG_deletechannel"]) - . = TRUE - if(channel && ((channel.operator == src) || netadmin_mode)) - qdel(channel) - channel = null - if(href_list["PRG_setpassword"]) - . = TRUE - if(!channel || ((channel.operator != src) && !netadmin_mode)) - return TRUE - - var/mob/living/user = usr - var/newpassword = sanitize(input(user, "Enter new password for this channel. Leave blank to cancel, enter 'nopassword' to remove password completely:")) - if(!channel || !newpassword || ((channel.operator != src) && !netadmin_mode)) - return TRUE - - if(newpassword == "nopassword") - channel.password = "" else - channel.password = newpassword - if(href_list["PRG_directmessage"]) - . = TRUE - direct_message(usr) - -/datum/computer_file/program/chatclient/proc/send_message() - var/mob/living/user = usr - if(ishuman(user)) - user.visible_message("[SPAN_BOLD("\The [user]")] taps on [user.get_pronoun("his")] computer's screen.") - var/message = sanitize(input(user, "Enter a message to send: ") as null|text) - if(!message) - return - return message - -/datum/computer_file/program/chatclient/proc/add_message(var/message, var/datum/ntnet_conversation/specific_channel) - if(!message) - return - var/datum/ntnet_conversation/sent_channel - if(specific_channel) - sent_channel = specific_channel + var/mob/living/user = usr + if(can_run(user, TRUE, access_network)) + netadmin_mode = TRUE + SSvueui.check_uis_for_change(src) + if(href_list["Reply"]) + var/mob/living/user = usr + var/datum/ntnet_conversation/conv = locate(href_list["Reply"]) + var/message = input(user, "Enter message or leave blank to cancel: ") + if(istype(conv) && message) + if(ishuman(user)) + user.visible_message("[SPAN_BOLD("\The [user]")] taps on [user.get_pronoun("his")] [computer.lexical_name]'s screen.") + conv.cl_send(src, message, user) + + +/datum/computer_file/program/chat_client/service_activate() + . = ..() + if(istype(my_user) && get_signal(NTNET_COMMUNICATION)) + activate_chat_client() + return TRUE else - sent_channel = channel - if(!sent_channel) // panikk - geeves - return - sent_channel.add_message(message, username, usr) - message_dead(FONT_SMALL("([sent_channel.get_dead_title()]) [username]: [message]")) + return FALSE -/datum/computer_file/program/chatclient/proc/direct_message(var/mob/user) - var/clients = list() - var/names = list() - for(var/cl in ntnet_global.chat_clients - src) - var/datum/computer_file/program/chatclient/C = cl - if(C.set_offline) - continue - clients[C.username] = C - names += C.username - if(!length(names)) - to_chat(user, SPAN_WARNING("You are the only user with an active account!")) - return - var/picked = input(user, "Select with whom you would like to start a conversation.") as null|anything in names - if(!picked) - return - var/datum/computer_file/program/chatclient/otherClient = clients[picked] - if(picked) - if(directmessagechannels[otherClient]) - channel = directmessagechannels[otherClient] - return - var/datum/ntnet_conversation/C = new /datum/ntnet_conversation("", TRUE) - C.begin_direct(src, otherClient) - channel = C - directmessagechannels[otherClient] = C - otherClient.directmessagechannels[src] = C +/datum/computer_file/program/chat_client/service_deactivate() + . = ..() + deactivate_chat_client() +/datum/computer_file/program/chat_client/process_tick() + . = ..() -/datum/computer_file/program/chatclient/process_tick() - ..() - if(program_state != PROGRAM_STATE_KILLED) - ui_header = "ntnrc_idle.gif" - if(channel) - // Remember the last message. If there is no message in the channel remember null. - if(length(channel.messages) > 1) // len - 1 = 0 and that's array out of bounds - last_message = channel.messages[channel.messages.len - 1] - else - last_message = null +/datum/computer_file/program/chat_client/kill_program(var/forced = FALSE) + return ..(forced) + +/datum/computer_file/program/chat_client/run_program(var/mob/user) + if(!istype(my_user)) + if(istype(computer, /obj/item/modular_computer/silicon)) + var/obj/item/modular_computer/silicon/SC = computer + var/mob/living/silicon/S = SC.computer_host + S.id_card.InitializeChatUser() + my_user = S.id_card.chat_user else - last_message = null - return 1 - if(channel?.messages?.len) - ui_header = last_message == channel.messages[channel.messages.len - 1] ? "ntnrc_idle.gif" : "ntnrc_new.gif" - else - ui_header = "ntnrc_idle.gif" - -/datum/computer_file/program/chatclient/kill_program(var/forced = FALSE) - if(!forced) - var/confirm = alert("Are you sure you want to close the NTNRC Client? You will not be reachable via messaging if you do so.", "Close?", "Yes", "No") - if((confirm != "Yes") || (CanUseTopic(usr) != STATUS_INTERACTIVE)) - return FALSE - - ntnet_global.chat_clients -= src - - channel = null - ..(forced) - return TRUE - -/datum/computer_file/program/chatclient/run_program(var/mob/user) - if(!computer) - return - if(!istype(computer, /obj/item/modular_computer/silicon)) - if((!computer.registered_id && !computer.register_account(src))) + if((!computer.registered_id && !computer.register_account(src))) + return + if(service_state == PROGRAM_STATE_DISABLED) + if(!computer.enable_service(null, user, src)) return - if(!(src in ntnet_global.chat_clients)) - ntnet_global.chat_clients += src - if(!username) - username = username_from_id() return ..(user) -/datum/computer_file/program/chatclient/proc/username_from_id() - if(istype(computer, /obj/item/modular_computer/silicon)) - var/obj/item/modular_computer/silicon/SC = computer - return SC.computer_host.name - if(!computer.registered_id) - return "Unknown" +/datum/computer_file/program/chat_client/event_registered() + . = ..() + computer.registered_id.InitializeChatUser() + my_user = computer.registered_id.chat_user + if(service_state > PROGRAM_STATE_KILLED) + activate_chat_client() + - return "[computer.registered_id.registered_name] ([computer.registered_id.assignment])" +/datum/computer_file/program/chat_client/event_unregistered() + . = ..() + if(service_state > PROGRAM_STATE_KILLED) + deactivate_chat_client() + my_user = null -/datum/computer_file/program/chatclient/event_unregistered() - ..() - computer.set_autorun(filename) - ntnet_global.chat_clients -= src - kill_program(TRUE) +/datum/computer_file/program/chat_client/event_silentmode() + . = ..() + silent = computer.silent -/datum/computer_file/program/chatclient/event_silentmode() - ..() - if(computer.silent != silent) - silent = computer.silent -/datum/nano_module/program/computer_chatclient - name = "Chat Client" - -/datum/nano_module/program/computer_chatclient/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - if(!ntnet_global || !ntnet_global.chat_channels) - return - - var/datum/computer_file/program/chatclient/C = program - - if(C.computer.hidden_uplink && C.syndi_auth) - if(alert(user, "Resume or close and secure?", name, "Resume", "Close") == "Resume") - C.computer.hidden_uplink.trigger(user) +/datum/computer_file/program/chat_client/ui_interact(var/mob/user) + if(computer.hidden_uplink && syndi_auth) + if(alert(user, "Resume or close and secure?", filedesc, "Resume", "Close") == "Resume") + computer.hidden_uplink.trigger(user) return else - C.syndi_auth = FALSE + syndi_auth = FALSE - var/list/data = list() - if(program) - data = list("_PC" = program.get_header_data()) - - if(!istype(C)) - return - - data["adminmode"] = C.netadmin_mode - if(C.channel) - data["title"] = C.channel.get_title(C) - var/list/messages[0] - for(var/M in C.channel.messages) - messages.Add(list(list( - "msg" = M - ))) - data["messages"] = messages - var/list/clients[0] - for(var/datum/computer_file/program/chatclient/cl in C.channel.clients) - clients.Add(list(list( - "name" = cl.username, - "active" = cl.program_state > PROGRAM_STATE_KILLED - ))) - data["clients"] = clients - C.operator_mode = (C.channel.operator == C) ? 1 : 0 - data["is_operator"] = C.operator_mode || C.netadmin_mode - data["is_direct"] = C.channel.direct - else // Channel selection screen - var/list/all_channels[0] - for(var/datum/ntnet_conversation/conv in ntnet_global.chat_channels) - if(conv && conv.title && conv.can_see(program)) - all_channels.Add(list(list( - "chan" = conv.get_title(C), - "id" = conv.id, - "con" = (program in conv.clients) - ))) - data["all_channels"] = all_channels - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + var/datum/vueui/ui = SSvueui.get_open_ui(user, src) if (!ui) - ui = new(user, src, ui_key, "ntnet_chat.tmpl", "NTNet Relay Chat Client", 575, 700, state = state) - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(TRUE) + ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-chat-index", 600, 500, capitalize(filedesc)) + ui.open() + +/datum/computer_file/program/chat_client/vueui_transfer(oldobj) + SSvueui.transfer_uis(oldobj, src, "mcomputer-chat-index", 600, 500, capitalize(filedesc)) + return TRUE + +/datum/computer_file/program/chat_client/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui) + . = ..() + data = . || data || list() + // Gather data for computer header + var/headerdata = get_header_data(data["_PC"]) + if(headerdata) + data["_PC"] = headerdata + . = data + + data["service"] = service_state > PROGRAM_STATE_KILLED + data["registered"] = istype(my_user) + data["signal"] = get_signal(NTNET_COMMUNICATION) + data["ringtone"] = ringtone + data["netadmin_mode"] = netadmin_mode + data["can_netadmin_mode"] = can_run(user, FALSE, access_network) + + if(data["registered"] && data["service"] && data["signal"]) + data["channels"] = list() + for(var/c in ntnet_global.chat_channels) + var/datum/ntnet_conversation/Channel = c + if(istype(Channel) && Channel.can_see(src)) + var/ref = ref(Channel) + var/can_interact = Channel.can_interact(src) + var/can_manage = Channel.can_manage(src) + data["channels"][ref] = list( + "title" = Channel.get_title(src), + "direct" = Channel.direct, + "password" = !!Channel.password, + "can_interact" = can_interact, + "can_manage" = can_manage + ) + if(can_interact) + data["channels"][ref]["msg"] = Channel.messages + data["channels"][ref]["users"] = list() + for(var/datum/ntnet_user/U in Channel.users) + var/uref = ref(U) + data["channels"][ref]["users"][uref] = U.username + data["users"] = list() + for(var/u in ntnet_global.chat_users) + var/datum/ntnet_user/nUser = u + if(nUser != my_user) + var/ref = ref(nUser) + data["users"][ref] = nUser.username + return data + +/datum/computer_file/program/chat_client/proc/activate_chat_client() + if(!istype(my_user)) + return + if(!(src in my_user.clients)) + my_user.clients.Add(src) + if(!(src in ntnet_global.chat_clients)) + ntnet_global.chat_clients.Add(src) + +/datum/computer_file/program/chat_client/proc/deactivate_chat_client() + if(!istype(my_user)) + return + if(src in my_user.clients) + my_user.clients.Remove(src) + if(src in ntnet_global.chat_clients) + ntnet_global.chat_clients.Remove(src) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/system/client_manager.dm b/code/modules/modular_computers/file_system/programs/system/client_manager.dm index 6374d725a21..a38b2f5f0ea 100644 --- a/code/modules/modular_computers/file_system/programs/system/client_manager.dm +++ b/code/modules/modular_computers/file_system/programs/system/client_manager.dm @@ -70,7 +70,7 @@ computer.enrolled = 2 // private devices computer.hard_drive.store_file(new /datum/computer_file/program/filemanager(computer)) computer.hard_drive.store_file(new /datum/computer_file/program/ntnetdownload(computer)) - computer.hard_drive.store_file(new /datum/computer_file/program/chatclient(computer)) + computer.hard_drive.store_file(new /datum/computer_file/program/chat_client(computer)) return TRUE //Set´s up the programs from the preset diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 39e6d5d0b35..8d0b9dec0f7 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -82,6 +82,7 @@ var/list/genetic_markings // Markings (body_markings) to apply to the icon var/list/temporary_markings // Same as above, but not preserved when cloning var/list/cached_markings // The two above lists cached for perf. reasons. + var/list/additional_images var/atom/movable/applied_pressure //Pressure applied to wounds. It'll make them bleed less, generally. diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index c3fd7fce6c9..61fd17c31c8 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -112,6 +112,7 @@ if(vampire && (vampire.status & VAMP_FRENZIED)) var/image/return_image = image(H.species.eyes_icons, H, "[H.species.eyes]_frenzy", EFFECTS_ABOVE_LIGHTING_LAYER) return_image.appearance_flags = KEEP_APART + LAZYADD(additional_images, return_image) return list(return_image) /obj/item/organ/external/proc/apply_markings(restrict_to_robotic = FALSE) @@ -223,6 +224,11 @@ /obj/item/organ/external/proc/get_additional_images(var/mob/living/carbon/human/H) return +/obj/item/organ/external/proc/cut_additional_images(var/mob/living/carbon/human/H) + if(LAZYLEN(additional_images)) + H.cut_overlay(additional_images, TRUE) + LAZYCLEARLIST(additional_images) + // 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/projectiles/guns/energy/disrupter.dm b/code/modules/projectiles/guns/energy/disrupter.dm index f08d5eaf51b..ec12cef41d1 100644 --- a/code/modules/projectiles/guns/energy/disrupter.dm +++ b/code/modules/projectiles/guns/energy/disrupter.dm @@ -17,7 +17,6 @@ secondary_projectile_type = /obj/item/projectile/energy/blaster max_shots = 8 charge_cost = 150 - fire_delay = 8 accuracy = 1 has_item_ratio = FALSE modifystate = "disruptorpistolstun" @@ -35,7 +34,7 @@ name = "miniature disruptor pistol" desc = "A Nanotrasen designed blaster pistol with two settings: stun and lethal. This is the miniature version." icon = 'icons/obj/guns/disruptorpistol/disruptorpistolc.dmi' - max_shots = 5 + max_shots = 6 force = 3 slot_flags = SLOT_BELT|SLOT_HOLSTER|SLOT_POCKET w_class = ITEMSIZE_SMALL diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 905b9f9471c..38c205a78d9 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -208,7 +208,7 @@ /obj/item/projectile/energy/disruptorstun name = "disruptor bolt" icon_state = "blue_laser" - agony = 25 + agony = 30 speed = 0.4 damage_type = PAIN // Can't blow your own head off with a stunbolt. taser_effect = TRUE diff --git a/code/modules/psionics/equipment/cerebro_enhancers.dm b/code/modules/psionics/equipment/cerebro_enhancers.dm index 684a3c53aa0..0fb48ce86d5 100644 --- a/code/modules/psionics/equipment/cerebro_enhancers.dm +++ b/code/modules/psionics/equipment/cerebro_enhancers.dm @@ -2,6 +2,7 @@ /obj/item/clothing/head/helmet/space/psi_amp name = "cerebro-energetic enhancer" desc = "A matte-black, eyeless cerebro-energetic enhancement helmet. It uses highly sophisticated, and illegal, techniques to drill into your brain and install psi-infected AIs into the fluid cavities between your lobes." + desc_info = "Due to the nature of this headgear, it will also protect you from the pressure of space. When installing the boosters, your chosen faculties will be boosted to the headgear's maximum potential, but the unchosen faculties will also be boosted somewhat." action_button_name = "Install Boosters" icon_state = "amp" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index e6518d901d3..8c2f56386e7 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -561,7 +561,8 @@ if((locate(/datum/reagent/adrenaline) in M.reagents.reagent_list)) if(M.reagents.get_reagent_amount(/datum/reagent/adrenaline) > 5) //So you can tolerate being attacked whilst hyperzine is in your system. - overdose = volume/2 //Straight to overdose. + overdose = 10 //Volume of hyperzine required to OD reduced from 15u to 10u. + od_minimum_dose = 0 /datum/reagent/hyperzine/overdose(var/mob/living/carbon/M, var/alien, var/removed) M.adjustNutritionLoss(5*removed) diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 93fc79f3418..8d8fecb7247 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -636,9 +636,9 @@ name = "Saline Plus" id = "saline" result = /datum/reagent/saline - required_reagents = list(/datum/reagent/water = 2, /datum/reagent/sugar = 0.2, /datum/reagent/sodiumchloride = 0.4) + required_reagents = list(/datum/reagent/water = 2, /datum/reagent/sugar = 0.5, /datum/reagent/sodiumchloride = 1) catalysts = list(/datum/reagent/toxin/phoron = 5) - result_amount = 1 + result_amount = 2 /datum/chemical_reaction/cataleptinol name = "Cataleptinol" diff --git a/config/example/config.txt b/config/example/config.txt index 47d71d6088c..983fbb02585 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -128,6 +128,7 @@ PROBABILITY S EXTENDED 1 PROBABILITY S MALFUNCTION 1 PROBABILITY S MERCENARY 1 PROBABILITY S WIZARD 1 +PROBABILITY S LONER 1 PROBABILITY S CHANGELING 1 PROBABILITY S CULT 1 PROBABILITY S BURGLARS 1 diff --git a/html/changelog.html b/html/changelog.html index a1222502591..6c05635cba6 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -35,6 +35,50 @@ -->
+

11 January 2021

+

Arrow768 updated:

+ +

Aticius updated:

+ +

Doxxmedearly updated:

+ +

Geeves updated:

+ +

Karolis2011 updated:

+ +

Kermit updated:

+ +

WickedCybs updated:

+ +

09 January 2021

Ferner updated: