Merge pull request #32624 from kevinz000/component_uplinks

[READY]Refactors uplinks to a component!
This commit is contained in:
oranges
2017-11-23 10:16:16 +13:00
committed by GitHub
24 changed files with 413 additions and 315 deletions

View File

@@ -63,4 +63,4 @@
// /obj/machinery signals // /obj/machinery signals
#define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): () #define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): ()
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () #define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()

View File

@@ -16,7 +16,7 @@
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE) qdel(src, TRUE, TRUE)
return return
_CheckDupesAndJoinParent(P) _CheckDupesAndJoinParent(P)
/datum/component/proc/_CheckDupesAndJoinParent() /datum/component/proc/_CheckDupesAndJoinParent()
@@ -45,12 +45,12 @@
if(!old) if(!old)
//let the others know //let the others know
P.SendSignal(COMSIG_COMPONENT_ADDED, src) P.SendSignal(COMSIG_COMPONENT_ADDED, src)
//lazy init the parent's dc list //lazy init the parent's dc list
var/list/dc = P.datum_components var/list/dc = P.datum_components
if(!dc) if(!dc)
P.datum_components = dc = list() P.datum_components = dc = list()
//set up the typecache //set up the typecache
var/our_type = type var/our_type = type
for(var/I in _GetInverseTypeList(our_type)) for(var/I in _GetInverseTypeList(our_type))
@@ -114,7 +114,7 @@
if(!procs) if(!procs)
procs = list() procs = list()
signal_procs = procs signal_procs = procs
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types) var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
for(var/sig_type in sig_types) for(var/sig_type in sig_types)
if(!override) if(!override)
@@ -177,7 +177,7 @@
for(var/I in target) for(var/I in target)
var/datum/component/C = I var/datum/component/C = I
if(!C.enabled) if(!C.enabled)
continue continue
var/list/sps = C.signal_procs var/list/sps = C.signal_procs
var/datum/callback/CB = LAZYACCESS(sps, sigtype) var/datum/callback/CB = LAZYACCESS(sps, sigtype)
if(!CB) if(!CB)
@@ -255,3 +255,6 @@
target.TakeComponent(I) target.TakeComponent(I)
else else
target.TakeComponent(comps) target.TakeComponent(comps)
/datum/component/ui_host()
return parent

View File

@@ -0,0 +1,204 @@
GLOBAL_LIST_EMPTY(uplinks)
/**
* Uplinks
*
* All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.'
* Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink.
* You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it.
**/
/datum/component/uplink
dupe_mode = COMPONENT_DUPE_UNIQUE
var/name = "syndicate uplink"
var/active = FALSE
var/lockable = TRUE
var/locked = TRUE
var/telecrystals
var/selected_cat
var/owner = null
var/datum/game_mode/gamemode
var/spent_telecrystals = 0
var/datum/uplink_purchase_log/purchase_log
var/list/uplink_items
var/hidden_crystals = 0
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
GLOB.uplinks += src
uplink_items = get_uplink_items(gamemode)
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/interact)
owner = _owner
if(owner)
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
if(GLOB.uplink_purchase_logs_by_key[owner])
purchase_log = GLOB.uplink_purchase_logs_by_key[owner]
else
purchase_log = new(owner, src)
lockable = _lockable
active = _enabled
gamemode = _gamemode
telecrystals = starting_tc
if(!lockable)
active = TRUE
locked = FALSE
/datum/component/uplink/InheritComponent(datum/component/uplink/U)
lockable |= U.lockable
active |= U.active
if(!gamemode)
gamemode = U.gamemode
telecrystals += U.telecrystals
if(purchase_log && U.purchase_log)
purchase_log.MergeWithAndDel(U.purchase_log)
/datum/component/uplink/Destroy()
GLOB.uplinks -= src
gamemode = null
return ..()
/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
if(!silent)
to_chat(user, "<span class='notice'>You slot [TC] into [parent] and charge its internal uplink.</span>")
var/amt = TC.amount
telecrystals += amt
TC.use(amt)
/datum/component/uplink/proc/set_gamemode(_gamemode)
gamemode = _gamemode
uplink_items = get_uplink_items(gamemode)
/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user)
if(!active)
return //no hitting everyone/everything just to try to slot tcs in!
if(istype(I, /obj/item/stack/telecrystal))
LoadTC(user, I)
for(var/item in subtypesof(/datum/uplink_item))
var/datum/uplink_item/UI = item
var/path = null
if(initial(UI.refund_path))
path = initial(UI.refund_path)
else
path = initial(UI.item)
var/cost = 0
if(initial(UI.refund_amount))
cost = initial(UI.refund_amount)
else
cost = initial(UI.cost)
var/refundable = initial(UI.refundable)
if(I.type == path && refundable && I.check_uplink_validity())
telecrystals += cost
spent_telecrystals -= cost
to_chat(user, "<span class='notice'>[I] refunded.</span>")
qdel(I)
return
/datum/component/uplink/proc/interact(mob/user)
if(locked)
return
active = TRUE
if(user)
ui_interact(user)
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui.set_style("syndicate")
ui.open()
/datum/component/uplink/ui_data(mob/user)
if(!user.mind)
return
var/list/data = list()
data["telecrystals"] = telecrystals
data["lockable"] = lockable
data["categories"] = list()
for(var/category in uplink_items)
var/list/cat = list(
"name" = category,
"items" = (category == selected_cat ? list() : null))
if(category == selected_cat)
for(var/item in uplink_items[category])
var/datum/uplink_item/I = uplink_items[category][item]
if(I.limited_stock == 0)
continue
if(I.restricted_roles.len)
var/is_inaccessible = 1
for(var/R in I.restricted_roles)
if(R == user.mind.assigned_role)
is_inaccessible = 0
if(is_inaccessible)
continue
cat["items"] += list(list(
"name" = I.name,
"cost" = I.cost,
"desc" = I.desc,
))
data["categories"] += list(cat)
return data
/datum/component/uplink/ui_act(action, params)
if(!active)
return
switch(action)
if("buy")
var/item = params["item"]
var/list/buyable_items = list()
for(var/category in uplink_items)
buyable_items += uplink_items[category]
if(item in buyable_items)
var/datum/uplink_item/I = buyable_items[item]
MakePurchase(usr, I)
. = TRUE
if("lock")
active = FALSE
locked = TRUE
telecrystals += hidden_crystals
hidden_crystals = 0
SStgui.close_uis(src)
if("select")
selected_cat = params["category"]
return TRUE
/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U)
if(!istype(U))
return
if (!user || user.incapacitated())
return
if(telecrystals < U.cost || U.limited_stock == 0)
return
telecrystals -= U.cost
var/atom/A = U.spawn_item(get_turf(user), src, user)
if(U.purchase_log_vis && purchase_log)
var/obj/item/storage/box/B = A
var/list/atom/logging = list()
if(istype(B) && B.contents.len > 0)
logging |= list(B)
else
logging |= A
for(var/atom/_logging in logging)
purchase_log.LogPurchase(_logging, U.cost)
if(U.limited_stock > 0)
U.limited_stock -= 1
SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(U.name)]", "[U.cost]"))
if(ishuman(user) && istype(A, /obj/item))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(A))
to_chat(H, "[A] materializes into your hands!")
else
to_chat(H, "\The [A] materializes onto the floor.")
return TRUE

