Merge branch 'master' into donoritemmodularization
This commit is contained in:
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
Exonet Protocol Version 2
|
||||
|
||||
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
|
||||
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
|
||||
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
|
||||
|
||||
Version 1 never existed.
|
||||
|
||||
*Setting up*
|
||||
|
||||
To set up the exonet link, define a variable on your desired atom it is like this;
|
||||
var/datum/exonet_protocol/exonet = null
|
||||
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
|
||||
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
|
||||
|
||||
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
|
||||
Destroy() also automatically calls remove_address().
|
||||
|
||||
*Sending messages*
|
||||
|
||||
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
|
||||
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
|
||||
ping yourself.
|
||||
|
||||
*Receiving messages*
|
||||
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
|
||||
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
|
||||
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
|
||||
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
|
||||
It's suggested to start with an if or switch statement for the message, to determine what to do.
|
||||
*/
|
||||
|
||||
/datum/exonet_protocol
|
||||
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
|
||||
var/atom/holder
|
||||
|
||||
/datum/exonet_protocol/New(var/atom/H)
|
||||
holder = H
|
||||
|
||||
/datum/exonet_protocol/Destroy()
|
||||
remove_address()
|
||||
holder = null
|
||||
return ..()
|
||||
|
||||
// Proc: make_address()
|
||||
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
|
||||
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
|
||||
/datum/exonet_protocol/proc/make_address(var/string)
|
||||
if(!string)
|
||||
return
|
||||
var/hex = copytext(md5(string),1,25)
|
||||
if(!hex)
|
||||
return
|
||||
var/addr_1 = copytext(hex,1,5)
|
||||
var/addr_2 = copytext(hex,5,9)
|
||||
var/addr_3 = copytext(hex,9,13)
|
||||
var/addr_4 = copytext(hex,13,17)
|
||||
address = "fc00:[addr_1]:[addr_2]:[addr_3]:[addr_4]"
|
||||
if(SScircuit.all_exonet_connections[address])
|
||||
stack_trace("WARNING: Exonet address collision in make_address. Holder type if applicable is [holder? holder.type : "NO HOLDER"]!")
|
||||
SScircuit.all_exonet_connections[address] = src
|
||||
|
||||
|
||||
// Proc: make_arbitrary_address()
|
||||
// Parameters: 1 (new_address - the desired address)
|
||||
// Description: Allocates that specific address, if it is available.
|
||||
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
|
||||
if(new_address)
|
||||
if(new_address == SScircuit.get_exonet_address(new_address) ) //Collision test.
|
||||
return FALSE
|
||||
address = new_address
|
||||
SScircuit.all_exonet_connections[address] = src
|
||||
return TRUE
|
||||
|
||||
|
||||
// Proc: remove_address()
|
||||
// Parameters: None
|
||||
// Description: Deallocates the address, freeing it for use.
|
||||
/datum/exonet_protocol/proc/remove_address()
|
||||
SScircuit.all_exonet_connections -= address
|
||||
address = ""
|
||||
|
||||
|
||||
|
||||
// Proc: send_message()
|
||||
// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for,
|
||||
// content - the actual 'message' being sent to the address)
|
||||
// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved.
|
||||
/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content)
|
||||
if(!address)
|
||||
return FALSE
|
||||
var/obj/machinery/exonet_node/node = SScircuit.get_exonet_node()
|
||||
if(!node) // Telecomms went boom, ion storm, etc.
|
||||
return FALSE
|
||||
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
|
||||
if(exonet)
|
||||
node.write_log(address, target_address, data_type, content)
|
||||
return exonet.receive_message(holder, address, data_type, content)
|
||||
|
||||
// Proc: receive_message()
|
||||
// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from,
|
||||
// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom)
|
||||
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
|
||||
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content)
|
||||
holder.receive_exonet_message(origin_atom, origin_address, data_type, content)
|
||||
return TRUE // for send_message()
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
|
||||
// Description: Override this to make your atom do something when a message is received.
|
||||
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
|
||||
return
|
||||
@@ -177,7 +177,7 @@
|
||||
to_chat(owner.current, "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>")
|
||||
reset_powers()
|
||||
canrespec = 0
|
||||
SSblackbox.add_details("changeling_power_purchase","Readapt")
|
||||
SSblackbox.record_feedback("tally", "changeling_power_purchase", 1, "Readapt")
|
||||
return 1
|
||||
else
|
||||
to_chat(owner.current, "<span class='danger'>You lack the power to readapt your evolutions!</span>")
|
||||
@@ -277,7 +277,7 @@
|
||||
if(stored_profiles.len > dna_max)
|
||||
if(!push_out_profile())
|
||||
return
|
||||
|
||||
|
||||
if(!first_prof)
|
||||
first_prof = prof
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
var/datum/action/innate/cult/comm/communion = new
|
||||
var/datum/action/innate/cult/mastervote/vote = new
|
||||
job_rank = ROLE_CULTIST
|
||||
var/ignore_implant = FALSE
|
||||
|
||||
/datum/antagonist/cult/Destroy()
|
||||
QDEL_NULL(communion)
|
||||
@@ -65,7 +66,7 @@
|
||||
|
||||
/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(. && !ignore_implant)
|
||||
. = is_convertable_to_cult(new_owner.current)
|
||||
|
||||
/datum/antagonist/cult/on_gain()
|
||||
@@ -121,6 +122,7 @@
|
||||
var/datum/action/innate/cult/master/finalreck/reckoning = new
|
||||
var/datum/action/innate/cult/master/cultmark/bloodmark = new
|
||||
var/datum/action/innate/cult/master/pulse/throwing = new
|
||||
ignore_implant = TRUE
|
||||
|
||||
/datum/antagonist/cult/master/Destroy()
|
||||
QDEL_NULL(reckoning)
|
||||
|
||||
@@ -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)])!")
|
||||
|
||||
+7
-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()
|
||||
@@ -149,6 +150,11 @@
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/ebeam/singularity_pull()
|
||||
return
|
||||
/obj/effect/ebeam/singularity_act()
|
||||
return
|
||||
|
||||
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time = 3)
|
||||
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
|
||||
INVOKE_ASYNC(newbeam, /datum/beam/.proc/Start)
|
||||
|
||||
@@ -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
|
||||
@@ -78,6 +78,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
1. `/datum/proc/SendSignal(signal, ...)` (public, final)
|
||||
* Call to send a signal to the components of the target datum
|
||||
* Extra arguments are to be specified in the signal definition
|
||||
* Returns a bitflag with signal specific information assembled from all activated components
|
||||
1. `/datum/component/New(datum/parent, ...)` (private, final)
|
||||
* Runs internal setup for the component
|
||||
* Extra arguments are passed to `Initialize()`
|
||||
|
||||
@@ -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
|
||||
@@ -10,13 +10,21 @@
|
||||
qdel(src)
|
||||
CRASH("[type] instantiated!")
|
||||
|
||||
//check for common mishaps
|
||||
if(!isnum(dupe_mode))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_mode!")
|
||||
if(dupe_type && !ispath(dupe_type))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_type!")
|
||||
|
||||
parent = P
|
||||
var/list/arguments = args.Copy()
|
||||
arguments.Cut(1, 2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
return
|
||||
|
||||
|
||||
_CheckDupesAndJoinParent(P)
|
||||
|
||||
/datum/component/proc/_CheckDupesAndJoinParent()
|
||||
@@ -45,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))
|
||||
@@ -114,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)
|
||||
@@ -125,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
|
||||
@@ -156,36 +166,35 @@
|
||||
/datum/proc/SendSignal(sigtype, ...)
|
||||
var/list/comps = datum_components
|
||||
if(!comps)
|
||||
return FALSE
|
||||
return NONE
|
||||
var/list/arguments = args.Copy()
|
||||
arguments.Cut(1, 2)
|
||||
var/target = comps[/datum/component]
|
||||
if(!length(target))
|
||||
var/datum/component/C = target
|
||||
if(!C.enabled)
|
||||
return FALSE
|
||||
var/list/sps = C.signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
return NONE
|
||||
var/datum/callback/CB = C.signal_procs[sigtype]
|
||||
if(!CB)
|
||||
return FALSE
|
||||
return NONE
|
||||
. = CB.InvokeAsync(arglist(arguments))
|
||||
if(.)
|
||||
if(. & COMPONENT_ACTIVATED)
|
||||
ComponentActivated(C)
|
||||
C.AfterComponentActivated()
|
||||
else
|
||||
. = FALSE
|
||||
. = NONE
|
||||
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
|
||||
if(CB.InvokeAsync(arglist(arguments)))
|
||||
var/retval = CB.InvokeAsync(arglist(arguments))
|
||||
. |= retval
|
||||
if(retval & COMPONENT_ACTIVATED)
|
||||
ComponentActivated(C)
|
||||
C.AfterComponentActivated()
|
||||
. = TRUE
|
||||
|
||||
/datum/proc/ComponentActivated(datum/component/C)
|
||||
set waitfor = FALSE
|
||||
@@ -255,3 +264,6 @@
|
||||
target.TakeComponent(I)
|
||||
else
|
||||
target.TakeComponent(comps)
|
||||
|
||||
/datum/component/ui_host()
|
||||
return parent
|
||||
|
||||
@@ -20,27 +20,26 @@
|
||||
/datum/component/archaeology/proc/Dig(obj/item/W, mob/living/user)
|
||||
if(dug)
|
||||
to_chat(user, "<span class='notice'>Looks like someone has dug here already.</span>")
|
||||
return FALSE
|
||||
else
|
||||
var/digging_speed
|
||||
if (istype(W, /obj/item/shovel))
|
||||
var/obj/item/shovel/S = W
|
||||
digging_speed = S.digspeed
|
||||
else if (istype(W, /obj/item/pickaxe))
|
||||
var/obj/item/pickaxe/P = W
|
||||
digging_speed = P.digspeed
|
||||
return
|
||||
|
||||
var/digging_speed
|
||||
if (istype(W, /obj/item/shovel))
|
||||
var/obj/item/shovel/S = W
|
||||
digging_speed = S.digspeed
|
||||
else if (istype(W, /obj/item/pickaxe))
|
||||
var/obj/item/pickaxe/P = W
|
||||
digging_speed = P.digspeed
|
||||
|
||||
if (digging_speed && isturf(user.loc))
|
||||
to_chat(user, "<span class='notice'>You start digging...</span>")
|
||||
playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
|
||||
if (digging_speed && isturf(user.loc))
|
||||
to_chat(user, "<span class='notice'>You start digging...</span>")
|
||||
playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
|
||||
if(do_after(user, digging_speed, target = parent))
|
||||
to_chat(user, "<span class='notice'>You dig a hole.</span>")
|
||||
gets_dug()
|
||||
dug = TRUE
|
||||
SSblackbox.add_details("pick_used_mining",W.type)
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(do_after(user, digging_speed, target = parent))
|
||||
to_chat(user, "<span class='notice'>You dig a hole.</span>")
|
||||
gets_dug()
|
||||
dug = TRUE
|
||||
SSblackbox.record_feedback("tally", "pick_used_mining", 1, W.type)
|
||||
return COMPONENT_NO_AFTERATTACK
|
||||
|
||||
/datum/component/archaeology/proc/gets_dug()
|
||||
if(dug)
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
if(istype(victim))
|
||||
for(var/datum/disease/D in diseases)
|
||||
victim.ContactContractDisease(D, "feet")
|
||||
return TRUE
|
||||
return COMPONENT_ACTIVATED
|
||||
@@ -53,11 +53,11 @@
|
||||
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return FALSE
|
||||
return
|
||||
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
return FALSE
|
||||
. = TRUE
|
||||
return
|
||||
. = COMPONENT_ACTIVATED | COMPONENT_NO_AFTERATTACK
|
||||
last_insert_success = FALSE
|
||||
var/datum/callback/pc = precondition
|
||||
if(pc && !pc.Invoke())
|
||||
|
||||
@@ -0,0 +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
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
/datum/component/spraycan_paintable/proc/Repaint(obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
|
||||
if(!istype(spraycan) || user.a_intent == INTENT_HARM)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
return
|
||||
. = COMPONENT_NO_AFTERATTACK
|
||||
if(spraycan.is_capped)
|
||||
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
|
||||
return
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
/datum/component/riding
|
||||
var/next_vehicle_move = 0 //used for move delays
|
||||
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
|
||||
var/keytype
|
||||
|
||||
var/slowed = FALSE
|
||||
var/slowvalue = 1
|
||||
|
||||
var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one.
|
||||
var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change.
|
||||
var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py)
|
||||
var/list/allowed_turf_typecache
|
||||
var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence.
|
||||
var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more.
|
||||
var/override_allow_spacemove = FALSE
|
||||
var/drive_verb = "drive"
|
||||
var/ride_check_rider_incapacitated = FALSE
|
||||
var/ride_check_rider_restrained = FALSE
|
||||
var/ride_check_ridden_incapacitated = FALSE
|
||||
|
||||
/datum/component/riding/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!")
|
||||
RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
|
||||
restore_position(M)
|
||||
unequip_buckle_inhands(M)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
|
||||
handle_vehicle_offsets()
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER)
|
||||
. = defaults["[AM.dir]"]
|
||||
if(directional_vehicle_layers["[AM.dir]"])
|
||||
. = directional_vehicle_layers["[AM.dir]"]
|
||||
if(isnull(.)) //you can set it to null to not change it.
|
||||
. = AM.layer
|
||||
AM.layer = .
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
|
||||
directional_vehicle_layers["[dir]"] = layer
|
||||
|
||||
/datum/component/riding/proc/vehicle_moved()
|
||||
var/atom/movable/AM = parent
|
||||
for(var/i in AM.buckled_mobs)
|
||||
ride_check(i)
|
||||
handle_vehicle_offsets()
|
||||
handle_vehicle_layer()
|
||||
|
||||
/datum/component/riding/proc/ride_check(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
var/mob/AMM = AM
|
||||
if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE)))
|
||||
AM.visible_message("<span class='warning'>[M] falls off of [AM]!</span>")
|
||||
AM.unbuckle_mob(M)
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
var/AM_dir = "[AM.dir]"
|
||||
var/passindex = 0
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/m in AM.buckled_mobs)
|
||||
passindex++
|
||||
var/mob/living/buckled_mob = m
|
||||
var/list/offsets = get_offsets(passindex)
|
||||
var/rider_dir = get_rider_dir(passindex)
|
||||
buckled_mob.setDir(rider_dir)
|
||||
dir_loop:
|
||||
for(var/offsetdir in offsets)
|
||||
if(offsetdir == AM_dir)
|
||||
var/list/diroffsets = offsets[offsetdir]
|
||||
buckled_mob.pixel_x = diroffsets[1]
|
||||
if(diroffsets.len >= 2)
|
||||
buckled_mob.pixel_y = diroffsets[2]
|
||||
if(diroffsets.len == 3)
|
||||
buckled_mob.layer = diroffsets[3]
|
||||
break dir_loop
|
||||
var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
var/px = default_vehicle_pixel_offsets[AM_dir]
|
||||
var/py = default_vehicle_pixel_offsets[AM_dir]
|
||||
if(directional_vehicle_offsets[AM_dir])
|
||||
if(isnull(directional_vehicle_offsets[AM_dir]))
|
||||
px = AM.pixel_x
|
||||
py = AM.pixel_y
|
||||
else
|
||||
px = directional_vehicle_offsets[AM_dir][1]
|
||||
py = directional_vehicle_offsets[AM_dir][2]
|
||||
AM.pixel_x = px
|
||||
AM.pixel_y = py
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y)
|
||||
directional_vehicle_offsets["[dir]"] = list(x, y)
|
||||
|
||||
//Override this to set your vehicle's various pixel offsets
|
||||
/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
. = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
if(riding_offsets["[pass_index]"])
|
||||
. = riding_offsets["[pass_index]"]
|
||||
else if(riding_offsets["[RIDING_OFFSET_ALL]"])
|
||||
. = riding_offsets["[RIDING_OFFSET_ALL]"]
|
||||
|
||||
/datum/component/riding/proc/set_riding_offsets(index, list/offsets)
|
||||
if(!islist(offsets))
|
||||
return FALSE
|
||||
riding_offsets["[index]"] = offsets
|
||||
|
||||
//Override this to set the passengers/riders dir based on which passenger they are.
|
||||
//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
|
||||
/datum/component/riding/proc/get_rider_dir(pass_index)
|
||||
var/atom/movable/AM = parent
|
||||
return AM.dir
|
||||
|
||||
//KEYS
|
||||
/datum/component/riding/proc/keycheck(mob/user)
|
||||
return !keytype || user.is_holding_item_of_type(keytype)
|
||||
|
||||
//BUCKLE HOOKS
|
||||
/datum/component/riding/proc/restore_position(mob/living/buckled_mob)
|
||||
if(buckled_mob)
|
||||
buckled_mob.pixel_x = 0
|
||||
buckled_mob.pixel_y = 0
|
||||
if(buckled_mob.client)
|
||||
buckled_mob.client.change_view(world.view)
|
||||
|
||||
//MOVEMENT
|
||||
/datum/component/riding/proc/turf_check(turf/next, turf/current)
|
||||
if(allowed_turf_typecache && !allowed_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type])
|
||||
else if(forbid_turf_typecache && forbid_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type])
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/handle_ride(mob/user, direction)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
Unbuckle(user)
|
||||
return
|
||||
|
||||
if(world.time < next_vehicle_move)
|
||||
return
|
||||
next_vehicle_move = world.time + vehicle_move_delay
|
||||
|
||||
if(keycheck(user))
|
||||
var/turf/next = get_step(AM, direction)
|
||||
var/turf/current = get_turf(AM)
|
||||
if(!istype(next) || !istype(current))
|
||||
return //not happening.
|
||||
if(!turf_check(next, current))
|
||||
to_chat(user, "Your \the [AM] can not go onto [next]!")
|
||||
return
|
||||
if(!Process_Spacemove(direction) || !isturf(AM.loc))
|
||||
return
|
||||
step(AM, direction)
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You'll need the keys in one of your hands to [drive_verb] [AM].</span>")
|
||||
|
||||
/datum/component/riding/proc/Unbuckle(atom/movable/M)
|
||||
addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/riding/proc/Process_Spacemove(direction)
|
||||
var/atom/movable/AM = parent
|
||||
return override_allow_spacemove || AM.has_gravity()
|
||||
|
||||
/datum/component/riding/proc/account_limbs(mob/living/M)
|
||||
if(M.get_num_legs() < 2 && !slowed)
|
||||
vehicle_move_delay = vehicle_move_delay + slowvalue
|
||||
slowed = TRUE
|
||||
else if(slowed)
|
||||
vehicle_move_delay = vehicle_move_delay - slowvalue
|
||||
slowed = FALSE
|
||||
|
||||
///////Yes, I said humans. No, this won't end well...//////////
|
||||
/datum/component/riding/human
|
||||
|
||||
/datum/component/riding/human/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
|
||||
|
||||
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
|
||||
var/mob/living/carbon/human/AM = parent
|
||||
if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
|
||||
force_dismount(target)
|
||||
|
||||
/datum/component/riding/human/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/human/force_dismount(mob/living/user)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(user)
|
||||
user.Knockdown(60)
|
||||
user.visible_message("<span class='warning'>[AM] pushes [user] off of them!</span>")
|
||||
|
||||
/datum/component/riding/cyborg
|
||||
|
||||
/datum/component/riding/cyborg/ride_check(mob/user)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
var/kick = TRUE
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(R.module && R.module.ride_allow_incapacitated)
|
||||
kick = FALSE
|
||||
if(kick)
|
||||
to_chat(user, "<span class='userdanger'>You fall off of [AM]!</span>")
|
||||
Unbuckle(user)
|
||||
return
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/carbonuser = user
|
||||
if(!carbonuser.get_num_arms())
|
||||
Unbuckle(user)
|
||||
to_chat(user, "<span class='userdanger'>You can't grab onto [AM] with no hands!</span>")
|
||||
return
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3))
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/M in AM.buckled_mobs)
|
||||
M.setDir(AM.dir)
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(istype(R.module))
|
||||
M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)]
|
||||
M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)]
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/component/riding/cyborg/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
var/turf/target = get_edge_target_turf(AM, AM.dir)
|
||||
var/turf/targetm = get_step(get_turf(AM), AM.dir)
|
||||
M.Move(targetm)
|
||||
M.visible_message("<span class='warning'>[M] is thrown clear of [AM]!</span>")
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
|
||||
var/atom/movable/AM = parent
|
||||
var/amount_equipped = 0
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
inhand.rider = user
|
||||
inhand.parent = AM
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
else
|
||||
break
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
else
|
||||
unequip_buckle_inhands(user)
|
||||
return FALSE
|
||||
|
||||
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
var/atom/movable/AM = parent
|
||||
for(var/obj/item/riding_offhand/O in user.contents)
|
||||
if(O.parent != AM)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/riding_offhand
|
||||
name = "offhand"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "offhand"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/mob/living/carbon/rider
|
||||
var/mob/living/parent
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/riding_offhand/dropped()
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/equipped()
|
||||
if(loc != rider)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/Destroy()
|
||||
var/atom/movable/AM = parent
|
||||
if(selfdeleting)
|
||||
if(rider in AM.buckled_mobs)
|
||||
AM.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
@@ -12,7 +12,7 @@
|
||||
var/mob/victim = AM
|
||||
if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags))
|
||||
slip_victim = victim
|
||||
return TRUE
|
||||
return COMPONENT_ACTIVATED
|
||||
|
||||
/datum/component/slippery/AfterComponentActivated()
|
||||
slip_victim = null
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.dna.species, /datum/species/skeleton))
|
||||
return ..() //undeads are unaffected by the spook-pocalypse.
|
||||
return //undeads are unaffected by the spook-pocalypse.
|
||||
if(istype(H.dna.species, /datum/species/zombie))
|
||||
H.adjustStaminaLoss(25)
|
||||
H.Knockdown(15) //zombies can't resist the doot
|
||||
|
||||
@@ -3,13 +3,30 @@
|
||||
var/amount
|
||||
var/overlay
|
||||
|
||||
var/static/list/blacklist = typecacheof(/turf/closed/wall/mineral/diamond)
|
||||
var/static/list/resistlist = typecacheof(/turf/closed/wall/r_wall)
|
||||
var/static/list/blacklist = typecacheof(
|
||||
/turf/open/lava,
|
||||
/turf/open/space,
|
||||
/turf/open/water,
|
||||
/turf/open/chasm,
|
||||
)
|
||||
|
||||
var/static/list/immunelist = typecacheof(
|
||||
/turf/closed/wall/mineral/diamond,
|
||||
/turf/closed/indestructible,
|
||||
/turf/open/indestructible,
|
||||
)
|
||||
|
||||
var/static/list/resistlist = typecacheof(
|
||||
/turf/closed/wall/r_wall,
|
||||
)
|
||||
|
||||
/datum/component/thermite/Initialize(_amount)
|
||||
if(!istype(parent, /turf))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("A thermite component has been applied to an incorrect object. parent: [parent]")
|
||||
if(blacklist[parent.type])
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(immunelist[parent.type])
|
||||
_amount*=0 //Yeah the overlay can still go on it and be cleaned but you arent burning down a diamond wall
|
||||
if(resistlist[parent.type])
|
||||
_amount*=0.25
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]"
|
||||
|
||||
|
||||
/datum/proc/on_reagent_change()
|
||||
/datum/proc/on_reagent_change(changetype)
|
||||
return
|
||||
|
||||
|
||||
@@ -748,6 +748,28 @@
|
||||
src.give_disease(M)
|
||||
href_list["datumrefresh"] = href_list["give_spell"]
|
||||
|
||||
else if(href_list["ninja"])
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/M = locate(href_list["ninja"]) in GLOB.carbon_list
|
||||
if(!istype(M))
|
||||
to_chat(usr, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
if(tgalert(usr, "Are you sure you want to make [M] into a ninja?", "Confirmation", "Yes", "No") == "No")
|
||||
return
|
||||
|
||||
if(!M.mind)
|
||||
M.mind_initialize()
|
||||
|
||||
var/datum/antagonist/ninja/hiyah = M.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!hiyah)
|
||||
hiyah = add_ninja(M)
|
||||
if(hiyah)
|
||||
hiyah.equip_space_ninja()
|
||||
href_list["datumrefresh"] = href_list["ninja"]
|
||||
|
||||
else if(href_list["gib"])
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
@@ -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
|
||||
@@ -101,8 +103,9 @@
|
||||
/datum/disease/proc/cure(add_resistance = TRUE)
|
||||
if(affected_mob)
|
||||
if(disease_flags & CAN_RESIST)
|
||||
if(add_resistance && !(type in affected_mob.resistances))
|
||||
affected_mob.resistances += type
|
||||
var/id = GetDiseaseID()
|
||||
if(add_resistance && !(id in affected_mob.resistances))
|
||||
affected_mob.resistances += id
|
||||
remove_virus()
|
||||
qdel(src)
|
||||
|
||||
@@ -119,7 +122,7 @@
|
||||
|
||||
|
||||
/datum/disease/proc/GetDiseaseID()
|
||||
return type
|
||||
return "[type]"
|
||||
|
||||
//don't use this proc directly. this should only ever be called by cure()
|
||||
/datum/disease/proc/remove_virus()
|
||||
|
||||
@@ -95,15 +95,6 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
// To add special resistances.
|
||||
/datum/disease/advance/cure(resistance=1)
|
||||
if(affected_mob)
|
||||
var/id = "[GetDiseaseID()]"
|
||||
if(resistance && !(id in affected_mob.resistances))
|
||||
affected_mob.resistances[id] = id
|
||||
remove_virus()
|
||||
qdel(src) //delete the datum to stop it processing
|
||||
|
||||
// Returns the advance disease with a different reference memory.
|
||||
/datum/disease/advance/Copy(process = 0)
|
||||
return new /datum/disease/advance(process, src, 1)
|
||||
|
||||
@@ -9,20 +9,15 @@
|
||||
base_message_chance = 20 //here used for the overlays
|
||||
symptom_delay_min = 1
|
||||
symptom_delay_max = 1
|
||||
var/hide_healing = FALSE
|
||||
var/passive_message = "" //random message to infected but not actively healing people
|
||||
threshold_desc = "<b>Stage Speed 6:</b> Doubles healing speed.<br>\
|
||||
<b>Stage Speed 11:</b> Triples healing speed.<br>\
|
||||
<b>Stealth 4:</b> Healing will no longer be visible to onlookers."
|
||||
|
||||
/datum/symptom/heal/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stealth"] >= 4) //invisible healing
|
||||
hide_healing = TRUE
|
||||
if(A.properties["stage_rate"] >= 6) //stronger healing
|
||||
power = 2
|
||||
if(A.properties["stage_rate"] >= 11) //even stronger healing
|
||||
power = 3
|
||||
|
||||
/datum/symptom/heal/Activate(datum/disease/advance/A)
|
||||
if(!..())
|
||||
@@ -31,299 +26,439 @@
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(A.stage)
|
||||
if(4, 5)
|
||||
Heal(M, A)
|
||||
var/effectiveness = CanHeal(A)
|
||||
if(!effectiveness)
|
||||
if(passive_message && prob(2) && passive_message_condition(M))
|
||||
to_chat(M, passive_message)
|
||||
return
|
||||
else
|
||||
Heal(M, A, effectiveness)
|
||||
return
|
||||
|
||||
/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A)
|
||||
return 1
|
||||
/datum/symptom/heal/proc/CanHeal(datum/disease/advance/A)
|
||||
return power
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A, actual_power)
|
||||
return TRUE
|
||||
|
||||
Toxin Filter
|
||||
/datum/symptom/heal/proc/passive_message_condition(mob/living/M)
|
||||
return TRUE
|
||||
|
||||
Little bit hidden.
|
||||
Lowers resistance tremendously.
|
||||
Decreases stage speed tremendously.
|
||||
Decreases transmittablity temrendously.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
Heals toxins in the affected mob's blood stream.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/heal/toxin
|
||||
name = "Toxic Filter"
|
||||
desc = "The virus synthesizes regenerative chemicals in the bloodstream, repairing damage caused by toxins."
|
||||
name = "Starlight Condensation"
|
||||
desc = "The virus reacts to direct starlight, producing regenerative chemicals that can cure toxin damage."
|
||||
stealth = 1
|
||||
resistance = -4
|
||||
stage_speed = -4
|
||||
transmittable = -4
|
||||
resistance = -3
|
||||
stage_speed = -3
|
||||
transmittable = -3
|
||||
level = 6
|
||||
passive_message = "<span class='notice'>You miss the feeling of starlight on your skin.</span>"
|
||||
var/nearspace_penalty = 0.3
|
||||
threshold_desc = "<b>Stage Speed 6:</b> Increases healing speed.<br>\
|
||||
<b>Transmission 6:</b> Removes penalty for only being close to space."
|
||||
|
||||
/datum/symptom/heal/toxin/Heal(mob/living/M, datum/disease/advance/A)
|
||||
var/heal_amt = 1 * power
|
||||
if(M.toxloss > 0 && prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#66FF99")
|
||||
/datum/symptom/heal/toxin/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["transmission"] >= 6)
|
||||
nearspace_penalty = 1
|
||||
if(A.properties["stage_rate"] >= 6)
|
||||
power = 2
|
||||
|
||||
/datum/symptom/heal/toxin/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(istype(get_turf(M), /turf/open/space))
|
||||
return power
|
||||
else
|
||||
for(var/turf/T in view(M, 2))
|
||||
if(istype(T, /turf/open/space))
|
||||
return power * nearspace_penalty
|
||||
|
||||
/datum/symptom/heal/toxin/Heal(mob/living/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = actual_power
|
||||
if(M.getToxLoss() && prob(5))
|
||||
to_chat(M, "<span class='notice'>Your skin tingles as the starlight purges toxins from your bloodstream.</span>")
|
||||
M.adjustToxLoss(-heal_amt)
|
||||
return 1
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
/datum/symptom/heal/toxin/passive_message_condition(mob/living/M)
|
||||
if(M.getToxLoss())
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
Apoptosis
|
||||
|
||||
Lowers resistance.
|
||||
Decreases stage speed.
|
||||
Decreases transmittablity.
|
||||
|
||||
Bonus
|
||||
Heals toxins in the affected mob's blood stream faster.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/heal/toxin/plus
|
||||
|
||||
name = "Apoptoxin filter"
|
||||
/datum/symptom/heal/chem
|
||||
name = "Toxolysis"
|
||||
stealth = 0
|
||||
resistance = -2
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 8
|
||||
desc = "The virus stimulates production of special stem cells in the bloodstream, causing rapid reparation of any damage caused by toxins."
|
||||
level = 7
|
||||
var/food_conversion = FALSE
|
||||
desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream."
|
||||
threshold_desc = "<b>Resistance 7:</b> Increases chem removal speed.<br>\
|
||||
<b>Stage Speed 6:</b> Consumed chemicals nourish the host."
|
||||
|
||||
/datum/symptom/heal/toxin/plus/Heal(mob/living/M, datum/disease/advance/A)
|
||||
var/heal_amt = 2 * power
|
||||
if(M.toxloss > 0 && prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#00FF00")
|
||||
M.adjustToxLoss(-heal_amt)
|
||||
/datum/symptom/heal/chem/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 6)
|
||||
food_conversion = TRUE
|
||||
if(A.properties["resistance"] >= 7)
|
||||
power = 2
|
||||
|
||||
/datum/symptom/heal/chem/Heal(mob/living/M, datum/disease/advance/A, actual_power)
|
||||
for(var/datum/reagent/R in M.reagents.reagent_list) //Not just toxins!
|
||||
M.reagents.remove_reagent(R.id, actual_power)
|
||||
if(food_conversion)
|
||||
M.nutrition += 0.3
|
||||
if(prob(2))
|
||||
to_chat(M, "<span class='notice'>You feel a mild warmth as your blood purifies itself.</span>")
|
||||
return 1
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Regeneration
|
||||
|
||||
Little bit hidden.
|
||||
Lowers resistance tremendously.
|
||||
Decreases stage speed tremendously.
|
||||
Decreases transmittablity temrendously.
|
||||
Fatal Level.
|
||||
/datum/symptom/heal/metabolism
|
||||
name = "Metabolic Boost"
|
||||
stealth = -1
|
||||
resistance = -2
|
||||
stage_speed = 2
|
||||
transmittable = 1
|
||||
level = 7
|
||||
var/triple_metabolism = FALSE
|
||||
var/reduced_hunger = FALSE
|
||||
desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\
|
||||
but also causing increased hunger."
|
||||
threshold_desc = "<b>Stealth 3:</b> Reduces hunger rate.<br>\
|
||||
<b>Stage Speed 10:</b> Chemical metabolization is tripled instead of doubled."
|
||||
|
||||
Bonus
|
||||
Heals brute damage slowly over time.
|
||||
/datum/symptom/heal/metabolism/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 10)
|
||||
triple_metabolism = TRUE
|
||||
if(A.properties["stealth"] >= 3)
|
||||
reduced_hunger = TRUE
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
/datum/symptom/heal/metabolism/Heal(mob/living/carbon/C, datum/disease/advance/A, actual_power)
|
||||
if(!istype(C))
|
||||
return
|
||||
C.reagents.metabolize(C, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself
|
||||
if(triple_metabolism)
|
||||
C.reagents.metabolize(C, can_overdose=TRUE)
|
||||
C.overeatduration = max(C.overeatduration - 2, 0)
|
||||
var/lost_nutrition = 9 - (reduced_hunger * 5)
|
||||
C.nutrition = max(C.nutrition - (lost_nutrition * HUNGER_FACTOR), 0) //Hunger depletes at 10x the normal speed
|
||||
if(prob(2))
|
||||
to_chat(C, "<span class='notice'>You feel an odd gurgle in your stomach, as if it was working much faster than normal.</span>")
|
||||
return 1
|
||||
|
||||
/datum/symptom/heal/brute
|
||||
|
||||
name = "Regeneration"
|
||||
desc = "The virus stimulates the regenerative process in the host, causing faster wound healing."
|
||||
name = "Cellular Molding"
|
||||
desc = "The virus is able to shift cells around when in conditions of high heat, repairing existing physical damage."
|
||||
stealth = 1
|
||||
resistance = -4
|
||||
stage_speed = -4
|
||||
transmittable = -4
|
||||
resistance = -3
|
||||
stage_speed = -3
|
||||
transmittable = -3
|
||||
level = 6
|
||||
passive_message = "<span class='notice'>You feel the flesh pulsing under your skin for a moment, but it's too cold to move.</span>"
|
||||
threshold_desc = "<b>Stage Speed 8:</b> Doubles healing speed."
|
||||
|
||||
/datum/symptom/heal/brute/Heal(mob/living/carbon/M, datum/disease/advance/A)
|
||||
var/heal_amt = 2 * power
|
||||
/datum/symptom/heal/brute/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 8)
|
||||
power = 2
|
||||
|
||||
/datum/symptom/heal/brute/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(M.bodytemperature)
|
||||
if(0 to 340)
|
||||
return FALSE
|
||||
if(340 to BODYTEMP_HEAT_DAMAGE_LIMIT)
|
||||
. = 0.3 * power
|
||||
if(BODYTEMP_HEAT_DAMAGE_LIMIT to 400)
|
||||
. = 0.75 * power
|
||||
if(400 to 460)
|
||||
. = power
|
||||
else
|
||||
. = 1.5 * power
|
||||
|
||||
if(M.on_fire)
|
||||
. *= 2
|
||||
|
||||
/datum/symptom/heal/brute/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = 2 * actual_power
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(1,0) //brute only
|
||||
|
||||
if(!parts.len)
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>You feel your flesh moving beneath your heated skin, mending your wounds.</span>")
|
||||
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(heal_amt/parts.len, 0))
|
||||
M.update_damage_overlays()
|
||||
|
||||
if(prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#FF3333")
|
||||
|
||||
return 1
|
||||
|
||||
/datum/symptom/heal/brute/passive_message_condition(mob/living/M)
|
||||
if(M.getBruteLoss())
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Flesh Mending
|
||||
|
||||
No resistance change.
|
||||
Decreases stage speed.
|
||||
Decreases transmittablity.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
Heals brute damage over time. Turns cloneloss into burn damage.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/heal/brute/plus
|
||||
|
||||
name = "Flesh Mending"
|
||||
desc = "The virus rapidly mutates into body cells, effectively allowing it to quickly fix the host's wounds."
|
||||
/datum/symptom/heal/coma
|
||||
name = "Regenerative Coma"
|
||||
desc = "The virus causes the host to fall into a death-like coma when severely damaged, then rapidly fixes the damage."
|
||||
stealth = 0
|
||||
resistance = 0
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 8
|
||||
passive_message = "<span class='notice'>The pain from your wounds makes you feel oddly sleepy...</span>"
|
||||
var/deathgasp = FALSE
|
||||
var/active_coma = FALSE //to prevent multiple coma procs
|
||||
threshold_desc = "<b>Stealth 2:</b> Host appears to die when falling into a coma.<br>\
|
||||
<b>Stage Speed 7:</b> Increases healing speed."
|
||||
|
||||
/datum/symptom/heal/brute/plus/Heal(mob/living/carbon/M, datum/disease/advance/A)
|
||||
var/heal_amt = 4 * power
|
||||
/datum/symptom/heal/coma/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 7)
|
||||
power = 1.5
|
||||
if(A.properties["stealth"] >= 2)
|
||||
deathgasp = TRUE
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(1,0) //brute only
|
||||
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(M.status_flags & FAKEDEATH)
|
||||
return power
|
||||
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
|
||||
return power * 0.9
|
||||
else if(M.stat == SOFT_CRIT)
|
||||
return power * 0.5
|
||||
else if(M.IsSleeping())
|
||||
return power * 0.25
|
||||
else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
|
||||
to_chat(M, "<span class='warning'>You feel yourself slip into a regenerative coma...</span>")
|
||||
active_coma = TRUE
|
||||
addtimer(CALLBACK(src, .proc/coma, M), 60)
|
||||
|
||||
if(M.getCloneLoss() > 0)
|
||||
M.adjustCloneLoss(-1)
|
||||
M.take_bodypart_damage(0, 1) //Deals BURN damage, which is not cured by this symptom
|
||||
if(!hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#33FFCC")
|
||||
/datum/symptom/heal/coma/proc/coma(mob/living/M)
|
||||
if(deathgasp)
|
||||
M.emote("deathgasp")
|
||||
M.status_flags |= FAKEDEATH
|
||||
M.update_stat()
|
||||
M.update_canmove()
|
||||
addtimer(CALLBACK(src, .proc/uncoma, M), 300)
|
||||
|
||||
/datum/symptom/heal/coma/proc/uncoma(mob/living/M)
|
||||
if(!active_coma)
|
||||
return
|
||||
active_coma = FALSE
|
||||
M.status_flags &= ~FAKEDEATH
|
||||
M.update_stat()
|
||||
M.update_canmove()
|
||||
|
||||
/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = 4 * actual_power
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(1,1)
|
||||
|
||||
if(!parts.len)
|
||||
return
|
||||
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(heal_amt/parts.len, 0))
|
||||
if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len))
|
||||
M.update_damage_overlays()
|
||||
|
||||
if(prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#CC1100")
|
||||
if(active_coma && M.getBruteLoss() + M.getFireLoss() == 0)
|
||||
uncoma(M)
|
||||
|
||||
return 1
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Tissue Regrowth
|
||||
|
||||
Little bit hidden.
|
||||
Lowers resistance tremendously.
|
||||
Decreases stage speed tremendously.
|
||||
Decreases transmittablity temrendously.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
Heals burn damage slowly over time.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
/datum/symptom/heal/coma/passive_message_condition(mob/living/M)
|
||||
if((M.getBruteLoss() + M.getFireLoss()) > 30)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/symptom/heal/burn
|
||||
|
||||
name = "Tissue Regrowth"
|
||||
desc = "The virus recycles dead and burnt tissues, speeding up the healing of damage caused by burns."
|
||||
name = "Tissue Hydration"
|
||||
desc = "The virus uses excess water inside and outside the body to repair burned tisue cells."
|
||||
stealth = 1
|
||||
resistance = -4
|
||||
stage_speed = -4
|
||||
transmittable = -4
|
||||
resistance = -3
|
||||
stage_speed = -3
|
||||
transmittable = -3
|
||||
level = 6
|
||||
passive_message = "<span class='notice'>Your burned skin feels oddly dry...</span>"
|
||||
var/absorption_coeff = 1
|
||||
threshold_desc = "<b>Resistance 5:</b> Water is consumed at a much slower rate.<br>\
|
||||
<b>Stage Speed 7:</b> Increases healing speed."
|
||||
|
||||
/datum/symptom/heal/burn/Heal(mob/living/carbon/M, datum/disease/advance/A)
|
||||
var/heal_amt = 2 * power
|
||||
/datum/symptom/heal/burn/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 7)
|
||||
power = 2
|
||||
if(A.properties["stealth"] >= 2)
|
||||
absorption_coeff = 0.25
|
||||
|
||||
/datum/symptom/heal/burn/CanHeal(datum/disease/advance/A)
|
||||
. = 0
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(M.fire_stacks < 0)
|
||||
M.fire_stacks = min(M.fire_stacks + 1 * absorption_coeff, 0)
|
||||
. += power
|
||||
if(M.reagents.has_reagent("holywater"))
|
||||
M.reagents.remove_reagent("holywater", 0.5 * absorption_coeff)
|
||||
. += power * 0.75
|
||||
else if(M.reagents.has_reagent("water"))
|
||||
M.reagents.remove_reagent("water", 0.5 * absorption_coeff)
|
||||
. += power * 0.5
|
||||
|
||||
/datum/symptom/heal/burn/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = 2 * actual_power
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(0,1) //burn only
|
||||
|
||||
if(!parts.len)
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>You feel yourself absorbing the water around you to soothe your burned skin.</span>")
|
||||
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(0, heal_amt/parts.len))
|
||||
M.update_damage_overlays()
|
||||
|
||||
if(prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#FF9933")
|
||||
return 1
|
||||
|
||||
/datum/symptom/heal/burn/passive_message_condition(mob/living/M)
|
||||
if(M.getFireLoss())
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Heat Resistance //Needs a better name
|
||||
|
||||
No resistance change.
|
||||
Decreases stage speed.
|
||||
Decreases transmittablity.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
Heals burn damage over time, and helps stabilize body temperature.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/heal/burn/plus
|
||||
|
||||
name = "Temperature Adaptation"
|
||||
desc = "The virus quickly balances body heat, while also replacing tissues damaged by external sources."
|
||||
/datum/symptom/heal/plasma
|
||||
name = "Plasma Fixation"
|
||||
desc = "The virus draws plasma from the atmosphere and from inside the body to stabilize body temperature and heal burns."
|
||||
stealth = 0
|
||||
resistance = 0
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 8
|
||||
passive_message = "<span class='notice'>You feel an odd attraction to plasma.</span>"
|
||||
var/temp_rate = 1
|
||||
threshold_desc = "<b>Transmission 6:</b> Increases temperature adjustment rate.<br>\
|
||||
<b>Stage Speed 7:</b> Increases healing speed."
|
||||
|
||||
/datum/symptom/heal/burn/plus/Heal(mob/living/carbon/M, datum/disease/advance/A)
|
||||
var/heal_amt = 4 * power
|
||||
/datum/symptom/heal/plasma/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 7)
|
||||
power = 2
|
||||
if(A.properties["trasmission"] >= 6)
|
||||
temp_rate = 4
|
||||
|
||||
/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
var/datum/gas_mixture/environment
|
||||
var/list/gases
|
||||
|
||||
. = 0
|
||||
|
||||
if(M.loc)
|
||||
environment = M.loc.return_air()
|
||||
if(environment)
|
||||
gases = environment.gases
|
||||
if(gases["plasma"] && gases["plasma"][MOLES] > gases["plasma"][GAS_META][META_GAS_MOLES_VISIBLE]) //if there's enough plasma in the air to see
|
||||
. += power * 0.5
|
||||
if(M.reagents.has_reagent("plasma"))
|
||||
. += power * 0.75
|
||||
|
||||
/datum/symptom/heal/plasma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = 4 * actual_power
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(0,1) //burn only
|
||||
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>You feel yourself absorbing plasma inside and around you...</span>")
|
||||
|
||||
if(M.bodytemperature > 310)
|
||||
M.bodytemperature = max(310, M.bodytemperature - (10 * heal_amt * TEMPERATURE_DAMAGE_COEFFICIENT))
|
||||
M.bodytemperature = max(310, M.bodytemperature - (20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT))
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>You feel less hot.</span>")
|
||||
else if(M.bodytemperature < 311)
|
||||
M.bodytemperature = min(310, M.bodytemperature + (10 * heal_amt * TEMPERATURE_DAMAGE_COEFFICIENT))
|
||||
M.bodytemperature = min(310, M.bodytemperature + (20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT))
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>You feel warmer.</span>")
|
||||
|
||||
if(!parts.len)
|
||||
return
|
||||
if(prob(5))
|
||||
to_chat(M, "<span class='notice'>The pain from your burns fades rapidly.</span>")
|
||||
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(0, heal_amt/parts.len))
|
||||
M.update_damage_overlays()
|
||||
|
||||
if(prob(base_message_chance) && !hide_healing)
|
||||
new /obj/effect/temp_visual/heal(get_turf(M), "#CC6600")
|
||||
return 1
|
||||
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
DNA Restoration
|
||||
|
||||
Not well hidden.
|
||||
Lowers resistance minorly.
|
||||
Does not affect stage speed.
|
||||
Decreases transmittablity greatly.
|
||||
Very high level.
|
||||
|
||||
Bonus
|
||||
Heals brain damage, treats radiation, cleans SE of non-power mutations.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/heal/dna
|
||||
|
||||
name = "Deoxyribonucleic Acid Restoration"
|
||||
desc = "The virus repairs the host's genome, purging negative mutations."
|
||||
/datum/symptom/heal/radiation
|
||||
name = "Radioactive Resonance"
|
||||
desc = "The virus uses radiation to fix damage through dna mutations."
|
||||
stealth = -1
|
||||
resistance = -1
|
||||
resistance = -2
|
||||
stage_speed = 0
|
||||
transmittable = -3
|
||||
level = 5
|
||||
symptom_delay_min = 3
|
||||
symptom_delay_max = 8
|
||||
threshold_desc = "<b>Stage Speed 6:</b> Additionally heals brain damage.<br>\
|
||||
<b>Stage Speed 11:</b> Increases brain damage healing."
|
||||
level = 6
|
||||
symptom_delay_min = 1
|
||||
symptom_delay_max = 1
|
||||
passive_message = "<span class='notice'>Your skin glows faintly for a moment.</span>"
|
||||
var/cellular_damage = FALSE
|
||||
threshold_desc = "<b>Transmission 6:</b> Additionally heals cellular damage.<br>\
|
||||
<b>Resistance 7:</b> Increases healing speed."
|
||||
|
||||
/datum/symptom/heal/dna/Heal(mob/living/carbon/M, datum/disease/advance/A)
|
||||
var/amt_healed = 2 * (power - 1)
|
||||
M.adjustBrainLoss(-amt_healed)
|
||||
//Non-power mutations, excluding race, so the virus does not force monkey -> human transformations.
|
||||
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations) - GLOB.mutations_list[RACEMUT]
|
||||
M.dna.remove_mutation_group(unclean_mutations)
|
||||
M.radiation = max(M.radiation - (2 * amt_healed), 0)
|
||||
/datum/symptom/heal/radiation/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["resistance"] >= 7)
|
||||
power = 2
|
||||
if(A.properties["trasmission"] >= 6)
|
||||
cellular_damage = TRUE
|
||||
|
||||
/datum/symptom/heal/radiation/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(M.radiation)
|
||||
if(0)
|
||||
return FALSE
|
||||
if(1 to RAD_MOB_SAFE)
|
||||
return 0.25
|
||||
if(RAD_MOB_SAFE to RAD_BURN_THRESHOLD)
|
||||
return 0.5
|
||||
if(RAD_BURN_THRESHOLD to RAD_MOB_MUTATE)
|
||||
return 0.75
|
||||
if(RAD_MOB_MUTATE to RAD_MOB_KNOCKDOWN)
|
||||
return 1
|
||||
else
|
||||
return 1.5
|
||||
|
||||
/datum/symptom/heal/radiation/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = actual_power
|
||||
|
||||
if(cellular_damage)
|
||||
M.adjustCloneLoss(-heal_amt * 0.5)
|
||||
|
||||
var/list/parts = M.get_damaged_bodyparts(1,1)
|
||||
|
||||
if(!parts.len)
|
||||
return
|
||||
|
||||
if(prob(4))
|
||||
to_chat(M, "<span class='notice'>Your skin glows faintly, and you feel your wounds mending themselves.</span>")
|
||||
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len))
|
||||
M.update_damage_overlays()
|
||||
return 1
|
||||
|
||||
@@ -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
|
||||
@@ -1,56 +1,6 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Weight Gain
|
||||
|
||||
Very Very Noticable.
|
||||
Decreases resistance.
|
||||
Decreases stage speed.
|
||||
Reduced transmittable.
|
||||
Intense Level.
|
||||
|
||||
Bonus
|
||||
Increases the weight gain of the mob,
|
||||
forcing it to eventually turn fat.
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/weight_gain
|
||||
|
||||
name = "Weight Gain"
|
||||
desc = "The virus mutates the host's metabolism, making it gain weight much faster than normal."
|
||||
stealth = -3
|
||||
resistance = -3
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 4
|
||||
severity = 3
|
||||
base_message_chance = 100
|
||||
symptom_delay_min = 15
|
||||
symptom_delay_max = 45
|
||||
threshold_desc = "<b>Stealth 4:</b> The symptom is less noticeable."
|
||||
|
||||
/datum/symptom/weight_gain/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.properties["stealth"] >= 4) //warn less often
|
||||
base_message_chance = 25
|
||||
|
||||
/datum/symptom/weight_gain/Activate(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(A.stage)
|
||||
if(1, 2, 3, 4)
|
||||
if(prob(base_message_chance))
|
||||
to_chat(M, "<span class='warning'>[pick("You feel blubbery.", "Your stomach hurts.")]</span>")
|
||||
else
|
||||
M.overeatduration = min(M.overeatduration + 100, 600)
|
||||
M.nutrition = min(M.nutrition + 100, NUTRITION_LEVEL_FULL)
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Weight Loss
|
||||
|
||||
Very Very Noticable.
|
||||
@@ -70,8 +20,8 @@ Bonus
|
||||
|
||||
name = "Weight Loss"
|
||||
desc = "The virus mutates the host's metabolism, making it almost unable to gain nutrition from food."
|
||||
stealth = -3
|
||||
resistance = -2
|
||||
stealth = -2
|
||||
resistance = 2
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 3
|
||||
@@ -99,43 +49,3 @@ Bonus
|
||||
to_chat(M, "<span class='warning'><i>[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]</i></span>")
|
||||
M.overeatduration = max(M.overeatduration - 100, 0)
|
||||
M.nutrition = max(M.nutrition - 100, 0)
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Weight Even
|
||||
|
||||
Very Noticable.
|
||||
Decreases resistance.
|
||||
Decreases stage speed.
|
||||
Reduced transmittable.
|
||||
High level.
|
||||
|
||||
Bonus
|
||||
Causes the weight of the mob to
|
||||
be even, meaning eating isn't
|
||||
required anymore.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/weight_even
|
||||
|
||||
name = "Weight Even"
|
||||
desc = "The virus alters the host's metabolism, making it far more efficient then normal, and synthesizing nutrients from normally unedible sources."
|
||||
stealth = -3
|
||||
resistance = -2
|
||||
stage_speed = -2
|
||||
transmittable = -2
|
||||
level = 4
|
||||
symptom_delay_min = 5
|
||||
symptom_delay_max = 5
|
||||
|
||||
/datum/symptom/weight_even/Activate(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(A.stage)
|
||||
if(4, 5)
|
||||
M.overeatduration = 0
|
||||
M.nutrition = NUTRITION_LEVEL_WELL_FED + 50
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
var/obj/item/oldcell = locate (/obj/item/stock_parts/cell) in m
|
||||
QDEL_NULL(oldcell)
|
||||
m.CheckParts(holder.contents)
|
||||
SSblackbox.record_feedback("tally", "mechas_created", 1, m.name)
|
||||
QDEL_NULL(holder)
|
||||
|
||||
/datum/construction/proc/set_desc(index as num)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
if(line)
|
||||
var/tmcommit = testmerge[line]["commit"]
|
||||
log_world("Test merge active of PR #[line] commit [tmcommit]")
|
||||
SSblackbox.add_details("testmerged_prs","[line]|[tmcommit]")
|
||||
SSblackbox.record_feedback("nested tally", "testmerged_prs", 1, list("[line]", "[tmcommit]"))
|
||||
log_world("Based off origin/master commit [originmastercommit]")
|
||||
else
|
||||
log_world(originmastercommit)
|
||||
|
||||
@@ -119,6 +119,9 @@
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
if(ismegafauna(teleatom))
|
||||
message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_COORDJMP(curturf)] to [ADMIN_COORDJMP(destturf)].")
|
||||
if(ismob(teleatom))
|
||||
var/mob/M = teleatom
|
||||
M.cancel_camera()
|
||||
return 1
|
||||
|
||||
/datum/teleport/proc/teleport()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+16
-2
@@ -1,12 +1,15 @@
|
||||
/* HUD DATUMS */
|
||||
|
||||
GLOBAL_LIST_EMPTY(all_huds)
|
||||
|
||||
//GLOBAL HUD LIST
|
||||
GLOBAL_LIST_INIT(huds, list(
|
||||
DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(),
|
||||
DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(),
|
||||
DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(),
|
||||
DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(),
|
||||
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(),
|
||||
DATA_HUD_DIAGNOSTIC_BASIC = new/datum/atom_hud/data/diagnostic/basic(),
|
||||
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(),
|
||||
ANTAG_HUD_CULT = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_REV = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_OPS = new/datum/atom_hud/antag(),
|
||||
@@ -28,6 +31,17 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
var/list/mob/hudusers = list() //list with all mobs who can see the hud
|
||||
var/list/hud_icons = list() //these will be the indexes for the atom's hud_list
|
||||
|
||||
/datum/atom_hud/New()
|
||||
GLOB.all_huds += src
|
||||
|
||||
/datum/atom_hud/Destroy()
|
||||
for(var/v in hudusers)
|
||||
remove_hud_from(v)
|
||||
for(var/v in hudatoms)
|
||||
remove_from_hud(v)
|
||||
GLOB.all_huds -= src
|
||||
return ..()
|
||||
|
||||
/datum/atom_hud/proc/remove_hud_from(mob/M)
|
||||
if(!M || !hudusers[M])
|
||||
return
|
||||
@@ -77,7 +91,7 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
|
||||
//MOB PROCS
|
||||
/mob/proc/reload_huds()
|
||||
for(var/datum/atom_hud/hud in (GLOB.huds|GLOB.active_alternate_appearances))
|
||||
for(var/datum/atom_hud/hud in GLOB.all_huds)
|
||||
if(hud && hud.hudusers[src])
|
||||
for(var/atom/A in hud.hudatoms)
|
||||
hud.add_to_single_hud(src, A)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/datum/looping_sound/supermatter
|
||||
mid_sounds = list('sound/machines/sm/supermatter1.ogg'=1,'sound/machines/sm/supermatter2.ogg'=1,'sound/machines/sm/supermatter3.ogg'=1)
|
||||
mid_length = 6
|
||||
mid_length = 10
|
||||
volume = 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+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)))
|
||||
|
||||
@@ -113,543 +113,6 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
/datum/mutation/human/proc/get_spans()
|
||||
return list()
|
||||
|
||||
/datum/mutation/human/hulk
|
||||
|
||||
name = "Hulk"
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
||||
species_allowed = list("fly") //no skeleton/lizard hulk
|
||||
health_req = 25
|
||||
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
var/status = CANSTUN | CANKNOCKDOWN | CANUNCONSCIOUS | CANPUSH
|
||||
owner.status_flags &= ~status
|
||||
owner.update_body_parts()
|
||||
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
if(proximity) //no telekinetic hulk attack
|
||||
return target.attack_hulk(owner)
|
||||
|
||||
/datum/mutation/human/hulk/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.health < 0)
|
||||
on_losing(owner)
|
||||
to_chat(owner, "<span class='danger'>You suddenly feel very weak.</span>")
|
||||
|
||||
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.status_flags |= CANSTUN | CANKNOCKDOWN | CANUNCONSCIOUS | CANPUSH
|
||||
owner.update_body_parts()
|
||||
|
||||
/datum/mutation/human/hulk/say_mod(message)
|
||||
if(message)
|
||||
message = "[uppertext(replacetext(message, ".", "!"))]!!"
|
||||
return message
|
||||
|
||||
/datum/mutation/human/telekinesis
|
||||
|
||||
name = "Telekinesis"
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>You feel smarter!</span>"
|
||||
limb_req = "head"
|
||||
|
||||
/datum/mutation/human/telekinesis/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
|
||||
target.attack_tk(owner)
|
||||
|
||||
/datum/mutation/human/cold_resistance
|
||||
|
||||
name = "Cold Resistance"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/cold_resistance/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.getFireLoss())
|
||||
if(prob(1))
|
||||
owner.heal_bodypart_damage(0,1) //Is this really needed?
|
||||
|
||||
/datum/mutation/human/x_ray
|
||||
|
||||
name = "X Ray Vision"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
time_coeff = 2
|
||||
|
||||
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
|
||||
owner.update_sight()
|
||||
|
||||
/datum/mutation/human/x_ray/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.update_sight()
|
||||
|
||||
/datum/mutation/human/nearsight
|
||||
|
||||
name = "Near Sightness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
|
||||
|
||||
/datum/mutation/human/nearsight/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.become_nearsighted()
|
||||
|
||||
/datum/mutation/human/nearsight/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.cure_nearsighted()
|
||||
|
||||
/datum/mutation/human/epilepsy
|
||||
|
||||
name = "Epilepsy"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You get a headache.</span>"
|
||||
|
||||
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(1) && owner.stat == CONSCIOUS)
|
||||
owner.visible_message("<span class='danger'>[owner] starts having a seizure!</span>", "<span class='userdanger'>You have a seizure!</span>")
|
||||
owner.Unconscious(200)
|
||||
owner.Jitter(1000)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less, owner), 90)
|
||||
|
||||
/datum/mutation/human/epilepsy/proc/jitter_less(mob/living/carbon/human/owner)
|
||||
if(owner)
|
||||
owner.jitteriness = 10
|
||||
|
||||
/datum/mutation/human/bad_dna
|
||||
name = "Unstable DNA"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel strange.</span>"
|
||||
|
||||
/datum/mutation/human/bad_dna/on_acquiring(mob/living/carbon/human/owner)
|
||||
to_chat(owner, text_gain_indication)
|
||||
var/mob/new_mob
|
||||
if(prob(95))
|
||||
if(prob(50))
|
||||
new_mob = owner.randmutb()
|
||||
else
|
||||
new_mob = owner.randmuti()
|
||||
else
|
||||
new_mob = owner.randmutg()
|
||||
if(new_mob && ismob(new_mob))
|
||||
owner = new_mob
|
||||
. = owner
|
||||
on_losing(owner)
|
||||
|
||||
/datum/mutation/human/cough
|
||||
name = "Cough"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You start coughing.</span>"
|
||||
|
||||
/datum/mutation/human/cough/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
owner.drop_all_held_items()
|
||||
owner.emote("cough")
|
||||
|
||||
/datum/mutation/human/dwarfism
|
||||
name = "Dwarfism"
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
|
||||
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 0.8
|
||||
owner.update_transform()
|
||||
owner.pass_flags |= PASSTABLE
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
|
||||
|
||||
/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 1.25
|
||||
owner.update_transform()
|
||||
owner.pass_flags &= ~PASSTABLE
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
|
||||
|
||||
/datum/mutation/human/clumsy
|
||||
|
||||
name = "Clumsiness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel lightheaded.</span>"
|
||||
|
||||
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= CLUMSY
|
||||
|
||||
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~CLUMSY
|
||||
|
||||
/datum/mutation/human/tourettes
|
||||
name = "Tourettes Syndrome"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You twitch.</span>"
|
||||
|
||||
/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10) && owner.stat == CONSCIOUS)
|
||||
owner.Stun(200)
|
||||
switch(rand(1, 3))
|
||||
if(1)
|
||||
owner.emote("twitch")
|
||||
if(2 to 3)
|
||||
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
|
||||
var/x_offset_old = owner.pixel_x
|
||||
var/y_offset_old = owner.pixel_y
|
||||
var/x_offset = owner.pixel_x + rand(-2,2)
|
||||
var/y_offset = owner.pixel_y + rand(-1,1)
|
||||
animate(owner, pixel_x = x_offset, pixel_y = y_offset, time = 1)
|
||||
animate(owner, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1)
|
||||
|
||||
/datum/mutation/human/nervousness
|
||||
name = "Nervousness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel nervous.</span>"
|
||||
|
||||
/datum/mutation/human/nervousness/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10))
|
||||
owner.stuttering = max(10, owner.stuttering)
|
||||
|
||||
/datum/mutation/human/deaf
|
||||
name = "Deafness"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to hear anything.</span>"
|
||||
|
||||
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= DEAF
|
||||
|
||||
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~DEAF
|
||||
|
||||
/datum/mutation/human/blind
|
||||
name = "Blindness"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
|
||||
|
||||
/datum/mutation/human/blind/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.become_blind()
|
||||
|
||||
/datum/mutation/human/blind/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.cure_blind()
|
||||
|
||||
|
||||
/datum/mutation/human/race
|
||||
name = "Monkified"
|
||||
quality = NEGATIVE
|
||||
time_coeff = 2
|
||||
|
||||
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(owner.has_brain_worms())
|
||||
to_chat(owner, "<span class='warning'>You feel something strongly clinging to your humanity!</span>")
|
||||
return
|
||||
if(..())
|
||||
return
|
||||
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
|
||||
/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
|
||||
if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)))
|
||||
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
|
||||
/datum/mutation/human/chameleon
|
||||
name = "Chameleon"
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>You feel one with your surroundings.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel oddly exposed.</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
|
||||
/datum/mutation/human/chameleon/on_life(mob/living/carbon/human/owner)
|
||||
owner.alpha = max(0, owner.alpha - 25)
|
||||
|
||||
/datum/mutation/human/chameleon/on_move(mob/living/carbon/human/owner)
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
|
||||
/datum/mutation/human/chameleon/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
if(proximity) //stops tk from breaking chameleon
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
return
|
||||
|
||||
/datum/mutation/human/chameleon/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.alpha = 255
|
||||
|
||||
/datum/mutation/human/wacky
|
||||
name = "Wacky"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
|
||||
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
|
||||
|
||||
/datum/mutation/human/wacky/get_spans()
|
||||
return list(SPAN_SANS)
|
||||
|
||||
/datum/mutation/human/mute
|
||||
name = "Mute"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel unable to express yourself at all.</span>"
|
||||
text_lose_indication = "<span class='danger'>You feel able to speak freely again.</span>"
|
||||
|
||||
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= MUTE
|
||||
|
||||
/datum/mutation/human/mute/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~MUTE
|
||||
|
||||
/datum/mutation/human/smile
|
||||
name = "Smile"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel so happy. Nothing can be wrong with anything. :)</span>"
|
||||
text_lose_indication = "<span class='notice'>Everything is terrible again. :(</span>"
|
||||
|
||||
/datum/mutation/human/smile/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
//Time for a friendly game of SS13
|
||||
message = replacetext(message," stupid "," smart ")
|
||||
message = replacetext(message," retard "," genius ")
|
||||
message = replacetext(message," unrobust "," robust ")
|
||||
message = replacetext(message," dumb "," smart ")
|
||||
message = replacetext(message," awful "," great ")
|
||||
message = replacetext(message," gay ",pick(" nice "," ok "," alright "))
|
||||
message = replacetext(message," horrible "," fun ")
|
||||
message = replacetext(message," terrible "," terribly fun ")
|
||||
message = replacetext(message," terrifying "," wonderful ")
|
||||
message = replacetext(message," gross "," cool ")
|
||||
message = replacetext(message," disgusting "," amazing ")
|
||||
message = replacetext(message," loser "," winner ")
|
||||
message = replacetext(message," useless "," useful ")
|
||||
message = replacetext(message," oh god "," cheese and crackers ")
|
||||
message = replacetext(message," jesus "," gee wiz ")
|
||||
message = replacetext(message," weak "," strong ")
|
||||
message = replacetext(message," kill "," hug ")
|
||||
message = replacetext(message," murder "," tease ")
|
||||
message = replacetext(message," ugly "," beautiful ")
|
||||
message = replacetext(message," douchbag "," nice guy ")
|
||||
message = replacetext(message," whore "," lady ")
|
||||
message = replacetext(message," nerd "," smart guy ")
|
||||
message = replacetext(message," moron "," fun person ")
|
||||
message = replacetext(message," IT'S LOOSE "," EVERYTHING IS FINE ")
|
||||
message = replacetext(message," sex "," hug fight ")
|
||||
message = replacetext(message," idiot "," genius ")
|
||||
message = replacetext(message," fat "," thin ")
|
||||
message = replacetext(message," beer "," water with ice ")
|
||||
message = replacetext(message," drink "," water ")
|
||||
message = replacetext(message," feminist "," empowered woman ")
|
||||
message = replacetext(message," i hate you "," you're mean ")
|
||||
message = replacetext(message," nigger "," african american ")
|
||||
message = replacetext(message," jew "," jewish ")
|
||||
message = replacetext(message," shit "," shiz ")
|
||||
message = replacetext(message," crap "," poo ")
|
||||
message = replacetext(message," slut "," tease ")
|
||||
message = replacetext(message," ass "," butt ")
|
||||
message = replacetext(message," damn "," dang ")
|
||||
message = replacetext(message," fuck "," ")
|
||||
message = replacetext(message," penis "," privates ")
|
||||
message = replacetext(message," cunt "," privates ")
|
||||
message = replacetext(message," dick "," jerk ")
|
||||
message = replacetext(message," vagina "," privates ")
|
||||
return trim(message)
|
||||
|
||||
/datum/mutation/human/unintelligable
|
||||
name = "Unintelligable"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
|
||||
text_lose_indication = "<span class='danger'>Your mind feels more clear.</span>"
|
||||
|
||||
/datum/mutation/human/unintelligable/say_mod(message)
|
||||
if(message)
|
||||
var/prefix=copytext(message,1,2)
|
||||
if(prefix == ";")
|
||||
message = copytext(message,2)
|
||||
else if(prefix in list(":","#"))
|
||||
prefix += copytext(message,2,3)
|
||||
message = copytext(message,3)
|
||||
else
|
||||
prefix=""
|
||||
|
||||
var/list/words = splittext(message," ")
|
||||
var/list/rearranged = list()
|
||||
for(var/i=1;i<=words.len;i++)
|
||||
var/cword = pick(words)
|
||||
words.Remove(cword)
|
||||
var/suffix = copytext(cword,length(cword)-1,length(cword))
|
||||
while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
|
||||
cword = copytext(cword,1 ,length(cword)-1)
|
||||
suffix = copytext(cword,length(cword)-1,length(cword) )
|
||||
if(length(cword))
|
||||
rearranged += cword
|
||||
message = "[prefix][uppertext(jointext(rearranged," "))]!!"
|
||||
return message
|
||||
|
||||
/datum/mutation/human/swedish
|
||||
name = "Swedish"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel Swedish, however that works.</span>"
|
||||
text_lose_indication = "<span class='notice'>The feeling of Swedishness passes.</span>"
|
||||
|
||||
/datum/mutation/human/swedish/say_mod(message)
|
||||
if(message)
|
||||
message = replacetext(message,"w","v")
|
||||
message = replacetext(message,"j","y")
|
||||
message = replacetext(message,"a",pick("�","�","�","a"))
|
||||
message = replacetext(message,"bo","bjo")
|
||||
message = replacetext(message,"o",pick("�","�","o"))
|
||||
if(prob(30))
|
||||
message += " Bork[pick("",", bork",", bork, bork")]!"
|
||||
return message
|
||||
|
||||
/datum/mutation/human/chav
|
||||
name = "Chav"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>Ye feel like a reet prat like, innit?</span>"
|
||||
text_lose_indication = "<span class='notice'>You no longer feel like being rude and sassy.</span>"
|
||||
|
||||
/datum/mutation/human/chav/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
message = replacetext(message," looking at "," gawpin' at ")
|
||||
message = replacetext(message," great "," bangin' ")
|
||||
message = replacetext(message," man "," mate ")
|
||||
message = replacetext(message," friend ",pick(" mate "," bruv "," bledrin "))
|
||||
message = replacetext(message," what "," wot ")
|
||||
message = replacetext(message," drink "," wet ")
|
||||
message = replacetext(message," get "," giz ")
|
||||
message = replacetext(message," what "," wot ")
|
||||
message = replacetext(message," no thanks "," wuddent fukken do one ")
|
||||
message = replacetext(message," i don't know "," wot mate ")
|
||||
message = replacetext(message," no "," naw ")
|
||||
message = replacetext(message," robust "," chin ")
|
||||
message = replacetext(message," hi "," how what how ")
|
||||
message = replacetext(message," hello "," sup bruv ")
|
||||
message = replacetext(message," kill "," bang ")
|
||||
message = replacetext(message," murder "," bang ")
|
||||
message = replacetext(message," windows "," windies ")
|
||||
message = replacetext(message," window "," windy ")
|
||||
message = replacetext(message," break "," do ")
|
||||
message = replacetext(message," your "," yer ")
|
||||
message = replacetext(message," security "," coppers ")
|
||||
return trim(message)
|
||||
|
||||
/datum/mutation/human/elvis
|
||||
name = "Elvis"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel pretty good, honeydoll.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel a little less conversation would be great.</span>"
|
||||
|
||||
/datum/mutation/human/elvis/on_life(mob/living/carbon/human/owner)
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
if(prob(15))
|
||||
var/list/dancetypes = list("swinging", "fancy", "stylish", "20'th century", "jivin'", "rock and roller", "cool", "salacious", "bashing", "smashing")
|
||||
var/dancemoves = pick(dancetypes)
|
||||
owner.visible_message("<b>[owner]</b> busts out some [dancemoves] moves!")
|
||||
if(2)
|
||||
if(prob(15))
|
||||
owner.visible_message("<b>[owner]</b> [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]!")
|
||||
|
||||
/datum/mutation/human/elvis/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
message = replacetext(message," i'm not "," I aint ")
|
||||
message = replacetext(message," girl ",pick(" honey "," baby "," baby doll "))
|
||||
message = replacetext(message," man ",pick(" son "," buddy "," brother"," pal "," friendo "))
|
||||
message = replacetext(message," out of "," outta ")
|
||||
message = replacetext(message," thank you "," thank you, thank you very much ")
|
||||
message = replacetext(message," what are you "," whatcha ")
|
||||
message = replacetext(message," yes ",pick(" sure", "yea "))
|
||||
message = replacetext(message," faggot "," square ")
|
||||
message = replacetext(message," muh valids "," getting my kicks ")
|
||||
return trim(message)
|
||||
|
||||
/datum/mutation/human/stoner
|
||||
name = "Stoner"
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel...totally chill, man!</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel like you have a better sense of time.</span>"
|
||||
|
||||
/datum/mutation/human/stoner/on_acquiring(mob/living/carbon/human/owner)
|
||||
..()
|
||||
owner.grant_language(/datum/language/beachbum)
|
||||
owner.remove_language(/datum/language/common)
|
||||
|
||||
/datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner)
|
||||
..()
|
||||
owner.grant_language(/datum/language/common)
|
||||
owner.remove_language(/datum/language/beachbum)
|
||||
|
||||
/datum/mutation/human/laser_eyes
|
||||
name = "Laser Eyes"
|
||||
quality = POSITIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
|
||||
layer_used = FRONT_MUTATIONS_LAYER
|
||||
limb_req = "head"
|
||||
|
||||
/datum/mutation/human/laser_eyes/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "lasereyes", -FRONT_MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target, mouseparams)
|
||||
if(owner.a_intent == INTENT_HARM)
|
||||
owner.LaserEyes(target, mouseparams)
|
||||
|
||||
|
||||
/mob/living/carbon/proc/update_mutations_overlay()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
//These mutations change your overall "form" somehow, like size
|
||||
|
||||
//Epilepsy gives a very small chance to have a seizure every life tick, knocking you unconscious.
|
||||
/datum/mutation/human/epilepsy
|
||||
name = "Epilepsy"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You get a headache.</span>"
|
||||
|
||||
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(1) && owner.stat == CONSCIOUS)
|
||||
owner.visible_message("<span class='danger'>[owner] starts having a seizure!</span>", "<span class='userdanger'>You have a seizure!</span>")
|
||||
owner.Unconscious(200)
|
||||
owner.Jitter(1000)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less, owner), 90)
|
||||
|
||||
/datum/mutation/human/epilepsy/proc/jitter_less(mob/living/carbon/human/owner)
|
||||
if(owner)
|
||||
owner.jitteriness = 10
|
||||
|
||||
|
||||
//Unstable DNA induces random mutations!
|
||||
/datum/mutation/human/bad_dna
|
||||
name = "Unstable DNA"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel strange.</span>"
|
||||
|
||||
/datum/mutation/human/bad_dna/on_acquiring(mob/living/carbon/human/owner)
|
||||
to_chat(owner, text_gain_indication)
|
||||
var/mob/new_mob
|
||||
if(prob(95))
|
||||
if(prob(50))
|
||||
new_mob = owner.randmutb()
|
||||
else
|
||||
new_mob = owner.randmuti()
|
||||
else
|
||||
new_mob = owner.randmutg()
|
||||
if(new_mob && ismob(new_mob))
|
||||
owner = new_mob
|
||||
. = owner
|
||||
on_losing(owner)
|
||||
|
||||
|
||||
//Cough gives you a chronic cough that causes you to drop items.
|
||||
/datum/mutation/human/cough
|
||||
name = "Cough"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You start coughing.</span>"
|
||||
|
||||
/datum/mutation/human/cough/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
owner.drop_all_held_items()
|
||||
owner.emote("cough")
|
||||
|
||||
|
||||
//Dwarfism shrinks your body and lets you pass tables.
|
||||
/datum/mutation/human/dwarfism
|
||||
name = "Dwarfism"
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
|
||||
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 0.8
|
||||
owner.update_transform()
|
||||
owner.pass_flags |= PASSTABLE
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
|
||||
|
||||
/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 1.25
|
||||
owner.update_transform()
|
||||
owner.pass_flags &= ~PASSTABLE
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
|
||||
|
||||
|
||||
//Clumsiness has a very large amount of small drawbacks depending on item.
|
||||
/datum/mutation/human/clumsy
|
||||
name = "Clumsiness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel lightheaded.</span>"
|
||||
|
||||
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= CLUMSY
|
||||
|
||||
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~CLUMSY
|
||||
|
||||
|
||||
//Tourettes causes you to randomly stand in place and shout.
|
||||
/datum/mutation/human/tourettes
|
||||
name = "Tourettes Syndrome"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You twitch.</span>"
|
||||
|
||||
/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10) && owner.stat == CONSCIOUS)
|
||||
owner.Stun(200)
|
||||
switch(rand(1, 3))
|
||||
if(1)
|
||||
owner.emote("twitch")
|
||||
if(2 to 3)
|
||||
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
|
||||
var/x_offset_old = owner.pixel_x
|
||||
var/y_offset_old = owner.pixel_y
|
||||
var/x_offset = owner.pixel_x + rand(-2,2)
|
||||
var/y_offset = owner.pixel_y + rand(-1,1)
|
||||
animate(owner, pixel_x = x_offset, pixel_y = y_offset, time = 1)
|
||||
animate(owner, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1)
|
||||
|
||||
|
||||
//Deafness makes you deaf.
|
||||
/datum/mutation/human/deaf
|
||||
name = "Deafness"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to hear anything.</span>"
|
||||
|
||||
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= DEAF
|
||||
|
||||
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~DEAF
|
||||
|
||||
|
||||
//Monified turns you into a monkey.
|
||||
/datum/mutation/human/race
|
||||
name = "Monkified"
|
||||
quality = NEGATIVE
|
||||
time_coeff = 2
|
||||
|
||||
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
|
||||
/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
|
||||
if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)))
|
||||
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
@@ -0,0 +1,30 @@
|
||||
//Chameleon causes the owner to slowly become transparent when not moving.
|
||||
/datum/mutation/human/chameleon
|
||||
name = "Chameleon"
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>You feel one with your surroundings.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel oddly exposed.</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
|
||||
/datum/mutation/human/chameleon/on_life(mob/living/carbon/human/owner)
|
||||
owner.alpha = max(0, owner.alpha - 25)
|
||||
|
||||
/datum/mutation/human/chameleon/on_move(mob/living/carbon/human/owner)
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
|
||||
/datum/mutation/human/chameleon/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
if(proximity) //stops tk from breaking chameleon
|
||||
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
|
||||
return
|
||||
|
||||
/datum/mutation/human/chameleon/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.alpha = 255
|
||||
@@ -0,0 +1,20 @@
|
||||
//Cold Resistance gives your entire body an orange halo, and makes you immune to the effects of vacuum and cold.
|
||||
/datum/mutation/human/cold_resistance
|
||||
name = "Cold Resistance"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/cold_resistance/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.getFireLoss())
|
||||
if(prob(1))
|
||||
owner.heal_bodypart_damage(0,1) //Is this really needed?
|
||||
@@ -0,0 +1,36 @@
|
||||
//Hulk turns your skin green, and allows you to punch through walls.
|
||||
/datum/mutation/human/hulk
|
||||
name = "Hulk"
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
||||
species_allowed = list("fly") //no skeleton/lizard hulk
|
||||
health_req = 25
|
||||
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
var/status = CANSTUN | CANKNOCKDOWN | CANUNCONSCIOUS | CANPUSH
|
||||
owner.status_flags &= ~status
|
||||
owner.update_body_parts()
|
||||
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
if(proximity) //no telekinetic hulk attack
|
||||
return target.attack_hulk(owner)
|
||||
|
||||
/datum/mutation/human/hulk/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.health < 0)
|
||||
on_losing(owner)
|
||||
to_chat(owner, "<span class='danger'>You suddenly feel very weak.</span>")
|
||||
|
||||
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.status_flags |= CANSTUN | CANKNOCKDOWN | CANUNCONSCIOUS | CANPUSH
|
||||
owner.update_body_parts()
|
||||
|
||||
/datum/mutation/human/hulk/say_mod(message)
|
||||
if(message)
|
||||
message = "[uppertext(replacetext(message, ".", "!"))]!!"
|
||||
return message
|
||||
@@ -0,0 +1,74 @@
|
||||
//Nearsightedness restricts your vision by several tiles.
|
||||
/datum/mutation/human/nearsight
|
||||
name = "Near Sightness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
|
||||
|
||||
/datum/mutation/human/nearsight/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.become_nearsighted()
|
||||
|
||||
/datum/mutation/human/nearsight/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.cure_nearsighted()
|
||||
|
||||
|
||||
//Blind makes you blind. Who knew?
|
||||
/datum/mutation/human/blind
|
||||
name = "Blindness"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
|
||||
|
||||
/datum/mutation/human/blind/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.become_blind()
|
||||
|
||||
/datum/mutation/human/blind/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.cure_blind()
|
||||
|
||||
|
||||
//X-Ray Vision lets you see through walls.
|
||||
/datum/mutation/human/x_ray
|
||||
name = "X Ray Vision"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
time_coeff = 2
|
||||
|
||||
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
|
||||
owner.update_sight()
|
||||
|
||||
/datum/mutation/human/x_ray/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.update_sight()
|
||||
|
||||
|
||||
//Laser Eyes lets you shoot lasers from your eyes!
|
||||
/datum/mutation/human/laser_eyes
|
||||
name = "Laser Eyes"
|
||||
quality = POSITIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
|
||||
layer_used = FRONT_MUTATIONS_LAYER
|
||||
limb_req = "head"
|
||||
|
||||
/datum/mutation/human/laser_eyes/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "lasereyes", -FRONT_MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target, mouseparams)
|
||||
if(owner.a_intent == INTENT_HARM)
|
||||
owner.LaserEyes(target, mouseparams)
|
||||
@@ -0,0 +1,231 @@
|
||||
//These are all minor mutations that affect your speech somehow.
|
||||
//Individual ones aren't commented since their functions should be evident at a glance
|
||||
|
||||
/datum/mutation/human/nervousness
|
||||
name = "Nervousness"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel nervous.</span>"
|
||||
|
||||
/datum/mutation/human/nervousness/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10))
|
||||
owner.stuttering = max(10, owner.stuttering)
|
||||
|
||||
|
||||
/datum/mutation/human/wacky
|
||||
name = "Wacky"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
|
||||
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
|
||||
|
||||
/datum/mutation/human/wacky/get_spans()
|
||||
return list(SPAN_SANS)
|
||||
|
||||
|
||||
/datum/mutation/human/mute
|
||||
name = "Mute"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel unable to express yourself at all.</span>"
|
||||
text_lose_indication = "<span class='danger'>You feel able to speak freely again.</span>"
|
||||
|
||||
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities |= MUTE
|
||||
|
||||
/datum/mutation/human/mute/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.disabilities &= ~MUTE
|
||||
|
||||
|
||||
/datum/mutation/human/smile
|
||||
name = "Smile"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel so happy. Nothing can be wrong with anything. :)</span>"
|
||||
text_lose_indication = "<span class='notice'>Everything is terrible again. :(</span>"
|
||||
|
||||
/datum/mutation/human/smile/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
//Time for a friendly game of SS13
|
||||
message = replacetext(message," stupid "," smart ")
|
||||
message = replacetext(message," retard "," genius ")
|
||||
message = replacetext(message," unrobust "," robust ")
|
||||
message = replacetext(message," dumb "," smart ")
|
||||
message = replacetext(message," awful "," great ")
|
||||
message = replacetext(message," gay ",pick(" nice "," ok "," alright "))
|
||||
message = replacetext(message," horrible "," fun ")
|
||||
message = replacetext(message," terrible "," terribly fun ")
|
||||
message = replacetext(message," terrifying "," wonderful ")
|
||||
message = replacetext(message," gross "," cool ")
|
||||
message = replacetext(message," disgusting "," amazing ")
|
||||
message = replacetext(message," loser "," winner ")
|
||||
message = replacetext(message," useless "," useful ")
|
||||
message = replacetext(message," oh god "," cheese and crackers ")
|
||||
message = replacetext(message," jesus "," gee wiz ")
|
||||
message = replacetext(message," weak "," strong ")
|
||||
message = replacetext(message," kill "," hug ")
|
||||
message = replacetext(message," murder "," tease ")
|
||||
message = replacetext(message," ugly "," beautiful ")
|
||||
message = replacetext(message," douchbag "," nice guy ")
|
||||
message = replacetext(message," whore "," lady ")
|
||||
message = replacetext(message," nerd "," smart guy ")
|
||||
message = replacetext(message," moron "," fun person ")
|
||||
message = replacetext(message," IT'S LOOSE "," EVERYTHING IS FINE ")
|
||||
message = replacetext(message," sex "," hug fight ")
|
||||
message = replacetext(message," idiot "," genius ")
|
||||
message = replacetext(message," fat "," thin ")
|
||||
message = replacetext(message," beer "," water with ice ")
|
||||
message = replacetext(message," drink "," water ")
|
||||
message = replacetext(message," feminist "," empowered woman ")
|
||||
message = replacetext(message," i hate you "," you're mean ")
|
||||
message = replacetext(message," nigger "," african american ")
|
||||
message = replacetext(message," jew "," jewish ")
|
||||
message = replacetext(message," shit "," shiz ")
|
||||
message = replacetext(message," crap "," poo ")
|
||||
message = replacetext(message," slut "," tease ")
|
||||
message = replacetext(message," ass "," butt ")
|
||||
message = replacetext(message," damn "," dang ")
|
||||
message = replacetext(message," fuck "," ")
|
||||
message = replacetext(message," penis "," privates ")
|
||||
message = replacetext(message," cunt "," privates ")
|
||||
message = replacetext(message," dick "," jerk ")
|
||||
message = replacetext(message," vagina "," privates ")
|
||||
return trim(message)
|
||||
|
||||
|
||||
/datum/mutation/human/unintelligable
|
||||
name = "Unintelligable"
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
|
||||
text_lose_indication = "<span class='danger'>Your mind feels more clear.</span>"
|
||||
|
||||
/datum/mutation/human/unintelligable/say_mod(message)
|
||||
if(message)
|
||||
var/prefix=copytext(message,1,2)
|
||||
if(prefix == ";")
|
||||
message = copytext(message,2)
|
||||
else if(prefix in list(":","#"))
|
||||
prefix += copytext(message,2,3)
|
||||
message = copytext(message,3)
|
||||
else
|
||||
prefix=""
|
||||
|
||||
var/list/words = splittext(message," ")
|
||||
var/list/rearranged = list()
|
||||
for(var/i=1;i<=words.len;i++)
|
||||
var/cword = pick(words)
|
||||
words.Remove(cword)
|
||||
var/suffix = copytext(cword,length(cword)-1,length(cword))
|
||||
while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
|
||||
cword = copytext(cword,1 ,length(cword)-1)
|
||||
suffix = copytext(cword,length(cword)-1,length(cword) )
|
||||
if(length(cword))
|
||||
rearranged += cword
|
||||
message = "[prefix][uppertext(jointext(rearranged," "))]!!"
|
||||
return message
|
||||
|
||||
|
||||
/datum/mutation/human/swedish
|
||||
name = "Swedish"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel Swedish, however that works.</span>"
|
||||
text_lose_indication = "<span class='notice'>The feeling of Swedishness passes.</span>"
|
||||
|
||||
/datum/mutation/human/swedish/say_mod(message)
|
||||
if(message)
|
||||
message = replacetext(message,"w","v")
|
||||
message = replacetext(message,"j","y")
|
||||
message = replacetext(message,"a",pick("�","�","�","a"))
|
||||
message = replacetext(message,"bo","bjo")
|
||||
message = replacetext(message,"o",pick("�","�","o"))
|
||||
if(prob(30))
|
||||
message += " Bork[pick("",", bork",", bork, bork")]!"
|
||||
return message
|
||||
|
||||
|
||||
/datum/mutation/human/chav
|
||||
name = "Chav"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>Ye feel like a reet prat like, innit?</span>"
|
||||
text_lose_indication = "<span class='notice'>You no longer feel like being rude and sassy.</span>"
|
||||
|
||||
/datum/mutation/human/chav/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
message = replacetext(message," looking at "," gawpin' at ")
|
||||
message = replacetext(message," great "," bangin' ")
|
||||
message = replacetext(message," man "," mate ")
|
||||
message = replacetext(message," friend ",pick(" mate "," bruv "," bledrin "))
|
||||
message = replacetext(message," what "," wot ")
|
||||
message = replacetext(message," drink "," wet ")
|
||||
message = replacetext(message," get "," giz ")
|
||||
message = replacetext(message," what "," wot ")
|
||||
message = replacetext(message," no thanks "," wuddent fukken do one ")
|
||||
message = replacetext(message," i don't know "," wot mate ")
|
||||
message = replacetext(message," no "," naw ")
|
||||
message = replacetext(message," robust "," chin ")
|
||||
message = replacetext(message," hi "," how what how ")
|
||||
message = replacetext(message," hello "," sup bruv ")
|
||||
message = replacetext(message," kill "," bang ")
|
||||
message = replacetext(message," murder "," bang ")
|
||||
message = replacetext(message," windows "," windies ")
|
||||
message = replacetext(message," window "," windy ")
|
||||
message = replacetext(message," break "," do ")
|
||||
message = replacetext(message," your "," yer ")
|
||||
message = replacetext(message," security "," coppers ")
|
||||
return trim(message)
|
||||
|
||||
|
||||
/datum/mutation/human/elvis
|
||||
name = "Elvis"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel pretty good, honeydoll.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel a little less conversation would be great.</span>"
|
||||
|
||||
/datum/mutation/human/elvis/on_life(mob/living/carbon/human/owner)
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
if(prob(15))
|
||||
var/list/dancetypes = list("swinging", "fancy", "stylish", "20'th century", "jivin'", "rock and roller", "cool", "salacious", "bashing", "smashing")
|
||||
var/dancemoves = pick(dancetypes)
|
||||
owner.visible_message("<b>[owner]</b> busts out some [dancemoves] moves!")
|
||||
if(2)
|
||||
if(prob(15))
|
||||
owner.visible_message("<b>[owner]</b> [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]!")
|
||||
|
||||
/datum/mutation/human/elvis/say_mod(message)
|
||||
if(message)
|
||||
message = " [message] "
|
||||
message = replacetext(message," i'm not "," I aint ")
|
||||
message = replacetext(message," girl ",pick(" honey "," baby "," baby doll "))
|
||||
message = replacetext(message," man ",pick(" son "," buddy "," brother"," pal "," friendo "))
|
||||
message = replacetext(message," out of "," outta ")
|
||||
message = replacetext(message," thank you "," thank you, thank you very much ")
|
||||
message = replacetext(message," what are you "," whatcha ")
|
||||
message = replacetext(message," yes ",pick(" sure", "yea "))
|
||||
message = replacetext(message," faggot "," square ")
|
||||
message = replacetext(message," muh valids "," getting my kicks ")
|
||||
return trim(message)
|
||||
|
||||
|
||||
/datum/mutation/human/stoner
|
||||
name = "Stoner"
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel...totally chill, man!</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel like you have a better sense of time.</span>"
|
||||
|
||||
/datum/mutation/human/stoner/on_acquiring(mob/living/carbon/human/owner)
|
||||
..()
|
||||
owner.grant_language(/datum/language/beachbum)
|
||||
owner.remove_language(/datum/language/common)
|
||||
|
||||
/datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner)
|
||||
..()
|
||||
owner.grant_language(/datum/language/common)
|
||||
owner.remove_language(/datum/language/beachbum)
|
||||
@@ -0,0 +1,18 @@
|
||||
//Telekinesis lets you interact with objects from range, and gives you a light blue halo around your head.
|
||||
/datum/mutation/human/telekinesis
|
||||
name = "Telekinesis"
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>You feel smarter!</span>"
|
||||
limb_req = "head"
|
||||
|
||||
/datum/mutation/human/telekinesis/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
|
||||
target.attack_tk(owner)
|
||||
@@ -1,442 +0,0 @@
|
||||
/datum/riding
|
||||
var/next_vehicle_move = 0 //used for move delays
|
||||
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
|
||||
var/keytype = null
|
||||
var/atom/movable/ridden = null
|
||||
|
||||
var/slowed = FALSE
|
||||
var/slowvalue = 1
|
||||
|
||||
/datum/riding/New(atom/movable/_ridden)
|
||||
ridden = _ridden
|
||||
|
||||
/datum/riding/Destroy()
|
||||
ridden = null
|
||||
return ..()
|
||||
|
||||
/datum/riding/proc/handle_vehicle_layer()
|
||||
if(ridden.dir != NORTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
|
||||
/datum/riding/proc/on_vehicle_move()
|
||||
for(var/mob/living/M in ridden.buckled_mobs)
|
||||
ride_check(M)
|
||||
handle_vehicle_offsets()
|
||||
handle_vehicle_layer()
|
||||
|
||||
/datum/riding/proc/ride_check(mob/living/M)
|
||||
return TRUE
|
||||
|
||||
/datum/riding/proc/force_dismount(mob/living/M)
|
||||
ridden.unbuckle_mob(M)
|
||||
|
||||
/datum/riding/proc/handle_vehicle_offsets()
|
||||
var/ridden_dir = "[ridden.dir]"
|
||||
var/passindex = 0
|
||||
if(ridden.has_buckled_mobs())
|
||||
for(var/m in ridden.buckled_mobs)
|
||||
passindex++
|
||||
var/mob/living/buckled_mob = m
|
||||
var/list/offsets = get_offsets(passindex)
|
||||
var/rider_dir = get_rider_dir(passindex)
|
||||
buckled_mob.setDir(rider_dir)
|
||||
dir_loop:
|
||||
for(var/offsetdir in offsets)
|
||||
if(offsetdir == ridden_dir)
|
||||
var/list/diroffsets = offsets[offsetdir]
|
||||
buckled_mob.pixel_x = diroffsets[1]
|
||||
if(diroffsets.len >= 2)
|
||||
buckled_mob.pixel_y = diroffsets[2]
|
||||
if(diroffsets.len == 3)
|
||||
buckled_mob.layer = diroffsets[3]
|
||||
break dir_loop
|
||||
|
||||
|
||||
//Override this to set your vehicle's various pixel offsets
|
||||
/datum/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 0), "[SOUTH]" = list(0, 0), "[EAST]" = list(0, 0), "[WEST]" = list(0, 0))
|
||||
|
||||
//Override this to set the passengers/riders dir based on which passenger they are.
|
||||
//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
|
||||
/datum/riding/proc/get_rider_dir(pass_index)
|
||||
return ridden.dir
|
||||
|
||||
//KEYS
|
||||
/datum/riding/proc/keycheck(mob/user)
|
||||
if(keytype)
|
||||
if(user.is_holding_item_of_type(keytype))
|
||||
return TRUE
|
||||
else
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//BUCKLE HOOKS
|
||||
/datum/riding/proc/restore_position(mob/living/buckled_mob)
|
||||
if(istype(buckled_mob))
|
||||
buckled_mob.pixel_x = 0
|
||||
buckled_mob.pixel_y = 0
|
||||
if(buckled_mob.client)
|
||||
buckled_mob.client.change_view(world.view)
|
||||
|
||||
//MOVEMENT
|
||||
/datum/riding/proc/handle_ride(mob/user, direction)
|
||||
if(user.incapacitated())
|
||||
Unbuckle(user)
|
||||
return
|
||||
|
||||
if(world.time < next_vehicle_move)
|
||||
return
|
||||
next_vehicle_move = world.time + vehicle_move_delay
|
||||
if(keycheck(user))
|
||||
if(!Process_Spacemove(direction) || !isturf(ridden.loc))
|
||||
return
|
||||
step(ridden, direction)
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You'll need the keys in one of your hands to drive \the [ridden.name].</span>")
|
||||
|
||||
/datum/riding/proc/Unbuckle(atom/movable/M)
|
||||
addtimer(CALLBACK(ridden, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/riding/proc/Process_Spacemove(direction)
|
||||
if(ridden.has_gravity())
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/riding/space/Process_Spacemove(direction)
|
||||
return 1
|
||||
|
||||
|
||||
//atv
|
||||
/datum/riding/atv
|
||||
keytype = /obj/item/key
|
||||
vehicle_move_delay = 1
|
||||
|
||||
/datum/riding/atv/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
|
||||
|
||||
|
||||
/datum/riding/atv/handle_vehicle_layer()
|
||||
if(ridden.dir == SOUTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
|
||||
/datum/riding/atv/turret
|
||||
var/obj/machinery/porta_turret/syndicate/vehicle_turret/turret = null
|
||||
|
||||
/datum/riding/atv/turret/handle_vehicle_layer()
|
||||
if(ridden.dir == SOUTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
|
||||
if(turret)
|
||||
if(ridden.dir == NORTH)
|
||||
turret.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
turret.layer = OBJ_LAYER
|
||||
|
||||
|
||||
/datum/riding/atv/turret/handle_vehicle_offsets()
|
||||
..()
|
||||
if(turret)
|
||||
turret.forceMove(get_turf(ridden))
|
||||
switch(ridden.dir)
|
||||
if(NORTH)
|
||||
turret.pixel_x = 0
|
||||
turret.pixel_y = 4
|
||||
if(EAST)
|
||||
turret.pixel_x = -12
|
||||
turret.pixel_y = 4
|
||||
if(SOUTH)
|
||||
turret.pixel_x = 0
|
||||
turret.pixel_y = 4
|
||||
if(WEST)
|
||||
turret.pixel_x = 12
|
||||
turret.pixel_y = 4
|
||||
|
||||
|
||||
//pimpin ride
|
||||
/datum/riding/janicart
|
||||
keytype = /obj/item/key/janitor
|
||||
|
||||
|
||||
/datum/riding/janicart/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 7), "[EAST]" = list(-12, 7), "[WEST]" = list( 12, 7))
|
||||
|
||||
//scooter
|
||||
/datum/riding/scooter/handle_vehicle_layer()
|
||||
if(ridden.dir == SOUTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
|
||||
/datum/riding/scooter/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0), "[SOUTH]" = list(-2), "[EAST]" = list(0), "[WEST]" = list( 2))
|
||||
|
||||
/datum/riding/scooter/handle_vehicle_offsets()
|
||||
..()
|
||||
if(ridden.has_buckled_mobs())
|
||||
for(var/m in ridden.buckled_mobs)
|
||||
var/mob/living/buckled_mob = m
|
||||
if(buckled_mob.get_num_legs() > 0)
|
||||
buckled_mob.pixel_y = 5
|
||||
else
|
||||
buckled_mob.pixel_y = -4
|
||||
|
||||
/datum/riding/proc/account_limbs(mob/living/M)
|
||||
if(M.get_num_legs() < 2 && !slowed)
|
||||
vehicle_move_delay = vehicle_move_delay + slowvalue
|
||||
slowed = TRUE
|
||||
else if(slowed)
|
||||
vehicle_move_delay = vehicle_move_delay - slowvalue
|
||||
slowed = FALSE
|
||||
|
||||
/datum/riding/scooter/skateboard
|
||||
vehicle_move_delay = 0//fast
|
||||
|
||||
|
||||
//secway
|
||||
/datum/riding/secway
|
||||
keytype = /obj/item/key/security
|
||||
|
||||
/datum/riding/secway/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
|
||||
|
||||
//i want to ride my
|
||||
/datum/riding/bicycle
|
||||
keytype = null
|
||||
vehicle_move_delay = 0
|
||||
|
||||
/datum/riding/bicycle/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
|
||||
|
||||
//speedbike
|
||||
/datum/riding/space/speedbike
|
||||
keytype = null
|
||||
vehicle_move_delay = 0
|
||||
|
||||
/datum/riding/space/speedbike/handle_vehicle_layer()
|
||||
switch(ridden.dir)
|
||||
if(NORTH,SOUTH)
|
||||
ridden.pixel_x = -16
|
||||
ridden.pixel_y = -16
|
||||
if(EAST,WEST)
|
||||
ridden.pixel_x = -18
|
||||
ridden.pixel_y = 0
|
||||
|
||||
/datum/riding/space/speedbike/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, -8), "[SOUTH]" = list(0, 4), "[EAST]" = list(-10, 5), "[WEST]" = list( 10, 5))
|
||||
|
||||
//SPEEDUWAGON
|
||||
|
||||
/datum/riding/space/speedwagon
|
||||
vehicle_move_delay = 0
|
||||
|
||||
/datum/riding/space/speedwagon/handle_vehicle_layer()
|
||||
ridden.layer = BELOW_MOB_LAYER
|
||||
|
||||
/datum/riding/space/speedwagon/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
switch(pass_index)
|
||||
if(1)
|
||||
return list("[NORTH]" = list(-10, -4), "[SOUTH]" = list(16, 3), "[EAST]" = list(-4, 30), "[WEST]" = list(4, -3))
|
||||
if(2)
|
||||
return list("[NORTH]" = list(19, -5, 4), "[SOUTH]" = list(-13, 3, 4), "[EAST]" = list(-4, -3, 4.1), "[WEST]" = list(4, 28, 3.9))
|
||||
if(3)
|
||||
return list("[NORTH]" = list(-10, -18, 4.2), "[SOUTH]" = list(16, 25, 3.9), "[EAST]" = list(-22, 30), "[WEST]" = list(22, -3, 4.1))
|
||||
if(4)
|
||||
return list("[NORTH]" = list(19, -18, 4.2), "[SOUTH]" = list(-13, 25, 3.9), "[EAST]" = list(-22, 3, 3.9), "[WEST]" = list(22, 28))
|
||||
|
||||
///////////////BOATS////////////
|
||||
/datum/riding/boat
|
||||
keytype = /obj/item/oar
|
||||
|
||||
/datum/riding/boat/handle_ride(mob/user, direction)
|
||||
var/turf/next = get_step(ridden, direction)
|
||||
var/turf/current = get_turf(ridden)
|
||||
|
||||
if(islava(next) || islava(current)) //We can move from land to lava, or lava to land, but not from land to land
|
||||
..()
|
||||
else
|
||||
to_chat(user, "Boats don't go on land!")
|
||||
return 0
|
||||
|
||||
/datum/riding/boat/dragon
|
||||
keytype = null
|
||||
vehicle_move_delay = 1
|
||||
|
||||
/datum/riding/boat/dragon/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(1, 2), "[SOUTH]" = list(1, 2), "[EAST]" = list(1, 2), "[WEST]" = list( 1, 2))
|
||||
|
||||
///////////////ANIMALS////////////
|
||||
//general animals
|
||||
/datum/riding/animal
|
||||
keytype = null
|
||||
|
||||
/datum/riding/animal/handle_ride(mob/user, direction)
|
||||
if(user.incapacitated())
|
||||
Unbuckle(user)
|
||||
return
|
||||
|
||||
if(world.time < next_vehicle_move)
|
||||
return
|
||||
|
||||
next_vehicle_move = world.time + vehicle_move_delay
|
||||
if(keycheck(user))
|
||||
if(!isturf(ridden.loc))
|
||||
return
|
||||
step(ridden, direction)
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You'll need something to guide the [ridden.name].</span>")
|
||||
|
||||
///////Humans. Yes, I said humans. No, this won't end well...//////////
|
||||
/datum/riding/human
|
||||
keytype = null
|
||||
|
||||
/datum/riding/human/ride_check(mob/living/M)
|
||||
var/mob/living/carbon/human/H = ridden //IF this runtimes I'm blaming the admins.
|
||||
if(M.incapacitated(FALSE, TRUE) || H.incapacitated(FALSE, TRUE))
|
||||
M.visible_message("<span class='warning'>[M] falls off [ridden]!</span>")
|
||||
Unbuckle(M)
|
||||
return FALSE
|
||||
if(M.restrained(TRUE))
|
||||
M.visible_message("<span class='warning'>[M] can't hang onto [ridden] with their hands cuffed!</span>") //Honestly this should put the ridden mob in a chokehold.
|
||||
Unbuckle(M)
|
||||
return FALSE
|
||||
if(H.pulling == M)
|
||||
H.stop_pulling()
|
||||
|
||||
/datum/riding/human/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 6), "[SOUTH]" = list(0, 6), "[EAST]" = list(-6, 4), "[WEST]" = list( 6, 4))
|
||||
|
||||
|
||||
/datum/riding/human/handle_vehicle_layer()
|
||||
if(ridden.buckled_mobs && ridden.buckled_mobs.len)
|
||||
if(ridden.dir == SOUTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
else
|
||||
ridden.layer = MOB_LAYER
|
||||
|
||||
/datum/riding/human/force_dismount(mob/living/user)
|
||||
ridden.unbuckle_mob(user)
|
||||
user.Knockdown(60)
|
||||
user.visible_message("<span class='warning'>[ridden] pushes [user] off of them!</span>")
|
||||
|
||||
/datum/riding/cyborg
|
||||
keytype = null
|
||||
|
||||
/datum/riding/cyborg/ride_check(mob/user)
|
||||
if(user.incapacitated())
|
||||
var/kick = TRUE
|
||||
if(iscyborg(ridden))
|
||||
var/mob/living/silicon/robot/R = ridden
|
||||
if(R.module && R.module.ride_allow_incapacitated)
|
||||
kick = FALSE
|
||||
if(kick)
|
||||
to_chat(user, "<span class='userdanger'>You fall off of [ridden]!</span>")
|
||||
Unbuckle(user)
|
||||
return
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/carbonuser = user
|
||||
if(!carbonuser.get_num_arms())
|
||||
Unbuckle(user)
|
||||
to_chat(user, "<span class='userdanger'>You can't grab onto [ridden] with no hands!</span>")
|
||||
return
|
||||
|
||||
/datum/riding/cyborg/handle_vehicle_layer()
|
||||
if(ridden.buckled_mobs && ridden.buckled_mobs.len)
|
||||
if(ridden.dir == SOUTH)
|
||||
ridden.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
ridden.layer = OBJ_LAYER
|
||||
else
|
||||
ridden.layer = MOB_LAYER
|
||||
|
||||
/datum/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(-6, 3), "[WEST]" = list( 6, 3))
|
||||
|
||||
/datum/riding/cyborg/handle_vehicle_offsets()
|
||||
if(ridden.has_buckled_mobs())
|
||||
for(var/mob/living/M in ridden.buckled_mobs)
|
||||
M.setDir(ridden.dir)
|
||||
if(iscyborg(ridden))
|
||||
var/mob/living/silicon/robot/R = ridden
|
||||
if(istype(R.module))
|
||||
M.pixel_x = R.module.ride_offset_x[dir2text(ridden.dir)]
|
||||
M.pixel_y = R.module.ride_offset_y[dir2text(ridden.dir)]
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/riding/cyborg/force_dismount(mob/living/M)
|
||||
ridden.unbuckle_mob(M)
|
||||
var/turf/target = get_edge_target_turf(ridden, ridden.dir)
|
||||
var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
|
||||
M.Move(targetm)
|
||||
M.visible_message("<span class='warning'>[M] is thrown clear of [ridden]!</span>")
|
||||
M.throw_at(target, 14, 5, ridden)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
|
||||
var/amount_equipped = 0
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
inhand.rider = user
|
||||
inhand.ridden = ridden
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
else
|
||||
break
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
else
|
||||
unequip_buckle_inhands(user)
|
||||
return FALSE
|
||||
|
||||
/datum/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
for(var/obj/item/riding_offhand/O in user.contents)
|
||||
if(O.ridden != ridden)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/riding_offhand
|
||||
name = "offhand"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "offhand"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/mob/living/carbon/rider
|
||||
var/mob/living/ridden
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/riding_offhand/dropped()
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/equipped()
|
||||
if(loc != rider)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/Destroy()
|
||||
if(selfdeleting)
|
||||
if(rider in ridden.buckled_mobs)
|
||||
ridden.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
@@ -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
|
||||
|
||||
@@ -42,4 +42,7 @@
|
||||
if(WIRE_LIMIT)
|
||||
C.strength_upper_limit = (mend ? 2 : 3)
|
||||
if(C.strength_upper_limit < C.strength)
|
||||
C.remove_strength()
|
||||
C.remove_strength()
|
||||
|
||||
/datum/wires/particle_accelerator/control_box/emp_pulse() // to prevent singulo from pulsing wires
|
||||
return
|
||||
Reference in New Issue
Block a user