mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-25 00:22:39 +00:00
* Minor typo and comment fixes follow-up for ID card rework (#57318) * Minor typo and comment fixes follow-up for ID card rework Co-authored-by: Timberpoes <silent_insomnia_pp@hotmail.co.uk>
1183 lines
44 KiB
Plaintext
1183 lines
44 KiB
Plaintext
/* Cards
|
|
* Contains:
|
|
* DATA CARD
|
|
* ID CARD
|
|
* FINGERPRINT CARD HOLDER
|
|
* FINGERPRINT CARD
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* DATA CARDS - Used for the IC data card reader
|
|
*/
|
|
|
|
/obj/item/card
|
|
name = "card"
|
|
desc = "Does card things."
|
|
icon = 'icons/obj/card.dmi'
|
|
w_class = WEIGHT_CLASS_TINY
|
|
|
|
var/list/files = list()
|
|
|
|
/obj/item/card/suicide_act(mob/living/carbon/user)
|
|
user.visible_message("<span class='suicide'>[user] begins to swipe [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
|
return BRUTELOSS
|
|
|
|
/obj/item/card/data
|
|
name = "data card"
|
|
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one has a stripe running down the middle."
|
|
icon_state = "data_1"
|
|
obj_flags = UNIQUE_RENAME
|
|
var/function = "storage"
|
|
var/data = "null"
|
|
var/special = null
|
|
inhand_icon_state = "card-id"
|
|
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
|
var/detail_color = COLOR_ASSEMBLY_ORANGE
|
|
|
|
/obj/item/card/data/Initialize()
|
|
.=..()
|
|
update_appearance()
|
|
|
|
/obj/item/card/data/update_overlays()
|
|
. = ..()
|
|
if(detail_color == COLOR_FLOORTILE_GRAY)
|
|
return
|
|
var/mutable_appearance/detail_overlay = mutable_appearance('icons/obj/card.dmi', "[icon_state]-color")
|
|
detail_overlay.color = detail_color
|
|
. += detail_overlay
|
|
|
|
/obj/item/card/data/full_color
|
|
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one has the entire card colored."
|
|
icon_state = "data_2"
|
|
|
|
/obj/item/card/data/disk
|
|
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one inexplicibly looks like a floppy disk."
|
|
icon_state = "data_3"
|
|
|
|
/*
|
|
* ID CARDS
|
|
*/
|
|
|
|
/// "Retro" ID card that renders itself as the icon state with no overlays.
|
|
/obj/item/card/id
|
|
name = "retro identification card"
|
|
desc = "A card used to provide ID and determine access across the station."
|
|
icon_state = "card_grey"
|
|
worn_icon_state = "card_retro"
|
|
inhand_icon_state = "card-id"
|
|
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
|
slot_flags = ITEM_SLOT_ID
|
|
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
|
|
resistance_flags = FIRE_PROOF | ACID_PROOF
|
|
|
|
/// How many magical mining Disney Dollars this card has for spending at the mining equipment vendors.
|
|
var/mining_points = 0
|
|
/// The name registered on the card (for example: Dr Bryan See)
|
|
var/registered_name = null
|
|
/// Linked bank account.
|
|
var/datum/bank_account/registered_account
|
|
/// Linked paystand.
|
|
var/obj/machinery/paystand/my_store
|
|
/// Registered owner's age.
|
|
var/registered_age = 13
|
|
|
|
/// The job name registered on the card (for example: Assistant).
|
|
var/assignment
|
|
|
|
/// Trim datum associated with the card. Controls which job icon is displayed on the card and which accesses do not require wildcards.
|
|
var/datum/id_trim/trim
|
|
|
|
/// Access levels held by this card.
|
|
var/list/access = list()
|
|
|
|
/// List of wildcard slot names as keys with lists of wildcard data as values.
|
|
var/list/wildcard_slots = list()
|
|
|
|
/obj/item/card/id/Initialize(mapload)
|
|
. = ..()
|
|
|
|
// Applying the trim updates the label and icon, so don't do this twice.
|
|
if(ispath(trim))
|
|
SSid_access.apply_trim_to_card(src, trim)
|
|
else
|
|
update_label()
|
|
update_icon()
|
|
|
|
RegisterSignal(src, COMSIG_ATOM_UPDATED_ICON, .proc/update_in_wallet)
|
|
|
|
/obj/item/card/id/Destroy()
|
|
if (registered_account)
|
|
registered_account.bank_cards -= src
|
|
if (my_store && my_store.my_card == src)
|
|
my_store.my_card = null
|
|
return ..()
|
|
|
|
/obj/item/card/id/get_id_examine_strings(mob/user)
|
|
. = ..()
|
|
. += list("[icon2html(get_icon_source(), user, extra_classes = "bigicon")]")
|
|
|
|
/// Simple helper proc. Returns the source of the icon for this card. Advanced cards can override this to return their icon that has been cached due to using overlays.
|
|
/obj/item/card/id/proc/get_icon_source()
|
|
return src
|
|
|
|
/**
|
|
* Helper proc, checks whether the ID card can hold any given set of wildcards.
|
|
*
|
|
* Returns TRUE if the card can hold the wildcards, FALSE otherwise.
|
|
* Arguments:
|
|
* * wildcard_list - List of accesses to check.
|
|
* * try_wildcard - If not null, will attempt to add wildcards for this wildcard specifically and will return FALSE if the card cannot hold all wildcards in this slot.
|
|
*/
|
|
/obj/item/card/id/proc/can_add_wildcards(list/wildcard_list, try_wildcard = null)
|
|
if(!length(wildcard_list))
|
|
return TRUE
|
|
|
|
var/list/new_wildcard_limits = list()
|
|
|
|
for(var/flag_name in wildcard_slots)
|
|
if(try_wildcard && !(flag_name == try_wildcard))
|
|
continue
|
|
var/list/wildcard_info = wildcard_slots[flag_name]
|
|
new_wildcard_limits[flag_name] = wildcard_info["limit"] - length(wildcard_info["usage"])
|
|
|
|
if(!length(new_wildcard_limits))
|
|
return FALSE
|
|
|
|
var/wildcard_allocated
|
|
for(var/wildcard in wildcard_list)
|
|
var/wildcard_flag = SSid_access.get_access_flag(wildcard)
|
|
wildcard_allocated = FALSE
|
|
for(var/flag_name in new_wildcard_limits)
|
|
var/limit_flags = SSid_access.wildcard_flags_by_wildcard[flag_name]
|
|
if(!(wildcard_flag & limit_flags))
|
|
continue
|
|
// Negative limits mean infinite slots. Positive limits mean limited slots still available. 0 slots means no slots.
|
|
if(new_wildcard_limits[flag_name] == 0)
|
|
continue
|
|
new_wildcard_limits[flag_name]--
|
|
wildcard_allocated = TRUE
|
|
break
|
|
if(!wildcard_allocated)
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
/**
|
|
* Attempts to add the given wildcards to the ID card.
|
|
*
|
|
* Arguments:
|
|
* * wildcard_list - List of accesses to add.
|
|
* * try_wildcard - If not null, will attempt to add all wildcards to this wildcard slot only.
|
|
* * mode - The method to use when adding wildcards. See define for ERROR_ON_FAIL
|
|
*/
|
|
/obj/item/card/id/proc/add_wildcards(list/wildcard_list, try_wildcard = null, mode = ERROR_ON_FAIL)
|
|
var/wildcard_allocated
|
|
// Iterate through each wildcard in our list. Get its access flag. Then iterate over wildcard slots and try to fit it in.
|
|
for(var/wildcard in wildcard_list)
|
|
var/wildcard_flag = SSid_access.get_access_flag(wildcard)
|
|
wildcard_allocated = FALSE
|
|
for(var/flag_name in wildcard_slots)
|
|
if(flag_name == WILDCARD_NAME_FORCED)
|
|
continue
|
|
|
|
if(try_wildcard && !(flag_name == try_wildcard))
|
|
continue
|
|
|
|
var/limit_flags = SSid_access.wildcard_flags_by_wildcard[flag_name]
|
|
|
|
if(!(wildcard_flag & limit_flags))
|
|
continue
|
|
|
|
var/list/wildcard_info = wildcard_slots[flag_name]
|
|
var/wildcard_limit = wildcard_info["limit"]
|
|
var/list/wildcard_usage = wildcard_info["usage"]
|
|
|
|
var/wildcard_count = wildcard_limit - length(wildcard_usage)
|
|
|
|
// Negative limits mean infinite slots. Positive limits mean limited slots still available. 0 slots means no slots.
|
|
if(wildcard_count == 0)
|
|
continue
|
|
|
|
wildcard_usage |= wildcard
|
|
access |= wildcard
|
|
wildcard_allocated = TRUE
|
|
break
|
|
// Fallback for if we couldn't allocate the wildcard for some reason.
|
|
if(!wildcard_allocated)
|
|
if(mode == ERROR_ON_FAIL)
|
|
CRASH("Wildcard ([wildcard]) could not be added to [src].")
|
|
|
|
if(mode == TRY_ADD_ALL)
|
|
continue
|
|
|
|
// If the card has no info for historic forced wildcards, create the list.
|
|
if(!wildcard_slots[WILDCARD_NAME_FORCED])
|
|
wildcard_slots[WILDCARD_NAME_FORCED] = list(limit = 0, usage = list())
|
|
|
|
var/list/wildcard_info = wildcard_slots[WILDCARD_NAME_FORCED]
|
|
var/list/wildcard_usage = wildcard_info["usage"]
|
|
wildcard_usage |= wildcard
|
|
access |= wildcard
|
|
wildcard_info["limit"] = length(wildcard_usage)
|
|
|
|
/**
|
|
* Removes wildcards from the ID card.
|
|
*
|
|
* Arguments:
|
|
* * wildcard_list - List of accesses to remove.
|
|
*/
|
|
/obj/item/card/id/proc/remove_wildcards(list/wildcard_list)
|
|
var/wildcard_removed
|
|
// Iterate through each wildcard in our list. Get its access flag. Then iterate over wildcard slots and try to remove it.
|
|
for(var/wildcard in wildcard_list)
|
|
wildcard_removed = FALSE
|
|
for(var/flag_name in wildcard_slots)
|
|
if(flag_name == WILDCARD_NAME_FORCED)
|
|
continue
|
|
|
|
var/list/wildcard_info = wildcard_slots[flag_name]
|
|
var/wildcard_usage = wildcard_info["usage"]
|
|
|
|
if(!(wildcard in wildcard_usage))
|
|
continue
|
|
|
|
wildcard_usage -= wildcard
|
|
access -= wildcard
|
|
wildcard_removed = TRUE
|
|
break
|
|
// Fallback to see if this was a force-added wildcard.
|
|
if(!wildcard_removed)
|
|
// If the card has no info for historic forced wildcards, that's an error state.
|
|
if(!wildcard_slots[WILDCARD_NAME_FORCED])
|
|
stack_trace("Wildcard ([wildcard]) could not be removed from [src]. This card has no forced wildcard data and the wildcard is not in this card's wildcard lists.")
|
|
|
|
var/list/wildcard_info = wildcard_slots[WILDCARD_NAME_FORCED]
|
|
var/wildcard_usage = wildcard_info["usage"]
|
|
|
|
if(!(wildcard in wildcard_usage))
|
|
stack_trace("Wildcard ([wildcard]) could not be removed from [src]. This access is not a wildcard on this card.")
|
|
|
|
wildcard_usage -= wildcard
|
|
access -= wildcard
|
|
wildcard_info["limit"] = length(wildcard_usage)
|
|
|
|
if(!wildcard_info["limit"])
|
|
wildcard_slots -= WILDCARD_NAME_FORCED
|
|
|
|
/**
|
|
* Attempts to add the given accesses to the ID card as non-wildcards.
|
|
*
|
|
* Depending on the mode, may add accesses as wildcards or error if it can't add them as non-wildcards.
|
|
* Arguments:
|
|
* * add_accesses - List of accesses to check.
|
|
* * try_wildcard - If not null, will attempt to add all accesses that require wildcard slots to this wildcard slot only.
|
|
* * mode - The method to use when adding accesses. See define for ERROR_ON_FAIL
|
|
*/
|
|
/obj/item/card/id/proc/add_access(list/add_accesses, try_wildcard = null, mode = ERROR_ON_FAIL)
|
|
var/list/wildcard_access = list()
|
|
var/list/normal_access = list()
|
|
|
|
build_access_lists(add_accesses, normal_access, wildcard_access)
|
|
|
|
// Check if we can add the wildcards.
|
|
if(mode == ERROR_ON_FAIL)
|
|
if(!can_add_wildcards(wildcard_access, try_wildcard))
|
|
CRASH("Cannot add wildcards from \[[add_accesses.Join(",")]\] to [src]")
|
|
|
|
// All clear to add the accesses.
|
|
access |= normal_access
|
|
if(mode != TRY_ADD_ALL_NO_WILDCARD)
|
|
add_wildcards(wildcard_access, try_wildcard, mode = mode)
|
|
|
|
return TRUE
|
|
|
|
/**
|
|
* Removes the given accesses from the ID Card.
|
|
*
|
|
* Will remove the wildcards if the accesses given are on the card as wildcard accesses.
|
|
* Arguments:
|
|
* * rem_accesses - List of accesses to remove.
|
|
*/
|
|
/obj/item/card/id/proc/remove_access(list/rem_accesses)
|
|
var/list/wildcard_access = list()
|
|
var/list/normal_access = list()
|
|
|
|
build_access_lists(rem_accesses, normal_access, wildcard_access)
|
|
|
|
access -= normal_access
|
|
remove_wildcards(wildcard_access)
|
|
|
|
/**
|
|
* Attempts to set the card's accesses to the given accesses, clearing all accesses not in the given list.
|
|
*
|
|
* Depending on the mode, may add accesses as wildcards or error if it can't add them as non-wildcards.
|
|
* Arguments:
|
|
* * new_access_list - List of all accesses that this card should hold exclusively.
|
|
* * mode - The method to use when setting accesses. See define for ERROR_ON_FAIL
|
|
*/
|
|
/obj/item/card/id/proc/set_access(list/new_access_list, mode = ERROR_ON_FAIL)
|
|
var/list/wildcard_access = list()
|
|
var/list/normal_access = list()
|
|
|
|
build_access_lists(new_access_list, normal_access, wildcard_access)
|
|
|
|
// Check if we can add the wildcards.
|
|
if(mode == ERROR_ON_FAIL)
|
|
if(!can_add_wildcards(wildcard_access))
|
|
CRASH("Cannot add wildcards from \[[new_access_list.Join(",")]\] to [src]")
|
|
|
|
clear_access()
|
|
|
|
access = normal_access.Copy()
|
|
|
|
if(mode != TRY_ADD_ALL_NO_WILDCARD)
|
|
add_wildcards(wildcard_access, mode = mode)
|
|
|
|
return TRUE
|
|
|
|
/// Clears all accesses from the ID card - both wildcard and normal.
|
|
/obj/item/card/id/proc/clear_access()
|
|
// Go through the wildcards and reset them.
|
|
for(var/flag_name in wildcard_slots)
|
|
var/list/wildcard_info = wildcard_slots[flag_name]
|
|
var/list/wildcard_usage = wildcard_info["usage"]
|
|
wildcard_usage.Cut()
|
|
|
|
// Hard reset access
|
|
access.Cut()
|
|
|
|
/**
|
|
* Helper proc. Creates access lists for the access procs.
|
|
*
|
|
* Takes the accesses list and compares it with the trim. Any basic accesses that match the trim are
|
|
* added to basic_access_list and the rest are added to wildcard_access_list.
|
|
|
|
* This proc directly modifies the lists passed in as args. It expects these lists to be instantiated.
|
|
* There is no return value.
|
|
* Arguments:
|
|
* * accesses - List of accesses you want to stort into basic_access_list and wildcard_access_list. Should not be null.
|
|
* * basic_access_list - Mandatory argument. The proc modifies the list passed in this argument and adds accesses the trim supports to it.
|
|
* * wildcard_access_list - Mandatory argument. The proc modifies the list passed in this argument and adds accesses the trim does not support to it.
|
|
*/
|
|
/obj/item/card/id/proc/build_access_lists(list/accesses, list/basic_access_list, list/wildcard_access_list)
|
|
if(!length(accesses) || isnull(basic_access_list) || isnull(wildcard_access_list))
|
|
CRASH("Invalid parameters passed to build_access_lists")
|
|
|
|
var/list/trim_accesses = trim?.access
|
|
|
|
// Populate the lists.
|
|
for(var/new_access in accesses)
|
|
if(new_access in trim_accesses)
|
|
basic_access_list |= new_access
|
|
continue
|
|
|
|
wildcard_access_list |= new_access
|
|
|
|
/obj/item/card/id/attack_self(mob/user)
|
|
if(Adjacent(user))
|
|
var/minor
|
|
if(registered_name && registered_age && registered_age < AGE_MINOR)
|
|
minor = " <b>[registered_age]</b>"
|
|
user.visible_message("<span class='notice'>[user] shows you: [icon2html(src, viewers(user))] [src.name][minor].</span>", "<span class='notice'>You show \the [src.name][minor].</span>")
|
|
add_fingerprint(user)
|
|
|
|
/obj/item/card/id/vv_edit_var(var_name, var_value)
|
|
. = ..()
|
|
if(.)
|
|
switch(var_name)
|
|
if(NAMEOF(src, assignment), NAMEOF(src, registered_name), NAMEOF(src, registered_age))
|
|
update_label()
|
|
update_icon()
|
|
if(NAMEOF(src, trim))
|
|
if(ispath(trim))
|
|
SSid_access.apply_trim_to_card(src, trim)
|
|
|
|
/obj/item/card/id/attackby(obj/item/W, mob/user, params)
|
|
if(istype(W, /obj/item/holochip))
|
|
insert_money(W, user)
|
|
return
|
|
else if(istype(W, /obj/item/stack/spacecash))
|
|
insert_money(W, user, TRUE)
|
|
return
|
|
else if(istype(W, /obj/item/coin))
|
|
insert_money(W, user, TRUE)
|
|
return
|
|
else if(istype(W, /obj/item/storage/bag/money))
|
|
var/obj/item/storage/bag/money/money_bag = W
|
|
var/list/money_contained = money_bag.contents
|
|
|
|
var/money_added = mass_insert_money(money_contained, user)
|
|
|
|
if (money_added)
|
|
to_chat(user, "<span class='notice'>You stuff the contents into the card! They disappear in a puff of bluespace smoke, adding [money_added] worth of credits to the linked account.</span>")
|
|
return
|
|
else
|
|
return ..()
|
|
|
|
/**
|
|
* Insert credits or coins into the ID card and add their value to the associated bank account.
|
|
*
|
|
* Arguments:
|
|
* money - The item to attempt to convert to credits and insert into the card.
|
|
* user - The user inserting the item.
|
|
* physical_currency - Boolean, whether this is a physical currency such as a coin and not a holochip.
|
|
*/
|
|
/obj/item/card/id/proc/insert_money(obj/item/money, mob/user, physical_currency)
|
|
if(!registered_account)
|
|
to_chat(user, "<span class='warning'>[src] doesn't have a linked account to deposit [money] into!</span>")
|
|
return
|
|
var/cash_money = money.get_item_credit_value()
|
|
if(!cash_money)
|
|
to_chat(user, "<span class='warning'>[money] doesn't seem to be worth anything!</span>")
|
|
return
|
|
registered_account.adjust_money(cash_money)
|
|
SSblackbox.record_feedback("amount", "credits_inserted", cash_money)
|
|
log_econ("[cash_money] credits were inserted into [src] owned by [src.registered_name]")
|
|
if(physical_currency)
|
|
to_chat(user, "<span class='notice'>You stuff [money] into [src]. It disappears in a small puff of bluespace smoke, adding [cash_money] credits to the linked account.</span>")
|
|
else
|
|
to_chat(user, "<span class='notice'>You insert [money] into [src], adding [cash_money] credits to the linked account.</span>")
|
|
|
|
to_chat(user, "<span class='notice'>The linked account now reports a balance of [registered_account.account_balance] cr.</span>")
|
|
qdel(money)
|
|
|
|
/**
|
|
* Insert multiple money or money-equivalent items at once.
|
|
*
|
|
* Arguments:
|
|
* money - List of items to attempt to convert to credits and insert into the card.
|
|
* user - The user inserting the items.
|
|
*/
|
|
/obj/item/card/id/proc/mass_insert_money(list/money, mob/user)
|
|
if(!registered_account)
|
|
to_chat(user, "<span class='warning'>[src] doesn't have a linked account to deposit into!</span>")
|
|
return FALSE
|
|
|
|
if (!money || !money.len)
|
|
return FALSE
|
|
|
|
var/total = 0
|
|
|
|
for (var/obj/item/physical_money in money)
|
|
total += physical_money.get_item_credit_value()
|
|
CHECK_TICK
|
|
|
|
registered_account.adjust_money(total)
|
|
SSblackbox.record_feedback("amount", "credits_inserted", total)
|
|
log_econ("[total] credits were inserted into [src] owned by [src.registered_name]")
|
|
QDEL_LIST(money)
|
|
|
|
return total
|
|
|
|
/// Helper proc. Can the user alt-click the ID?
|
|
/obj/item/card/id/proc/alt_click_can_use_id(mob/living/user)
|
|
if(!isliving(user))
|
|
return
|
|
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
return
|
|
|
|
return TRUE
|
|
|
|
/// Attempts to set a new bank account on the ID card.
|
|
/obj/item/card/id/proc/set_new_account(mob/living/user)
|
|
. = FALSE
|
|
var/datum/bank_account/old_account = registered_account
|
|
|
|
var/new_bank_id = input(user, "Enter your account ID number.", "Account Reclamation", 111111) as num | null
|
|
|
|
if (isnull(new_bank_id))
|
|
return
|
|
|
|
if(!alt_click_can_use_id(user))
|
|
return
|
|
if(!new_bank_id || new_bank_id < 111111 || new_bank_id > 999999)
|
|
to_chat(user, "<span class='warning'>The account ID number needs to be between 111111 and 999999.</span>")
|
|
return
|
|
if (registered_account && registered_account.account_id == new_bank_id)
|
|
to_chat(user, "<span class='warning'>The account ID was already assigned to this card.</span>")
|
|
return
|
|
|
|
var/datum/bank_account/B = SSeconomy.bank_accounts_by_id["[new_bank_id]"]
|
|
if(B)
|
|
if (old_account)
|
|
old_account.bank_cards -= src
|
|
|
|
B.bank_cards += src
|
|
registered_account = B
|
|
to_chat(user, "<span class='notice'>The provided account has been linked to this ID card.</span>")
|
|
|
|
return TRUE
|
|
|
|
to_chat(user, "<span class='warning'>The account ID number provided is invalid.</span>")
|
|
return
|
|
|
|
/obj/item/card/id/AltClick(mob/living/user)
|
|
if(!alt_click_can_use_id(user))
|
|
return
|
|
|
|
if(!registered_account)
|
|
set_new_account(user)
|
|
return
|
|
|
|
if (registered_account.being_dumped)
|
|
registered_account.bank_card_talk("<span class='warning'>内部服务器错误</span>", TRUE)
|
|
return
|
|
|
|
var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num|null, 1)
|
|
|
|
if(!amount_to_remove || amount_to_remove < 0)
|
|
return
|
|
if(!alt_click_can_use_id(user))
|
|
return
|
|
if(registered_account.adjust_money(-amount_to_remove))
|
|
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
|
|
user.put_in_hands(holochip)
|
|
to_chat(user, "<span class='notice'>You withdraw [amount_to_remove] credits into a holochip.</span>")
|
|
SSblackbox.record_feedback("amount", "credits_removed", amount_to_remove)
|
|
log_econ("[amount_to_remove] credits were removed from [src] owned by [src.registered_name]")
|
|
return
|
|
else
|
|
var/difference = amount_to_remove - registered_account.account_balance
|
|
registered_account.bank_card_talk("<span class='warning'>ERROR: The linked account requires [difference] more credit\s to perform that withdrawal.</span>", TRUE)
|
|
|
|
/obj/item/card/id/examine(mob/user)
|
|
. = ..()
|
|
if(registered_account)
|
|
. += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr."
|
|
. += "<span class='notice'><i>There's more information below, you can look again to take a closer look...</i></span>"
|
|
|
|
/obj/item/card/id/examine_more(mob/user)
|
|
var/list/msg = list("<span class='notice'><i>You examine [src] closer, and note the following...</i></span>")
|
|
|
|
if(registered_age)
|
|
msg += "The card indicates that the holder is [registered_age] years old. [(registered_age < AGE_MINOR) ? "There's a holographic stripe that reads <b><span class='danger'>'MINOR: DO NOT SERVE ALCOHOL OR TOBACCO'</span></b> along the bottom of the card." : ""]"
|
|
if(mining_points)
|
|
msg += "There's [mining_points] mining equipment redemption point\s loaded onto this card."
|
|
if(registered_account)
|
|
msg += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr."
|
|
if(registered_account.account_job)
|
|
var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department)
|
|
if(D)
|
|
msg += "The [D.account_holder] reports a balance of [D.account_balance] cr."
|
|
msg += "<span class='info'>Alt-Click the ID to pull money from the linked account in the form of holochips.</span>"
|
|
msg += "<span class='info'>You can insert credits into the linked account by pressing holochips, cash, or coins against the ID.</span>"
|
|
if(registered_account.civilian_bounty)
|
|
msg += "<span class='info'><b>There is an active civilian bounty.</b>"
|
|
msg += "<span class='info'><i>[registered_account.bounty_text()]</i></span>"
|
|
msg += "<span class='info'>Quantity: [registered_account.bounty_num()]</span>"
|
|
msg += "<span class='info'>Reward: [registered_account.bounty_value()]</span>"
|
|
if(registered_account.account_holder == user.real_name)
|
|
msg += "<span class='boldnotice'>If you lose this ID card, you can reclaim your account by Alt-Clicking a blank ID card while holding it and entering your account ID number.</span>"
|
|
else
|
|
msg += "<span class='info'>There is no registered account linked to this card. Alt-Click to add one.</span>"
|
|
|
|
return msg
|
|
|
|
/obj/item/card/id/GetAccess()
|
|
return access
|
|
|
|
/obj/item/card/id/GetID()
|
|
return src
|
|
|
|
/obj/item/card/id/RemoveID()
|
|
return src
|
|
|
|
/// Called on COMSIG_ATOM_UPDATED_ICON. Updates the visuals of the wallet this card is in.
|
|
/obj/item/card/id/proc/update_in_wallet()
|
|
SIGNAL_HANDLER
|
|
|
|
if(istype(loc, /obj/item/storage/wallet))
|
|
var/obj/item/storage/wallet/powergaming = loc
|
|
if(powergaming.front_id == src)
|
|
powergaming.update_label()
|
|
powergaming.update_appearance()
|
|
|
|
/// Updates the name based on the card's vars and state.
|
|
/obj/item/card/id/proc/update_label()
|
|
var/blank = !registered_name
|
|
name = "[blank ? initial(name) : "[registered_name]'s ID Card"][(!assignment) ? "" : " ([assignment])"]"
|
|
|
|
/obj/item/card/id/away
|
|
name = "\proper a perfectly generic identification card"
|
|
desc = "A perfectly generic identification card. Looks like it could use some flavor."
|
|
trim = /datum/id_trim/away
|
|
icon_state = "retro"
|
|
registered_age = null
|
|
|
|
/obj/item/card/id/away/hotel
|
|
name = "Staff ID"
|
|
desc = "A staff ID used to access the hotel's doors."
|
|
trim = /datum/id_trim/away/hotel
|
|
|
|
/obj/item/card/id/away/hotel/securty
|
|
name = "Officer ID"
|
|
trim = /datum/id_trim/away/hotel/security
|
|
|
|
/obj/item/card/id/away/old
|
|
name = "\proper a perfectly generic identification card"
|
|
desc = "A perfectly generic identification card. Looks like it could use some flavor."
|
|
|
|
/obj/item/card/id/away/old/sec
|
|
name = "Charlie Station Security Officer's ID card"
|
|
desc = "A faded Charlie Station ID card. You can make out the rank \"Security Officer\"."
|
|
trim = /datum/id_trim/away/old/sec
|
|
|
|
/obj/item/card/id/away/old/sci
|
|
name = "Charlie Station Scientist's ID card"
|
|
desc = "A faded Charlie Station ID card. You can make out the rank \"Scientist\"."
|
|
trim = /datum/id_trim/away/old/sci
|
|
|
|
/obj/item/card/id/away/old/eng
|
|
name = "Charlie Station Engineer's ID card"
|
|
desc = "A faded Charlie Station ID card. You can make out the rank \"Station Engineer\"."
|
|
trim = /datum/id_trim/away/old/eng
|
|
|
|
/obj/item/card/id/away/old/apc
|
|
name = "APC Access ID"
|
|
desc = "A special ID card that allows access to APC terminals."
|
|
trim = /datum/id_trim/away/old/apc
|
|
|
|
/obj/item/card/id/away/deep_storage //deepstorage.dmm space ruin
|
|
name = "bunker access ID"
|
|
|
|
/obj/item/card/id/departmental_budget
|
|
name = "departmental card (ERROR)"
|
|
desc = "Provides access to the departmental budget."
|
|
icon_state = "budgetcard"
|
|
var/department_ID = ACCOUNT_CIV
|
|
var/department_name = ACCOUNT_CIV_NAME
|
|
registered_age = null
|
|
|
|
/obj/item/card/id/departmental_budget/Initialize()
|
|
. = ..()
|
|
var/datum/bank_account/B = SSeconomy.get_dep_account(department_ID)
|
|
if(B)
|
|
registered_account = B
|
|
if(!B.bank_cards.Find(src))
|
|
B.bank_cards += src
|
|
name = "departmental card ([department_name])"
|
|
desc = "Provides access to the [department_name]."
|
|
SSeconomy.dep_cards += src
|
|
|
|
/obj/item/card/id/departmental_budget/Destroy()
|
|
SSeconomy.dep_cards -= src
|
|
return ..()
|
|
|
|
/obj/item/card/id/departmental_budget/update_label()
|
|
return
|
|
|
|
/obj/item/card/id/departmental_budget/car
|
|
department_ID = ACCOUNT_CAR
|
|
department_name = ACCOUNT_CAR_NAME
|
|
icon_state = "car_budget" //saving up for a new tesla
|
|
|
|
/obj/item/card/id/departmental_budget/AltClick(mob/living/user)
|
|
registered_account.bank_card_talk("<span class='warning'>Withdrawing is not compatible with this card design.</span>", TRUE) //prevents the vault bank machine being useless and putting money from the budget to your card to go over personal crates
|
|
|
|
/obj/item/card/id/advanced
|
|
name = "identification card"
|
|
desc = "A card used to provide ID and determine access across the station. Has an integrated digital display and advanced microchips."
|
|
icon_state = "card_grey"
|
|
worn_icon_state = "card_grey"
|
|
|
|
wildcard_slots = WILDCARD_LIMIT_GREY
|
|
|
|
/// An overlay icon state for when the card is assigned to a name. Usually manifests itself as a little scribble to the right of the job icon.
|
|
var/assigned_icon_state = "assigned"
|
|
/// Cached icon that has been built for this card.
|
|
var/icon/cached_flat_icon
|
|
|
|
/// If this is set, will manually override the icon file for the trim. Intended for admins to VV edit and chameleon ID cards.
|
|
var/trim_icon_override
|
|
/// If this is set, will manually override the icon state for the trim. Intended for admins to VV edit and chameleon ID cards.
|
|
var/trim_state_override
|
|
|
|
/obj/item/card/id/advanced/get_icon_source()
|
|
return get_cached_flat_icon()
|
|
|
|
/// If no cached_flat_icon exists, this proc creates it. This proc then returns the cached_flat_icon.
|
|
/obj/item/card/id/advanced/proc/get_cached_flat_icon()
|
|
if(!cached_flat_icon)
|
|
cached_flat_icon = getFlatIcon(src)
|
|
return cached_flat_icon
|
|
|
|
/obj/item/card/id/advanced/get_examine_string(mob/user, thats = FALSE)
|
|
return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" //displays all overlays in chat
|
|
|
|
/obj/item/card/id/advanced/update_overlays()
|
|
. = ..()
|
|
|
|
cached_flat_icon = null
|
|
|
|
if(registered_name && registered_name != "Captain")
|
|
. += mutable_appearance(icon, assigned_icon_state)
|
|
|
|
var/trim_icon_file = trim_icon_override ? trim_icon_override : trim?.trim_icon
|
|
var/trim_icon_state = trim_state_override ? trim_state_override : trim?.trim_state
|
|
|
|
if(!trim_icon_file || !trim_icon_state)
|
|
return
|
|
|
|
. += mutable_appearance(trim_icon_file, trim_icon_state)
|
|
|
|
/obj/item/card/id/advanced/silver
|
|
name = "silver identification card"
|
|
desc = "A silver card which shows honour and dedication."
|
|
icon_state = "card_silver"
|
|
worn_icon_state = "card_silver"
|
|
inhand_icon_state = "silver_id"
|
|
wildcard_slots = WILDCARD_LIMIT_SILVER
|
|
|
|
/datum/id_trim/maint_reaper
|
|
access = list(ACCESS_MAINT_TUNNELS)
|
|
trim_state = "trim_janitor"
|
|
assignment = "Reaper"
|
|
|
|
/obj/item/card/id/advanced/silver/reaper
|
|
name = "Thirteen's ID Card (Reaper)"
|
|
trim = /datum/id_trim/maint_reaper
|
|
registered_name = "Thirteen"
|
|
|
|
/obj/item/card/id/advanced/gold
|
|
name = "gold identification card"
|
|
desc = "A golden card which shows power and might."
|
|
icon_state = "card_gold"
|
|
worn_icon_state = "card_gold"
|
|
inhand_icon_state = "gold_id"
|
|
wildcard_slots = WILDCARD_LIMIT_GOLD
|
|
|
|
/obj/item/card/id/advanced/gold/captains_spare
|
|
name = "captain's spare ID"
|
|
desc = "The spare ID of the High Lord himself."
|
|
registered_name = "Captain"
|
|
trim = /datum/id_trim/job/captain
|
|
registered_age = null
|
|
|
|
/obj/item/card/id/advanced/gold/captains_spare/update_label() //so it doesn't change to Captain's ID card (Captain) on a sneeze
|
|
if(registered_name == "Captain")
|
|
name = "[initial(name)][(!assignment || assignment == "Captain") ? "" : " ([assignment])"]"
|
|
update_appearance(UPDATE_ICON)
|
|
else
|
|
..()
|
|
|
|
/obj/item/card/id/advanced/centcom
|
|
name = "\improper CentCom ID"
|
|
desc = "An ID straight from Central Command."
|
|
icon_state = "card_centcom"
|
|
worn_icon_state = "card_centcom"
|
|
assigned_icon_state = "assigned_centcom"
|
|
registered_name = "Central Command"
|
|
registered_age = null
|
|
trim = /datum/id_trim/centcom
|
|
wildcard_slots = WILDCARD_LIMIT_CENTCOM
|
|
|
|
/obj/item/card/id/advanced/centcom/ert
|
|
name = "\improper CentCom ID"
|
|
desc = "An ERT ID card."
|
|
registered_age = null
|
|
registered_name = "Emergency Response Intern"
|
|
trim = /datum/id_trim/centcom/ert
|
|
|
|
/obj/item/card/id/advanced/centcom/ert
|
|
registered_name = "Emergency Response Team Commander"
|
|
trim = /datum/id_trim/centcom/ert/commander
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/security
|
|
registered_name = "Security Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/security
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/engineer
|
|
registered_name = "Engineering Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/engineer
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/medical
|
|
registered_name = "Medical Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/medical
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/chaplain
|
|
registered_name = "Religious Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/chaplain
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/janitor
|
|
registered_name = "Janitorial Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/janitor
|
|
|
|
/obj/item/card/id/advanced/centcom/ert/clown
|
|
registered_name = "Entertainment Response Officer"
|
|
trim = /datum/id_trim/centcom/ert/clown
|
|
|
|
/obj/item/card/id/advanced/black
|
|
name = "black identification card"
|
|
desc = "This card is telling you one thing and one thing alone. The person holding this card is an utter badass."
|
|
icon_state = "card_black"
|
|
worn_icon_state = "card_black"
|
|
assigned_icon_state = "assigned_syndicate"
|
|
wildcard_slots = WILDCARD_LIMIT_GOLD
|
|
|
|
/obj/item/card/id/advanced/black/deathsquad
|
|
name = "\improper Death Squad ID"
|
|
desc = "A Death Squad ID card."
|
|
registered_name = "Death Commando"
|
|
trim = /datum/id_trim/centcom/deathsquad
|
|
wildcard_slots = WILDCARD_LIMIT_DEATHSQUAD
|
|
|
|
/obj/item/card/id/advanced/black/syndicate_command
|
|
name = "syndicate ID card"
|
|
desc = "An ID straight from the Syndicate."
|
|
registered_name = "Syndicate"
|
|
registered_age = null
|
|
trim = /datum/id_trim/syndicom
|
|
wildcard_slots = WILDCARD_LIMIT_SYNDICATE
|
|
|
|
/obj/item/card/id/advanced/black/syndicate_command/crew_id
|
|
name = "syndicate ID card"
|
|
desc = "An ID straight from the Syndicate."
|
|
registered_name = "Syndicate"
|
|
trim = /datum/id_trim/syndicom/crew
|
|
|
|
/obj/item/card/id/advanced/black/syndicate_command/captain_id
|
|
name = "syndicate captain ID card"
|
|
desc = "An ID straight from the Syndicate."
|
|
registered_name = "Syndicate"
|
|
trim = /datum/id_trim/syndicom/captain
|
|
|
|
/obj/item/card/id/advanced/debug
|
|
name = "\improper Debug ID"
|
|
desc = "A debug ID card. Has ALL the all access, you really shouldn't have this."
|
|
icon_state = "card_centcom"
|
|
worn_icon_state = "card_centcom"
|
|
assigned_icon_state = "assigned_centcom"
|
|
trim = /datum/id_trim/admin
|
|
wildcard_slots = WILDCARD_LIMIT_ADMIN
|
|
|
|
/obj/item/card/id/advanced/debug/Initialize()
|
|
. = ..()
|
|
registered_account = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
|
|
|
/obj/item/card/id/advanced/prisoner
|
|
name = "prisoner ID card"
|
|
desc = "You are a number, you are not a free man."
|
|
icon_state = "card_prisoner"
|
|
worn_icon_state = "card_prisoner"
|
|
inhand_icon_state = "orange-id"
|
|
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
|
registered_name = "Scum"
|
|
registered_age = null
|
|
trim = /datum/id_trim/job/prisoner
|
|
|
|
wildcard_slots = WILDCARD_LIMIT_PRISONER
|
|
|
|
/// Number of gulag points required to earn freedom.
|
|
var/goal = 0
|
|
/// Number of gulag points earned.
|
|
var/points = 0
|
|
// SKYRAT EDIT: Start - Genpop IDs
|
|
access = list(ACCESS_ENTER_GENPOP)
|
|
var/sentence = 0 //When world.time is greater than this number, the card will have its ACCESS_ENTER_GENPOP access replaced with ACCESS_LEAVE_GENPOP the next time it's checked, unless this value is 0/null
|
|
var/crime= "\[REDACTED\]"
|
|
|
|
/obj/item/card/id/advanced/prisoner/GetAccess()
|
|
if((sentence && world.time >= sentence) || (goal && points >= goal))
|
|
access = list(ACCESS_LEAVE_GENPOP)
|
|
return ..()
|
|
|
|
/obj/item/card/id/advanced/prisoner/examine(mob/user)
|
|
. = ..()
|
|
if(sentence && world.time < sentence)
|
|
to_chat(user, "<span class='notice'>You're currently serving a sentence for [crime]. <b>[DisplayTimeText(sentence - world.time)]</b> left.</span>")
|
|
else if(goal)
|
|
to_chat(user, "<span class='notice'>You have accumulated [points] out of the [goal] points you need for freedom.</span>")
|
|
else if(!sentence)
|
|
to_chat(user, "<span class='warning'>You are currently serving a permanent sentence for [crime].</span>")
|
|
else
|
|
to_chat(user, "<span class='notice'>Your sentence is up! You're free!</span>")
|
|
|
|
/obj/item/card/id/advanced/prisoner/process()
|
|
if(!sentence)
|
|
STOP_PROCESSING(SSobj, src)
|
|
return
|
|
if(world.time >= sentence)
|
|
if(prob(90))
|
|
playsound(loc, 'sound/machines/ping.ogg', 50, 1)
|
|
if(isliving(loc))
|
|
to_chat(loc, "<span class='boldnotice'>[src]</span><span class='notice'> buzzes: You have served your sentence! You may now exit prison through the turnstiles and collect your belongings.</span>")
|
|
else
|
|
playsound(loc, 'modular_skyrat/modules/mapping/code/quest_succeeded.ogg', 50, 1)
|
|
if(isliving(loc))
|
|
to_chat(loc, "<span class='boldnotice'>[src]</span><span class='notice'><b>Quest Completed!</b> <i>Serve your prison sentence</i>. You may now leave the prison through the turnstiles and return this ID to the locker to retrieve your belongings.</span>")
|
|
STOP_PROCESSING(SSobj, src)
|
|
return
|
|
// SKYRAT EDIT: End - Genpop IDs
|
|
|
|
/obj/item/card/id/advanced/prisoner/attack_self(mob/user)
|
|
to_chat(usr, "<span class='notice'>You have accumulated [points] out of the [goal] points you need for freedom.</span>")
|
|
|
|
/obj/item/card/id/advanced/prisoner/one
|
|
name = "Prisoner #13-001"
|
|
registered_name = "Prisoner #13-001"
|
|
trim = /datum/id_trim/job/prisoner/one
|
|
|
|
/obj/item/card/id/advanced/prisoner/two
|
|
name = "Prisoner #13-002"
|
|
registered_name = "Prisoner #13-002"
|
|
trim = /datum/id_trim/job/prisoner/two
|
|
|
|
/obj/item/card/id/advanced/prisoner/three
|
|
name = "Prisoner #13-003"
|
|
registered_name = "Prisoner #13-003"
|
|
trim = /datum/id_trim/job/prisoner/three
|
|
|
|
/obj/item/card/id/advanced/prisoner/four
|
|
name = "Prisoner #13-004"
|
|
registered_name = "Prisoner #13-004"
|
|
trim = /datum/id_trim/job/prisoner/four
|
|
|
|
/obj/item/card/id/advanced/prisoner/five
|
|
name = "Prisoner #13-005"
|
|
registered_name = "Prisoner #13-005"
|
|
trim = /datum/id_trim/job/prisoner/five
|
|
|
|
/obj/item/card/id/advanced/prisoner/six
|
|
name = "Prisoner #13-006"
|
|
registered_name = "Prisoner #13-006"
|
|
trim = /datum/id_trim/job/prisoner/six
|
|
|
|
/obj/item/card/id/advanced/prisoner/seven
|
|
name = "Prisoner #13-007"
|
|
registered_name = "Prisoner #13-007"
|
|
trim = /datum/id_trim/job/prisoner/seven
|
|
|
|
/obj/item/card/id/advanced/mining
|
|
name = "mining ID"
|
|
trim = /datum/id_trim/job/shaft_miner/spare
|
|
|
|
/obj/item/card/id/advanced/highlander
|
|
name = "highlander ID"
|
|
registered_name = "Highlander"
|
|
desc = "There can be only one!"
|
|
icon_state = "card_black"
|
|
worn_icon_state = "card_black"
|
|
assigned_icon_state = "assigned_syndicate"
|
|
trim = /datum/id_trim/highlander
|
|
wildcard_slots = WILDCARD_LIMIT_ADMIN
|
|
|
|
/obj/item/card/id/advanced/chameleon
|
|
name = "agent card"
|
|
desc = "A highly advanced chameleon ID card. Touch this card on another ID card to choose which accesses to copy."
|
|
wildcard_slots = WILDCARD_LIMIT_CHAMELEON
|
|
|
|
/// Have we set a custom name and job assignment, or will we use what we're given when we chameleon change?
|
|
var/forged = FALSE
|
|
/// Anti-metagaming protections. If TRUE, anyone can change the ID card's details. If FALSE, only syndicate agents can.
|
|
var/anyone = FALSE
|
|
/// Weak ref to the ID card we're currently attempting to steal access from.
|
|
var/datum/weakref/theft_target
|
|
|
|
/obj/item/card/id/advanced/chameleon/Initialize()
|
|
. = ..()
|
|
var/datum/action/item_action/chameleon/change/id/chameleon_card_action = new(src)
|
|
chameleon_card_action.chameleon_type = /obj/item/card/id/advanced
|
|
chameleon_card_action.chameleon_name = "ID Card"
|
|
chameleon_card_action.initialize_disguises()
|
|
|
|
/obj/item/card/id/advanced/chameleon/Destroy()
|
|
theft_target = null
|
|
. = ..()
|
|
|
|
/obj/item/card/id/advanced/chameleon/afterattack(obj/item/O, mob/user, proximity)
|
|
if(!proximity)
|
|
return
|
|
if(istype(O, /obj/item/card/id))
|
|
theft_target = WEAKREF(O)
|
|
ui_interact(user)
|
|
return
|
|
|
|
return ..()
|
|
|
|
/obj/item/card/id/advanced/chameleon/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ChameleonCard", name)
|
|
ui.open()
|
|
|
|
/obj/item/card/id/advanced/chameleon/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
data["wildcardFlags"] = SSid_access.wildcard_flags_by_wildcard
|
|
data["accessFlagNames"] = SSid_access.access_flag_string_by_flag
|
|
data["accessFlags"] = SSid_access.flags_by_access
|
|
return data
|
|
|
|
/obj/item/card/id/advanced/chameleon/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["showBasic"] = FALSE
|
|
|
|
var/list/regions = list()
|
|
|
|
var/obj/item/card/id/target_card = theft_target.resolve()
|
|
if(target_card)
|
|
var/list/tgui_region_data = SSid_access.all_region_access_tgui
|
|
for(var/region in SSid_access.station_regions)
|
|
regions += tgui_region_data[region]
|
|
|
|
data["accesses"] = regions
|
|
data["ourAccess"] = access
|
|
data["ourTrimAccess"] = trim ? trim.access : list()
|
|
data["theftAccess"] = target_card.access.Copy()
|
|
data["wildcardSlots"] = wildcard_slots
|
|
data["selectedList"] = access
|
|
data["trimAccess"] = list()
|
|
|
|
return data
|
|
|
|
/obj/item/card/id/advanced/chameleon/ui_act(action, list/params)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
var/obj/item/card/id/target_card = theft_target?.resolve()
|
|
if(QDELETED(target_card))
|
|
to_chat(usr, "<span class='notice'>The ID card you were attempting to scan is no longer in range.</span>")
|
|
target_card = null
|
|
return TRUE
|
|
|
|
// Wireless ID theft!
|
|
var/turf/our_turf = get_turf(src)
|
|
var/turf/target_turf = get_turf(target_card)
|
|
if(!our_turf.Adjacent(target_turf))
|
|
to_chat(usr, "<span class='notice'>The ID card you were attempting to scan is no longer in range.</span>")
|
|
target_card = null
|
|
return TRUE
|
|
|
|
switch(action)
|
|
if("mod_access")
|
|
var/access_type = params["access_target"]
|
|
var/try_wildcard = params["access_wildcard"]
|
|
if(access_type in access)
|
|
remove_access(list(access_type))
|
|
LOG_ID_ACCESS_CHANGE(usr, src, "removed [SSid_access.get_access_desc(access_type)]")
|
|
return TRUE
|
|
|
|
if(!(access_type in target_card.access))
|
|
to_chat(usr, "<span class='notice'>ID error: ID card rejected your attempted access modification.</span>")
|
|
LOG_ID_ACCESS_CHANGE(usr, src, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]")
|
|
return TRUE
|
|
|
|
if(!can_add_wildcards(list(access_type), try_wildcard))
|
|
to_chat(usr, "<span class='notice'>ID error: ID card rejected your attempted access modification.</span>")
|
|
LOG_ID_ACCESS_CHANGE(usr, src, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]")
|
|
return TRUE
|
|
|
|
if(!add_access(list(access_type), try_wildcard))
|
|
to_chat(usr, "<span class='notice'>ID error: ID card rejected your attempted access modification.</span>")
|
|
LOG_ID_ACCESS_CHANGE(usr, src, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]")
|
|
return TRUE
|
|
|
|
if(access_type in ACCESS_ALERT_ADMINS)
|
|
message_admins("[ADMIN_LOOKUPFLW(usr)] just added [SSid_access.get_access_desc(access_type)] to an ID card [ADMIN_VV(src)] [(registered_name) ? "belonging to [registered_name]." : "with no registered name."]")
|
|
LOG_ID_ACCESS_CHANGE(usr, src, "added [SSid_access.get_access_desc(access_type)]")
|
|
return TRUE
|
|
|
|
/obj/item/card/id/advanced/chameleon/attack_self(mob/user)
|
|
if(isliving(user) && user.mind)
|
|
var/popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset", "Change Account ID")
|
|
if(user.incapacitated())
|
|
return
|
|
if(!user.is_holding(src))
|
|
return
|
|
if(popup_input == "Forge/Reset")
|
|
if(!forged)
|
|
var/input_name = stripped_input(user, "What name would you like to put on this card? Leave blank to randomise.", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN)
|
|
input_name = sanitize_name(input_name)
|
|
if(!input_name)
|
|
// Invalid/blank names give a randomly generated one.
|
|
if(user.gender == MALE)
|
|
input_name = "[pick(GLOB.first_names_male)] [pick(GLOB.last_names)]"
|
|
else if(user.gender == FEMALE)
|
|
input_name = "[pick(GLOB.first_names_female)] [pick(GLOB.last_names)]"
|
|
else
|
|
input_name = "[pick(GLOB.first_names)] [pick(GLOB.last_names)]"
|
|
|
|
registered_name = input_name
|
|
|
|
var/change_trim = alert(user, "Adjust the appearance of your card's trim?", "Modify Trim", "Yes", "No")
|
|
if(change_trim == "Yes")
|
|
var/list/blacklist = typecacheof(type) + typecacheof(/obj/item/card/id/advanced/simple_bot)
|
|
var/list/trim_list = list()
|
|
for(var/trim_path in typesof(/datum/id_trim))
|
|
if(blacklist[trim_path])
|
|
continue
|
|
|
|
var/datum/id_trim/trim = SSid_access.trim_singletons_by_path[trim_path]
|
|
|
|
if(trim && trim.trim_state && trim.assignment)
|
|
var/fake_trim_name = "[trim.assignment] ([trim.trim_state])"
|
|
trim_list[fake_trim_name] = trim_path
|
|
|
|
var/selected_trim_path
|
|
selected_trim_path = input("Select trim to apply to your card.\nNote: This will not grant any trim accesses.", "Forge Trim", selected_trim_path) as null|anything in sortList(trim_list, /proc/cmp_typepaths_asc)
|
|
if(selected_trim_path)
|
|
SSid_access.apply_trim_to_chameleon_card(src, trim_list[selected_trim_path])
|
|
|
|
var/target_occupation = stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels.", "Agent card job assignment", assignment ? assignment : "Assistant", MAX_MESSAGE_LEN)
|
|
if(target_occupation)
|
|
assignment = target_occupation
|
|
|
|
var/new_age = input(user, "Choose the ID's age:\n([AGE_MIN]-[AGE_MAX])", "Agent card age") as num|null
|
|
if(new_age)
|
|
registered_age = max(round(text2num(new_age)), 0)
|
|
|
|
update_label()
|
|
update_icon()
|
|
forged = TRUE
|
|
to_chat(user, "<span class='notice'>You successfully forge the ID card.</span>")
|
|
log_game("[key_name(user)] has forged \the [initial(name)] with name \"[registered_name]\", occupation \"[assignment]\" and trim \"[trim?.assignment]\".")
|
|
|
|
if(!registered_account)
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/accountowner = user
|
|
|
|
var/datum/bank_account/account = SSeconomy.bank_accounts_by_id["[accountowner.account_id]"]
|
|
if(account)
|
|
account.bank_cards += src
|
|
registered_account = account
|
|
to_chat(user, "<span class='notice'>Your account number has been automatically assigned.</span>")
|
|
return
|
|
if(forged)
|
|
registered_name = initial(registered_name)
|
|
assignment = initial(assignment)
|
|
SSid_access.remove_trim_from_card(src)
|
|
log_game("[key_name(user)] has reset \the [initial(name)] named \"[src]\" to default.")
|
|
update_label()
|
|
update_icon()
|
|
forged = FALSE
|
|
to_chat(user, "<span class='notice'>You successfully reset the ID card.</span>")
|
|
return
|
|
if (popup_input == "Change Account ID")
|
|
set_new_account(user)
|
|
return
|
|
return ..()
|
|
|
|
/// A special variant of the classic chameleon ID card which accepts all access.
|
|
/obj/item/card/id/advanced/chameleon/black
|
|
icon_state = "card_black"
|
|
worn_icon_state = "card_black"
|
|
assigned_icon_state = "assigned_syndicate"
|
|
wildcard_slots = WILDCARD_LIMIT_GOLD
|
|
|
|
/obj/item/card/id/advanced/engioutpost
|
|
registered_name = "George 'Plastic' Miller"
|
|
desc = "A card used to provide ID and determine access across the station. There's blood dripping from the corner. Ew."
|
|
trim = /datum/id_trim/engioutpost
|
|
registered_age = 47
|
|
|
|
/obj/item/card/id/advanced/simple_bot
|
|
name = "simple bot ID card"
|
|
desc = "An internal ID card used by the station's non-sentient bots. You should report this to a coder if you're holding it."
|
|
wildcard_slots = WILDCARD_LIMIT_ADMIN
|