View File

@@ -295,9 +295,7 @@
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0 . = 0
else else
var/obj/item/device/uplink/U = new(uplink_loc) uplink_loc.LoadComponent(/datum/component/uplink, traitor_mob.key)
U.owner = "[traitor_mob.key]"
uplink_loc.hidden_uplink = U
if(uplink_loc == R) if(uplink_loc == R)
R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ)) R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
@@ -713,7 +711,7 @@
if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current)) if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current))
text = "Uplink: <a href='?src=[REF(src)];common=uplink'>give</a>" text = "Uplink: <a href='?src=[REF(src)];common=uplink'>give</a>"
var/obj/item/device/uplink/U = find_syndicate_uplink() var/datum/component/uplink/U = find_syndicate_uplink()
if(U) if(U)
text += " | <a href='?src=[REF(src)];common=takeuplink'>take</a>" text += " | <a href='?src=[REF(src)];common=takeuplink'>take</a>"
if (check_rights(R_FUN, 0)) if (check_rights(R_FUN, 0))
@@ -1296,7 +1294,7 @@
log_admin("[key_name(usr)] removed [current]'s uplink.") log_admin("[key_name(usr)] removed [current]'s uplink.")
if("crystals") if("crystals")
if(check_rights(R_FUN, 0)) if(check_rights(R_FUN, 0))
var/obj/item/device/uplink/U = find_syndicate_uplink() var/datum/component/uplink/U = find_syndicate_uplink()
if(U) if(U)
var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num
if(!isnull(crystals)) if(!isnull(crystals))
@@ -1325,15 +1323,14 @@
/datum/mind/proc/find_syndicate_uplink() /datum/mind/proc/find_syndicate_uplink()
var/list/L = current.GetAllContents() var/list/L = current.GetAllContents()
for (var/obj/item/I in L) for (var/i in L)
if (I.hidden_uplink) var/atom/movable/I = i
return I.hidden_uplink . = I.GetComponent(/datum/component/uplink)
return null if(.)
break
/datum/mind/proc/take_uplink() /datum/mind/proc/take_uplink()
var/obj/item/device/uplink/H = find_syndicate_uplink() qdel(find_syndicate_uplink())
if(H)
qdel(H)
/datum/mind/proc/make_Traitor() /datum/mind/proc/make_Traitor()
if(!(has_antag_datum(ANTAG_DATUM_TRAITOR))) if(!(has_antag_datum(ANTAG_DATUM_TRAITOR)))

View File

