diff --git a/code/game/objects/items/stacks/marker_beacons.dm b/code/game/objects/items/stacks/marker_beacons.dm
index 5c7ed3aa04..f5de239b9a 100644
--- a/code/game/objects/items/stacks/marker_beacons.dm
+++ b/code/game/objects/items/stacks/marker_beacons.dm
@@ -86,23 +86,31 @@ var/list/marker_beacon_colors = list(
light_power = 0.8
var/remove_speed = 15
var/picked_color
+ var/perma = FALSE
+ var/mapped_in_color
/obj/structure/marker_beacon/New(newloc, set_color)
. = ..()
- picked_color = set_color
+ if(set_color)
+ picked_color = set_color
+ else if(mapped_in_color)
+ picked_color = mapped_in_color
update_icon()
/obj/structure/marker_beacon/examine(mob/user)
. = ..()
- . += "Alt-click to select a color. Current color is [picked_color]."
+ if(!perma)
+ . += "Alt-click to select a color. Current color is [picked_color]."
/obj/structure/marker_beacon/update_icon()
- while(!picked_color || !marker_beacon_colors[picked_color])
+ if(!picked_color || !marker_beacon_colors[picked_color])
picked_color = pick(marker_beacon_colors)
icon_state = "[initial(icon_state)][lowertext(picked_color)]-on"
set_light(light_range, light_power, marker_beacon_colors[picked_color])
/obj/structure/marker_beacon/attack_hand(mob/living/user)
+ if(perma)
+ return
to_chat(user, "You start picking [src] up...")
if(do_after(user, remove_speed, target = src))
var/obj/item/stack/marker_beacon/M = new(loc)
@@ -114,6 +122,8 @@ var/list/marker_beacon_colors = list(
qdel(src) //otherwise delete us
/obj/structure/marker_beacon/attackby(obj/item/I, mob/user, params)
+ if(perma)
+ return
if(istype(I, /obj/item/stack/marker_beacon))
var/obj/item/stack/marker_beacon/M = I
to_chat(user, "You start picking [src] up...")
@@ -126,6 +136,8 @@ var/list/marker_beacon_colors = list(
/obj/structure/marker_beacon/AltClick(mob/living/user)
..()
+ if(perma)
+ return
if(user.incapacitated() || !istype(user))
to_chat(user, "You can't do that right now!")
return
diff --git a/code/game/turfs/simulated/outdoors/snow.dm b/code/game/turfs/simulated/outdoors/snow.dm
index 366fdfa5e6..07a6804803 100644
--- a/code/game/turfs/simulated/outdoors/snow.dm
+++ b/code/game/turfs/simulated/outdoors/snow.dm
@@ -51,6 +51,7 @@
name = "ice"
icon_state = "ice"
desc = "Looks slippery."
+ edge_blending_priority = 0
/turf/simulated/floor/outdoors/ice/Entered(var/mob/living/M)
sleep(1 * world.tick_lag)
diff --git a/code/game/turfs/simulated/wall_icon.dm b/code/game/turfs/simulated/wall_icon.dm
index 409df2a23d..e6fe1cbc57 100644
--- a/code/game/turfs/simulated/wall_icon.dm
+++ b/code/game/turfs/simulated/wall_icon.dm
@@ -113,6 +113,18 @@
if(can_join_with(W))
dirs += get_dir(src, W)
+ if(material.icon_base == "hull") // Could be improved...
+ var/additional_dirs = 0
+ for(var/direction in alldirs)
+ var/turf/T = get_step(src,direction)
+ if(T && (locate(/obj/structure/hull_corner) in T))
+ dirs += direction
+ additional_dirs |= direction
+ if(additional_dirs)
+ for(var/diag_dir in cornerdirs)
+ if ((additional_dirs & diag_dir) == diag_dir)
+ dirs += diag_dir
+
wall_connections = dirs_to_corner_states(dirs)
/turf/simulated/wall/proc/can_join_with(var/turf/simulated/wall/W)
diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm
index 96979c8452..a93a53efa2 100644
--- a/code/game/turfs/simulated/wall_types.dm
+++ b/code/game/turfs/simulated/wall_types.dm
@@ -246,3 +246,64 @@
var/image/I = image(icon = src.icon, icon_state = "o_[icon_state]")
I.color = stripe_color
add_overlay(I)
+
+// Fake corners for making hulls look pretty
+/obj/structure/hull_corner
+ name = "hull corner"
+
+ icon = 'icons/turf/wall_masks.dmi'
+ icon_state = "hull_corner"
+
+ anchored = TRUE
+ density = TRUE
+ breakable = TRUE
+
+/obj/structure/hull_corner/Initialize()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/structure/hull_corner/LateInitialize()
+ . = ..()
+ update_look()
+
+/obj/structure/hull_corner/proc/get_dirs_to_test()
+ return list(dir, turn(dir,90))
+
+/obj/structure/hull_corner/proc/update_look()
+ cut_overlays()
+
+ var/turf/simulated/wall/T
+ for(var/direction in get_dirs_to_test())
+ T = get_step(src, direction)
+ if(!istype(T))
+ continue
+
+ name = T.name
+ desc = T.desc
+
+ var/datum/material/B = T.material
+ var/datum/material/R = T.reinf_material
+
+ if(B?.icon_colour)
+ color = B.icon_colour
+ if(R?.icon_colour)
+ var/image/I = image(icon, icon_state+"_reinf", dir=dir)
+ I.color = R.icon_colour
+ add_overlay(I)
+ break
+
+ if(!T)
+ warning("Hull corner at [x],[y] not placed adjacent to a hull it can find.")
+
+/obj/structure/hull_corner/long_vert
+ icon = 'icons/turf/wall_masks32x64.dmi'
+ bound_height = 64
+
+/obj/structure/hull_corner/long_vert/get_dirs_to_test()
+ return list(dir, turn(dir,90), turn(dir,-90))
+
+/obj/structure/hull_corner/long_horiz
+ icon = 'icons/turf/wall_masks64x32.dmi'
+ bound_width = 64
+
+/obj/structure/hull_corner/long_horiz/get_dirs_to_test()
+ return list(dir, turn(dir,90), turn(dir,-90))
diff --git a/code/modules/ai/ai_holder_combat_unseen.dm b/code/modules/ai/ai_holder_combat_unseen.dm
index 5c29f8a31b..ae6743832f 100644
--- a/code/modules/ai/ai_holder_combat_unseen.dm
+++ b/code/modules/ai/ai_holder_combat_unseen.dm
@@ -3,16 +3,19 @@
// Used when a target is out of sight or invisible.
/datum/ai_holder/proc/engage_unseen_enemy()
ai_log("engage_unseen_enemy() : Entering.", AI_LOG_TRACE)
+ // Also handled in strategic updates but handling it here allows for more fine resolution timeouts
+ if((lose_target_time+lose_target_timeout) >= world.time)
+ return remove_target()
// Lets do some last things before giving up.
if(conserve_ammo || !holder.ICheckRangedAttack(target_last_seen_turf))
if(get_dist(holder, target_last_seen_turf) > 1) // We last saw them over there.
// Go to where you last saw the enemy.
return give_destination(target_last_seen_turf, 1, TRUE) // Sets stance as well
- else if(lose_target_time < world.time) // We last saw them next to us, so do a blind attack on that tile.
- if(melee_on_tile(target_last_seen_turf) != ATTACK_SUCCESSFUL && intelligence_level >= AI_NORMAL)
- var/obj/O = find_escape_route()
- if(istype(O))
- return give_destination(get_turf(O), 0, TRUE)
+ // We last saw them next to us, so do a blind attack on that tile.
+ else if(melee_on_tile(target_last_seen_turf) != ATTACK_SUCCESSFUL && intelligence_level >= AI_NORMAL)
+ var/obj/O = find_escape_route()
+ if(istype(O))
+ return give_destination(get_turf(O), 0, TRUE)
else
return find_target()
else
diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm
index 22572bd134..f23c70cb5b 100644
--- a/code/modules/ai/ai_holder_targeting.dm
+++ b/code/modules/ai/ai_holder_targeting.dm
@@ -183,6 +183,7 @@
give_up_movement()
lose_target_position()
set_stance(STANCE_IDLE)
+ return TRUE
// Check if target is visible to us.
/datum/ai_holder/proc/can_see_target(atom/movable/the_target, view_range = vision_range)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
index 51b07954a6..eb55b02dab 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm
@@ -140,7 +140,7 @@
if(large_cocoon)
C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3")
- ai_holder.target = null
+ ai_holder.remove_target()
return TRUE
diff --git a/code/modules/persistence/graffiti.dm b/code/modules/persistence/graffiti.dm
index 539b7b7a3b..9f0a7c3a32 100644
--- a/code/modules/persistence/graffiti.dm
+++ b/code/modules/persistence/graffiti.dm
@@ -18,7 +18,8 @@
..(newloc)
if(!isnull(_age))
graffiti_age = _age
- message = _message
+ if(!isnull(_message))
+ message = _message
if(!isnull(author))
author = _author
diff --git a/icons/turf/wall_masks.dmi b/icons/turf/wall_masks.dmi
index c8564ac407..be2f48cd03 100644
Binary files a/icons/turf/wall_masks.dmi and b/icons/turf/wall_masks.dmi differ
diff --git a/icons/turf/wall_masks32x64.dmi b/icons/turf/wall_masks32x64.dmi
new file mode 100644
index 0000000000..a87cdcf03a
Binary files /dev/null and b/icons/turf/wall_masks32x64.dmi differ
diff --git a/icons/turf/wall_masks64x32.dmi b/icons/turf/wall_masks64x32.dmi
new file mode 100644
index 0000000000..ae6d99d05f
Binary files /dev/null and b/icons/turf/wall_masks64x32.dmi differ