mirror of
https://github.com/goonstation/goonstation-2016.git
synced 2026-03-22 09:22:37 +00:00
850 lines
26 KiB
Plaintext
850 lines
26 KiB
Plaintext
#define DESERIALIZE_ERROR 0
|
|
#define DESERIALIZE_OK 1
|
|
#define DESERIALIZE_NEED_POSTPROCESS 2
|
|
#define DESERIALIZE_NOT_IMPLEMENTED 4
|
|
|
|
/datum/sandbox
|
|
var/list/context = list()
|
|
|
|
/proc/icon_serializer(var/savefile/F, var/path, var/datum/sandbox/sandbox, var/icon, var/icon_state)
|
|
var/iname = "[icon]"
|
|
F["[path].icon"] << iname
|
|
F["[path].icon_state"] << icon_state
|
|
if (!("icon" in sandbox.context))
|
|
sandbox.context += "icon"
|
|
sandbox.context["icon"] = list()
|
|
if (!(iname in sandbox.context["icon"]))
|
|
sandbox.context["icon"] += iname
|
|
sandbox.context["icon"][iname] = icon
|
|
F["ICONS.[iname]"] << icon
|
|
|
|
/datum/iconDeserializerData
|
|
var/icon/icon
|
|
var/icon_state
|
|
|
|
/proc/icon_deserializer(var/savefile/F, var/path, var/datum/sandbox/sandbox, var/defaultIcon, var/defaultState)
|
|
var/iname
|
|
var/datum/iconDeserializerData/IDS = new()
|
|
IDS.icon = defaultIcon
|
|
IDS.icon_state = defaultState
|
|
F["[path].icon"] >> iname
|
|
if (!fexists(iname))
|
|
if ("[defaultIcon]" == iname) // fuck off byond fuck you
|
|
F["[path].icon_state"] >> IDS.icon_state
|
|
else
|
|
if (!("icon_failures" in sandbox.context))
|
|
sandbox.context += "icon_failures"
|
|
sandbox.context["icon_failures"] = list("total" = 0)
|
|
if (!(iname in sandbox.context["icon_failures"]))
|
|
sandbox.context["icon_failures"] += iname
|
|
sandbox.context["icon_failures"][iname] = 0
|
|
sandbox.context["icon_failures"]["total"]++
|
|
sandbox.context["icon_failures"][iname]++
|
|
|
|
F["ICONS.[iname]"] >> IDS.icon
|
|
if (!IDS.icon && usr)
|
|
boutput(usr, "<span style=\"color:red\">Fatal error: Saved copy of icon [iname] cannot be loaded. Local loading failed. Falling back to default icon.</span>")
|
|
else if (IDS.icon)
|
|
F["[path].icon_state"] >> IDS.icon_state
|
|
else
|
|
IDS.icon = icon(file(iname))
|
|
F["[path].icon_state"] >> IDS.icon_state
|
|
return IDS
|
|
|
|
/proc/matrix_serializer(var/savefile/F, var/path, var/datum/sandbox/sandbox, var/name, var/matrix/mx)
|
|
var/base = "[path].[name]"
|
|
F["[base].a"] << mx.a
|
|
F["[base].b"] << mx.b
|
|
F["[base].c"] << mx.c
|
|
F["[base].d"] << mx.d
|
|
F["[base].e"] << mx.e
|
|
F["[base].f"] << mx.f
|
|
|
|
/proc/matrix_deserializer(var/savefile/F, var/path, var/datum/sandbox/sandbox, var/name, var/matrix/defMx = matrix())
|
|
var
|
|
a
|
|
b
|
|
c
|
|
d
|
|
e
|
|
f
|
|
|
|
var/base = "[path].[name]"
|
|
F["[base].a"] >> a
|
|
if (!a)
|
|
return defMx
|
|
F["[base].d"] >> d
|
|
if (!d)
|
|
return defMx
|
|
F["[base].b"] >> b
|
|
F["[base].c"] >> c
|
|
F["[base].e"] >> e
|
|
F["[base].f"] >> f
|
|
return new /matrix(a,b,c,d,e,f)
|
|
|
|
/atom
|
|
layer = TURF_LAYER
|
|
var/datum/mechanics_holder/mechanics = null
|
|
var/level = 2
|
|
var/flags = FPRINT
|
|
var/fingerprints = null
|
|
var/list/fingerprintshidden = new/list()
|
|
var/fingerprintslast = null
|
|
var/blood_DNA = null
|
|
var/blood_type = null
|
|
var/last_bumped = 0
|
|
var/shrunk = 0
|
|
var/area/last_area = null
|
|
var/texture_size = 0 //Override for the texture size used by setTexture.
|
|
|
|
/* -------------------- name stuff -------------------- */
|
|
/*
|
|
to change names: either add or remove something with the appropriate proc(s) and then call atom.UpdateName()
|
|
|
|
to add to names: call atom.name_prefix(text_to_add) or thing.name_suffix(text_to_add) depending on where you want it
|
|
text_to_add will run strip_html() on the text, which also limits the text to MAX_MESSAGE_LEN
|
|
|
|
to remove from names: call atom.remove_prefixes(num) or atom.remove_suffixes(num)
|
|
num can be either a number (obviously) OR text (I had already named the var okay)
|
|
if num is a number it'll remove that many things from the total amount of pre/suffixes, starting from the earliest one
|
|
if num is text, it'll remove that specific text from the list, once
|
|
*/
|
|
|
|
var/list/name_prefixes = list()
|
|
var/list/name_suffixes = list()
|
|
var/num_allowed_prefixes = 10
|
|
var/num_allowed_suffixes = 5
|
|
|
|
proc/name_prefix(var/text_to_add, var/return_prefixes = 0)
|
|
var/prefix = ""
|
|
if (istext(text_to_add) && length(text_to_add) && islist(src.name_prefixes))
|
|
if (src.name_prefixes.len >= src.num_allowed_prefixes)
|
|
src.remove_prefixes(1)
|
|
src.name_prefixes += strip_html(text_to_add)
|
|
if (return_prefixes)
|
|
var/amt_prefixes = 0
|
|
for (var/i in src.name_prefixes)
|
|
if (amt_prefixes >= src.num_allowed_prefixes)
|
|
prefix += " "
|
|
break
|
|
prefix += i + " "
|
|
amt_prefixes ++
|
|
return prefix
|
|
|
|
proc/name_suffix(var/text_to_add, var/return_suffixes = 0)
|
|
var/suffix = ""
|
|
if (istext(text_to_add) && length(text_to_add) && islist(src.name_suffixes))
|
|
if (src.name_suffixes.len >= src.num_allowed_suffixes)
|
|
src.remove_suffixes(1)
|
|
src.name_suffixes += strip_html(text_to_add)
|
|
if (return_suffixes)
|
|
var/amt_suffixes = 0
|
|
for (var/i in src.name_suffixes)
|
|
if (amt_suffixes >= src.num_allowed_suffixes)
|
|
break
|
|
suffix += " " + i
|
|
amt_suffixes ++
|
|
return suffix
|
|
|
|
proc/remove_prefixes(var/num = 1)
|
|
if (!num)
|
|
return
|
|
if (istext(num)) // :v
|
|
src.name_prefixes -= num
|
|
return
|
|
if (islist(src.name_prefixes) && src.name_prefixes.len)
|
|
for (var/i in src.name_prefixes)
|
|
if (num <= 0 || !src.name_prefixes.len)
|
|
return
|
|
src.name_prefixes -= i
|
|
num --
|
|
|
|
proc/remove_suffixes(var/num = 1)
|
|
if (!num)
|
|
return
|
|
if (istext(num))
|
|
src.name_suffixes -= num
|
|
return
|
|
if (islist(src.name_suffixes) && src.name_suffixes.len)
|
|
for (var/i in src.name_suffixes)
|
|
if (num <= 0 || !src.name_suffixes.len)
|
|
return
|
|
src.name_suffixes -= i
|
|
num --
|
|
|
|
proc/UpdateName()
|
|
src.name = "[name_prefix(null, 1)][initial(src.name)][name_suffix(null, 1)]"
|
|
|
|
/* -------------------- end name stuff -------------------- */
|
|
|
|
var/mat_changename = 1 //Change the name of this atom when a material is applied?
|
|
var/mat_changedesc = 1 //Change the desc of this atom when a material is applied?
|
|
|
|
var/matrix/_transform
|
|
|
|
var/list/attached_objs = list() //List of attached objects. Objects in this list will follow this atom around as it moves.
|
|
|
|
var/explosion_resistance = 0
|
|
var/explosion_protection = 0 //Reduces damage from explosions
|
|
|
|
///Chemistry.
|
|
var/datum/reagents/reagents = null
|
|
|
|
//var/chem_is_open_container = 0
|
|
// replaced by OPENCONTAINER flags and atom/proc/is_open_container()
|
|
|
|
disposing()
|
|
material = null
|
|
reagents = null
|
|
fingerprintshidden = null
|
|
tag = null
|
|
..()
|
|
///Chemistry.
|
|
|
|
proc/Turn(var/rot)
|
|
src.transform = matrix(src.transform, rot, MATRIX_ROTATE)
|
|
|
|
proc/Scale(var/scalex = 1, var/scaley = 1)
|
|
src.transform = matrix(src.transform, scalex, scaley, MATRIX_SCALE)
|
|
|
|
proc/Translate(var/x = 0, var/y = 0)
|
|
src.transform = matrix(src.transform, x, y, MATRIX_TRANSLATE)
|
|
|
|
proc/assume_air(datum/air_group/giver)
|
|
giver.dispose()
|
|
return null
|
|
|
|
proc/remove_air(amount)
|
|
return null
|
|
|
|
proc/return_air()
|
|
return null
|
|
|
|
proc/grab_smash(obj/item/grab/G as obj, mob/user as mob)
|
|
var/mob/M = G.affecting
|
|
|
|
if (!(ismob(G.affecting)))
|
|
return 0
|
|
|
|
if (get_dist(src, M) > 1)
|
|
return 0
|
|
|
|
user.visible_message("<span style=\"color:red\"><B>[M] has been smashed against [src] by [user]!</B></span>")
|
|
logTheThing("combat", user, M, "smashes %target% against [src]")
|
|
|
|
random_brute_damage(G.affecting, rand(2,3))
|
|
G.affecting.TakeDamage("chest", 0, rand(4,5))
|
|
playsound(G.affecting.loc, "punch", 25, 1, -1)
|
|
|
|
user.u_equip(G)
|
|
G.dispose()
|
|
return 1
|
|
|
|
// Convenience proc to see if a container is open for chemistry handling
|
|
// returns true if open
|
|
// false if closed
|
|
proc/is_open_container()
|
|
return flags & OPENCONTAINER
|
|
|
|
proc/transfer_all_reagents(var/atom/A as turf|obj|mob, var/mob/user as mob)
|
|
// trans from src to A
|
|
if (!src.reagents || !A.reagents)
|
|
return // what're we gunna do here?? ain't got no reagent holder
|
|
|
|
if (!src.reagents.total_volume) // Check to make sure the from container isn't empty.
|
|
boutput(user, "<span style=\"color:red\">[src] is empty!</span>")
|
|
return
|
|
else if (A.reagents.total_volume == A.reagents.maximum_volume) // Destination Container is full, quit trying to do things what you can't do!
|
|
boutput(user, "<span style=\"color:red\">[A] is full!</span>") // Notify the user, then exit the process.
|
|
return
|
|
|
|
var/T //Placeholder for total volume transferred
|
|
|
|
if ((A.reagents.total_volume + src.reagents.total_volume) > A.reagents.maximum_volume) // Check to make sure that both containers content's combined won't overfill the destination container.
|
|
T = (A.reagents.maximum_volume - A.reagents.total_volume) // Dump only what fills up the destination container.
|
|
logTheThing("combat", user, null, "transfers chemicals from [src] [log_reagents(src)] to [A] at [log_loc(A)].") // This wasn't logged. Call before trans_to (Convair880).
|
|
src.reagents.trans_to(A, T) // Dump the amount of reagents.
|
|
boutput(user, "<span style=\"color:blue\">You transfer [T] units into [A].</span>") // Tell the user they did a thing.
|
|
return
|
|
else
|
|
T = src.reagents.total_volume // Just make T the whole dang amount then.
|
|
logTheThing("combat", user, null, "transfers chemicals from [src] [log_reagents(src)] to [A] at [log_loc(A)].") // Ditto (Convair880).
|
|
src.reagents.trans_to(A, T) // Dump it all!
|
|
boutput(user, "<span style=\"color:blue\">You transfer [T] units into [A].</span>")
|
|
return
|
|
|
|
proc/handle_event(var/event) //This is sort of like a version of Topic that is not for browsing.
|
|
return
|
|
|
|
//Called AFTER the material of the object was changed.
|
|
proc/onMaterialChanged()
|
|
if(istype(src.material))
|
|
explosion_resistance = material.hasProperty(PROP_COMPRESSIVE) ? round(material.getProperty(PROP_COMPRESSIVE) / 33) : explosion_resistance
|
|
explosion_protection = material.hasProperty(PROP_COMPRESSIVE) ? round(material.getProperty(PROP_COMPRESSIVE) / 33) : explosion_protection
|
|
if(!(flags & CONDUCT) && (src.material.getProperty(PROP_ELECTRICAL) / 100) >= 0.45) flags |= CONDUCT
|
|
return
|
|
|
|
proc/serialize_icon(var/savefile/F, var/path, var/datum/sandbox/sandbox)
|
|
icon_serializer(F, path, sandbox, icon, icon_state)
|
|
|
|
proc/deserialize_icon(var/savefile/F, path, var/datum/sandbox/sandbox)
|
|
var/datum/iconDeserializerData/IDS = icon_deserializer(F, path, sandbox, icon, icon_state)
|
|
icon = IDS.icon
|
|
icon_state = IDS.icon_state
|
|
|
|
proc/serialize(var/savefile/F, var/path, var/datum/sandbox/sandbox)
|
|
return
|
|
|
|
proc/deserialize(var/savefile/F, var/path, var/datum/sandbox/sandbox)
|
|
return DESERIALIZE_NOT_IMPLEMENTED
|
|
|
|
proc/deserialize_postprocess()
|
|
return
|
|
|
|
obj
|
|
assume_air(datum/air_group/giver)
|
|
if(loc)
|
|
return loc.assume_air(giver)
|
|
else
|
|
return null
|
|
|
|
remove_air(amount)
|
|
if(loc)
|
|
return loc.remove_air(amount)
|
|
else
|
|
return null
|
|
|
|
return_air()
|
|
if(loc)
|
|
return loc.return_air()
|
|
else
|
|
return null
|
|
|
|
/atom/proc/ex_act(var/severity=0,var/last_touched=0)
|
|
return
|
|
|
|
/atom/proc/reagent_act(var/reagent_id,var/volume)
|
|
if (!istext(reagent_id) || !isnum(volume) || volume < 1)
|
|
return 1
|
|
return 0
|
|
|
|
/atom/proc/emp_act()
|
|
return
|
|
|
|
/atom/proc/emag_act(var/mob/user, var/obj/item/card/emag/E) //This is gonna be fun!
|
|
return 0
|
|
|
|
/atom/proc/demag(var/mob/user) //hail satan full of grace
|
|
return 0
|
|
|
|
/atom/proc/meteorhit(obj/meteor as obj)
|
|
qdel(src)
|
|
return
|
|
|
|
/atom/proc/allow_drop()
|
|
return 1
|
|
|
|
/atom/proc/CheckExit(atom/mover, turf/target)
|
|
//return !(src.flags & ON_BORDER) || src.CanPass(mover, target, 1, 0)
|
|
return 1 // fuck it
|
|
|
|
/atom/proc/HasEntered(atom/movable/AM as mob|obj, atom/OldLoc)
|
|
return
|
|
|
|
/atom/proc/HasExited(atom/movable/AM as mob|obj, atom/NewLoc)
|
|
return
|
|
|
|
/atom/proc/ProximityLeave(atom/movable/AM as mob|obj)
|
|
return
|
|
|
|
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
|
|
return
|
|
/*
|
|
/atom/MouseEntered()
|
|
usr << output("[src.name]", "atom_label")
|
|
*/
|
|
/atom/movable/overlay/attackby(a, b)
|
|
if (src.master)
|
|
return src.master.attackby(a, b)
|
|
return
|
|
|
|
/atom/movable/overlay/attack_hand(a, b, c)
|
|
if (src.master)
|
|
return src.master.attack_hand(a, b, c)
|
|
return
|
|
|
|
/atom/movable/overlay/New()
|
|
for(var/x in src.verbs)
|
|
src.verbs -= x
|
|
return
|
|
|
|
/atom/movable/disposing()
|
|
set_loc(null)
|
|
..()
|
|
|
|
/atom/movable
|
|
layer = OBJ_LAYER
|
|
var/last_move = null
|
|
var/anchored = 0
|
|
// var/elevation = 2 - not used anywhere
|
|
var/move_speed = 10
|
|
var/l_move_time = 1
|
|
var/throwing = 0
|
|
var/throw_speed = 2
|
|
var/throw_range = 7
|
|
var/throwforce = 1
|
|
var/soundproofing = 5
|
|
|
|
/atom/movable/overlay
|
|
var/atom/master = null
|
|
anchored = 1
|
|
|
|
/atom/movable/overlay/disposing()
|
|
master = null
|
|
..()
|
|
|
|
/atom/movable/Move(NewLoc, direct)
|
|
if (direct & (direct - 1))
|
|
if (direct & NORTH)
|
|
if (direct & EAST)
|
|
if (step(src, NORTH))
|
|
step(src, EAST)
|
|
else if (step(src, EAST))
|
|
step(src, NORTH)
|
|
else
|
|
if (step(src, NORTH))
|
|
step(src, WEST)
|
|
else if (step(src, WEST))
|
|
step(src, NORTH)
|
|
else
|
|
if (direct & EAST)
|
|
if (step(src, SOUTH))
|
|
step(src, EAST)
|
|
else if (step(src, EAST))
|
|
step(src, SOUTH)
|
|
else
|
|
if (step(src, SOUTH))
|
|
step(src, WEST)
|
|
else if (step(src, WEST))
|
|
step(src, SOUTH)
|
|
return // this should in turn fire off its own slew of move calls, so don't do anything here
|
|
|
|
var/atom/A = src.loc
|
|
. = ..()
|
|
src.move_speed = world.timeofday - src.l_move_time
|
|
src.l_move_time = world.timeofday
|
|
if ((A != src.loc && A && A.z == src.z))
|
|
src.last_move = get_dir(A, src.loc)
|
|
for(var/atom/movable/M in attached_objs)
|
|
M.set_loc(src.loc)
|
|
actions.interrupt(src, INTERRUPT_MOVE)
|
|
|
|
/atom/movable/verb/pull()
|
|
set name = "Pull"
|
|
set src in oview(1)
|
|
set category = "Local"
|
|
|
|
if (!( usr ))
|
|
return
|
|
|
|
if(src.loc == usr)
|
|
return
|
|
|
|
// eyebots aint got no arms man, how can they be pulling stuff???????
|
|
if (isshell(usr))
|
|
if (!ticker)
|
|
return
|
|
if (!ticker.mode)
|
|
return
|
|
if (!istype(ticker.mode, /datum/game_mode/construction))
|
|
return
|
|
// no pulling other mobs for ghostdrones (but they can pull other ghostdrones)
|
|
else if (isghostdrone(usr) && (isliving(src) && !isghostdrone(src)))
|
|
return
|
|
|
|
if (istype(usr, /mob/living/carbon) || istype(usr, /mob/living/silicon))
|
|
add_fingerprint(usr)
|
|
|
|
if (istype(src,/obj/item/old_grenade/light_gimmick))
|
|
boutput(usr, "<span style=\"color:blue\">You feel your hand reach out and clasp the grenade.</span>")
|
|
src.attack_hand(usr)
|
|
return
|
|
if (!( src.anchored ))
|
|
usr.pulling = src
|
|
//Wire: Hi this was so dumb. Turns out it isn't only humans that have huds, who woulda thunk!!
|
|
if (usr:hud && usr:hud:pulling) //yes this uses the dreaded ":", deal with it
|
|
usr:hud:update_pulling()
|
|
return
|
|
|
|
/atom/proc/get_desc(dist)
|
|
|
|
/atom/verb/examine()
|
|
set name = "Examine"
|
|
set category = "Local"
|
|
set src in view(12) //make it work from farther away
|
|
|
|
var/output = "This is \an [src.name]."
|
|
|
|
// Added for forensics (Convair880).
|
|
if (isitem(src) && src.blood_DNA)
|
|
output = "<span style=\"color:red\">This is a bloody [src.name].</span>"
|
|
//boutput(usr, "<span style=\"color:red\">This is a bloody [src.name].</span>")
|
|
if (src.desc)
|
|
output += "<br>[src.desc] It seems to be covered in blood."
|
|
//boutput(usr, "[src.desc] It seems to be covered in blood.")
|
|
else if (src.desc)
|
|
output += "<br>[src.desc]"
|
|
/*boutput(usr, "This is \an [src.name].")
|
|
if (src.desc)
|
|
boutput(usr, src.desc)*/
|
|
|
|
var/dist = get_dist(src, usr)
|
|
if (istype(usr, /mob/dead/target_observer))
|
|
dist = get_dist(src, usr:target)
|
|
var/extra = src.get_desc(dist, usr)
|
|
if (extra)
|
|
output += " [extra]"
|
|
//boutput(usr, extra)
|
|
|
|
if (output)
|
|
boutput(usr, output)
|
|
|
|
/atom/proc/MouseDrop_T()
|
|
return
|
|
|
|
/atom/proc/attack_hand(mob/user as mob)
|
|
return
|
|
|
|
/atom/proc/attack_ai(mob/user as mob)
|
|
return
|
|
|
|
/atom/proc/hitby(atom/movable/AM as mob|obj)
|
|
return
|
|
|
|
/atom/proc/attackby(obj/item/W as obj, mob/user as mob, params)
|
|
if (user && W && !(W.flags & SUPPRESSATTACK)) //!( istype(W, /obj/item/grab) || istype(W, /obj/item/spraybottle) || istype(W, /obj/item/card/emag)))
|
|
user.visible_message("<span class='combat'><B>[user] hits [src] with [W]!</B></span>")
|
|
return
|
|
|
|
/atom/proc/add_fingerprint(mob/living/M as mob)
|
|
if(!ismob(M)) return
|
|
if(isnull(M)) return
|
|
if(isnull(M.key)) return
|
|
if (!( src.flags ) & 256)
|
|
return
|
|
|
|
if (ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
var/list/L = params2list(src.fingerprints)
|
|
|
|
if (H.gloves) // Fixed: now adds distorted prints even if 'fingerprintslast == ckey'. Important for the clean_forensic proc (Convair880).
|
|
var/gloveprints = H.gloves.distort_prints(md5(H.bioHolder.Uid), 1)
|
|
if (!isnull(gloveprints))
|
|
L -= gloveprints
|
|
if (L.len >= 6) //Limit fingerprints in the list to 6
|
|
L.Cut(1,2)
|
|
L += gloveprints
|
|
src.fingerprints = list2params(L)
|
|
|
|
if(src.fingerprintslast != H.key)
|
|
src.fingerprintshidden += text("(Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
|
|
src.fingerprintslast = H.key
|
|
|
|
return 0
|
|
|
|
if (!( src.fingerprints ))
|
|
src.fingerprints = "[md5(H.bioHolder.Uid)]"
|
|
if(src.fingerprintslast != H.key)
|
|
src.fingerprintshidden += "Real name: [H.real_name], Key: [H.key]"
|
|
src.fingerprintslast = H.key
|
|
|
|
return 1
|
|
|
|
else
|
|
L -= md5(H.bioHolder.Uid)
|
|
while(L.len >= 6) // limit the number of fingerprints to 6, previously 3
|
|
L -= L[1]
|
|
L += md5(H.bioHolder.Uid)
|
|
src.fingerprints = list2params(L)
|
|
if(src.fingerprintslast != H.key)
|
|
src.fingerprintshidden += "Real name: [H.real_name], Key: [H.key]"
|
|
src.fingerprintslast = H.key
|
|
|
|
else
|
|
if(src.fingerprintslast != M.key)
|
|
src.fingerprintshidden += "Real name: [M.real_name], Key: [M.key]"
|
|
src.fingerprintslast = M.key
|
|
|
|
return
|
|
|
|
//This will looks stupid on objects larger than 32x32. Might have to write something for that later. -Keelin
|
|
/atom/proc/setTexture(var/texture = "damaged", var/blendMode = BLEND_MULTIPLY, var/key = "texture")
|
|
var/image/I = getTexturedImage(src, texture, blendMode)//, key)
|
|
if (!I)
|
|
return
|
|
src.UpdateOverlays(I, key)
|
|
return
|
|
|
|
/proc/getTexturedImage(var/atom/A, var/texture = "damaged", var/blendMode = BLEND_MULTIPLY)//, var/key = "texture")
|
|
if (!A)
|
|
return
|
|
var/icon/tex = null
|
|
|
|
//Try to find an appropriately sized icon.
|
|
if(istype(A, /atom/movable))
|
|
var/atom/movable/M = A
|
|
if(A.texture_size == 32 || ((M.bound_height == 32 && M.bound_width == 32) && !A.texture_size))
|
|
tex = icon('icons/effects/atom_textures_32.dmi', texture)
|
|
else if(A.texture_size == 64 || ((M.bound_height == 64 && M.bound_width == 64) && !A.texture_size))
|
|
tex = icon('icons/effects/atom_textures_64.dmi', texture)
|
|
else
|
|
tex = icon('icons/effects/atom_textures_32.dmi', texture)
|
|
else if (isicon(A))
|
|
var/icon/I = A
|
|
if(I.Height() > 32)
|
|
tex = icon('icons/effects/atom_textures_64.dmi', texture)
|
|
else
|
|
tex = icon('icons/effects/atom_textures_32.dmi', texture)
|
|
else
|
|
if(A.texture_size == 32)
|
|
tex = icon('icons/effects/atom_textures_32.dmi', texture)
|
|
else if(A.texture_size == 64)
|
|
tex = icon('icons/effects/atom_textures_64.dmi', texture)
|
|
else
|
|
tex = icon('icons/effects/atom_textures_32.dmi', texture)
|
|
|
|
var/icon/mask = null
|
|
mask = new(isicon(A) ? A : A.icon)
|
|
mask.MapColors(1,1,1, 1,1,1, 1,1,1, 1,1,1)
|
|
mask.Blend(tex, ICON_MULTIPLY)
|
|
//mask is now a cut-out of the texture shaped like the object.
|
|
var/image/finished = image(mask,"")
|
|
finished.blend_mode = blendMode
|
|
return finished
|
|
|
|
// WHAT THE ACTUAL FUCK IS THIS SHIT
|
|
// WHO THE FUCK WROTE THIS
|
|
/atom/proc/add_blood(mob/living/M as mob, var/amount = 5)
|
|
if (!( istype(M, /mob/living) ) || !M.blood_id)
|
|
return 0
|
|
if (!( src.flags ) & 256)
|
|
return
|
|
var/b_uid = "--unidentified substance--"
|
|
var/b_type = "--unidentified substance--"
|
|
if (M.bioHolder)
|
|
b_uid = M.bioHolder.Uid
|
|
b_type = M.bioHolder.bloodType
|
|
if (!( src.blood_DNA ))
|
|
if (istype(src, /obj/item))
|
|
var/datum/reagent/R = reagents_cache[M.blood_id]
|
|
var/obj/item/source2 = src
|
|
source2.icon_old = src.icon
|
|
var/icon/I = new /icon(src.icon, src.icon_state)
|
|
I.Blend(new /icon('icons/effects/blood.dmi', "thisisfuckingstupid"),ICON_ADD)
|
|
if (R)
|
|
I.Blend(rgb(R.fluid_r, R.fluid_g, R.fluid_b),ICON_MULTIPLY)
|
|
I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY)
|
|
I.Blend(new /icon(src.icon, src.icon_state),ICON_UNDERLAY)
|
|
src.icon = I
|
|
src.blood_DNA = b_uid
|
|
src.blood_type = b_type
|
|
else if (istype(src, /turf/simulated))
|
|
bleed(M, amount, 5)
|
|
else if (istype(src, /mob/living/carbon/human))
|
|
src.blood_DNA = b_uid
|
|
src.blood_type = b_type
|
|
else
|
|
return
|
|
else
|
|
var/list/L = params2list(src.blood_DNA)
|
|
L -= b_uid
|
|
while(L.len >= 6) // Increased from 3 (Convair880).
|
|
L -= L[1]
|
|
L += b_uid
|
|
src.blood_DNA = list2params(L)
|
|
return
|
|
|
|
// Was clean_blood. Reworked the proc to take care of other forensic evidence as well (Convair880).
|
|
/atom/proc/clean_forensic()
|
|
if (!src)
|
|
return
|
|
|
|
if (!( src.flags ) & 256)
|
|
return
|
|
|
|
// The first version accidently looped through everything for every atom. Consequently, cleaner grenades caused horrendous lag on my local server. Woops.
|
|
if (!ismob(src)) // Mobs are a special case.
|
|
if (istype(src, /obj/item) && (src.fingerprints || src.blood_DNA || src.blood_type))
|
|
src.fingerprints = null
|
|
src.blood_type = null
|
|
|
|
if (src.blood_DNA)
|
|
var/obj/item/CI = src
|
|
CI.blood_DNA = null
|
|
var/icon/SI = new /icon(CI.icon_old, CI.icon_state)
|
|
CI.icon = SI
|
|
|
|
else if (istype(src, /obj/decal/cleanable))
|
|
qdel(src)
|
|
|
|
else if (istype(src, /turf))
|
|
//src.overlays = null
|
|
for(var/obj/decal/cleanable/mess in get_turf(src))
|
|
qdel(mess)
|
|
|
|
else // Don't think it should clean doors and the like. Give the detective at least something to work with.
|
|
return
|
|
|
|
else
|
|
if (isobserver(src) || isintangible(src) || iswraith(src)) // Just in case.
|
|
return
|
|
|
|
if (ishuman(src))
|
|
var/mob/living/carbon/human/M = src
|
|
var/list/gear_to_clean = list(M.r_hand, M.l_hand, M.head, M.wear_mask, M.w_uniform, M.wear_suit, M.belt, M.gloves, M.glasses, M.shoes, M.wear_id, M.back)
|
|
for (var/obj/item/check in gear_to_clean)
|
|
if (check.fingerprints || check.blood_DNA || check.blood_type)
|
|
check.fingerprints = null
|
|
check.blood_type = null
|
|
if (check.blood_DNA)
|
|
check.blood_DNA = null
|
|
var/icon/WI = new /icon(check.icon_old, check.icon_state)
|
|
check.icon = WI
|
|
|
|
if (isnull(M.gloves)) // Can't clean your hands when wearing gloves.
|
|
M.blood_DNA = null
|
|
M.blood_type = null
|
|
|
|
M.fingerprints = null // Foreign fingerprints on the mob.
|
|
M.gunshot_residue = 0 // Only humans can have residue at the moment.
|
|
M.set_clothing_icon_dirty()
|
|
|
|
else
|
|
|
|
var/mob/living/L = src // Punching cyborgs does leave fingerprints for instance.
|
|
L.fingerprints = null
|
|
L.blood_DNA = null
|
|
L.blood_type = null
|
|
L.set_clothing_icon_dirty()
|
|
|
|
return
|
|
|
|
/atom/MouseDrop(atom/over_object as mob|obj|turf)
|
|
spawn( 0 )
|
|
if (istype(over_object, /atom))
|
|
if (usr.stat == 0)
|
|
//To stop ghostdrones dragging people anywhere
|
|
if (isghostdrone(usr) && ismob(src) && src != usr)
|
|
return
|
|
|
|
/* This was SUPPOSED to make the innerItem of items act on the mousedrop instead but it doesnt work for no reason
|
|
if (istype(src, /obj/item))
|
|
var/obj/item/W = src
|
|
if (W.useInnerItem && W.contents.len > 0)
|
|
target = pick(W.contents)
|
|
//world.log << "calling mousedrop_t on [over_object] with params: [src], [usr]"
|
|
*/
|
|
|
|
over_object.MouseDrop_T(src, usr)
|
|
else
|
|
if (istype(over_object, /obj/machinery)) // For cyborg docking stations (Convair880).
|
|
var/obj/machinery/M = over_object
|
|
if (M.allow_stunned_dragndrop == 1)
|
|
M.MouseDrop_T(src, usr)
|
|
return
|
|
..()
|
|
return
|
|
|
|
/atom/proc/relaymove()
|
|
return
|
|
|
|
/atom/proc/on_reagent_change(var/add = 0) // if the reagent container just had something added, add will be 1.
|
|
return
|
|
|
|
/atom/proc/Bumped(AM as mob|obj)
|
|
return
|
|
|
|
/atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes)
|
|
spawn( 0 )
|
|
if ((A && yes)) //wtf
|
|
A.last_bumped = world.timeofday
|
|
A.Bumped(src)
|
|
return
|
|
..()
|
|
return
|
|
|
|
// bullet_act called when anything is hit buy a projectile (bullet, tazer shot, laser, etc.)
|
|
// flag is projectile type, can be:
|
|
//PROJECTILE_TASER = 1 taser gun
|
|
//PROJECTILE_LASER = 2 laser gun
|
|
//PROJECTILE_BULLET = 3 traitor pistol
|
|
//PROJECTILE_PULSE = 4 pulse rifle
|
|
//PROJECTILE_BOLT = 5 crossbow
|
|
//PROJECTILE_WEAKBULLET = 6 detective's revolver
|
|
|
|
//Return an atom if you want to make the projectile's effects affect that instead.
|
|
|
|
/atom/proc/bullet_act(var/obj/projectile/P)
|
|
if(src.material) src.material.triggerOnAttacked(src, P.shooter, src, (ismob(P.shooter) ? P.shooter:equipped() : P.shooter))
|
|
for(var/atom/A in src)
|
|
if(A.material)
|
|
A.material.triggerOnAttacked(A, P.shooter, src, (ismob(P.shooter) ? P.shooter:equipped() : P.shooter))
|
|
return
|
|
|
|
|
|
// this handles RL_Lighting for luminous atoms and some child types override it for extra stuff
|
|
// like the 2x2 pod camera. fixes that bug where you go through a warp portal but your camera doesn't update
|
|
//
|
|
// there are lots of old places in the code that set loc directly.
|
|
// ignore them they'll be fixed later, please use this proc in the future
|
|
/atom/movable/proc/set_loc(var/newloc as turf|mob|obj in world)
|
|
if (loc == newloc)
|
|
return src
|
|
|
|
if (ismob(src)) // fuck haxploits
|
|
var/mob/SM = src
|
|
if (!(SM.client && SM.client.holder))
|
|
if (istype(newloc, /turf/unsimulated))
|
|
var/turf/unsimulated/T = newloc
|
|
if (T.density)
|
|
return
|
|
|
|
if (isturf(loc))
|
|
loc.Exited(src)
|
|
|
|
var/area/my_area = get_area(src)
|
|
var/area/new_area = get_area(newloc)
|
|
if(my_area != new_area && my_area)
|
|
my_area.Exited(src)
|
|
|
|
loc = newloc
|
|
|
|
if(my_area != new_area && new_area)
|
|
new_area.Entered(src)
|
|
|
|
if(isturf(newloc))
|
|
var/turf/nloc = newloc
|
|
nloc.Entered(src)
|
|
|
|
for(var/atom/movable/M in attached_objs)
|
|
M.set_loc(src.loc)
|
|
|
|
return src
|
|
|
|
// standardized damage procs
|
|
|
|
/atom/proc/damage_blunt(var/amount)
|
|
|
|
/atom/proc/damage_piercing(var/amount)
|
|
|
|
/atom/proc/damage_slashing(var/amount)
|
|
|
|
/atom/proc/damage_corrosive(var/amount)
|
|
|
|
/atom/proc/damage_electricity(var/amount)
|
|
|
|
/atom/proc/damage_radiation(var/amount)
|
|
|
|
/atom/proc/damage_heat(var/amount)
|
|
|
|
/atom/proc/damage_cold(var/amount) |