@@ -89,43 +89,10 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
/datum/uplink_item/proc/get_discount() /datum/uplink_item/proc/get_discount()
return pick(4;0.75,2;0.5,1;0.25) return pick(4;0.75,2;0.5,1;0.25)
/datum/uplink_item/proc/spawn_item(turf/loc, obj/item/device/uplink/U) /datum/uplink_item/proc/spawn_item(turf/loc, datum/component/uplink/U, mob/user)
if(item) if(item)
SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(name)]", "[cost]"))
return new item(loc) return new item(loc)
/datum/uplink_item/proc/buy(mob/user, obj/item/device/uplink/U)
if(!istype(U))
return
if (!user || user.incapacitated())
return
if(U.telecrystals < cost || limited_stock == 0)
return
else
U.telecrystals -= cost
U.spent_telecrystals += cost
var/atom/A = spawn_item(get_turf(user), U)
var/obj/item/storage/box/B = A
if(istype(B) && B.contents.len > 0)
for(var/obj/item/I in B)
U.purchase_log += "<big>[icon2base64html(I)]</big>"
else
if(purchase_log_vis)
U.purchase_log += "<big>[icon2base64html(A)]</big>"
if(limited_stock > 0)
limited_stock -= 1
if(ishuman(user) && istype(A, /obj/item))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(A))
to_chat(H, "[A] materializes into your hands!")
else
to_chat(H, "\The [A] materializes onto the floor.")
return 1
/datum/uplink_item/Destroy() /datum/uplink_item/Destroy()
if(src in GLOB.uplink_items) if(src in GLOB.uplink_items)
GLOB.uplink_items -= src //Take us out instead of leaving a null! GLOB.uplink_items -= src //Take us out instead of leaving a null!
@@ -368,7 +335,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 12 cost = 12
surplus = 35 surplus = 35
include_modes = list(/datum/game_mode/nuclear) include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/guardian /datum/uplink_item/dangerous/guardian
name = "Holoparasites" name = "Holoparasites"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \ desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
@@ -976,8 +943,8 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/briefcase_launchpad item = /obj/item/briefcase_launchpad
cost = 6 cost = 6
/datum/uplink_item/device_tools/briefcase_launchpad/buy(mob/user, obj/item/device/uplink/U) /datum/uplink_item/device_tools/briefcase_launchpad/spawn_item(turf/loc, datum/component/uplink/U, mob/user)
var/obj/item/device/launchpad_remote/L = new(get_turf(user)) //free remote var/obj/item/device/launchpad_remote/L = new(loc) //free remote
if(ishuman(user)) if(ishuman(user))
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(H.put_in_hands(L)) if(H.put_in_hands(L))
@@ -1380,7 +1347,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
exclude_modes = list(/datum/game_mode/nuclear) exclude_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE cant_discount = TRUE
/datum/uplink_item/badass/surplus/spawn_item(turf/loc, obj/item/device/uplink/U) /datum/uplink_item/badass/surplus/spawn_item(turf/loc, datum/component/uplink/U)
var/list/uplink_items = get_uplink_items(SSticker.mode) var/list/uplink_items = get_uplink_items(SSticker.mode)
var/crate_value = 50 var/crate_value = 50
@@ -1396,7 +1363,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
continue continue
crate_value -= I.cost crate_value -= I.cost
var/obj/goods = new I.item(C) var/obj/goods = new I.item(C)
U.purchase_log += "<big>[icon2base64html(goods)]</big>" U.purchase_log.LogPurchase(goods, I.cost)
SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(name)]", "[cost]")) SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(name)]", "[cost]"))
return C return C
@@ -1408,7 +1375,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 0 cost = 0
cant_discount = TRUE cant_discount = TRUE
/datum/uplink_item/badass/random/spawn_item(turf/loc, obj/item/device/uplink/U) /datum/uplink_item/badass/random/spawn_item(turf/loc, datum/component/uplink/U)
var/list/uplink_items = get_uplink_items(SSticker.mode) var/list/uplink_items = get_uplink_items(SSticker.mode)
var/list/possible_items = list() var/list/possible_items = list()
for(var/category in uplink_items) for(var/category in uplink_items)

View File

@@ -0,0 +1,64 @@
GLOBAL_LIST(uplink_purchase_logs_by_key) //assoc key = /datum/uplink_purchase_log
/datum/uplink_purchase_log
var/owner
var/list/purchase_log //assoc path-of-item = /datum/uplink_purchase_entry
var/datum/component/uplink/parent
var/total_spent = 0
/datum/uplink_purchase_log/New(_owner, datum/component/uplink/_parent)
owner = _owner
parent = _parent
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
if(owner)
if(GLOB.uplink_purchase_logs_by_key[owner])
stack_trace("WARNING: DUPLICATE PURCHASE LOGS DETECTED. [_owner] [_parent] [_parent.type]")
MergeWithAndDel(GLOB.uplink_purchase_logs_by_key[owner])
GLOB.uplink_purchase_logs_by_key[owner] = src
purchase_log = list()
/datum/uplink_purchase_log/Destroy()
purchase_log = null
parent = null
return ..()
/datum/uplink_purchase_log/proc/MergeWithAndDel(datum/uplink_purchase_log/other)
if(!istype(other))
return
. = owner == other.owner
if(!.)
return
for(var/path in other.purchase_log)
if(!purchase_log[path])
purchase_log[path] = other.purchase_log[path]
else
var/datum/uplink_purchase_entry/UPE = purchase_log[path]
var/datum/uplink_purchase_entry/UPE_O = other.purchase_log[path]
UPE.amount_purchased += UPE_O.amount_purchased
qdel(other)
/datum/uplink_purchase_log/proc/TotalTelecrystalsSpent()
. = total_spent
/datum/uplink_purchase_log/proc/generate_render(show_key = TRUE)
. = ""
for(var/path in purchase_log)
var/datum/uplink_purchase_entry/UPE = purchase_log[path]
. += "<big>\[[UPE.icon_b64][show_key?"([owner])":""]\]</big>"
/datum/uplink_purchase_log/proc/LogPurchase(atom/A, cost)
var/datum/uplink_purchase_entry/UPE
if(purchase_log[A.type])
UPE = purchase_log[A.type]
else
UPE = new
purchase_log[A.type] = UPE
UPE.path = A.type
UPE.icon_b64 = "[icon2base64html(A)]"
UPE.amount_purchased++
total_spent += cost
/datum/uplink_purchase_entry
var/amount_purchased = 0
var/path
var/icon_b64

View File

