Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into upstream-merge-27675

This commit is contained in:
LetterJay
2017-05-30 14:14:25 -05:00
194 changed files with 129384 additions and 9238 deletions
+2 -1
View File
@@ -86,6 +86,7 @@
/area/lavaland
icon_state = "mining"
has_gravity = 1
flags = NONE
/area/lavaland/surface
name = "Lavaland"
@@ -123,4 +124,4 @@
icon_state = "danger"
/area/lavaland/surface/outdoors/explored
name = "Lavaland Labor Camp"
name = "Lavaland Labor Camp"
+13
View File
@@ -5,6 +5,7 @@
icon_state = "away"
has_gravity = 1
hidden = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/ruin/unpowered
@@ -199,3 +200,15 @@
/area/ruin/abandonedzoo
name = "Abandoned Zoo"
icon_state = "green"
//Xeno Nest
/area/ruin/xenonest
name = "The Hive"
always_unpowered = 1
power_environ = 0
power_equip = 0
power_light = 0
poweralm = 0
+3
View File
@@ -104,6 +104,9 @@
return ..()
/atom/proc/handle_ricochet(obj/item/projectile/P)
return
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
return (!density || !height)
+1 -1
View File
@@ -236,7 +236,7 @@
/obj/item/weapon/antag_spawner/slaughter_demon/attack_self(mob/user)
if(user.z != 1)
if(user.z != ZLEVEL_STATION)
to_chat(user, "<span class='notice'>You should probably wait until you reach the station.</span>")
return
if(used)
+2 -2
View File
@@ -233,11 +233,11 @@
if(ishuman(M))
if(!M.stat)
surviving_humans++
if(M.z == 2)
if(M.z == ZLEVEL_CENTCOM)
escaped_humans++
if(!M.stat)
surviving_total++
if(M.z == 2)
if(M.z == ZLEVEL_CENTCOM)
escaped_total++
-2
View File
@@ -53,7 +53,6 @@
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
@@ -91,7 +90,6 @@
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
+3 -2
View File
@@ -326,6 +326,7 @@
if(spawn_msg)
to_chat(user, spawn_msg)
/datum/gang_item/equipment/wetwork_boots
name = "Wetwork boots"
id = "wetwork"
@@ -412,7 +413,7 @@
/datum/gang_item/equipment/dominator/purchase(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
var/area/usrarea = get_area(user.loc)
var/usrturf = get_turf(user.loc)
if(initial(usrarea.name) == "Space" || isspaceturf(usrturf) || usr.z != 1)
if(initial(usrarea.name) == "Space" || isspaceturf(usrturf) || usr.z != ZLEVEL_STATION)
to_chat(user, "<span class='warning'>You can only use this on the station!</span>")
return FALSE
@@ -422,7 +423,7 @@
return FALSE
if(dominator_excessive_walls(user))
to_chat(user, "span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires a sizable open space within three standard units so that walls do not interfere with the signal.</span>")
to_chat(user, "<span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires a sizable open space within three standard units so that walls do not interfere with the signal.</span>")
return FALSE
if(!(usrarea.type in gang.territory|gang.territory_new))
+2 -2
View File
@@ -194,7 +194,7 @@
return 0
var/turf/userturf = get_turf(user)
if(userturf.z != 1) //Shuttle can only be recalled while on station
if(userturf.z != ZLEVEL_STATION) //Shuttle can only be recalled while on station
to_chat(user, "<span class='warning'>\icon[src]Error: Device out of range of station communication arrays.</span>")
recalling = 0
return 0
@@ -212,7 +212,7 @@
log_game("[key_name(user)] has tried to recall the shuttle with a gangtool.")
message_admins("[key_name_admin(user)] has tried to recall the shuttle with a gangtool.", 1)
userturf = get_turf(user)
if(userturf.z == 1) //Check one more time that they are on station.
if(userturf.z == ZLEVEL_STATION) //Check one more time that they are on station.
if(SSshuttle.cancelEvac(user))
gang.recalls -= 1
return 1
@@ -70,12 +70,12 @@
origin.vest_mode_action.Remove(C)
origin.vest_disguise_action.Remove(C)
origin.set_droppoint_action.Remove(C)
remote_eye.eye_user = null
C.reset_perspective(null)
if(C.client)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
@@ -181,6 +181,7 @@
to_chat(H, "<span class='warning'>You feel intensely watched.</span>")
sleep(5)
to_chat(H, "<span class='warning'><b>Your mind snaps!</b></span>")
to_chat(H, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
var/objtype = pick(subtypesof(/datum/objective/abductee/))
var/datum/objective/abductee/O = new objtype()
SSticker.mode.abductees += H.mind
@@ -15,7 +15,7 @@
var/icon_stun = "revenant_stun"
var/icon_drain = "revenant_draining"
var/stasis = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
health = INFINITY //Revenants don't use health, they use essence instead
maxHealth = INFINITY
@@ -102,7 +102,7 @@
if(unreveal_time && world.time >= unreveal_time)
unreveal_time = 0
revealed = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
to_chat(src, "<span class='revenboldnotice'>You are once more concealed.</span>")
if(unstun_time && world.time >= unstun_time)
@@ -222,7 +222,7 @@
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
R.revenant = src
invisibility = INVISIBILITY_ABSTRACT
invisibility = INVISIBILITY_ABSTRACT
revealed = FALSE
ghostize(0)//Don't re-enter invisible corpse
return
@@ -236,7 +236,7 @@
return
revealed = TRUE
invisibility = 0
incorporeal_move = 0
incorporeal_move = FALSE
if(!unreveal_time)
to_chat(src, "<span class='revendanger'>You have been revealed!</span>")
unreveal_time = world.time + time
@@ -309,12 +309,12 @@
/mob/living/simple_animal/revenant/proc/death_reset()
revealed = FALSE
unreveal_time = 0
unreveal_time = 0
notransform = 0
unstun_time = 0
inhibited = FALSE
draining = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
alpha=255
stasis = FALSE
+28 -7
View File
@@ -1,6 +1,8 @@
#define PINPOINTER_MINIMUM_RANGE 15
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
#define PINPOINTER_PING_TIME 40
#define PROB_ACTUAL_TRAITOR 20
#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent"
/datum/game_mode/traitor/internal_affairs
name = "Internal Affairs"
@@ -171,7 +173,10 @@
if(!objective.check_completion())
traitored = FALSE
return
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
if(owner.special_role == TRAITOR_AGENT_ROLE)
to_chat(owner.current,"<span class='userdanger'> All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. </span>")
else
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
replace_escape_objective(owner)
@@ -194,7 +199,10 @@
if(objective.stolen)
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
if(traitored)
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
if(owner.special_role == TRAITOR_AGENT_ROLE)
fail_msg += "<span class='userdanger'> You no longer have permission to die. </span>"
else
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
reinstate_escape_objective(owner)
traitored = FALSE
to_chat(owner.current, fail_msg)
@@ -238,6 +246,10 @@
state.add_steal_targets_timer()
if(!issilicon(traitor.current))
give_pinpointer(traitor)
//Optional traitor objective
if(prob(PROB_ACTUAL_TRAITOR))
traitor.special_role = TRAITOR_AGENT_ROLE
forge_single_objective(traitor)
else
..() // Give them standard objectives.
@@ -289,11 +301,18 @@
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
if(traitor.special_role == TRAITOR_AGENT_ROLE)
to_chat(traitor.current, "<span class='userdanger'>You are the [TRAITOR_AGENT_ROLE].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</font></B>")
to_chat(traitor.current, "<span class='userdanger'> You have been provided with a standard uplink to accomplish your task. </span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
else
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
traitor.announce_objectives()
@@ -301,6 +320,8 @@
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
return
#undef PROB_ACTUAL_TRAITOR
#undef PINPOINTER_EXTRA_RANDOM_RANGE
#undef PINPOINTER_MINIMUM_RANGE
#undef PINPOINTER_PING_TIME
+55 -51
View File
@@ -85,40 +85,65 @@
character.make_Traitor()
/datum/game_mode/proc/forge_single_objective(datum/mind/traitor) //Returns how many objectives are added
.=1
if(issilicon(traitor.current))
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = traitor
traitor.objectives += block_objective
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = traitor
traitor.objectives += purge_objective
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = traitor
traitor.objectives += robot_objective
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = traitor
traitor.objectives += yandere_one
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = traitor
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
traitor.objectives += yandere_two
.=2
else
if(prob(50))
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = traitor
destroy_objective.find_target()
traitor.objectives += destroy_objective
else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
else
var/datum/objective/steal/steal_objective = new
steal_objective.owner = traitor
steal_objective.find_target()
traitor.objectives += steal_objective
/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor)
if(issilicon(traitor.current))
var/objective_count = 0
if(prob(30))
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = traitor
traitor.objectives += block_objective
objective_count++
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = traitor
traitor.objectives += purge_objective
objective_count++
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = traitor
traitor.objectives += robot_objective
objective_count++
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = traitor
traitor.objectives += yandere_one
yandere_one.find_target()
objective_count++
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = traitor
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
traitor.objectives += yandere_two
objective_count++
objective_count+=forge_single_objective(traitor)
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
var/datum/objective/assassinate/kill_objective = new
@@ -142,29 +167,8 @@
assign_exchange_role(exchange_red)
assign_exchange_role(exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/list/active_ais = active_ais()
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
if(prob(50))
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = traitor
destroy_objective.find_target()
traitor.objectives += destroy_objective
else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
else
var/datum/objective/steal/steal_objective = new
steal_objective.owner = traitor
steal_objective.find_target()
traitor.objectives += steal_objective
forge_single_objective(traitor)
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in traitor.objectives))
+14 -8
View File
@@ -44,8 +44,8 @@
"corazone", // prevents cardiac arrest damage
"mimesbane") // stops them gasping from lack of air.
/obj/machinery/clonepod/New()
..()
/obj/machinery/clonepod/Initialize()
. = ..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
B.apply_default_parts(src)
@@ -358,8 +358,12 @@
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/mob/living/mob_occupant = occupant
var/turf/T = get_turf(src)
if(mess) //Clean that mess and dump those gibs!
for(var/obj/fl in unattached_flesh)
fl.forceMove(T)
unattached_flesh.Cut()
mess = FALSE
new /obj/effect/gibspawner/generic(loc)
audible_message("<span class='italics'>You hear a splat.</span>")
@@ -375,10 +379,12 @@
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
mob_occupant.flash_act()
var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
for(var/fl in unattached_flesh)
qdel(fl)
unattached_flesh.Cut()
occupant = null
@@ -389,8 +395,7 @@
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
for(var/obj/item/O in unattached_flesh)
qdel(O)
maim_clone(mob_occupant) //Remove every bit that's grown back so far to drop later, also destroys bits that haven't grown yet
icon_state = "pod_g"
if(mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
@@ -450,9 +455,10 @@
var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
for(var/zone in zones)
var/obj/item/bodypart/BP = H.get_bodypart(zone)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
if(BP)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
for(var/o in H.internal_organs)
var/obj/item/organ/organ = o
@@ -178,7 +178,7 @@
/obj/item/weapon/circuitboard/computer/xenobiology
name = "circuit board (Xenobiology Console)"
build_path = /obj/machinery/computer/camera_advanced/xenobio
origin_tech = "programming=3;bio=3"
origin_tech = "programming=3;biotech=3"
/obj/item/weapon/circuitboard/computer/base_construction
name = "circuit board (Aux Mining Base Construction Console)"
build_path = /obj/machinery/computer/camera_advanced/base_construction
@@ -151,13 +151,13 @@ obj/machinery/computer/camera_advanced/attack_ai(mob/user)
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
remote_eye.origin.current_user = null
remote_eye.origin.jump_action.Remove(C)
remote_eye.eye_user = null
if(C.client)
C.reset_perspective(null)
if(remote_eye.visible_icon)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
@@ -54,7 +54,7 @@
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return
if (src.z > ZLEVEL_CENTCOM) //Can only use on centcom and SS13
if (z != ZLEVEL_STATION && z != ZLEVEL_CENTCOM) //Can only use on centcom and SS13
to_chat(usr, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
usr.set_machine(src)
+1 -1
View File
@@ -317,7 +317,7 @@
/obj/machinery/disco/proc/dance(var/mob/living/M) //Show your moves
set waitfor = FALSE
switch(rand(0,9))
if(0 to 1)
dance2(M)
+10 -14
View File
@@ -97,7 +97,14 @@
var/static/list/airlock_overlays = list()
/obj/machinery/door/airlock/Initialize()
..()
. = ..()
if (cyclelinkeddir)
cyclelinkairlock()
if(frequency)
set_frequency(frequency)
update_icon()
wires = new /datum/wires/airlock(src)
if(src.closeOtherId != null)
spawn (5)
@@ -120,14 +127,6 @@
diag_hud.add_to_hud(src)
diag_hud_set_electrified()
/obj/machinery/door/airlock/Initialize()
..()
if (cyclelinkeddir)
cyclelinkairlock()
if(frequency)
set_frequency(frequency)
update_icon()
/obj/machinery/door/airlock/proc/cyclelinkairlock()
if (cyclelinkedairlock)
cyclelinkedairlock.cyclelinkedairlock = null
@@ -199,14 +198,11 @@
qdel(src)
/obj/machinery/door/airlock/Destroy()
qdel(wires)
wires = null
QDEL_NULL(wires)
if(charge)
qdel(charge)
charge = null
if(electronics)
qdel(electronics)
electronics = null
QDEL_NULL(electronics)
if (cyclelinkedairlock)
if (cyclelinkedairlock.cyclelinkedairlock == src)
cyclelinkedairlock.cyclelinkedairlock = null
+11 -1
View File
@@ -51,7 +51,7 @@ Possible to do for anyone motivated enough:
var/static/list/holopads = list()
/obj/machinery/holopad/Initialize()
..()
. = ..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/holopad(null)
B.apply_default_parts(src)
holopads += src
@@ -112,6 +112,10 @@ Possible to do for anyone motivated enough:
return ..()
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
if(isAI(user))
hangup_all_calls()
return
if(!CheckCallClose())
interact(user)
@@ -157,6 +161,12 @@ Possible to do for anyone motivated enough:
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
//Stop ringing the AI!!
/obj/machinery/holopad/proc/hangup_all_calls()
for(var/I in holo_calls)
var/datum/holocall/HC = I
HC.Disconnect(src)
/obj/machinery/holopad/Topic(href, href_list)
if(..() || isAI(usr))
return
+8 -1
View File
@@ -632,7 +632,14 @@ GLOBAL_LIST_EMPTY(PDAs)
L = get(src, /mob/living/silicon)
if(L && L.stat != UNCONSCIOUS)
to_chat(L, "\icon[src] <b>Message from [source.owner] ([source.ownjob]), </b>\"[msg.message]\"[msg.get_photo_ref()] (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[source]'>Reply</a>)")
var/hrefstart
var/hrefend
if (isAI(L))
hrefstart = "<a href='?src=\ref[L];track=[html_encode(source.owner)]'>"
hrefend = "</a>"
to_chat(L, "\icon[src.icon] <b>Message from [hrefstart][source.owner] ([source.ownjob])[hrefend], </b>\"[msg.message]\"[msg.get_photo_ref()] (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[source]'>Reply</a>)")
update_icon()
add_overlay(icon_alert)
+8 -9
View File
@@ -10,15 +10,14 @@
resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE
/obj/item/device/paicard/Initialize()
..()
SSpai.pai_card_list += src
add_overlay("pai-off")
return ..()
/obj/item/device/paicard/Destroy()
//Will stop people throwing friend pAIs into the singularity so they can respawn
SSpai.pai_card_list -= src
if(!isnull(pai))
pai.death(0)
QDEL_NULL(pai)
return ..()
/obj/item/device/paicard/attack_self(mob/user)
@@ -26,9 +25,9 @@
return
user.set_machine(src)
var/dat = "<TT><B>Personal AI Device</B><BR>"
if(pai && (!pai.master_dna || !pai.master))
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
if(pai)
if(!pai.master_dna || !pai.master)
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
dat += "Installed Personality: [pai.name]<br>"
dat += "Prime directive: <br>[pai.laws.zeroth]<br>"
for(var/slaws in pai.laws.supplied)
@@ -86,7 +85,7 @@
to_chat(pai, "<span class='danger'>Byte by byte you lose your sense of self.</span>")
to_chat(pai, "<span class='userdanger'>Your mental faculties leave you.</span>")
to_chat(pai, "<span class='rose'>oblivion... </span>")
pai.death(0)
removePersonality()
if(href_list["wires"])
var/wire = text2num(href_list["wires"])
if(pai.radio)
@@ -119,9 +118,9 @@
audible_message("\The [src] plays a cheerful startup noise!")
/obj/item/device/paicard/proc/removePersonality()
src.pai = null
src.cut_overlays()
src.add_overlay("pai-off")
QDEL_NULL(pai)
cut_overlays()
add_overlay("pai-off")
/obj/item/device/paicard/proc/setEmotion(emotion)
if(pai)
+16 -11
View File
@@ -504,6 +504,8 @@
S.change_head_color(color2)
dropped = TRUE
#define PKBORG_DAMPEN_CYCLE_DELAY 20
//Peacekeeper Cyborg Projectile Dampenening Field
/obj/item/borg/projectile_dampen
name = "Hyperkinetic Dampening projector"
@@ -526,6 +528,7 @@
var/image/projectile_effect
var/field_radius = 3
var/active = FALSE
var/cycle_delay = 0
/obj/item/borg/projectile_dampen/debug
maxenergy = 50000
@@ -545,29 +548,31 @@
return ..()
/obj/item/borg/projectile_dampen/attack_self(mob/user)
if(!istype(dampening_field))
activate_field()
active = TRUE
if(cycle_delay > world.time)
to_chat(user, "<span class='boldwarning'>\the [src] is still recycling its projectors!</span>")
return
cycle_delay = world.time + PKBORG_DAMPEN_CYCLE_DELAY
active = !active
if(active)
activate_field(user)
else
deactivate_field()
active = FALSE
update_icon()
to_chat(user, "<span class='boldnotice'>You [active? "activate":"deactivate"] the [src].</span>")
/obj/item/borg/projectile_dampen/update_icon()
. = ..()
icon_state = "[initial(icon_state)][active]"
/obj/item/borg/projectile_dampen/proc/activate_field()
if(!istype(dampening_field))
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
update_icon()
if(istype(dampening_field))
QDEL_NULL(dampening_field)
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
/obj/item/borg/projectile_dampen/proc/deactivate_field()
QDEL_NULL(dampening_field)
visible_message("<span class='warning'>The [src] shuts off!</span>")
for(var/obj/item/projectile/P in tracked)
visible_message("<span class='warning'>\The [src] shuts off!</span>")
for(var/P in tracked)
restore_projectile(P)
update_icon()
/obj/item/borg/projectile_dampen/dropped()
. = ..()
@@ -83,6 +83,14 @@
var/list/access = list()
var/registered_name = null // The name registered_name on the card
var/assignment = null
var/access_txt // mapping aid
/obj/item/weapon/card/id/Initialize(mapload)
. = ..()
if(mapload && access_txt)
access = text2access(access_txt)
/obj/item/weapon/card/id/attack_self(mob/user)
user.visible_message("<span class='notice'>[user] shows you: \icon[src] [src.name].</span>", \
@@ -54,10 +54,10 @@
var/obj/effect/chrono_field/field = null
var/turf/startpos = null
/obj/item/weapon/gun/energy/chrono_gun/New(var/obj/item/weapon/chrono_eraser/T)
/obj/item/weapon/gun/energy/chrono_gun/Initialize()
. = ..()
if(istype(T))
TED = T
if(istype(loc, /obj/item/weapon/chrono_eraser))
TED = loc
else //admin must have spawned it
TED = new(src.loc)
qdel(src)
@@ -622,6 +622,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
icon = 'icons/obj/clothing/masks.dmi'
icon_state = null
item_state = null
w_class = WEIGHT_CLASS_TINY
var/chem_volume = 100
var/vapetime = 0 //this so it won't puff out clouds every tick
var/screw = 0 // kinky
@@ -633,8 +634,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return (TOXLOSS|OXYLOSS)
/obj/item/clothing/mask/vape/New(loc, var/param_color = null)
..()
/obj/item/clothing/mask/vape/Initialize(mapload, param_color)
. = ..()
create_reagents(chem_volume)
reagents.set_reacting(FALSE) // so it doesn't react until you light it
reagents.add_reagent("nicotine", 50)
+8 -8
View File
@@ -23,14 +23,14 @@
var/combat = 0 //can we revive through space suits?
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
/obj/item/weapon/defibrillator/New() //starts without a cell for rnd
..()
/obj/item/weapon/defibrillator/Initialize() //starts without a cell for rnd
. = ..()
paddles = make_paddles()
update_icon()
return
/obj/item/weapon/defibrillator/loaded/New() //starts with hicap
..()
/obj/item/weapon/defibrillator/loaded/Initialize() //starts with hicap
. = ..()
paddles = make_paddles()
bcell = new(src)
update_icon()
@@ -237,8 +237,8 @@
if(slot == user.getBeltSlot())
return 1
/obj/item/weapon/defibrillator/compact/loaded/New()
..()
/obj/item/weapon/defibrillator/compact/loaded/Initialize()
. = ..()
paddles = make_paddles()
bcell = new(src)
update_icon()
@@ -249,8 +249,8 @@
combat = 1
safety = 0
/obj/item/weapon/defibrillator/compact/combat/loaded/New()
..()
/obj/item/weapon/defibrillator/compact/combat/loaded/Initialize()
. = ..()
paddles = make_paddles()
bcell = new /obj/item/weapon/stock_parts/cell/infinite(src)
update_icon()
@@ -235,7 +235,7 @@
to_chat(user, "<span class='notice'>You start planting the bomb...</span>")
if(do_after(user, 50, target = AM))
if(do_after(user, 30, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
+3 -1
View File
@@ -65,6 +65,7 @@
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP_ACCURATE
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 50)
var/bayonet = FALSE //Can this be attached to a gun?
/obj/item/weapon/kitchen/knife/attack(mob/living/carbon/M, mob/living/carbon/user)
if(user.zone_selected == "eyes")
@@ -107,7 +108,7 @@
throwforce = 20
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
bayonet = TRUE
/obj/item/weapon/kitchen/knife/combat/survival
name = "survival knife"
@@ -115,6 +116,7 @@
desc = "A hunting grade survival knife."
force = 15
throwforce = 15
bayonet = TRUE
/obj/item/weapon/kitchen/knife/combat/bone
name = "bone dagger"
@@ -270,4 +270,4 @@
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/process()
if(++charge_tick >= charge_ticks)
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie, charge_amount)
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie/cream, charge_amount)
+6 -8
View File
@@ -21,10 +21,9 @@
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (FIRELOSS)
/obj/item/weapon/melee/baton/New()
..()
/obj/item/weapon/melee/baton/Initialize()
. = ..()
update_icon()
return
/obj/item/weapon/melee/baton/throw_impact(atom/hit_atom)
..()
@@ -32,10 +31,9 @@
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
baton_stun(hit_atom)
/obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed.
..()
/obj/item/weapon/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
bcell = new(src)
update_icon()
. = ..()
/obj/item/weapon/melee/baton/proc/deductcharge(chrgdeductamt)
if(bcell)
@@ -188,8 +186,8 @@
slot_flags = SLOT_BACK
var/obj/item/device/assembly/igniter/sparkler = 0
/obj/item/weapon/melee/baton/cattleprod/New()
..()
/obj/item/weapon/melee/baton/cattleprod/Initialize()
. = ..()
sparkler = new (src)
/obj/item/weapon/melee/baton/cattleprod/baton_stun()
@@ -140,7 +140,7 @@
item_state = "plasmaman_tank_belt"
slot_flags = SLOT_BELT
force = 5
volume = 3
volume = 6
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
/obj/item/weapon/tank/internals/plasmaman/belt/full/New()
+2 -2
View File
@@ -5,7 +5,7 @@
/obj/structure/easel
name = "easel"
desc = "only for the finest of art!"
desc = "Only for the finest of art!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "easel"
density = 1
@@ -49,7 +49,7 @@ GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES))
/obj/item/weapon/canvas
name = "canvas"
desc = "draw out your soul on this canvas!"
desc = "Draw out your soul on this canvas!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "11x11"
resistance_flags = FLAMMABLE
@@ -161,7 +161,16 @@
anchored = 0
buildstacktype = /obj/item/stack/sheet/mineral/wood
buildstackamount = 10
var/mob/living/owner = null
/obj/structure/bed/dogbed/proc/update_owner(mob/living/M)
owner = M
name = "[M]'s bed"
desc = "[M]'s bed! Looks comfy."
/obj/structure/bed/dogbed/buckle_mob(mob/living/M, force, check_loc)
. = ..()
update_owner(M)
/obj/structure/bed/alien
name = "resting contraption"
+10 -10
View File
@@ -146,49 +146,49 @@
/obj/structure/sign/biohazard
name = "\improper BIOHAZARD"
desc = "A warning sign which reads 'BIOHAZARD'"
desc = "A warning sign which reads 'BIOHAZARD'."
icon_state = "bio"
/obj/structure/sign/electricshock
name = "\improper HIGH VOLTAGE"
desc = "A warning sign which reads 'HIGH VOLTAGE'"
desc = "A warning sign which reads 'HIGH VOLTAGE'."
icon_state = "shock"
/obj/structure/sign/examroom
name = "\improper EXAM ROOM"
desc = "A guidance sign which reads 'EXAM ROOM'"
desc = "A guidance sign which reads 'EXAM ROOM'."
icon_state = "examroom"
/obj/structure/sign/vacuum
name = "\improper HARD VACUUM AHEAD"
desc = "A warning sign which reads 'HARD VACUUM AHEAD'"
desc = "A warning sign which reads 'HARD VACUUM AHEAD'."
icon_state = "space"
/obj/structure/sign/deathsposal
name = "\improper DISPOSAL: LEADS TO SPACE"
desc = "A warning sign which reads 'DISPOSAL: LEADS TO SPACE'"
desc = "A warning sign which reads 'DISPOSAL: LEADS TO SPACE'."
icon_state = "deathsposal"
/obj/structure/sign/pods
name = "\improper ESCAPE PODS"
desc = "A warning sign which reads 'ESCAPE PODS'"
desc = "A warning sign which reads 'ESCAPE PODS'."
icon_state = "pods"
/obj/structure/sign/fire
name = "\improper DANGER: FIRE"
desc = "A warning sign which reads 'DANGER: FIRE'"
desc = "A warning sign which reads 'DANGER: FIRE'."
icon_state = "fire"
/obj/structure/sign/nosmoking_1
name = "\improper NO SMOKING"
desc = "A warning sign which reads 'NO SMOKING'"
desc = "A warning sign which reads 'NO SMOKING'."
icon_state = "nosmoking"
/obj/structure/sign/nosmoking_2
name = "\improper NO SMOKING"
desc = "A warning sign which reads 'NO SMOKING'"
desc = "A warning sign which reads 'NO SMOKING'."
icon_state = "nosmoking2"
/obj/structure/sign/radiation
@@ -223,7 +223,7 @@
/obj/structure/sign/nanotrasen
name = "\improper NanoTrasen Logo "
desc = "A sign with the Nanotrasen Logo on it. Glory to Nanotrasen!"
desc = "A sign with the Nanotrasen Logo on it. Glory to Nanotrasen!"
icon_state = "nanotrasen"
/obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map
+8 -3
View File
@@ -5,6 +5,9 @@
density = 1
blocks_air = 1
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/closed/indestructible
name = "wall"
icon = 'icons/turf/walls.dmi'
@@ -24,9 +27,6 @@
/turf/closed/indestructible/oldshuttle/corner
icon_state = "corner"
/turf/closed/indestructible/splashscreen
name = "Space Station 13"
icon = 'config/title_screens/images/blank.png'
@@ -111,6 +111,11 @@
explosion_block = 50
baseturf = /turf/closed/indestructible/necropolis
/turf/closed/indestructible/necropolis/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "necro1"
return TRUE
/turf/closed/indestructible/riveted/hierophant
name = "wall"
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
+3
View File
@@ -45,6 +45,9 @@
/turf/open/indestructible/hierophant/two
/turf/open/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/open/indestructible/paper
name = "notebook floor"
desc = "A floor made of invulnerable notebook paper."
+9
View File
@@ -22,6 +22,10 @@
if(!drop_stuff())
STOP_PROCESSING(SSobj, src)
/turf/open/chasm/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "basalt"
return TRUE
/turf/open/chasm/attackby(obj/item/C, mob/user, params, area/area_restriction)
..()
@@ -171,6 +175,11 @@
planetary_atmos = TRUE
initial_gas_mix = "o2=14;n2=23;TEMP=300"
/turf/open/chasm/jungle/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "dirt"
return TRUE
/turf/open/chasm/straight_down/jungle
icon = 'icons/turf/floors/junglechasm.dmi'
planetary_atmos = TRUE
+17 -4
View File
@@ -140,7 +140,7 @@
floor_tile = /obj/item/stack/tile/carpet
broken_states = list("damaged")
smooth = SMOOTH_TRUE
canSmoothWith = list(/turf/open/floor/carpet, /turf/open/chasm)
canSmoothWith = list(/turf/open/floor/carpet)
flags = NONE
/turf/open/floor/carpet/Initialize()
@@ -175,15 +175,22 @@
burnt = 1
update_icon()
/turf/open/floor/carpet/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
turf/open/floor/fakepit
/turf/open/floor/fakepit
desc = "A clever illusion designed to look like a bottomless pit."
smooth = SMOOTH_TRUE | SMOOTH_BORDER | SMOOTH_MORE
canSmoothWith = list(/turf/open/floor/fakepit, /turf/open/chasm)
canSmoothWith = list(/turf/open/floor/fakepit)
icon = 'icons/turf/floors/Chasms.dmi'
icon_state = "smooth"
/turf/open/floor/fakepit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "basalt"
return TRUE
/turf/open/floor/fakespace
icon = 'icons/turf/space.dmi'
icon_state = "0"
@@ -193,4 +200,10 @@ turf/open/floor/fakepit
/turf/open/floor/fakespace/Initialize()
..()
icon_state = "[rand(0,25)]"
icon_state = SPACE_ICON_STATE
/turf/open/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
return TRUE
@@ -38,6 +38,11 @@
/turf/open/floor/plating/lava/make_plating()
return
/turf/open/floor/plating/lava/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "basalt"
return TRUE
/turf/open/floor/plating/lava/GetHeatCapacity()
. = 700000
+8 -1
View File
@@ -26,7 +26,7 @@
/turf/closed/mineral/Initialize()
if (!canSmoothWith)
canSmoothWith = list(/turf/closed)
canSmoothWith = list(/turf/closed/mineral, /turf/closed/indestructible)
pixel_y = -4
pixel_x = -4
icon = smooth_icon
@@ -42,6 +42,13 @@
setDir(angle2dir(rotation+dir2angle(dir)))
queue_smooth(src)
/turf/closed/mineral/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
if(turf_type)
underlay_appearance.icon = initial(turf_type.icon)
underlay_appearance.icon_state = initial(turf_type.icon_state)
return TRUE
return ..()
/turf/closed/mineral/attackby(obj/item/weapon/pickaxe/P, mob/user, params)
if (!user.IsAdvancedToolUser())
@@ -175,6 +175,7 @@
desc = "A light-weight titanium wall used in shuttles."
icon = 'icons/turf/walls/shuttle_wall.dmi'
icon_state = "map-shuttle"
flags = CAN_BE_DIRTY | CHECK_RICOCHET
sheet_type = /obj/item/stack/sheet/mineral/titanium
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock/, /turf/closed/wall/shuttle, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium)
+14
View File
@@ -28,6 +28,20 @@
/turf/closed/wall/attack_tk()
return
/turf/closed/wall/handle_ricochet(obj/item/projectile/P) //A huge pile of shitcode!
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
var/incidence_s = get_angle_of_incidence(face_angle, P.Angle)
var/new_angle = face_angle + incidence_s
var/new_angle_s = new_angle
while(new_angle_s > 180) // Translate to regular projectile degrees
new_angle_s -= 360
while(new_angle_s < -180)
new_angle_s += 360
P.Angle = new_angle_s
return TRUE
/turf/closed/wall/proc/dismantle_wall(devastated=0, explode=0)
if(devastated)
devastate_wall()
+6
View File
@@ -160,6 +160,12 @@
/turf/open/space/acid_act(acidpwr, acid_volume)
return 0
/turf/open/space/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
return TRUE
/turf/open/space/rcd_vals(mob/user, obj/item/weapon/construction/rcd/the_rcd)
if(!CanBuildHere())
+33 -21
View File
@@ -4,6 +4,11 @@
baseturf = /turf/open/space/transit
flags = NOJAUNT //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
. = ..()
underlay_appearance.icon_state = "speedspace_ns_[get_transit_state(asking_turf)]"
underlay_appearance.transform = turn(matrix(), get_transit_angle(asking_turf))
/turf/open/space/transit/south
dir = SOUTH
@@ -69,25 +74,32 @@
throw_atom(AM)
/turf/open/space/transit/proc/update_icon()
var/p = 9
var/angle = 0
var/state = 1
switch(dir)
if(NORTH)
angle = 180
state = ((-p*x+y) % 15) + 1
if(state < 1)
state += 15
if(EAST)
angle = 90
state = ((x+p*y) % 15) + 1
if(WEST)
angle = -90
state = ((x-p*y) % 15) + 1
if(state < 1)
state += 15
else
state = ((p*x+y) % 15) + 1
icon_state = "speedspace_ns_[get_transit_state(src)]"
transform = turn(matrix(), get_transit_angle(src))
icon_state = "speedspace_ns_[state]"
transform = turn(matrix(), angle)
/proc/get_transit_state(turf/T)
var/p = 9
. = 1
switch(T.dir)
if(NORTH)
. = ((-p*T.x+T.y) % 15) + 1
if(. < 1)
. += 15
if(EAST)
. = ((T.x+p*T.y) % 15) + 1
if(WEST)
. = ((T.x-p*T.y) % 15) + 1
if(. < 1)
. += 15
else
. = ((p*T.x+T.y) % 15) + 1
/proc/get_transit_angle(turf/T)
. = 0
switch(T.dir)
if(NORTH)
. = 180
if(EAST)
. = 90
if(WEST)
. = -90
+6
View File
@@ -394,6 +394,12 @@
if(ismob(A) || .)
A.ratvar_act()
/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = icon
underlay_appearance.icon_state = icon_state
underlay_appearance.dir = adjacency_dir
return TRUE
/turf/proc/add_blueprints(atom/movable/AM)
var/image/I = new
I.appearance = AM.appearance