diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 170ceab5ee1..6c197d0b58b 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -39,7 +39,15 @@ /// The failsafe code that causes this uplink to blow up. var/failsafe_code -/datum/component/uplink/Initialize(owner, lockable = TRUE, enabled = FALSE, uplink_flag = UPLINK_TRAITORS, starting_tc = TELECRYSTALS_DEFAULT, has_progression = FALSE, datum/uplink_handler/uplink_handler_override) +/datum/component/uplink/Initialize( + owner, + lockable = TRUE, + enabled = FALSE, + uplink_flag = UPLINK_TRAITORS, + starting_tc = TELECRYSTALS_DEFAULT, + has_progression = FALSE, + datum/uplink_handler/uplink_handler_override, +) if(!isitem(parent)) return COMPONENT_INCOMPATIBLE @@ -57,6 +65,7 @@ RegisterSignal(parent, COMSIG_RADIO_NEW_FREQUENCY, .proc/new_frequency) else if(istype(parent, /obj/item/pen)) RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation) + if(owner) src.owner = owner LAZYINITLIST(GLOB.uplink_purchase_logs_by_key) @@ -184,11 +193,12 @@ "name" = item.name, "cost" = item.cost, "desc" = item.desc, - "category" = item.category? initial(item.category.name) : null, + "category" = item.category ? initial(item.category.name) : null, "purchasable_from" = item.purchasable_from, "restricted" = item.restricted, "limited_stock" = item.limited_stock, "restricted_roles" = item.restricted_roles, + "restricted_species" = item.restricted_species, "progression_minimum" = item.progression_minimum, "ref" = REF(item) )) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5dab9fc6bdb..ad464e96d32 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -431,6 +431,9 @@ if(!new_uplink) CRASH("Uplink creation failed.") new_uplink.setup_unlock_code() + new_uplink.uplink_handler.owner = traitor_mob.mind + new_uplink.uplink_handler.assigned_role = traitor_mob.mind.assigned_role.title + new_uplink.uplink_handler.assigned_species = traitor_mob.dna.species.id if(uplink_loc == R) unlock_text = "Your Uplink is cunningly disguised as your [R.name]. Simply dial the frequency [format_frequency(new_uplink.unlock_code)] to unlock its hidden features." else if(uplink_loc == PDA) @@ -440,7 +443,8 @@ new_uplink.unlock_text = unlock_text if(!silent) to_chat(traitor_mob, span_boldnotice(unlock_text)) - antag_datum.antag_memory += new_uplink.unlock_note + "
" + if(antag_datum) + antag_datum.antag_memory += new_uplink.unlock_note + "
" //Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does. @@ -698,7 +702,8 @@ message_admins("[key_name_admin(usr)] failed to give [current] a traitor objective ([objective_typepath]).") log_admin("[key_name(usr)] failed to give [current] a traitor objective ([objective_typepath]).") if("uplink") - if(!give_uplink(antag_datum = has_antag_datum(/datum/antagonist/traitor))) + var/datum/antagonist/traitor/traitor_datum = has_antag_datum(/datum/antagonist/traitor) + if(!give_uplink(antag_datum = traitor_datum || null)) to_chat(usr, span_danger("Equipping a syndicate failed!")) log_admin("[key_name(usr)] tried and failed to give [current] an uplink.") else diff --git a/code/game/objects/items/implants/implantuplink.dm b/code/game/objects/items/implants/implantuplink.dm index f79bc9e66d1..8f6c95fe69a 100644 --- a/code/game/objects/items/implants/implantuplink.dm +++ b/code/game/objects/items/implants/implantuplink.dm @@ -8,15 +8,26 @@ var/starting_tc = 0 /// The uplink flags of the implant uplink inside, only checked during initialisation so modifying it after initialisation will do nothing var/uplink_flag = UPLINK_TRAITORS + ///Reference to the uplink handler, deciding which type of uplink this implant has. + var/uplink_handler -/obj/item/implant/uplink/Initialize(mapload, owner, uplink_handler) +/obj/item/implant/uplink/Initialize(mapload, uplink_handler) . = ..() if(!uplink_flag) uplink_flag = src.uplink_flag - var/datum/component/uplink/new_uplink = AddComponent(/datum/component/uplink, owner = owner, lockable = TRUE, enabled = FALSE, uplink_handler_override = uplink_handler, starting_tc = starting_tc) - new_uplink.unlock_text = "Your Syndicate Uplink has been cunningly implanted in you, for a small TC fee. Simply trigger the uplink to access it." + src.uplink_handler = uplink_handler RegisterSignal(src, COMSIG_COMPONENT_REMOVING, .proc/_component_removal) +/obj/item/implant/uplink/implant(mob/living/carbon/target, mob/user, silent, force) + . = ..() + var/datum/component/uplink/new_uplink = AddComponent(/datum/component/uplink, owner = target?.key, lockable = TRUE, enabled = FALSE, uplink_handler_override = uplink_handler, starting_tc = starting_tc) + new_uplink.unlock_text = "Your Syndicate Uplink has been cunningly implanted in you, for a small TC fee. Simply trigger the uplink to access it." + if(target.mind) + new_uplink.uplink_handler.owner = target.mind + new_uplink.uplink_handler.assigned_role = target.mind.assigned_role.title + new_uplink.uplink_handler.assigned_species = target.dna.species.id + + /** * Proc called when component is removed; ie. uplink component * @@ -34,7 +45,7 @@ imp_type = /obj/item/implant/uplink /obj/item/implanter/uplink/Initialize(mapload, uplink_handler) - imp = new imp_type(src, null, uplink_handler) + imp = new imp_type(src, uplink_handler) return ..() /obj/item/implanter/uplink/precharged diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 9130f04024a..28a3499e4fb 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -51,8 +51,6 @@ SStraitor.register_uplink_handler(uplink_handler) uplink_handler.has_objectives = TRUE - uplink_handler.owner = owner - uplink_handler.assigned_role = owner.assigned_role.title uplink_handler.generate_objectives() if(uplink_handler.progression_points < SStraitor.current_global_progression) @@ -60,7 +58,10 @@ var/list/uplink_items = list() for(var/datum/uplink_item/item as anything in SStraitor.uplink_items) if(item.item && (!length(item.restricted_roles) || (uplink_handler.assigned_role in item.restricted_roles)) \ - && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost > 1) + && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost > 1) + uplink_items += item + if(item.item && (!length(item.restricted_species) || (uplink_handler.assigned_species in item.restricted_species)) \ + && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost > 1) uplink_items += item uplink_handler.extra_purchasable += create_uplink_sales(uplink_sale_count, /datum/uplink_category/discounts, -1, uplink_items) diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm index 2fc20ede33f..6c48e71156f 100644 --- a/code/modules/antagonists/traitor/uplink_handler.dm +++ b/code/modules/antagonists/traitor/uplink_handler.dm @@ -38,6 +38,8 @@ var/list/potential_duplicate_objectives = list() /// The role that this uplink handler is associated to. var/assigned_role + /// The species this uplink handler is associated to. + var/assigned_species /// Whether this is in debug mode or not. If in debug mode, allows all purchases var/debug_mode = FALSE @@ -60,6 +62,8 @@ if(length(to_purchase.restricted_roles) && !(assigned_role in to_purchase.restricted_roles)) return FALSE + if(length(to_purchase.restricted_species) && !(assigned_species in to_purchase.restricted_species)) + return FALSE var/stock = item_stock[to_purchase] || INFINITY if(telecrystals < to_purchase.cost || stock <= 0 || (has_progression && progression_points < to_purchase.progression_minimum)) diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 7b24cebfdff..18a941f8a74 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -578,6 +578,7 @@ "restricted" = item.restricted, "limited_stock" = item.limited_stock, "restricted_roles" = item.restricted_roles, + "restricted_species" = item.restricted_species, "progression_minimum" = item.progression_minimum, )) } diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 4c9dbd137a8..b60d8ac7ba2 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -53,6 +53,8 @@ var/purchasable_from = ALL /// If this uplink item is only available to certain roles. Roles are dependent on the frequency chip or stored ID. var/list/restricted_roles = list() + /// The species able to purchase this uplink item. + var/restricted_species = list() /// The minimum amount of progression needed for this item to be added to uplinks. var/progression_minimum = 0 /// Whether this purchase is visible in the purchase log. diff --git a/code/modules/uplink/uplink_items/species.dm b/code/modules/uplink/uplink_items/species.dm new file mode 100644 index 00000000000..e0974aaf7c4 --- /dev/null +++ b/code/modules/uplink/uplink_items/species.dm @@ -0,0 +1,15 @@ +/datum/uplink_category/species + name = "Species Restricted" + weight = 1 + +/datum/uplink_item/species_restricted + category = /datum/uplink_category/species + purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) + +/datum/uplink_item/species_restricted/moth_lantern + name = "Extra-Bright Lantern" + desc = "We heard that moths such as yourself really like lamps, so we decided to grant you early access to a prototype \ + Syndicate brand \"Extra-Bright Lantern™\". Enjoy." + cost = 2 + item = /obj/item/flashlight/lantern/syndicate + restricted_species = list(SPECIES_MOTH) diff --git a/tgstation.dme b/tgstation.dme index 19408a6d468..4a16e2e5cb6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4002,6 +4002,7 @@ #include "code\modules\uplink\uplink_items\implant.dm" #include "code\modules\uplink\uplink_items\job.dm" #include "code\modules\uplink\uplink_items\nukeops.dm" +#include "code\modules\uplink\uplink_items\species.dm" #include "code\modules\uplink\uplink_items\stealthy.dm" #include "code\modules\uplink\uplink_items\stealthy_tools.dm" #include "code\modules\uplink\uplink_items\suits.dm" diff --git a/tgui/packages/tgui/interfaces/Uplink/index.tsx b/tgui/packages/tgui/interfaces/Uplink/index.tsx index 775e3760804..6cfd4edc5cf 100644 --- a/tgui/packages/tgui/interfaces/Uplink/index.tsx +++ b/tgui/packages/tgui/interfaces/Uplink/index.tsx @@ -19,6 +19,7 @@ type UplinkItem = { restricted: BooleanLike, limited_stock: number, restricted_roles: string, + restricted_species: string, progression_minimum: number, ref?: string, } @@ -31,6 +32,7 @@ type UplinkData = { current_progression_scaling: number, uplink_flag: number, assigned_role: string, + assigned_species: string, debug: BooleanLike, extra_purchasable: UplinkItem[], extra_purchasable_stock: { @@ -89,6 +91,7 @@ export class Uplink extends Component<{}, UplinkState> { const uplinkFlag = data.uplink_flag; const uplinkRole = data.assigned_role; + const uplinkSpecies = data.assigned_species; const uplinkData = await fetchServerData; uplinkData.items = uplinkData.items.sort((a, b) => { @@ -107,6 +110,10 @@ export class Uplink extends Component<{}, UplinkState> { && !value.restricted_roles.includes(uplinkRole)) { return false; } + if (value.restricted_species.length > 0 + && !value.restricted_species.includes(uplinkSpecies)) { + return false; + } { if (value.purchasable_from & uplinkFlag) { return true; } }