@@ -264,10 +264,11 @@
var/TC_uses = 0 var/TC_uses = 0
for(var/datum/mind/syndicate in syndicates) for(var/datum/mind/syndicate in syndicates)
text += printplayer(syndicate) text += printplayer(syndicate)
for(var/obj/item/device/uplink/H in GLOB.uplinks) for(var/datum/component/uplink/H in GLOB.uplinks)
if(H && H.owner && H.owner == syndicate.key) if(H.purchase_log)
TC_uses += H.spent_telecrystals purchases += H.purchase_log.generate_render()
purchases += H.purchase_log else
stack_trace("WARNING: Uplink with no purchase_log in nuclear mode! Owner: [H.owner]")
text += "<br>" text += "<br>"
text += "(Syndicates used [TC_uses] TC) [purchases]" text += "(Syndicates used [TC_uses] TC) [purchases]"
if(TC_uses == 0 && station_was_nuked && !are_operatives_dead()) if(TC_uses == 0 && station_was_nuked && !are_operatives_dead())
@@ -325,9 +326,7 @@
R.freqlock = 1 R.freqlock = 1
if(tc) if(tc)
var/obj/item/device/radio/uplink/nuclear/U = new(H) var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc)
U.hidden_uplink.owner = "[H.key]"
U.hidden_uplink.telecrystals = tc
H.equip_to_slot_or_del(U, slot_in_backpack) H.equip_to_slot_or_del(U, slot_in_backpack)
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H) var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)

View File

@@ -54,10 +54,7 @@
var/obj/item/circuitboard/computer/syndicate_shuttle/board = V var/obj/item/circuitboard/computer/syndicate_shuttle/board = V
board.challenge = TRUE board.challenge = TRUE
var/obj/item/device/radio/uplink/nuclear/U = new(get_turf(user)) new /obj/item/device/radio/uplink/nuclear(get_turf(user), user.key, CHALLENGE_TELECRYSTALS)
U.hidden_uplink.owner = "[user.key]"
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY)) CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1) SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
@@ -66,22 +63,22 @@
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user) /obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)
if(declaring_war) if(declaring_war)
to_chat(user, "You are already in the process of declaring war! Make your mind up.") to_chat(user, "You are already in the process of declaring war! Make your mind up.")
return 0 return FALSE
if(GLOB.player_list.len < CHALLENGE_MIN_PLAYERS) if(GLOB.player_list.len < CHALLENGE_MIN_PLAYERS)
to_chat(user, "The enemy crew is too small to be worth declaring war on.") to_chat(user, "The enemy crew is too small to be worth declaring war on.")
return 0 return FALSE
if(user.z != ZLEVEL_CENTCOM) if(user.z != ZLEVEL_CENTCOM)
to_chat(user, "You have to be at your base to use this.") to_chat(user, "You have to be at your base to use this.")
return 0 return FALSE
if(world.time-SSticker.round_start_time > CHALLENGE_TIME_LIMIT) if(world.time-SSticker.round_start_time > CHALLENGE_TIME_LIMIT)
to_chat(user, "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand.") to_chat(user, "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand.")
return 0 return FALSE
for(var/V in GLOB.syndicate_shuttle_boards) for(var/V in GLOB.syndicate_shuttle_boards)
var/obj/item/circuitboard/computer/syndicate_shuttle/board = V var/obj/item/circuitboard/computer/syndicate_shuttle/board = V
if(board.moved) if(board.moved)
to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.") to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.")
return 0 return FALSE
return 1 return TRUE
#undef CHALLENGE_TELECRYSTALS #undef CHALLENGE_TELECRYSTALS
#undef CHALLENGE_MIN_PLAYERS #undef CHALLENGE_MIN_PLAYERS

View File

@@ -28,7 +28,7 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
var/global/list/spawn_forbidden = list( var/global/list/spawn_forbidden = list(
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you /obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
/obj/item/assembly, /obj/item/device/onetankbomb, /obj/item/radio, /obj/item/device/pda/ai, /obj/item/assembly, /obj/item/device/onetankbomb, /obj/item/radio, /obj/item/device/pda/ai,
/obj/item/device/uplink, /obj/item/smallDelivery, /obj/item/projectile, /obj/item/smallDelivery, /obj/item/projectile,
/obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module) /obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module)
/datum/hSB/proc/update() /datum/hSB/proc/update()

View File

@@ -103,11 +103,11 @@
var/TC_uses = 0 var/TC_uses = 0
var/uplink_true = FALSE var/uplink_true = FALSE
var/purchases = "" var/purchases = ""
for(var/obj/item/device/uplink/H in GLOB.uplinks) for(var/datum/component/uplink/H in GLOB.uplinks)
if(H && H.owner && H.owner == traitor.key) if(H && H.owner && H.owner == traitor.key)
TC_uses += H.spent_telecrystals TC_uses += H.spent_telecrystals
uplink_true = TRUE uplink_true = TRUE
purchases += H.purchase_log purchases += H.purchase_log.generate_render(FALSE)
var/objectives = "" var/objectives = ""
if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this.

View File

