mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-09 08:10:15 +01:00
435 lines
13 KiB
Plaintext
435 lines
13 KiB
Plaintext
/atom
|
|
layer = 2
|
|
var/level = 2
|
|
var/flags = 0
|
|
var/list/fingerprints
|
|
var/list/fingerprintshidden
|
|
var/fingerprintslast = null
|
|
var/list/blood_DNA
|
|
var/last_bumped = 0
|
|
var/throwpass = 0
|
|
|
|
///Chemistry.
|
|
var/datum/reagents/reagents = null
|
|
|
|
//This atom's HUD (med/sec, etc) images. Associative list.
|
|
var/list/image/hud_list = list()
|
|
//HUD images that this atom can provide.
|
|
var/list/hud_possible
|
|
|
|
//var/chem_is_open_container = 0
|
|
// replaced by OPENCONTAINER flags and atom/proc/is_open_container()
|
|
///Chemistry.
|
|
var/allow_spin = 1
|
|
/atom/proc/onCentcom()
|
|
var/turf/T = get_turf(src)
|
|
if(!T)
|
|
return 0
|
|
|
|
if(T.z != ZLEVEL_CENTCOM)//if not, don't bother
|
|
return 0
|
|
|
|
//check for centcomm shuttles
|
|
for(var/centcom_shuttle in list("emergency", "pod1", "pod2", "pod3", "pod4", "ferry"))
|
|
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(centcom_shuttle)
|
|
if(T in M.areaInstance)
|
|
return 1
|
|
|
|
//finally check for centcom itself
|
|
return istype(T.loc,/area/centcom)
|
|
|
|
/atom/proc/throw_impact(atom/hit_atom)
|
|
if(istype(hit_atom,/mob/living))
|
|
var/mob/living/M = hit_atom
|
|
M.hitby(src)
|
|
|
|
else if(isobj(hit_atom))
|
|
var/obj/O = hit_atom
|
|
if(!O.anchored)
|
|
step(O, src.dir)
|
|
O.hitby(src)
|
|
|
|
else if(isturf(hit_atom))
|
|
var/turf/T = hit_atom
|
|
if(T.density)
|
|
spawn(2)
|
|
step(src, turn(src.dir, 180))
|
|
if(istype(src,/mob/living))
|
|
var/mob/living/M = src
|
|
M.take_organ_damage(20)
|
|
|
|
/atom/proc/attack_hulk(mob/living/carbon/human/hulk, do_attack_animation = 0)
|
|
if(do_attack_animation)
|
|
hulk.changeNext_move(CLICK_CD_MELEE)
|
|
add_logs(hulk, src, "punched", "hulk powers", admin=0)
|
|
hulk.do_attack_animation(src)
|
|
return
|
|
|
|
/atom/proc/CheckParts()
|
|
return
|
|
|
|
/atom/proc/assume_air(datum/gas_mixture/giver)
|
|
del(giver)
|
|
return null
|
|
|
|
/atom/proc/remove_air(amount)
|
|
return null
|
|
|
|
/atom/proc/return_air()
|
|
if(loc)
|
|
return loc.return_air()
|
|
else
|
|
return null
|
|
|
|
/atom/proc/check_eye(user as mob)
|
|
if (istype(user, /mob/living/silicon/ai)) // WHYYYY
|
|
return 1
|
|
return
|
|
|
|
/atom/proc/on_reagent_change()
|
|
return
|
|
|
|
/atom/proc/Bumped(AM as mob|obj)
|
|
return
|
|
|
|
// Convenience proc to see if a container is open for chemistry handling
|
|
// returns true if open
|
|
// false if closed
|
|
/atom/proc/is_open_container()
|
|
return flags & OPENCONTAINER
|
|
|
|
/*//Convenience proc to see whether a container can be accessed in a certain way.
|
|
|
|
proc/can_subract_container()
|
|
return flags & EXTRACT_CONTAINER
|
|
|
|
proc/can_add_container()
|
|
return flags & INSERT_CONTAINER
|
|
*/
|
|
|
|
|
|
/atom/proc/allow_drop()
|
|
return 1
|
|
|
|
/atom/proc/CheckExit()
|
|
return 1
|
|
|
|
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
|
|
return
|
|
|
|
/atom/proc/emp_act(var/severity)
|
|
return
|
|
|
|
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
|
|
. = P.on_hit(src, 0, def_zone)
|
|
|
|
/atom/proc/in_contents_of(container)//can take class or object instance as argument
|
|
if(ispath(container))
|
|
if(istype(src.loc, container))
|
|
return 1
|
|
else if(src in container)
|
|
return 1
|
|
return
|
|
|
|
/*
|
|
* atom/proc/search_contents_for(path,list/filter_path=null)
|
|
* Recursevly searches all atom contens (including contents contents and so on).
|
|
*
|
|
* ARGS: path - search atom contents for atoms of this type
|
|
* list/filter_path - if set, contents of atoms not of types in this list are excluded from search.
|
|
*
|
|
* RETURNS: list of found atoms
|
|
*/
|
|
|
|
/atom/proc/search_contents_for(path,list/filter_path=null)
|
|
var/list/found = list()
|
|
for(var/atom/A in src)
|
|
if(istype(A, path))
|
|
found += A
|
|
if(filter_path)
|
|
var/pass = 0
|
|
for(var/type in filter_path)
|
|
pass |= istype(A, type)
|
|
if(!pass)
|
|
continue
|
|
if(A.contents.len)
|
|
found += A.search_contents_for(path,filter_path)
|
|
return found
|
|
|
|
|
|
|
|
|
|
/*
|
|
Beam code by Gunbuddy
|
|
|
|
Beam() proc will only allow one beam to come from a source at a time. Attempting to call it more than
|
|
once at a time per source will cause graphical errors.
|
|
Also, the icon used for the beam will have to be vertical and 32x32.
|
|
The math involved assumes that the icon is vertical to begin with so unless you want to adjust the math,
|
|
its easier to just keep the beam vertical.
|
|
*/
|
|
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10)
|
|
//BeamTarget represents the target for the beam, basically just means the other end.
|
|
//Time is the duration to draw the beam
|
|
//Icon is obviously which icon to use for the beam, default is beam.dmi
|
|
//Icon_state is what icon state is used. Default is b_beam which is a blue beam.
|
|
//Maxdistance is the longest range the beam will persist before it gives up.
|
|
var/EndTime=world.time+time
|
|
while(BeamTarget&&world.time<EndTime&&get_dist(src,BeamTarget)<maxdistance&&z==BeamTarget.z)
|
|
//If the BeamTarget gets deleted, the time expires, or the BeamTarget gets out
|
|
//of range or to another z-level, then the beam will stop. Otherwise it will
|
|
//continue to draw.
|
|
|
|
dir=get_dir(src,BeamTarget) //Causes the source of the beam to rotate to continuosly face the BeamTarget.
|
|
|
|
for(var/obj/effect/overlay/beam/O in orange(10,src)) //This section erases the previously drawn beam because I found it was easier to
|
|
if(O.BeamSource==src) //just draw another instance of the beam instead of trying to manipulate all the
|
|
qdel(O) //pieces to a new orientation.
|
|
var/Angle=round(Get_Angle(src,BeamTarget))
|
|
var/icon/I=new(icon,icon_state)
|
|
I.Turn(Angle)
|
|
var/DX=(32*BeamTarget.x+BeamTarget.pixel_x)-(32*x+pixel_x)
|
|
var/DY=(32*BeamTarget.y+BeamTarget.pixel_y)-(32*y+pixel_y)
|
|
var/N=0
|
|
var/length=round(sqrt((DX)**2+(DY)**2))
|
|
for(N,N<length,N+=32)
|
|
var/obj/effect/overlay/beam/X=new(loc)
|
|
X.BeamSource=src
|
|
if(N+32>length)
|
|
var/icon/II=new(icon,icon_state)
|
|
II.DrawBox(null,1,(length-N),32,32)
|
|
II.Turn(Angle)
|
|
X.icon=II
|
|
else X.icon=I
|
|
var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32)
|
|
var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32)
|
|
if(DX==0) Pixel_x=0
|
|
if(DY==0) Pixel_y=0
|
|
if(Pixel_x>32)
|
|
for(var/a=0, a<=Pixel_x,a+=32)
|
|
X.x++
|
|
Pixel_x-=32
|
|
if(Pixel_x<-32)
|
|
for(var/a=0, a>=Pixel_x,a-=32)
|
|
X.x--
|
|
Pixel_x+=32
|
|
if(Pixel_y>32)
|
|
for(var/a=0, a<=Pixel_y,a+=32)
|
|
X.y++
|
|
Pixel_y-=32
|
|
if(Pixel_y<-32)
|
|
for(var/a=0, a>=Pixel_y,a-=32)
|
|
X.y--
|
|
Pixel_y+=32
|
|
X.pixel_x=Pixel_x
|
|
X.pixel_y=Pixel_y
|
|
sleep(3) //Changing this to a lower value will cause the beam to follow more smoothly with movement, but it will also be more laggy.
|
|
//I've found that 3 ticks provided a nice balance for my use.
|
|
for(var/obj/effect/overlay/beam/O in orange(10,src)) if(O.BeamSource==src) qdel(O)
|
|
|
|
/atom/proc/examine(mob/user)
|
|
//This reformat names to get a/an properly working on item descriptions when they are bloody
|
|
var/f_name = "\a [src]."
|
|
if(src.blood_DNA && !istype(src, /obj/effect/decal))
|
|
if(gender == PLURAL)
|
|
f_name = "some "
|
|
else
|
|
f_name = "a "
|
|
f_name += "<span class='danger'>blood-stained</span> [name]!"
|
|
|
|
user << "\icon[src] That's [f_name]"
|
|
|
|
if(desc)
|
|
user << desc
|
|
// *****RM
|
|
//user << "[name]: Dn:[density] dir:[dir] cont:[contents] icon:[icon] is:[icon_state] loc:[loc]"
|
|
|
|
if(reagents && is_open_container()) //is_open_container() isn't really the right proc for this, but w/e
|
|
user << "It contains:"
|
|
if(reagents.reagent_list.len)
|
|
for(var/datum/reagent/R in reagents.reagent_list)
|
|
user << "[R.volume] units of [R.name]"
|
|
else
|
|
user << "Nothing."
|
|
|
|
/atom/proc/relaymove()
|
|
return
|
|
|
|
/atom/proc/contents_explosion(severity, target)
|
|
for(var/atom/A in contents)
|
|
A.ex_act(severity, target)
|
|
|
|
/atom/proc/ex_act(severity, target)
|
|
contents_explosion(severity, target)
|
|
|
|
/atom/proc/blob_act()
|
|
return
|
|
|
|
/atom/proc/fire_act()
|
|
return
|
|
|
|
/atom/proc/hitby(atom/movable/AM as mob|obj)
|
|
return
|
|
|
|
|
|
var/list/blood_splatter_icons = list()
|
|
|
|
/atom/proc/blood_splatter_index()
|
|
return "\ref[initial(icon)]-[initial(icon_state)]"
|
|
|
|
/atom/proc/add_blood_list(mob/living/carbon/M)
|
|
// Returns 0 if we have that blood already
|
|
if(!istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it.
|
|
blood_DNA = list()
|
|
//if this blood isn't already in the list, add it
|
|
if(blood_DNA[M.dna.unique_enzymes])
|
|
return 0 //already bloodied with this blood. Cannot add more.
|
|
blood_DNA[M.dna.unique_enzymes] = M.dna.blood_type
|
|
return 1
|
|
|
|
//returns 1 if made bloody, returns 0 otherwise
|
|
/atom/proc/add_blood(mob/living/carbon/M)
|
|
if(ishuman(M) && M.dna)
|
|
var/mob/living/carbon/human/H = M
|
|
if(NOBLOOD in H.dna.species.specflags)
|
|
return 0
|
|
if(rejects_blood())
|
|
return 0
|
|
if(!istype(M))
|
|
return 0
|
|
if(!check_dna_integrity(M)) //check dna is valid and create/setup if necessary
|
|
return 0 //no dna!
|
|
return 1
|
|
|
|
/obj/add_blood(mob/living/carbon/M)
|
|
if(..() == 0)
|
|
return 0
|
|
return add_blood_list(M)
|
|
|
|
/obj/item/add_blood(mob/living/carbon/M)
|
|
var/blood_count = blood_DNA == null ? 0 : blood_DNA.len
|
|
if(..() == 0)
|
|
return 0
|
|
//apply the blood-splatter overlay if it isn't already in there
|
|
if(!blood_count && initial(icon) && initial(icon_state))
|
|
//try to find a pre-processed blood-splatter. otherwise, make a new one
|
|
var/index = blood_splatter_index()
|
|
var/icon/blood_splatter_icon = blood_splatter_icons[index]
|
|
if(!blood_splatter_icon)
|
|
blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
|
|
blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
|
|
blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
|
|
blood_splatter_icon = fcopy_rsc(blood_splatter_icon)
|
|
blood_splatter_icons[index] = blood_splatter_icon
|
|
overlays += blood_splatter_icon
|
|
return 1 //we applied blood to the item
|
|
|
|
/obj/item/clothing/gloves/add_blood(mob/living/carbon/M)
|
|
if(..() == 0)
|
|
return 0
|
|
transfer_blood = rand(2, 4)
|
|
bloody_hands_mob = M
|
|
return 1
|
|
|
|
/turf/simulated/add_blood(mob/living/carbon/human/M)
|
|
if(..() == 0)
|
|
return 0
|
|
|
|
var/obj/effect/decal/cleanable/blood/B = locate() in contents //check for existing blood splatter
|
|
if(!B)
|
|
blood_splatter(src,M.get_blood(M.vessel),1)
|
|
B = locate(/obj/effect/decal/cleanable/blood) in contents
|
|
B.add_blood_list(M)
|
|
return 1 //we bloodied the floor
|
|
|
|
/mob/living/carbon/human/add_blood(mob/living/carbon/M)
|
|
if(..() == 0)
|
|
return 0
|
|
add_blood_list(M)
|
|
bloody_hands = rand(2, 4)
|
|
bloody_hands_mob = M
|
|
update_inv_gloves() //handles bloody hands overlays and updating
|
|
return 1 //we applied blood to the item
|
|
|
|
/atom/proc/rejects_blood()
|
|
return 0
|
|
|
|
/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0)
|
|
if( istype(src, /turf/simulated) )
|
|
var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src)
|
|
if(M.reagents)
|
|
M.reagents.trans_to(this, M.reagents.total_volume / 10)
|
|
// Make toxins vomit look different
|
|
if(toxvomit)
|
|
this.icon_state = "vomittox_[pick(1,4)]"
|
|
|
|
/*for(var/datum/disease/D in M.viruses)
|
|
var/datum/disease/newDisease = D.Copy(1)
|
|
this.viruses += newDisease
|
|
newDisease.holder = this*/
|
|
|
|
// Only adds blood on the floor -- Skie
|
|
/atom/proc/add_blood_floor(mob/living/carbon/M as mob)
|
|
if(istype(src, /turf/simulated))
|
|
if(check_dna_integrity(M)) //mobs with dna = (monkeys + humans at time of writing)
|
|
var/obj/effect/decal/cleanable/blood/B = locate() in contents
|
|
if(!B)
|
|
blood_splatter(src,M,1)
|
|
B = locate(/obj/effect/decal/cleanable/blood) in contents
|
|
B.blood_DNA[M.dna.unique_enzymes] = M.dna.blood_type
|
|
else if(istype(M, /mob/living/carbon/alien))
|
|
var/obj/effect/decal/cleanable/xenoblood/B = locate() in contents
|
|
if(!B) B = new(src)
|
|
B.blood_DNA["UNKNOWN BLOOD"] = "X*"
|
|
else if(istype(M, /mob/living/silicon/robot))
|
|
var/obj/effect/decal/cleanable/oil/B = locate() in contents
|
|
if(!B) B = new(src)
|
|
|
|
/atom/proc/clean_blood()
|
|
if(istype(blood_DNA, /list))
|
|
blood_DNA = null
|
|
return 1
|
|
|
|
|
|
/atom/proc/get_global_map_pos()
|
|
if(!islist(global_map) || isemptylist(global_map)) return
|
|
var/cur_x = null
|
|
var/cur_y = null
|
|
var/list/y_arr = null
|
|
for(cur_x=1,cur_x<=global_map.len,cur_x++)
|
|
y_arr = global_map[cur_x]
|
|
cur_y = y_arr.Find(src.z)
|
|
if(cur_y)
|
|
break
|
|
// world << "X = [cur_x]; Y = [cur_y]"
|
|
if(cur_x && cur_y)
|
|
return list("x"=cur_x,"y"=cur_y)
|
|
else
|
|
return 0
|
|
|
|
/atom/proc/isinspace()
|
|
if(istype(get_turf(src), /turf/space))
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
/atom/proc/handle_fall()
|
|
return
|
|
|
|
/atom/proc/handle_slip()
|
|
return
|
|
/atom/proc/singularity_act()
|
|
return
|
|
|
|
/atom/proc/singularity_pull()
|
|
return
|
|
|
|
/atom/proc/acid_act(var/acidpwr, var/toxpwr, var/acid_volume)
|
|
return
|
|
|
|
/atom/proc/emag_act()
|
|
return
|
|
|
|
/atom/proc/narsie_act()
|
|
return
|