Merge pull request #4074 from Citadel-Station-13/upstream-merge-32624

[MIRROR] [READY]Refactors uplinks to a component!
This commit is contained in:
deathride58
2017-12-04 23:12:45 +00:00
committed by GitHub
30 changed files with 648 additions and 546 deletions
+1 -1
View File
@@ -78,4 +78,4 @@
// /obj/machinery signals
#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(): ()
+1 -1
View File
@@ -1 +1 @@
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
@@ -1,36 +1,36 @@
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = 80
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = 80
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE
+7 -4
View File
@@ -24,7 +24,7 @@
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE)
return
_CheckDupesAndJoinParent(P)
/datum/component/proc/_CheckDupesAndJoinParent()
@@ -53,12 +53,12 @@
if(!old)
//let the others know
P.SendSignal(COMSIG_COMPONENT_ADDED, src)
//lazy init the parent's dc list
var/list/dc = P.datum_components
if(!dc)
P.datum_components = dc = list()
//set up the typecache
var/our_type = type
for(var/I in _GetInverseTypeList(our_type))
@@ -122,7 +122,7 @@
if(!procs)
procs = list()
signal_procs = procs
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)
if(!override)
@@ -264,3 +264,6 @@
target.TakeComponent(I)
else
target.TakeComponent(comps)
/datum/component/ui_host()
return parent
+59 -59
View File
@@ -1,59 +1,59 @@
//Thing meant for allowing datums and objects to access a NTnet network datum.
/datum/proc/ntnet_recieve(datum/netdata/data)
return
/datum/proc/ntnet_send(datum/netdata/data, netid)
GET_COMPONENT(NIC, /datum/component/ntnet_interface)
if(!NIC)
return FALSE
return NIC.__network_send(data, netid)
/datum/component/ntnet_interface
var/hardware_id //text
var/network_name = "" //text
var/list/networks_connected_by_id = list() //id = datum/ntnet
/datum/component/ntnet_interface/Initialize(force_ID, force_name = "NTNet Device", autoconnect_station_network = TRUE) //Don't force ID unless you know what you're doing!
if(!force_ID)
hardware_id = "[SSnetworks.assignment_hardware_id++]"
else
hardware_id = force_ID
network_name = force_name
SSnetworks.register_interface(src)
if(autoconnect_station_network)
register_connection(SSnetworks.station_network)
/datum/component/ntnet_interface/Destroy()
unregister_all_connections()
SSnetworks.unregister_interface(src)
return ..()
/datum/component/ntnet_interface/proc/__network_recieve(datum/netdata/data) //Do not directly proccall!
parent.SendSignal(COMSIG_COMPONENT_NTNET_RECIEVE, data)
parent.ntnet_recieve(data)
/datum/component/ntnet_interface/proc/__network_send(datum/netdata/data, netid) //Do not directly proccall!
if(netid)
if(networks_connected_by_id[netid])
var/datum/ntnet/net = networks_connected_by_id[netid]
return net.process_data_transmit(src, data)
return FALSE
for(var/i in networks_connected_by_id)
var/datum/ntnet/net = networks_connected_by_id[i]
net.process_data_transmit(src, data)
return TRUE
/datum/component/ntnet_interface/proc/register_connection(datum/ntnet/net)
if(net.interface_connect(src))
networks_connected_by_id[net.network_id] = net
return TRUE
/datum/component/ntnet_interface/proc/unregister_all_connections()
for(var/i in networks_connected_by_id)
unregister_connection(networks_connected_by_id[i])
return TRUE
/datum/component/ntnet_interface/proc/unregister_connection(datum/ntnet/net)
net.interface_disconnect(src)
networks_connected_by_id -= net.network_id
return TRUE
//Thing meant for allowing datums and objects to access a NTnet network datum.
/datum/proc/ntnet_recieve(datum/netdata/data)
return
/datum/proc/ntnet_send(datum/netdata/data, netid)
GET_COMPONENT(NIC, /datum/component/ntnet_interface)
if(!NIC)
return FALSE
return NIC.__network_send(data, netid)
/datum/component/ntnet_interface
var/hardware_id //text
var/network_name = "" //text
var/list/networks_connected_by_id = list() //id = datum/ntnet
/datum/component/ntnet_interface/Initialize(force_ID, force_name = "NTNet Device", autoconnect_station_network = TRUE) //Don't force ID unless you know what you're doing!
if(!force_ID)
hardware_id = "[SSnetworks.assignment_hardware_id++]"
else
hardware_id = force_ID
network_name = force_name
SSnetworks.register_interface(src)
if(autoconnect_station_network)
register_connection(SSnetworks.station_network)
/datum/component/ntnet_interface/Destroy()
unregister_all_connections()
SSnetworks.unregister_interface(src)
return ..()
/datum/component/ntnet_interface/proc/__network_recieve(datum/netdata/data) //Do not directly proccall!
parent.SendSignal(COMSIG_COMPONENT_NTNET_RECIEVE, data)
parent.ntnet_recieve(data)
/datum/component/ntnet_interface/proc/__network_send(datum/netdata/data, netid) //Do not directly proccall!
if(netid)
if(networks_connected_by_id[netid])
var/datum/ntnet/net = networks_connected_by_id[netid]
return net.process_data_transmit(src, data)
return FALSE
for(var/i in networks_connected_by_id)
var/datum/ntnet/net = networks_connected_by_id[i]
net.process_data_transmit(src, data)
return TRUE
/datum/component/ntnet_interface/proc/register_connection(datum/ntnet/net)
if(net.interface_connect(src))
networks_connected_by_id[net.network_id] = net
return TRUE
/datum/component/ntnet_interface/proc/unregister_all_connections()
for(var/i in networks_connected_by_id)
unregister_connection(networks_connected_by_id[i])
return TRUE
/datum/component/ntnet_interface/proc/unregister_connection(datum/ntnet/net)
net.interface_disconnect(src)
networks_connected_by_id -= net.network_id
return TRUE
+204
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
+9 -12
View File
@@ -299,9 +299,7 @@
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
var/obj/item/device/uplink/U = new(uplink_loc)
U.owner = "[traitor_mob.key]"
uplink_loc.hidden_uplink = U
uplink_loc.LoadComponent(/datum/component/uplink, traitor_mob.key)
if(uplink_loc == R)
R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
@@ -717,7 +715,7 @@
if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current))
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)
text += " | <a href='?src=[REF(src)];common=takeuplink'>take</a>"
if (check_rights(R_FUN, 0))
@@ -1306,7 +1304,7 @@
log_admin("[key_name(usr)] removed [current]'s uplink.")
if("crystals")
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)
var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num
if(!isnull(crystals))
@@ -1335,15 +1333,14 @@
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.GetAllContents()
for (var/obj/item/I in L)
if (I.hidden_uplink)
return I.hidden_uplink
return null
for (var/i in L)
var/atom/movable/I = i
. = I.GetComponent(/datum/component/uplink)
if(.)
break
/datum/mind/proc/take_uplink()
var/obj/item/device/uplink/H = find_syndicate_uplink()
if(H)
qdel(H)
qdel(find_syndicate_uplink())
/datum/mind/proc/make_Traitor()
if(!(has_antag_datum(ANTAG_DATUM_TRAITOR)))
@@ -89,43 +89,11 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
/datum/uplink_item/proc/get_discount()
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)
SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(name)]", "[cost]"))
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()
if(src in GLOB.uplink_items)
GLOB.uplink_items -= src //Take us out instead of leaving a null!
@@ -368,7 +336,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 12
surplus = 35
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
@@ -977,8 +945,8 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/briefcase_launchpad
cost = 6
/datum/uplink_item/device_tools/briefcase_launchpad/buy(mob/user, obj/item/device/uplink/U)
var/obj/item/device/launchpad_remote/L = new(get_turf(user)) //free remote
/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(loc) //free remote
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(L))
@@ -1381,7 +1349,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
exclude_modes = list(/datum/game_mode/nuclear)
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 && SSticker.mode? SSticker.mode : null)
var/crate_value = 50
@@ -1397,7 +1365,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
continue
crate_value -= I.cost
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]"))
return C
@@ -1409,7 +1377,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 0
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 && SSticker.mode? SSticker.mode : null)
var/list/possible_items = list()
for(var/category in uplink_items)
+64
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
+6 -7
View File
@@ -264,10 +264,11 @@
var/TC_uses = 0
for(var/datum/mind/syndicate in syndicates)
text += printplayer(syndicate)
for(var/obj/item/device/uplink/H in GLOB.uplinks)
if(H && H.owner && H.owner == syndicate.key)
TC_uses += H.spent_telecrystals
purchases += H.purchase_log
for(var/datum/component/uplink/H in GLOB.uplinks)
if(H.purchase_log)
purchases += H.purchase_log.generate_render()
else
stack_trace("WARNING: Uplink with no purchase_log in nuclear mode! Owner: [H.owner]")
text += "<br>"
text += "(Syndicates used [TC_uses] TC) [purchases]"
if(TC_uses == 0 && station_was_nuked && !are_operatives_dead())
@@ -325,9 +326,7 @@
R.freqlock = 1
if(tc)
var/obj/item/device/radio/uplink/nuclear/U = new(H)
U.hidden_uplink.owner = "[H.key]"
U.hidden_uplink.telecrystals = tc
var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc)
H.equip_to_slot_or_del(U, slot_in_backpack)
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
@@ -54,10 +54,7 @@
var/obj/item/circuitboard/computer/syndicate_shuttle/board = V
board.challenge = TRUE
var/obj/item/device/radio/uplink/nuclear/U = new(get_turf(user))
U.hidden_uplink.owner = "[user.key]"
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
new /obj/item/device/radio/uplink/nuclear(get_turf(user), user.key, CHALLENGE_TELECRYSTALS)
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
@@ -66,22 +63,22 @@
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)
if(declaring_war)
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)
to_chat(user, "The enemy crew is too small to be worth declaring war on.")
return 0
return FALSE
if(user.z != ZLEVEL_CENTCOM)
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)
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)
var/obj/item/circuitboard/computer/syndicate_shuttle/board = V
if(board.moved)
to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.")
return 0
return 1
return FALSE
return TRUE
#undef CHALLENGE_TELECRYSTALS
#undef CHALLENGE_MIN_PLAYERS
+1 -1
View File
@@ -28,7 +28,7 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
var/global/list/spawn_forbidden = list(
/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/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)
/datum/hSB/proc/update()
+2 -2
View File
@@ -103,11 +103,11 @@
var/TC_uses = 0
var/uplink_true = FALSE
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)
TC_uses += H.spent_telecrystals
uplink_true = TRUE
purchases += H.purchase_log
purchases += H.purchase_log.generate_render(FALSE)
var/objectives = ""
if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this.
@@ -33,7 +33,8 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>")
return
if(I.hidden_uplink)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
if(hidden_uplink)
if(!user.transferItemToLoc(I, src))
return
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)
if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
if(amt < 0)
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
linkedboss.storedcrystals += hidden_uplink.telecrystals
if(addLog)
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
uplinkholder.hidden_uplink.telecrystals = 0
else if(amt <= uplinkholder.hidden_uplink.telecrystals)
uplinkholder.hidden_uplink.telecrystals -= amt
linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].")
hidden_uplink.telecrystals = 0
else if(amt <= hidden_uplink.telecrystals)
hidden_uplink.telecrystals -= amt
linkedboss.storedcrystals += amt
if(addLog)
linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
if(amt < 0)
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
linkedboss.storedcrystals = 0
else if(amt <= linkedboss.storedcrystals)
uplinkholder.hidden_uplink.telecrystals += amt
hidden_uplink.telecrystals += amt
linkedboss.storedcrystals -= amt
if(addLog)
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>"
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)
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>"
@@ -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)
dat += "[A.name] | "
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)
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>"
-4
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/armour_penetration = 0 //percentage of armour effectiveness to remove
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_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
@@ -224,9 +223,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/interact(mob/user)
add_fingerprint(user)
if(hidden_uplink && hidden_uplink.active)
hidden_uplink.interact(user)
return 1
ui_interact(user)
/obj/item/ui_act(action, params)
+8 -6
View File
@@ -155,15 +155,17 @@ GLOBAL_LIST_EMPTY(PDAs)
return
/obj/item/device/pda/attack_self(mob/user)
if(!user.IsAdvancedToolUser())
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
. = ..()
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
assets.send(user)
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>"
@@ -496,7 +498,9 @@ GLOBAL_LIST_EMPTY(PDAs)
if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text
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))))
hidden_uplink.locked = FALSE
hidden_uplink.interact(U)
to_chat(U, "The PDA softly beeps.")
U << browse(null, "window=pda")
@@ -822,8 +826,6 @@ GLOBAL_LIST_EMPTY(PDAs)
var/obj/item/photo/P = C
photo = P.img
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
return ..()
@@ -7,7 +7,7 @@
/obj/item/cartridge/virus/message_header()
return "<b>[charges] viral files left.</b><HR>"
/obj/item/cartridge/virus/message_special(obj/item/device/pda/target)
if (!istype(loc, /obj/item/device/pda))
return "" //Sanity check, this shouldn't be possible.
@@ -67,11 +67,12 @@
var/difficulty = 0
if(target.cartridge)
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
else
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)
else
U.show_message("<span class='notice'>Success!</span>", 1)
@@ -92,14 +93,14 @@
charges--
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>")
if(!target.hidden_uplink)
var/obj/item/device/uplink/uplink = new(target)
target.hidden_uplink = uplink
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
if(!hidden_uplink)
hidden_uplink = target.LoadComponent(/datum/component/uplink)
target.lock_code = lock_code
else
target.hidden_uplink.hidden_crystals += target.hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals.
target.hidden_uplink.telecrystals = telecrystals
hidden_uplink.hidden_crystals += hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals.
hidden_uplink.telecrystals = telecrystals
telecrystals = 0
target.hidden_uplink.active = TRUE
hidden_uplink.active = TRUE
else
to_chat(U, "PDA not found.")
@@ -155,7 +155,9 @@
if(.)
frequency = sanitize_frequency(tune, freerange)
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)
ui.close()
if("listen")
@@ -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"
@@ -1,42 +1,48 @@
/obj/item/implant/uplink
name = "uplink implant"
desc = "Sneeki breeki."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
origin_tech = "materials=4;magnets=4;programming=4;biotech=4;syndicate=5;bluespace=5"
var/starting_tc = 0
/obj/item/implant/uplink/New()
hidden_uplink = new(src)
hidden_uplink.telecrystals = starting_tc
..()
/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0)
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/imp_e = X
imp_e.hidden_uplink.telecrystals += hidden_uplink.telecrystals
qdel(src)
return 1
if(..())
hidden_uplink.owner = "[user.key]"
return 1
return 0
/obj/item/implant/uplink/activate()
if(hidden_uplink)
hidden_uplink.interact(usr)
/obj/item/implanter/uplink
name = "implanter (uplink)"
imp_type = /obj/item/implant/uplink
/obj/item/implanter/uplink/precharged
name = "implanter (precharged uplink)"
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
starting_tc = 10
/obj/item/implant/uplink
name = "uplink implant"
desc = "Sneeki breeki."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/starting_tc = 0
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0)
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink)
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/imp_e = X
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)
hidden_uplink.owner = "[user.key]"
return TRUE
return FALSE
/obj/item/implant/uplink/activate()
GET_COMPONENT(hidden_uplink, /datum/component/uplink)
if(hidden_uplink)
hidden_uplink.interact(usr)
/obj/item/implanter/uplink
name = "implanter (uplink)"
imp_type = /obj/item/implant/uplink
/obj/item/implanter/uplink/precharged
name = "implanter (precharged uplink)"
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
starting_tc = 10
+10 -10
View File
@@ -13,18 +13,16 @@
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)
if(I && I.imp_in)
I.hidden_uplink.telecrystals += amount
use(amount)
to_chat(user, "<span class='notice'>You press [src] onto yourself and charge your hidden uplink.</span>")
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
if(hidden_uplink)
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)
if(!proximity)
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))
if(istype(I, /obj/item/cartridge/virus/frame))
var/obj/item/cartridge/virus/frame/cart = I
if(!cart.charges)
to_chat(user, "<span class='notice'>[cart] is out of charges, it's refusing to accept [src].</span>")
@@ -32,6 +30,8 @@
cart.telecrystals += 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>")
else
return ..()
/obj/item/stack/telecrystal/five
amount = 5
@@ -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."
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
name = "Syndicate Snow Operative"
outfit = /datum/outfit/snowsyndie/corpse
@@ -1,19 +1,19 @@
/datum/species/corporate
name = "Corporate Agent"
id = "agent"
hair_alpha = 0
say_mod = "declares"
speedmod = -2//Fast
brutemod = 0.7//Tough against firearms
burnmod = 0.65//Tough against lasers
coldmod = 0
heatmod = 0.5//it's a little tough to burn them to death not as hard though.
punchdamagelow = 20
punchdamagehigh = 30//they are inhumanly strong
punchstunthreshold = 25
attack_verb = "smash"
attack_sound = 'sound/weapons/resonator_blast.ogg'
blacklisted = 1
use_skintones = 0
species_traits = list(SPECIES_ORGANIC,RADIMMUNE,VIRUSIMMUNE,NOBLOOD,PIERCEIMMUNE,EYECOLOR,NODISMEMBER,NOHUNGER)
sexes = 0
/datum/species/corporate
name = "Corporate Agent"
id = "agent"
hair_alpha = 0
say_mod = "declares"
speedmod = -2//Fast
brutemod = 0.7//Tough against firearms
burnmod = 0.65//Tough against lasers
coldmod = 0
heatmod = 0.5//it's a little tough to burn them to death not as hard though.
punchdamagelow = 20
punchdamagehigh = 30//they are inhumanly strong
punchstunthreshold = 25
attack_verb = "smash"
attack_sound = 'sound/weapons/resonator_blast.ogg'
blacklisted = 1
use_skintones = 0
species_traits = list(SPECIES_ORGANIC,RADIMMUNE,VIRUSIMMUNE,NOBLOOD,PIERCEIMMUNE,EYECOLOR,NODISMEMBER,NOHUNGER)
sexes = 0
@@ -1,71 +1,71 @@
/datum/species/pod
// A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness.
name = "Podperson"
id = "pod"
default_color = "59CE00"
species_traits = list(SPECIES_ORGANIC,MUTCOLORS,EYECOLOR)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.25
heatmod = 1.55
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = NONE
liked_food = NONE
toxic_food = NONE
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
C.faction |= "vines"
/datum/species/pod/on_species_loss(mob/living/carbon/C)
. = ..()
C.faction -= "plants"
C.faction -= "vines"
/datum/species/pod/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
light_amount = min(1,T.get_lumcount()) - 0.5
H.nutrition += light_amount * 10
if(H.nutrition > NUTRITION_LEVEL_FULL)
H.nutrition = NUTRITION_LEVEL_FULL
if(light_amount > 0.2) //if there's enough light, heal
H.heal_overall_damage(0.75,0)
H.adjustOxyLoss(-0.5)
if(H.nutrition < NUTRITION_LEVEL_STARVING + 55)
H.adjustOxyLoss(5) //can eat to negate this unfortunately
H.adjustToxLoss(3)
/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "plantbgone")
H.adjustToxLoss(5)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
H.confused = max(H.confused, 1)
return TRUE
/datum/species/pod/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
switch(P.type)
if(/obj/item/projectile/energy/floramut)
if(prob(15))
H.rad_act(rand(30,80))
H.Knockdown(100)
H.visible_message("<span class='warning'>[H] writhes in pain as [H.p_their()] vacuoles boil.</span>", "<span class='userdanger'>You writhe in pain as your vacuoles boil!</span>", "<span class='italics'>You hear the crunching of leaves.</span>")
if(prob(80))
H.randmutb()
else
H.randmutg()
H.domutcheck()
else
H.adjustFireLoss(rand(5,15))
H.show_message("<span class='userdanger'>The radiation beam singes you!</span>")
if(/obj/item/projectile/energy/florayield)
H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL)
/datum/species/pod
// A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness.
name = "Podperson"
id = "pod"
default_color = "59CE00"
species_traits = list(SPECIES_ORGANIC,MUTCOLORS,EYECOLOR)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.25
heatmod = 1.55
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = NONE
liked_food = NONE
toxic_food = NONE
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
C.faction |= "vines"
/datum/species/pod/on_species_loss(mob/living/carbon/C)
. = ..()
C.faction -= "plants"
C.faction -= "vines"
/datum/species/pod/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
light_amount = min(1,T.get_lumcount()) - 0.5
H.nutrition += light_amount * 10
if(H.nutrition > NUTRITION_LEVEL_FULL)
H.nutrition = NUTRITION_LEVEL_FULL
if(light_amount > 0.2) //if there's enough light, heal
H.heal_overall_damage(0.75,0)
H.adjustOxyLoss(-0.5)
if(H.nutrition < NUTRITION_LEVEL_STARVING + 55)
H.adjustOxyLoss(5) //can eat to negate this unfortunately
H.adjustToxLoss(3)
/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "plantbgone")
H.adjustToxLoss(5)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
H.confused = max(H.confused, 1)
return TRUE
/datum/species/pod/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
switch(P.type)
if(/obj/item/projectile/energy/floramut)
if(prob(15))
H.rad_act(rand(30,80))
H.Knockdown(100)
H.visible_message("<span class='warning'>[H] writhes in pain as [H.p_their()] vacuoles boil.</span>", "<span class='userdanger'>You writhe in pain as your vacuoles boil!</span>", "<span class='italics'>You hear the crunching of leaves.</span>")
if(prob(80))
H.randmutb()
else
H.randmutg()
H.domutcheck()
else
H.adjustFireLoss(rand(5,15))
H.show_message("<span class='userdanger'>The radiation beam singes you!</span>")
if(/obj/item/projectile/energy/florayield)
H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL)
@@ -34,7 +34,8 @@
/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()
..()
@@ -47,7 +48,8 @@
/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)
W.implant(src)
@@ -1,18 +1,18 @@
/mob/living/simple_animal/hostile/creature
name = "creature"
desc = "A sanity-destroying otherthing."
icon_state = "otherthing"
icon_living = "otherthing"
icon_dead = "otherthing-dead"
health = 80
maxHealth = 80
obj_damage = 100
melee_damage_lower = 25
melee_damage_upper = 50
attacktext = "chomps"
attack_sound = 'sound/weapons/bite.ogg'
faction = list("creature")
speak_emote = list("screams")
gold_core_spawnable = HOSTILE_SPAWN
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
/mob/living/simple_animal/hostile/creature
name = "creature"
desc = "A sanity-destroying otherthing."
icon_state = "otherthing"
icon_living = "otherthing"
icon_dead = "otherthing-dead"
health = 80
maxHealth = 80
obj_damage = 100
melee_damage_lower = 25
melee_damage_upper = 50
attacktext = "chomps"
attack_sound = 'sound/weapons/bite.ogg'
faction = list("creature")
speak_emote = list("screams")
gold_core_spawnable = HOSTILE_SPAWN
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
+2 -8
View File
@@ -99,19 +99,13 @@
if(deg && (deg > 0 && deg <= 360))
degrees = deg
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)
to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>")
degrees = 0
hidden_uplink.locked = FALSE
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)
if(!istype(M))
return
-162
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
-178
View File
@@ -1,178 +0,0 @@
/datum/uplink_item/stealthy_tools/syndi_borer
name = "Syndicate Brain Slug"
desc = "A small cortical borer, modified to be completely loyal to the owner. \
Genetically infertile, these brain slugs can assist medically in a support role, or take direct action \
to assist their host."
item = /obj/item/antag_spawner/syndi_borer
refundable = TRUE
cost = 10
surplus = 20 //Let's not have this be too common
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/holoparasite
name="Holoparasite Injector"
desc="An injector containing a swarm of holographic parasites. \
They mimic the function of the guardians employed by the Space Wizard Federation, and their form can be selected upon application \
NOTE: The precise nature of the symbiosis required by the parasites renders them incompatible with changelings" //updated to actually describe what they do and warn traitorchans not to buy it
item = /obj/item/storage/box/syndie_kit/holoparasite
refundable = TRUE
cost = 15
surplus = 20 //Nobody needs a ton of parasites
exclude_modes = list(/datum/game_mode/nuclear)
refund_path = /obj/item/guardiancreator/tech/choose/traitor
/obj/item/storage/box/syndie_kit/holoparasite
name = "box"
/obj/item/storage/box/syndie_kit/holoparasite/PopulateContents()
new /obj/item/guardiancreator/tech/choose/traitor(src)
new /obj/item/paper/guides/antag/guardian(src)
/datum/uplink_item/dangerous/antitank
name = "Anti Tank Pistol"
desc = "Essentially amounting to a sniper rifle with no stock and barrel (or indeed, any rifling at all), \
this extremely dubious pistol is guaranteed to dislocate your wrists and hit the broad side of a barn! \
Uses sniper ammo. \
Bullets tend to veer off-course. We are not responsible for any unintentional damage or injury resulting from inaacuracy."
item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
cost = 14
surplus = 25
include_modes = list(/datum/game_mode/nuclear)
/* Commented out due to introduction of reskinnable stetchkins. May still have a niche if people decide it somehow has value.
/datum/uplink_item/dangerous/stealthpistol
name = "Stealth Pistol"
desc = "A compact, easily concealable bullpup pistol that fires 10mm auto rounds in 8 round magazines. \
Has an integrated suppressor."
item = /obj/item/gun/ballistic/automatic/pistol/stealth
cost = 10
surplus = 30
*/
///Soporific 10mm mags///
/datum/uplink_item/ammo/pistolzzz
name = "10mm Soporific Magazine"
desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \
NOTE: Soporific is not instant acting due to the constraints of the round's scale. Will usually require three shots to take effect."
item = /obj/item/ammo_box/magazine/m10mm/soporific
cost = 2
///flechette memes///
/datum/uplink_item/dangerous/flechettegun
name = "Flechette Launcher"
desc = "A compact bullpup that fires micro-flechettes.\
Flechettes have very poor performance idividually, but can be very deadly in numbers. \
Pre-loaded with armor piercing flechettes that are capable of puncturing most kinds of armor."
item = /obj/item/gun/ballistic/automatic/flechette
cost = 12
surplus = 30
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/flechetteap
name = "Armor Piercing Flechette Magazine"
desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective agaisnt flesh."
item = /obj/item/ammo_box/magazine/flechette
cost = 2
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/flechettes
name = "Serrated Flechette Magazine"
desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
Loaded with serrated flechettes that shreds flesh, but is stopped dead in its tracks by armor. \
These flechettes are highly likely to sever arteries, and even limbs."
item = /obj/item/ammo_box/magazine/flechette/s
cost = 2
include_modes = list(/datum/game_mode/nuclear)
///shredder///
/datum/uplink_item/nukeoffer/shredder
name = "Shredder bundle"
desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
cost = 30 // normally 41
///Modular Pistols///
/datum/uplink_item/bundle/modular
name="Modular Pistol Kit"
desc="A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
Includes a suit jacket that is padded with a robust liner."
item = /obj/item/storage/briefcase/modularbundle
cost = 12
//////Bundle stuff//////
///bundle category///
/datum/uplink_item/bundle
category = "Bundles"
surplus = 0
cant_discount = TRUE
///place bundle storage items here I guess///
/obj/item/storage/briefcase/modularbundle
name = "briefcase"
desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding."
icon_state = "briefcase"
flags_1 = CONDUCT_1
force = 10
hitsound = "swing_hit"
throw_speed = 2
throw_range = 4
w_class = WEIGHT_CLASS_BULKY
max_w_class = WEIGHT_CLASS_NORMAL
max_combined_w_class = 21
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
resistance_flags = FLAMMABLE
max_integrity = 150
/obj/item/storage/briefcase/modularbundle/PopulateContents()
new /obj/item/gun/ballistic/automatic/pistol/modular(src)
new /obj/item/suppressor(src)
new /obj/item/ammo_box/magazine/m10mm(src)
new /obj/item/ammo_box/magazine/m10mm/soporific(src)
new /obj/item/ammo_box/c10mm/soporific(src)
new /obj/item/clothing/under/lawyer/blacksuit(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
/obj/item/clothing/suit/toggle/lawyer/black/syndie
desc = "A snappy dress jacket. Suspiciously has no tags or branding."
armor = list(melee = 10, bullet = 10, laser = 10, energy = 10, bomb = 10)
/obj/item/storage/backpack/duffelbag/syndie/shredderbundle
desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
new /obj/item/ammo_box/magazine/flechette/shredder(src)
new /obj/item/ammo_box/magazine/flechette/shredder(src)
new /obj/item/ammo_box/magazine/flechette/shredder(src)
new /obj/item/ammo_box/magazine/flechette/shredder(src)
new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
new /obj/item/storage/belt/military(src)
new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
///End of Bundle stuff///
/*/////////////////////////////////////////////////////////////////////////
///////////// The TRUE Energy Sword ///////////////////////////
*//////////////////////////////////////////////////////////////////////////
/datum/uplink_item/dangerous/cxneb
name = "Dragon's Tooth Non-Eutactic Blade"
desc = "An illegal modification of a weapon that is functionally identical to the energy sword, \
the Non-Eutactic Blade (NEB) forges a hardlight blade on-demand, \
generating an extremely sharp, unbreakable edge that is guaranteed to satisfy your every need. \
This particular model has a polychromic hardlight generator, allowing you to murder in style! \
The illegal modifications bring this weapon up to par with the classic energy sword, and also gives it the energy sword's distinctive sounds."
item = /obj/item/melee/transforming/energy/sword/cx/traitor
cost = 8