@@ -33,7 +33,8 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder) if(uplinkholder)
to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>") to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>")
return return
if(I.hidden_uplink) GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
if(hidden_uplink)
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
uplinkholder = I uplinkholder = I
@@ -56,26 +57,28 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1) /obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss) if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
if(amt < 0) if(amt < 0)
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals linkedboss.storedcrystals += hidden_uplink.telecrystals
if(addLog) if(addLog)
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].") linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].")
uplinkholder.hidden_uplink.telecrystals = 0 hidden_uplink.telecrystals = 0
else if(amt <= uplinkholder.hidden_uplink.telecrystals) else if(amt <= hidden_uplink.telecrystals)
uplinkholder.hidden_uplink.telecrystals -= amt hidden_uplink.telecrystals -= amt
linkedboss.storedcrystals += amt linkedboss.storedcrystals += amt
if(addLog) if(addLog)
linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].") linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1) /obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss) if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
if(amt < 0) if(amt < 0)
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog) if(addLog)
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].") linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
linkedboss.storedcrystals = 0 linkedboss.storedcrystals = 0
else if(amt <= linkedboss.storedcrystals) else if(amt <= linkedboss.storedcrystals)
uplinkholder.hidden_uplink.telecrystals += amt hidden_uplink.telecrystals += amt
linkedboss.storedcrystals -= amt linkedboss.storedcrystals -= amt
if(addLog) if(addLog)
linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].") linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].")
@@ -95,7 +98,8 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
dat += "No linked management consoles detected. Scan for uplink stations using the management console.<BR><BR>" dat += "No linked management consoles detected. Scan for uplink stations using the management console.<BR><BR>"
if(uplinkholder) if(uplinkholder)
dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>" GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
if(linkedboss) if(linkedboss)
dat += "Donate TC: <a href='byond://?src=[REF(src)];donate=1'>1</a> | <a href='byond://?src=[REF(src)];donate=5'>5</a> | <a href='byond://?src=[REF(src)];donate=-1'>All</a>" dat += "Donate TC: <a href='byond://?src=[REF(src)];donate=1'>1</a> | <a href='byond://?src=[REF(src)];donate=5'>5</a> | <a href='byond://?src=[REF(src)];donate=-1'>All</a>"
dat += "<br><a href='byond://?src=[REF(src)];eject=1'>Eject Uplink</a>" dat += "<br><a href='byond://?src=[REF(src)];eject=1'>Eject Uplink</a>"
@@ -175,7 +179,8 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
dat += "[A.name] | " dat += "[A.name] | "
if(A.uplinkholder) if(A.uplinkholder)
dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals." GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, A.uplinkholder)
dat += "[hidden_uplink.telecrystals] telecrystals."
if(storedcrystals) if(storedcrystals)
dat+= "<BR>Add TC: <a href ='?src=[REF(src)];target=[REF(A)];give=1'>1</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=5'>5</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=10'>10</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=-1'>All</a>" dat+= "<BR>Add TC: <a href ='?src=[REF(src)];target=[REF(A)];give=1'>1</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=5'>5</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=10'>10</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=-1'>All</a>"
dat += "<BR>" dat += "<BR>"

View File

@@ -57,7 +57,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up
var/armour_penetration = 0 //percentage of armour effectiveness to remove var/armour_penetration = 0 //percentage of armour effectiveness to remove
var/list/allowed = null //suit storage stuff. var/list/allowed = null //suit storage stuff.
var/obj/item/device/uplink/hidden_uplink = null
var/equip_delay_self = 0 //In deciseconds, how long an item takes to equip; counts only for normal clothing slots, not pockets etc. var/equip_delay_self = 0 //In deciseconds, how long an item takes to equip; counts only for normal clothing slots, not pockets etc.
var/equip_delay_other = 20 //In deciseconds, how long an item takes to put on another person var/equip_delay_other = 20 //In deciseconds, how long an item takes to put on another person
var/strip_delay = 40 //In deciseconds, how long an item takes to remove from another person var/strip_delay = 40 //In deciseconds, how long an item takes to remove from another person
@@ -228,9 +227,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/interact(mob/user) /obj/item/interact(mob/user)
add_fingerprint(user) add_fingerprint(user)
if(hidden_uplink && hidden_uplink.active)
hidden_uplink.interact(user)
return 1
ui_interact(user) ui_interact(user)
/obj/item/ui_act(action, params) /obj/item/ui_act(action, params)

View File

@@ -158,15 +158,13 @@ GLOBAL_LIST_EMPTY(PDAs)
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>") to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return return
. = ..()
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda) var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
assets.send(user) assets.send(user)
user.set_machine(src) user.set_machine(src)
if(hidden_uplink && hidden_uplink.active)
hidden_uplink.interact(user)
return
var/dat = "<!DOCTYPE html><html><head><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}a img{padding-right: 9px;}</style>" var/dat = "<!DOCTYPE html><html><head><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}a img{padding-right: 9px;}</style>"
@@ -499,7 +497,9 @@ GLOBAL_LIST_EMPTY(PDAs)
if("Ringtone") if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text var/t = input(U, "Please enter new ringtone", name, ttone) as text
if(in_range(src, U) && loc == U && t) if(in_range(src, U) && loc == U && t)
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink && (trim(lowertext(t)) == trim(lowertext(lock_code)))) if(hidden_uplink && (trim(lowertext(t)) == trim(lowertext(lock_code))))
hidden_uplink.locked = FALSE
hidden_uplink.interact(U) hidden_uplink.interact(U)
to_chat(U, "The PDA softly beeps.") to_chat(U, "The PDA softly beeps.")
U << browse(null, "window=pda") U << browse(null, "window=pda")
@@ -825,8 +825,6 @@ GLOBAL_LIST_EMPTY(PDAs)
var/obj/item/photo/P = C var/obj/item/photo/P = C
photo = P.img photo = P.img
to_chat(user, "<span class='notice'>You scan \the [C].</span>") to_chat(user, "<span class='notice'>You scan \the [C].</span>")
else if(hidden_uplink && hidden_uplink.active)
hidden_uplink.attackby(C, user, params)
else else
return ..() return ..()

View File

