Merge branch 'master' into upstream-merge-32249
This commit is contained in:
@@ -134,11 +134,11 @@
|
||||
|
||||
/datum/antagonist/rev/farewell()
|
||||
if(ishuman(owner.current))
|
||||
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!", \
|
||||
"<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
|
||||
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!")
|
||||
to_chat(owner, "<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
|
||||
else if(issilicon(owner.current))
|
||||
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", \
|
||||
"<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
|
||||
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.")
|
||||
to_chat(owner, "<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
|
||||
|
||||
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
|
||||
log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!")
|
||||
|
||||
+2
-1
@@ -29,7 +29,8 @@
|
||||
icon = beam_icon
|
||||
icon_state = beam_icon_state
|
||||
beam_type = btype
|
||||
addtimer(CALLBACK(src,.proc/End), time)
|
||||
if(time < INFINITY)
|
||||
addtimer(CALLBACK(src,.proc/End), time)
|
||||
|
||||
/datum/beam/proc/Start()
|
||||
Draw()
|
||||
|
||||
@@ -34,7 +34,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Lazy associated list of type -> component/list of components.
|
||||
1. `/datum/component/var/enabled` (protected, boolean)
|
||||
* If the component is enabled. If not, it will not react to signals
|
||||
* `TRUE` by default
|
||||
* `FALSE` by default, set to `TRUE` when a signal is registered
|
||||
1. `/datum/component/var/dupe_mode` (protected, enum)
|
||||
* How duplicate component types are handled when added to the datum.
|
||||
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/component
|
||||
var/enabled = TRUE
|
||||
var/enabled = FALSE
|
||||
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
|
||||
var/dupe_type
|
||||
var/list/signal_procs
|
||||
@@ -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)
|
||||
@@ -133,6 +133,8 @@
|
||||
if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
|
||||
proc_or_callback = CALLBACK(src, proc_or_callback)
|
||||
procs[sig_type] = proc_or_callback
|
||||
|
||||
enabled = TRUE
|
||||
|
||||
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
|
||||
return
|
||||
@@ -172,8 +174,7 @@
|
||||
var/datum/component/C = target
|
||||
if(!C.enabled)
|
||||
return NONE
|
||||
var/list/sps = C.signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
var/datum/callback/CB = C.signal_procs[sigtype]
|
||||
if(!CB)
|
||||
return NONE
|
||||
. = CB.InvokeAsync(arglist(arguments))
|
||||
@@ -185,9 +186,8 @@
|
||||
for(var/I in target)
|
||||
var/datum/component/C = I
|
||||
if(!C.enabled)
|
||||
continue
|
||||
var/list/sps = C.signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
continue
|
||||
var/datum/callback/CB = C.signal_procs[sigtype]
|
||||
if(!CB)
|
||||
continue
|
||||
var/retval = CB.InvokeAsync(arglist(arguments))
|
||||
@@ -264,3 +264,6 @@
|
||||
target.TakeComponent(I)
|
||||
else
|
||||
target.TakeComponent(comps)
|
||||
|
||||
/datum/component/ui_host()
|
||||
return parent
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -143,14 +143,25 @@
|
||||
//Proc to use when you 100% want to infect someone, as long as they aren't immune
|
||||
/mob/proc/ForceContractDisease(datum/disease/D)
|
||||
if(!CanContractDisease(D))
|
||||
return 0
|
||||
return FALSE
|
||||
AddDisease(D)
|
||||
|
||||
|
||||
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
|
||||
if(dna && (VIRUSIMMUNE in dna.species.species_traits) && !D.bypasses_immunity)
|
||||
return 0
|
||||
|
||||
if(dna)
|
||||
if((VIRUSIMMUNE in dna.species.species_traits) && !D.bypasses_immunity)
|
||||
return FALSE
|
||||
|
||||
var/can_infect = FALSE
|
||||
for(var/host_type in D.infectable_hosts)
|
||||
if(host_type in dna.species.species_traits)
|
||||
can_infect = TRUE
|
||||
break
|
||||
if(!can_infect)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in D.required_organs)
|
||||
if(!((locate(thing) in bodyparts) || (locate(thing) in internal_organs)))
|
||||
return 0
|
||||
return FALSE
|
||||
return ..()
|
||||
@@ -30,6 +30,8 @@
|
||||
var/list/required_organs = list()
|
||||
var/needs_all_cures = TRUE
|
||||
var/list/strain_data = list() //dna_spread special bullshit
|
||||
var/list/infectable_hosts = list(SPECIES_ORGANIC) //if the disease can spread on organics, synthetics, or undead
|
||||
var/process_dead = FALSE //if this ticks while the host is dead
|
||||
|
||||
/datum/disease/Destroy()
|
||||
affected_mob = null
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/datum/symptom/undead_adaptation
|
||||
name = "Necrotic Metabolism"
|
||||
desc = "The virus is able to thrive and act even within dead hosts."
|
||||
stealth = 2
|
||||
resistance = -2
|
||||
stage_speed = 1
|
||||
transmittable = 0
|
||||
level = 5
|
||||
severity = 0
|
||||
|
||||
/datum/symptom/undead_adaptation/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
A.process_dead = TRUE
|
||||
A.infectable_hosts |= SPECIES_UNDEAD
|
||||
|
||||
/datum/symptom/inorganic_adaptation
|
||||
name = "Inorganic Biology"
|
||||
desc = "The virus can survive and replicate even in an inorganic environment, increasing its resistance and infection rate."
|
||||
stealth = -1
|
||||
resistance = 4
|
||||
stage_speed = -2
|
||||
transmittable = 3
|
||||
level = 5
|
||||
severity = 0
|
||||
|
||||
/datum/symptom/inorganic_adaptation/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
A.infectable_hosts |= SPECIES_INORGANIC
|
||||
@@ -10,6 +10,7 @@
|
||||
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
|
||||
desc = "If left untreated subject will regurgitate bees."
|
||||
severity = VIRUS_SEVERITY_MEDIUM
|
||||
infectable_hosts = list(SPECIES_ORGANIC, SPECIES_UNDEAD) //bees nesting in corpses
|
||||
|
||||
/datum/disease/beesease/stage_act()
|
||||
..()
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
permeability_mod = 0.75
|
||||
desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field."
|
||||
severity = VIRUS_SEVERITY_MEDIUM
|
||||
infectable_hosts = list(SPECIES_ORGANIC, SPECIES_ROBOTIC)
|
||||
process_dead = TRUE
|
||||
|
||||
/datum/disease/magnitis/stage_act()
|
||||
..()
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
desc = "Subject is possesed by the vengeful spirit of a parrot. Call the priest."
|
||||
severity = VIRUS_SEVERITY_MEDIUM
|
||||
infectable_hosts = list(SPECIES_ORGANIC, SPECIES_UNDEAD, SPECIES_INORGANIC, SPECIES_ROBOTIC)
|
||||
bypasses_immunity = TRUE //2spook
|
||||
var/mob/living/simple_animal/parrot/Poly/ghost/parrot
|
||||
|
||||
/datum/disease/parrot_possession/stage_act()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
permeability_mod = 1
|
||||
severity = VIRUS_SEVERITY_BIOHAZARD
|
||||
process_dead = TRUE
|
||||
|
||||
/datum/disease/rhumba_beat/stage_act()
|
||||
..()
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
stage4 = list("<span class='danger'>Your skin feels very loose.</span>", "<span class='danger'>You can feel... something...inside you.</span>")
|
||||
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
|
||||
new_form = /mob/living/silicon/robot
|
||||
|
||||
infectable_hosts = list(SPECIES_ORGANIC, SPECIES_UNDEAD, SPECIES_ROBOTIC)
|
||||
|
||||
/datum/disease/transformation/robot/stage_act()
|
||||
..()
|
||||
@@ -240,3 +240,4 @@
|
||||
stage4 = list("<span class='danger'>You're ravenous.</span>")
|
||||
stage5 = list("<span class='danger'>You have become a morph.</span>")
|
||||
new_form = /mob/living/simple_animal/hostile/morph
|
||||
infectable_hosts = list(SPECIES_ORGANIC, SPECIES_INORGANIC, SPECIES_UNDEAD) //magic!
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
#define HOLOPAD_MAX_DIAL_TIME 200
|
||||
|
||||
#define HOLORECORD_DELAY "delay"
|
||||
#define HOLORECORD_SAY "say"
|
||||
#define HOLORECORD_SOUND "sound"
|
||||
#define HOLORECORD_LANGUAGE "lang"
|
||||
#define HOLORECORD_PRESET "preset"
|
||||
#define HOLORECORD_RENAME "rename"
|
||||
|
||||
#define HOLORECORD_MAX_LENGTH 200
|
||||
|
||||
/mob/camera/aiEye/remote/holo/setLoc()
|
||||
. = ..()
|
||||
var/obj/machinery/holopad/H = origin
|
||||
@@ -184,3 +193,122 @@
|
||||
|
||||
/datum/action/innate/end_holocall/Activate()
|
||||
hcall.Disconnect(hcall.calling_holopad)
|
||||
|
||||
|
||||
//RECORDS
|
||||
/datum/holorecord
|
||||
var/caller_name = "Unknown" //Caller name
|
||||
var/image/caller_image
|
||||
var/list/entries = list()
|
||||
var/language = /datum/language/common //Initial language, can be changed by HOLORECORD_LANGUAGE entries
|
||||
|
||||
/obj/item/disk/holodisk
|
||||
name = "holorecord disk"
|
||||
desc = "Stores recorder holocalls."
|
||||
icon_state = "holodisk"
|
||||
var/datum/holorecord/record
|
||||
//Preset variables
|
||||
var/preset_image_type
|
||||
var/preset_record_text
|
||||
|
||||
/obj/item/disk/holodisk/Initialize(mapload)
|
||||
. = ..()
|
||||
if(preset_record_text)
|
||||
build_record()
|
||||
|
||||
/obj/item/disk/holodisk/Destroy()
|
||||
QDEL_NULL(record)
|
||||
return ..()
|
||||
|
||||
/obj/item/disk/holodisk/proc/build_record()
|
||||
record = new
|
||||
var/list/lines = splittext(preset_record_text,"\n")
|
||||
for(var/line in lines)
|
||||
var/prepared_line = trim(line)
|
||||
if(!length(prepared_line))
|
||||
continue
|
||||
var/splitpoint = findtext(prepared_line," ")
|
||||
if(!splitpoint)
|
||||
continue
|
||||
var/command = copytext(prepared_line,1,splitpoint)
|
||||
var/value = copytext(prepared_line,splitpoint+1)
|
||||
switch(command)
|
||||
if("DELAY")
|
||||
var/delay_value = text2num(value)
|
||||
if(!delay_value)
|
||||
continue
|
||||
record.entries += list(list(HOLORECORD_DELAY,delay_value))
|
||||
if("NAME")
|
||||
if(!record.caller_name)
|
||||
record.caller_name = value
|
||||
else
|
||||
record.entries += list(list(HOLORECORD_RENAME,value))
|
||||
if("SAY")
|
||||
record.entries += list(list(HOLORECORD_SAY,value))
|
||||
if("SOUND")
|
||||
record.entries += list(list(HOLORECORD_SOUND,value))
|
||||
if("LANGUAGE")
|
||||
var/lang_type = text2path(value)
|
||||
if(ispath(lang_type,/datum/language))
|
||||
record.entries += list(list(HOLORECORD_LANGUAGE,lang_type))
|
||||
if("PRESET")
|
||||
var/preset_type = text2path(value)
|
||||
if(ispath(preset_type,/datum/preset_holoimage))
|
||||
record.entries += list(list(HOLORECORD_PRESET,preset_type))
|
||||
if(!preset_image_type)
|
||||
record.caller_image = image('icons/mob/animal.dmi',"old")
|
||||
else
|
||||
var/datum/preset_holoimage/H = new preset_image_type
|
||||
record.caller_image = H.build_image()
|
||||
|
||||
//These build caller image from outfit and some additional data, for use by mappers for ruin holorecords
|
||||
/datum/preset_holoimage
|
||||
var/nonhuman_mobtype //Fill this if you just want something nonhuman
|
||||
var/outfit_type
|
||||
var/species_type = /datum/species/human
|
||||
|
||||
/datum/preset_holoimage/proc/build_image()
|
||||
if(nonhuman_mobtype)
|
||||
var/mob/living/L = nonhuman_mobtype
|
||||
. = image(initial(L.icon),initial(L.icon_state))
|
||||
else
|
||||
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy("HOLODISK_PRESET")
|
||||
if(species_type)
|
||||
mannequin.set_species(species_type)
|
||||
if(outfit_type)
|
||||
mannequin.equipOutfit(outfit_type,TRUE)
|
||||
mannequin.setDir(SOUTH)
|
||||
COMPILE_OVERLAYS(mannequin)
|
||||
. = getFlatIcon(mannequin)
|
||||
unset_busy_human_dummy("HOLODISK_PRESET")
|
||||
|
||||
/obj/item/disk/holodisk/example
|
||||
preset_image_type = /datum/preset_holoimage/clown
|
||||
preset_record_text = {"
|
||||
NAME Clown
|
||||
DELAY 10
|
||||
SAY Why did the chaplain cross the maint ?
|
||||
DELAY 20
|
||||
SAY He wanted to get to the other side!
|
||||
SOUND clownstep
|
||||
DELAY 30
|
||||
LANGUAGE /datum/language/narsie
|
||||
SAY Helped him get there!
|
||||
DELAY 10
|
||||
SAY ALSO IM SECRETLY A GORILLA
|
||||
DELAY 10
|
||||
PRESET /datum/preset_holoimage/gorilla
|
||||
NAME Gorilla
|
||||
LANGUAGE /datum/language/common
|
||||
SAY OOGA
|
||||
DELAY 20"}
|
||||
|
||||
/datum/preset_holoimage/engineer
|
||||
outfit_type = /datum/outfit/job/engineer/gloved/rig
|
||||
|
||||
/datum/preset_holoimage/gorilla
|
||||
nonhuman_mobtype = /mob/living/simple_animal/hostile/gorilla
|
||||
|
||||
/datum/preset_holoimage/clown
|
||||
outfit_type = /datum/outfit/job/clown
|
||||
|
||||
|
||||
+9
-12
@@ -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)))
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/datum/saymode
|
||||
var/key
|
||||
var/mode
|
||||
|
||||
//Return FALSE if you have handled the message. Otherwise, return TRUE and saycode will continue doing saycode things.
|
||||
//user = whoever said the message
|
||||
//message = the message
|
||||
//language = the language.
|
||||
/datum/saymode/proc/handle_message(mob/living/user, message, datum/language/language)
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/saymode/changeling
|
||||
key = "g"
|
||||
mode = MODE_CHANGELING
|
||||
|
||||
/datum/saymode/changeling/handle_message(mob/living/user, message, datum/language/language)
|
||||
switch(user.lingcheck())
|
||||
if(LINGHIVE_LINK)
|
||||
var/msg = "<i><font color=#800040><b>[user.mind]:</b> [message]</font></i>"
|
||||
for(var/_M in GLOB.mob_list)
|
||||
var/mob/M = _M
|
||||
if(M in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(M, user)
|
||||
to_chat(M, "[link] [msg]")
|
||||
else
|
||||
switch(M.lingcheck())
|
||||
if(LINGHIVE_LINK, LINGHIVE_LING)
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_OUTSIDER)
|
||||
if(prob(40))
|
||||
to_chat(M, "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>")
|
||||
if(LINGHIVE_LING)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/msg = "<i><font color=#800080><b>[changeling.changelingID]:</b> [message]</font></i>"
|
||||
log_talk(src,"[changeling.changelingID]/[user.key] : [message]",LOGSAY)
|
||||
for(var/_M in GLOB.mob_list)
|
||||
var/mob/M = _M
|
||||
if(M in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(M, user)
|
||||
to_chat(M, "[link] [msg]")
|
||||
else
|
||||
switch(M.lingcheck())
|
||||
if(LINGHIVE_LINK)
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_LING)
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_OUTSIDER)
|
||||
if(prob(40))
|
||||
to_chat(M, "<i><font color=#800080>We can faintly sense another of our kind trying to communicate through the hivemind...</font></i>")
|
||||
if(LINGHIVE_OUTSIDER)
|
||||
to_chat(user, "<i><font color=#800080>Our senses have not evolved enough to be able to communicate this way...</font></i>")
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/saymode/xeno
|
||||
key = "a"
|
||||
mode = MODE_ALIEN
|
||||
|
||||
/datum/saymode/xeno/handle_message(mob/living/user, message, datum/language/language)
|
||||
if(user.hivecheck())
|
||||
user.alien_talk(message)
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/saymode/vocalcords
|
||||
key = "x"
|
||||
mode = MODE_VOCALCORDS
|
||||
|
||||
/datum/saymode/vocalcords/handle_message(mob/living/user, message, datum/language/language)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
|
||||
if(V && V.can_speak_with())
|
||||
V.handle_speech(message) //message
|
||||
V.speak_with(message) //action
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/saymode/binary //everything that uses .b (silicons, drones, blobbernauts/spores, swarmers)
|
||||
key = "b"
|
||||
mode = MODE_BINARY
|
||||
|
||||
/datum/saymode/binary/handle_message(mob/living/user, message, datum/language/language)
|
||||
if(isswarmer(user))
|
||||
var/mob/living/simple_animal/hostile/swarmer/S = user
|
||||
S.swarmer_chat(message)
|
||||
return FALSE
|
||||
if(isblobmonster(user))
|
||||
var/mob/living/simple_animal/hostile/blob/B = user
|
||||
B.blob_chat(message)
|
||||
return FALSE
|
||||
if(isdrone(user))
|
||||
var/mob/living/simple_animal/drone/D = user
|
||||
D.drone_chat(message)
|
||||
return FALSE
|
||||
if(user.binarycheck())
|
||||
user.robot_talk(message)
|
||||
return FALSE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/saymode/holopad
|
||||
key = "h"
|
||||
mode = MODE_HOLOPAD
|
||||
|
||||
/datum/saymode/holopad/handle_message(mob/living/user, message, datum/language/language)
|
||||
if(isAI(user))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
AI.holopad_talk(message, language)
|
||||
return FALSE
|
||||
return FALSE
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -20,10 +20,11 @@
|
||||
|
||||
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
|
||||
immunity_type = "lava"
|
||||
|
||||
|
||||
/datum/weather/floor_is_lava/weather_act(mob/living/L)
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density)
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density || (L in O.buckled_mobs && istype(O, /obj/structure/bed)))
|
||||
return
|
||||
if(L.loc.density)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user