@@ -7,7 +7,7 @@
/obj/item/cartridge/virus/message_header() /obj/item/cartridge/virus/message_header()
return "<b>[charges] viral files left.</b><HR>" return "<b>[charges] viral files left.</b><HR>"
/obj/item/cartridge/virus/message_special(obj/item/device/pda/target) /obj/item/cartridge/virus/message_special(obj/item/device/pda/target)
if (!istype(loc, /obj/item/device/pda)) if (!istype(loc, /obj/item/device/pda))
return "" //Sanity check, this shouldn't be possible. return "" //Sanity check, this shouldn't be possible.
@@ -67,11 +67,12 @@
var/difficulty = 0 var/difficulty = 0
if(target.cartridge) if(target.cartridge)
difficulty += BitCount(target.cartridge.access&(CART_MEDICAL | CART_SECURITY | CART_ENGINE | CART_CLOWN | CART_JANITOR | CART_MANIFEST)) difficulty += BitCount(target.cartridge.access&(CART_MEDICAL | CART_SECURITY | CART_ENGINE | CART_CLOWN | CART_JANITOR | CART_MANIFEST))
if(target.cartridge.access & CART_MANIFEST) if(target.cartridge.access & CART_MANIFEST)
difficulty++ //if cartridge has manifest access it has extra snowflake difficulty difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
else else
difficulty += 2 difficulty += 2
if(!target.detonatable || prob(difficulty * 15) || (target.hidden_uplink)) GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
if(!target.detonatable || prob(difficulty * 15) || (hidden_uplink))
U.show_message("<span class='danger'>An error flashes on your [src].</span>", 1) U.show_message("<span class='danger'>An error flashes on your [src].</span>", 1)
else else
U.show_message("<span class='notice'>Success!</span>", 1) U.show_message("<span class='notice'>Success!</span>", 1)
@@ -92,14 +93,14 @@
charges-- charges--
var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]" var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
to_chat(U, "<span class='notice'>Virus Sent! The unlock code to the target is: [lock_code]</span>") to_chat(U, "<span class='notice'>Virus Sent! The unlock code to the target is: [lock_code]</span>")
if(!target.hidden_uplink) GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
var/obj/item/device/uplink/uplink = new(target) if(!hidden_uplink)
target.hidden_uplink = uplink hidden_uplink = target.LoadComponent(/datum/component/uplink)
target.lock_code = lock_code target.lock_code = lock_code
else else
target.hidden_uplink.hidden_crystals += target.hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals. hidden_uplink.hidden_crystals += hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals.
target.hidden_uplink.telecrystals = telecrystals hidden_uplink.telecrystals = telecrystals
telecrystals = 0 telecrystals = 0
target.hidden_uplink.active = TRUE hidden_uplink.active = TRUE
else else
to_chat(U, "PDA not found.") to_chat(U, "PDA not found.")

View File

@@ -155,7 +155,9 @@
if(.) if(.)
frequency = sanitize_frequency(tune, freerange) frequency = sanitize_frequency(tune, freerange)
set_frequency(frequency) set_frequency(frequency)
if(frequency == traitor_frequency && hidden_uplink) GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink && (frequency == traitor_frequency))
hidden_uplink.locked = FALSE
hidden_uplink.interact(usr) hidden_uplink.interact(usr)
ui.close() ui.close()
if("listen") if("listen")

View File

@@ -0,0 +1,31 @@
// A collection of pre-set uplinks, for admin spawns.
/obj/item/device/radio/uplink/Initialize(mapload, _owner, _tc_amount = 20)
. = ..()
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
/obj/item/device/radio/uplink/nuclear/Initialize()
. = ..()
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20)
. = ..()
LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
/obj/item/pen/uplink/Initialize(mapload, _owner, _tc_amount = 20)
. = ..()
LoadComponent(/datum/component/uplink)
traitor_unlock_degrees = 360
/obj/item/device/radio/uplink/old
name = "dusty radio"
desc = "A dusty looking radio."
/obj/item/device/radio/uplink/old/Initialize(mapload, _owner, _tc_amount = 10)
. = ..()
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
hidden_uplink.name = "dusty radio"

View File

@@ -7,25 +7,32 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/starting_tc = 0 var/starting_tc = 0
/obj/item/implant/uplink/New() /obj/item/implant/uplink/Initialize(mapload, _owner)
hidden_uplink = new(src) . = ..()
hidden_uplink.telecrystals = starting_tc LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
..()
/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0) /obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0)
for(var/X in target.implants) GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(istype(X, type)) if(hidden_uplink)
var/obj/item/implant/imp_e = X for(var/X in target.implants)
imp_e.hidden_uplink.telecrystals += hidden_uplink.telecrystals if(istype(X, type))
qdel(src) var/obj/item/implant/imp_e = X
return 1 GET_COMPONENT_FROM(their_hidden_uplink, /datum/component/uplink, imp_e)
if(their_hidden_uplink)
their_hidden_uplink.telecrystals += hidden_uplink.telecrystals
qdel(src)
return TRUE
else
qdel(imp_e) //INFERIOR AND EMPTY!
if(..()) if(..())
hidden_uplink.owner = "[user.key]" if(hidden_uplink)
return 1 hidden_uplink.owner = "[user.key]"
return 0 return TRUE
return FALSE
/obj/item/implant/uplink/activate() /obj/item/implant/uplink/activate()
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink) if(hidden_uplink)
hidden_uplink.interact(usr) hidden_uplink.interact(usr)

View File

@@ -12,18 +12,16 @@
if(target == user) //You can't go around smacking people with crystals to find out if they have an uplink or not. if(target == user) //You can't go around smacking people with crystals to find out if they have an uplink or not.
for(var/obj/item/implant/uplink/I in target) for(var/obj/item/implant/uplink/I in target)
if(I && I.imp_in) if(I && I.imp_in)
I.hidden_uplink.telecrystals += amount GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
use(amount) if(hidden_uplink)
to_chat(user, "<span class='notice'>You press [src] onto yourself and charge your hidden uplink.</span>") hidden_uplink.telecrystals += amount
use(amount)
to_chat(user, "<span class='notice'>You press [src] onto yourself and charge your hidden uplink.</span>")
else
return ..()
/obj/item/stack/telecrystal/afterattack(obj/item/I, mob/user, proximity) /obj/item/stack/telecrystal/afterattack(obj/item/I, mob/user, proximity)
if(!proximity) if(istype(I, /obj/item/cartridge/virus/frame))
return
if(isitem(I) && I.hidden_uplink && I.hidden_uplink.active) //No metagaming by using this on every PDA around just to see if it gets used up.
I.hidden_uplink.telecrystals += amount
use(amount)
to_chat(user, "<span class='notice'>You slot [src] into [I] and charge its internal uplink.</span>")
else if(istype(I, /obj/item/cartridge/virus/frame))
var/obj/item/cartridge/virus/frame/cart = I var/obj/item/cartridge/virus/frame/cart = I
if(!cart.charges) if(!cart.charges)
to_chat(user, "<span class='notice'>[cart] is out of charges, it's refusing to accept [src].</span>") to_chat(user, "<span class='notice'>[cart] is out of charges, it's refusing to accept [src].</span>")
@@ -31,6 +29,8 @@
cart.telecrystals += amount cart.telecrystals += amount
use(amount) use(amount)
to_chat(user, "<span class='notice'>You slot [src] into [cart]. The next time it's used, it will also give telecrystals.</span>") to_chat(user, "<span class='notice'>You slot [src] into [cart]. The next time it's used, it will also give telecrystals.</span>")
else
return ..()
/obj/item/stack/telecrystal/five /obj/item/stack/telecrystal/five
amount = 5 amount = 5

View File

@@ -218,15 +218,6 @@
desc = "This wand uses healing magics to heal and revive. The years of the cold have weakened the magic inside the wand." desc = "This wand uses healing magics to heal and revive. The years of the cold have weakened the magic inside the wand."
max_charges = 5 max_charges = 5
/obj/item/device/radio/uplink/old
name = "dusty radio"
desc = "A dusty looking radio."
/obj/item/device/radio/uplink/old/Initialize()
. = ..()
hidden_uplink.name = "dusty radio"
hidden_uplink.telecrystals = 10
/obj/effect/mob_spawn/human/syndicatesoldier/coldres /obj/effect/mob_spawn/human/syndicatesoldier/coldres
name = "Syndicate Snow Operative" name = "Syndicate Snow Operative"
outfit = /datum/outfit/snowsyndie/corpse outfit = /datum/outfit/snowsyndie/corpse

View File

@@ -34,7 +34,8 @@
/mob/living/simple_animal/drone/syndrone/Initialize() /mob/living/simple_animal/drone/syndrone/Initialize()
. = ..() . = ..()
internal_storage.hidden_uplink.telecrystals = 10 GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
hidden_uplink.telecrystals = 10
/mob/living/simple_animal/drone/syndrone/Login() /mob/living/simple_animal/drone/syndrone/Login()
..() ..()
@@ -47,7 +48,8 @@
/mob/living/simple_animal/drone/syndrone/badass/Initialize() /mob/living/simple_animal/drone/syndrone/badass/Initialize()
. = ..() . = ..()
internal_storage.hidden_uplink.telecrystals = 30 GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
hidden_uplink.telecrystals = 30
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(src) var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(src)
W.implant(src) W.implant(src)

View File

@@ -99,19 +99,13 @@
if(deg && (deg > 0 && deg <= 360)) if(deg && (deg > 0 && deg <= 360))
degrees = deg degrees = deg
to_chat(user, "<span class='notice'>You rotate the top of the pen to [degrees] degrees.</span>") to_chat(user, "<span class='notice'>You rotate the top of the pen to [degrees] degrees.</span>")
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink && degrees == traitor_unlock_degrees) if(hidden_uplink && degrees == traitor_unlock_degrees)
to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>") to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>")
degrees = 0 degrees = 0
hidden_uplink.locked = FALSE
hidden_uplink.interact(user) hidden_uplink.interact(user)
/obj/item/pen/attackby(obj/item/I, mob/user, params)
if(hidden_uplink)
return hidden_uplink.attackby(I, user, params)
else
return ..()
/obj/item/pen/attack(mob/living/M, mob/user,stealth) /obj/item/pen/attack(mob/living/M, mob/user,stealth)
if(!istype(M)) if(!istype(M))
return return

View File

@@ -733,7 +733,7 @@
out += "[taste_desc]" out += "[taste_desc]"
return english_list(out, "something indescribable") return english_list(out, "something indescribable")
/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) /datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02)
var/temp_delta = (temperature - chem_temp) * coeff var/temp_delta = (temperature - chem_temp) * coeff
if(temp_delta > 0) if(temp_delta > 0)

View File

@@ -1,162 +0,0 @@
GLOBAL_LIST_EMPTY(uplinks)
/**
* Uplinks
*
* All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.'
* Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink.
* You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it.
**/
/obj/item/device/uplink
name = "syndicate uplink"
desc = "There is something wrong if you're examining this."
var/active = FALSE
var/lockable = TRUE
var/telecrystals = 20
var/selected_cat = null
var/owner = null
var/datum/game_mode/gamemode = null
var/spent_telecrystals = 0
var/purchase_log = ""
var/list/uplink_items
var/hidden_crystals = 0
/obj/item/device/uplink/Initialize()
. = ..()
GLOB.uplinks += src
uplink_items = get_uplink_items(gamemode)
/obj/item/device/uplink/proc/set_gamemode(gamemode)
src.gamemode = gamemode
uplink_items = get_uplink_items(gamemode)
/obj/item/device/uplink/Destroy()
GLOB.uplinks -= src
return ..()
/obj/item/device/uplink/attackby(obj/item/I, mob/user, params)
for(var/item in subtypesof(/datum/uplink_item))
var/datum/uplink_item/UI = item
var/path = null
if(initial(UI.refund_path))
path = initial(UI.refund_path)
else
path = initial(UI.item)
var/cost = 0
if(initial(UI.refund_amount))
cost = initial(UI.refund_amount)
else
cost = initial(UI.cost)
var/refundable = initial(UI.refundable)
if(I.type == path && refundable && I.check_uplink_validity())
telecrystals += cost
spent_telecrystals -= cost
to_chat(user, "<span class='notice'>[I] refunded.</span>")
qdel(I)
return
..()
/obj/item/device/uplink/interact(mob/user)
active = TRUE
if(user)
ui_interact(user)
/obj/item/device/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui.set_style("syndicate")
ui.open()
/obj/item/device/uplink/ui_data(mob/user)
if(!user.mind)
return
var/list/data = list()
data["telecrystals"] = telecrystals
data["lockable"] = lockable
data["categories"] = list()
for(var/category in uplink_items)
var/list/cat = list(
"name" = category,
"items" = (category == selected_cat ? list() : null))
if(category == selected_cat)
for(var/item in uplink_items[category])
var/datum/uplink_item/I = uplink_items[category][item]
if(I.limited_stock == 0)
continue
if(I.restricted_roles.len)
var/is_inaccessible = 1
for(var/R in I.restricted_roles)
if(R == user.mind.assigned_role)
is_inaccessible = 0
if(is_inaccessible)
continue
cat["items"] += list(list(
"name" = I.name,
"cost" = I.cost,
"desc" = I.desc,
))
data["categories"] += list(cat)
return data
/obj/item/device/uplink/ui_act(action, params)
if(!active)
return
switch(action)
if("buy")
var/item = params["item"]
var/list/buyable_items = list()
for(var/category in uplink_items)
buyable_items += uplink_items[category]
if(item in buyable_items)
var/datum/uplink_item/I = buyable_items[item]
I.buy(usr, src)
. = TRUE
if("lock")
active = FALSE
telecrystals += hidden_crystals
hidden_crystals = 0
SStgui.close_uis(src)
if("select")
selected_cat = params["category"]
return 1
/obj/item/device/uplink/ui_host()
return loc
// Refund certain items by hitting the uplink with it.
/obj/item/device/radio/uplink/attackby(obj/item/I, mob/user, params)
return hidden_uplink.attackby(I, user, params)
// A collection of pre-set uplinks, for admin spawns.
/obj/item/device/radio/uplink/Initialize()
. = ..()
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
hidden_uplink = new(src)
hidden_uplink.active = TRUE
hidden_uplink.lockable = FALSE
/obj/item/device/radio/uplink/nuclear/Initialize()
. = ..()
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/device/multitool/uplink/Initialize()
. = ..()
hidden_uplink = new(src)
hidden_uplink.active = TRUE
hidden_uplink.lockable = FALSE
/obj/item/pen/uplink/Initialize()
. = ..()
hidden_uplink = new(src)
traitor_unlock_degrees = 360

View File

@@ -269,6 +269,8 @@
#include "code\datums\shuttles.dm" #include "code\datums\shuttles.dm"
#include "code\datums\soullink.dm" #include "code\datums\soullink.dm"
#include "code\datums\spawners_menu.dm" #include "code\datums\spawners_menu.dm"
#include "code\datums\uplink_items.dm"
#include "code\datums\uplink_purchase_log.dm"
#include "code\datums\verbs.dm" #include "code\datums\verbs.dm"
#include "code\datums\weakrefs.dm" #include "code\datums\weakrefs.dm"
#include "code\datums\world_topic.dm" #include "code\datums\world_topic.dm"
@@ -301,6 +303,7 @@
#include "code\datums\components\spooky.dm" #include "code\datums\components\spooky.dm"
#include "code\datums\components\squeek.dm" #include "code\datums\components\squeek.dm"
#include "code\datums\components\thermite.dm" #include "code\datums\components\thermite.dm"
#include "code\datums\components\uplink.dm"
#include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_disease.dm"
#include "code\datums\diseases\_MobProcs.dm" #include "code\datums\diseases\_MobProcs.dm"
#include "code\datums\diseases\anxiety.dm" #include "code\datums\diseases\anxiety.dm"
@@ -855,6 +858,7 @@
#include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\taperecorder.dm"
#include "code\game\objects\items\devices\traitordevices.dm" #include "code\game\objects\items\devices\traitordevices.dm"
#include "code\game\objects\items\devices\transfer_valve.dm" #include "code\game\objects\items\devices\transfer_valve.dm"
#include "code\game\objects\items\devices\uplink_devices.dm"
#include "code\game\objects\items\devices\PDA\cart.dm" #include "code\game\objects\items\devices\PDA\cart.dm"
#include "code\game\objects\items\devices\PDA\PDA.dm" #include "code\game\objects\items\devices\PDA\PDA.dm"
#include "code\game\objects\items\devices\PDA\PDA_types.dm" #include "code\game\objects\items\devices\PDA\PDA_types.dm"
@@ -2299,8 +2303,6 @@
#include "code\modules\tgui\states\self.dm" #include "code\modules\tgui\states\self.dm"
#include "code\modules\tgui\states\zlevel.dm" #include "code\modules\tgui\states\zlevel.dm"
#include "code\modules\tooltip\tooltip.dm" #include "code\modules\tooltip\tooltip.dm"
#include "code\modules\uplink\uplink.dm"
#include "code\modules\uplink\uplink_item.dm"
#include "code\modules\vehicles\atv.dm" #include "code\modules\vehicles\atv.dm"
#include "code\modules\vehicles\bicycle.dm" #include "code\modules\vehicles\bicycle.dm"
#include "code\modules\vehicles\pimpin_ride.dm" #include "code\modules\vehicles\pimpin_ride.dm"