From bd582f2098b537e1434d212be22bef62ad1c3e4a Mon Sep 17 00:00:00 2001
From: Ghom <42542238+Ghommie@users.noreply.github.com>
Date: Tue, 12 Jan 2021 03:03:54 +0100
Subject: [PATCH] Fixing bugs about the worst simple_animal coded in and
material tiles. (#54885)
Fixed floorbots applying floor tiles onto already tiled turfs.
Fixed floorbot issues with material tiles.
Fixed emagged floorbots spawning lattice when deconstructing floor into plating.
---
code/__DEFINES/traits.dm | 1 +
code/game/objects/items/stacks/stack.dm | 5 +-
code/game/objects/items/stacks/tiles/light.dm | 5 +
.../objects/items/stacks/tiles/tile_types.dm | 10 ++
code/game/turfs/open/floor/plating.dm | 15 +-
code/game/turfs/open/floor/reinf_floor.dm | 2 +-
.../mob/living/simple_animal/bot/floorbot.dm | 162 ++++++++++--------
7 files changed, 115 insertions(+), 85 deletions(-)
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 8ca59caee70..866207201fa 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -442,6 +442,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define LEAPER_BUBBLE_TRAIT "leaper-bubble"
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
#define SKILLCHIP_TRAIT "skillchip"
+#define BUSY_FLOORBOT_TRAIT "busy-floorbot"
#define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit"
#define LOCKED_BORG_TRAIT "locked-borg"
#define LACKING_LOCOMOTION_APPENDAGES_TRAIT "lacking-locomotion-appengades" //trait associated to not having locomotion appendages nor the ability to fly or float
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 24cb7d83692..5393091e631 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -417,14 +417,15 @@
return FALSE
return TRUE
-/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
+///Merges src into S, as much as possible. If present, the limit arg overrides S.max_amount for transfer.
+/obj/item/stack/proc/merge(obj/item/stack/S, limit)
if(QDELETED(S) || QDELETED(src) || S == src) //amusingly this can cause a stack to consume itself, let's not allow that.
return
var/transfer = get_amount()
if(S.is_cyborg)
transfer = min(transfer, round((S.source.max_energy - S.source.energy) / S.cost))
else
- transfer = min(transfer, S.max_amount - S.amount)
+ transfer = min(transfer, (limit ? limit : S.max_amount) - S.amount)
if(pulledby)
pulledby.start_pulling(S)
S.copy_evidences(src)
diff --git a/code/game/objects/items/stacks/tiles/light.dm b/code/game/objects/items/stacks/tiles/light.dm
index 9206be0b33d..506d1222ed7 100644
--- a/code/game/objects/items/stacks/tiles/light.dm
+++ b/code/game/objects/items/stacks/tiles/light.dm
@@ -19,3 +19,8 @@
qdel(src)
else
return ..()
+
+/obj/item/stack/tile/light/place_tile(turf/open/T)
+ . = ..()
+ var/turf/open/floor/light/F = .
+ F?.state = state
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 2a0497d4315..4c5cd820216 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -94,6 +94,11 @@
else
return ..()
+/obj/item/stack/tile/proc/place_tile(turf/open/T)
+ if(!turf_type || !use(1))
+ return
+ . = T.PlaceOnTop(turf_type, flags = CHANGETURF_INHERIT_AIR)
+
//Grass
/obj/item/stack/tile/grass
name = "grass tile"
@@ -421,6 +426,11 @@
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
merge_type = /obj/item/stack/tile/material
+/obj/item/stack/tile/material/place_tile(turf/open/T)
+ . = ..()
+ var/turf/open/floor/material/F = .
+ F?.set_custom_materials(mats_per_unit)
+
/obj/item/stack/tile/eighties
name = "retro tile"
singular_name = "retro floor tile"
diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm
index 180bb7e2a4e..1235dde1c0c 100644
--- a/code/game/turfs/open/floor/plating.dm
+++ b/code/game/turfs/open/floor/plating.dm
@@ -66,19 +66,8 @@
for(var/M in O.buckled_mobs)
to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")
return
- var/obj/item/stack/tile/W = C
- if(!W.use(1))
- return
- if(istype(W, /obj/item/stack/tile/material))
- var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR)
- newturf.set_custom_materials(W.mats_per_unit)
- else if(W.turf_type)
- var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR)
- if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow
- var/obj/item/stack/tile/light/L = W
- var/turf/open/floor/light/F = T
- F.state = L.state
-
+ var/obj/item/stack/tile/tile = C
+ tile.place_tile(src)
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
else
if(!iscyborg(user))
diff --git a/code/game/turfs/open/floor/reinf_floor.dm b/code/game/turfs/open/floor/reinf_floor.dm
index 37409b5b661..dfed384f0d1 100644
--- a/code/game/turfs/open/floor/reinf_floor.dm
+++ b/code/game/turfs/open/floor/reinf_floor.dm
@@ -27,7 +27,7 @@
/turf/open/floor/engine/make_plating(force = FALSE)
if(force)
- ..()
+ return ..()
return //unplateable
/turf/open/floor/engine/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index 04d52d20f0c..d53710aeb2a 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -5,7 +5,6 @@
icon = 'icons/mob/aibots.dmi'
icon_state = "floorbot0"
density = FALSE
- anchored = FALSE
health = 25
maxHealth = 25
@@ -22,9 +21,8 @@
var/targetdirection
var/replacetiles = FALSE
var/placetiles = FALSE
- var/specialtiles = 0
var/maxtiles = 100
- var/obj/item/stack/tile/tiletype
+ var/obj/item/stack/tile/tilestack
var/fixfloors = TRUE
var/autotile = FALSE
var/max_targets = 50
@@ -53,6 +51,17 @@
health = 100
maxHealth = 100
+/mob/living/simple_animal/bot/floorbot/Exited(atom/movable/A, atom/newloc)
+ if(A == tilestack)
+ if(tilestack && tilestack.max_amount < tilestack.amount) //split the stack if it exceeds its normal max_amount
+ var/iterations = round(tilestack.amount/tilestack.max_amount) //round() without second arg floors the value
+ for(var/a in 1 to iterations)
+ if(a == iterations)
+ tilestack.split_stack(null, tilestack.amount - tilestack.max_amount)
+ else
+ tilestack.split_stack(null, tilestack.max_amount)
+ tilestack = null
+
/mob/living/simple_animal/bot/floorbot/turn_on()
. = ..()
update_icon()
@@ -66,8 +75,7 @@
target = null
oldloc = null
ignore_list = list()
- anchored = FALSE
- update_icon()
+ toggle_magnet(FALSE)
/mob/living/simple_animal/bot/floorbot/set_custom_texts()
text_hack = "You corrupt [name]'s construction protocols."
@@ -82,8 +90,8 @@
dat += "Status: [on ? "On" : "Off"]
"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]
"
dat += "Special tiles: "
- if(specialtiles)
- dat += "Loaded \[[specialtiles]/[maxtiles]\]
"
+ if(tilestack)
+ dat += "Loaded \[[tilestack.amount]/[maxtiles]\]
"
else
dat += "None Loaded
"
@@ -93,7 +101,7 @@
dat += "Place floor tiles: [placetiles ? "Yes" : "No"]
"
dat += "Replace existing floor tiles with custom tiles: [replacetiles ? "Yes" : "No"]
"
dat += "Repair damaged tiles and platings: [fixfloors ? "Yes" : "No"]
"
- dat += "Traction Magnets: [anchored ? "Engaged" : "Disengaged"]
"
+ dat += "Traction Magnets: [HAS_TRAIT_FROM(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT) ? "Engaged" : "Disengaged"]
"
dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
"
var/bmode
if(targetdirection)
@@ -108,23 +116,25 @@
if(istype(W, /obj/item/stack/tile/plasteel))
to_chat(user, "The floorbot can produce normal tiles itself.")
return
- if(specialtiles && istype(W, /obj/item/stack/tile))
- var/obj/item/stack/tile/usedtile = W
- if(usedtile.type != tiletype)
- to_chat(user, "Different custom tiles are already inside the floorbot.")
- return
if(istype(W, /obj/item/stack/tile))
- if(specialtiles >= maxtiles)
- return
- var/obj/item/stack/tile/tiles = W //used only to get the amount
- tiletype = W.type
- var/loaded = min(maxtiles-specialtiles, tiles.amount)
- tiles.use(loaded)
- specialtiles += loaded
- if(loaded > 0)
- to_chat(user, "You load [loaded] tiles into the floorbot. It now contains [specialtiles] tiles.")
+ var/old_amount = tilestack ? tilestack.amount : 0
+ var/obj/item/stack/tile/tiles = W
+ if(tilestack)
+ if(!tiles.can_merge(tilestack))
+ to_chat(user, "Different custom tiles are already inside the floorbot.")
+ return
+ if(tilestack.amount >= maxtiles)
+ to_chat(user, "The floorbot can't hold any more custom tiles.")
+ return
+ tiles.merge(tilestack, maxtiles)
else
- to_chat(user, "You need at least one floor tile to put into [src]!")
+ if(tiles.amount > maxtiles)
+ tilestack = tilestack.split_stack(null, maxtiles)
+ else
+ tilestack = W
+ tilestack.forceMove(src)
+ to_chat(user, "You load [tilestack.amount - old_amount] tiles into the floorbot. It now contains [tilestack.amount] tiles.")
+ return
else
..()
@@ -134,6 +144,19 @@
if(user)
to_chat(user, "[src] buzzes and beeps.")
+///mobs should use move_resist instead of anchored.
+/mob/living/simple_animal/bot/floorbot/proc/toggle_magnet(engage = TRUE, change_icon = TRUE)
+ if(engage)
+ ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT)
+ move_resist = INFINITY
+ if(change_icon)
+ icon_state = "[toolbox_color]floorbot-c"
+ else
+ REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT)
+ move_resist = initial(move_resist)
+ if(change_icon)
+ update_icon()
+
/mob/living/simple_animal/bot/floorbot/Topic(href, href_list)
if(..())
return TRUE
@@ -147,11 +170,11 @@
fixfloors = !fixfloors
if("autotile")
autotile = !autotile
- if("anchor")
- set_anchored(!anchored)
+ if("magnet")
+ toggle_magnet(!HAS_TRAIT_FROM(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT), FALSE)
if("eject")
- if(specialtiles && tiletype != null)
- empty_tiles()
+ if(tilestack)
+ tilestack.forceMove(drop_location())
if("linemode")
var/setdir = input("Select construction direction:") as null|anything in list("north","east","south","west","disable")
@@ -168,11 +191,6 @@
targetdirection = null
update_controls()
-/mob/living/simple_animal/bot/floorbot/proc/empty_tiles()
- new tiletype(drop_location(), specialtiles)
- specialtiles = 0
- tiletype = null
-
/mob/living/simple_animal/bot/floorbot/handle_automated_action()
if(!..())
return
@@ -204,7 +222,7 @@
process_type = FIX_TILE
target = scan(/turf/open/floor)
- if(!target && replacetiles && specialtiles > 0) //Replace a floor tile with custom tile
+ if(!target && replacetiles && tilestack) //Replace a floor tile with custom tile
process_type = REPLACE_TILE //The target must be a tile. The floor must already have a floortile.
target = scan(/turf/open/floor)
@@ -234,9 +252,12 @@
repair(target)
else if(emagged == 2 && isfloorturf(target))
var/turf/open/floor/F = target
- set_anchored(TRUE)
+ toggle_magnet()
mode = BOT_REPAIRING
- F.ReplaceWithLattice()
+ if(isplatingturf(F))
+ F.ReplaceWithLattice()
+ else
+ F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
audible_message("[src] makes an excited booping sound.")
addtimer(CALLBACK(src, .proc/go_idle), 0.5 SECONDS)
path = list()
@@ -263,7 +284,7 @@
oldloc = loc
/mob/living/simple_animal/bot/floorbot/proc/go_idle()
- anchored = FALSE
+ toggle_magnet(FALSE)
mode = BOT_IDLE
target = null
@@ -278,15 +299,16 @@
/mob/living/simple_animal/bot/floorbot/process_scan(scan_target)
var/result
var/turf/open/floor/F
+ move_resist = initial(move_resist)
switch(process_type)
if(HULL_BREACH) //The most common job, patching breaches in the station's hull.
if(is_hull_breach(scan_target)) //Ensure that the targeted space turf is actually part of the station, and not random space.
result = scan_target
- set_anchored(TRUE) //Prevent the floorbot being blown off-course while trying to reach a hull breach.
+ move_resist = INFINITY //Prevent the floorbot being blown off-course while trying to reach a hull breach.
if(LINE_SPACE_MODE) //Space turfs in our chosen direction are considered.
if(get_dir(src, scan_target) == targetdirection)
result = scan_target
- set_anchored(TRUE)
+ move_resist = INFINITY
if(PLACE_TILE)
F = scan_target
if(isplatingturf(F)) //The floor must not already have a tile.
@@ -321,55 +343,57 @@
else if(!isfloorturf(target_turf))
return
if(isspaceturf(target_turf)) //If we are fixing an area not part of pure space, it is
- set_anchored(TRUE)
- icon_state = "[toolbox_color]floorbot-c"
+ toggle_magnet()
visible_message("[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] ")
mode = BOT_REPAIRING
- sleep(50)
- if(mode == BOT_REPAIRING && src.loc == target_turf)
+ if(do_after(src, 50, target = target_turf) && mode == BOT_REPAIRING)
if(autotile) //Build the floor and include a tile.
- target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
+ if(replacetiles && tilestack)
+ tilestack.place_tile(target_turf)
+ if(!tilestack)
+ speak("Requesting refill of custom floor tiles to continue replacing.")
+ else
+ target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
else //Build a hull plating without a floor tile.
target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
var/turf/open/floor/F = target_turf
+ var/success = FALSE
+ var/was_replacing = replacetiles
- if(F.type != initial(tiletype.turf_type) && (F.broken || F.burnt || isplatingturf(F)) || F.type == (initial(tiletype.turf_type) && (F.broken || F.burnt)))
- set_anchored(TRUE)
- icon_state = "[toolbox_color]floorbot-c"
+ if(F.broken || F.burnt || isplatingturf(F))
+ toggle_magnet()
mode = BOT_REPAIRING
- visible_message("[src] begins repairing the floor.")
- sleep(50)
- if(mode == BOT_REPAIRING && F && src.loc == F)
- F.broken = FALSE
- F.burnt = FALSE
- F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
+ visible_message("[src] begins [(F.broken || F.burnt) ? "repairing the floor" : "placing a floor tile"].")
+ if(do_after(src, 50, target = F) && mode == BOT_REPAIRING)
+ success = TRUE
- if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
- set_anchored(TRUE)
- icon_state = "[toolbox_color]floorbot-c"
+ else if(replacetiles && tilestack && F.type != tilestack.turf_type)
+ toggle_magnet()
mode = BOT_REPAIRING
visible_message("[src] begins replacing the floor tiles.")
- sleep(50)
- if(mode == BOT_REPAIRING && F && loc == F && replacetiles && specialtiles) //make sure our mode and tiles are the same after sleeping.
- F.broken = FALSE
- F.burnt = FALSE
- F.PlaceOnTop(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR)
- specialtiles--
- if(specialtiles == 0)
+ if(do_after(src, 50, target = target_turf) && mode == BOT_REPAIRING && tilestack)
+ success = TRUE
+
+ if(success)
+ F = F.make_plating(TRUE) || F
+ if(was_replacing && tilestack)
+ tilestack.place_tile(F)
+ if(!tilestack)
speak("Requesting refill of custom floor tiles to continue replacing.")
- mode = BOT_IDLE
- update_icon()
- anchored = FALSE
- target = null
+ else
+ F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
+
+ if(!QDELETED(src))
+ go_idle()
/mob/living/simple_animal/bot/floorbot/update_icon()
icon_state = "[toolbox_color]floorbot[on]"
-
/mob/living/simple_animal/bot/floorbot/explode()
on = FALSE
+ target = null
visible_message("[src] blows apart!")
var/atom/Tsec = drop_location()
@@ -377,8 +401,8 @@
new /obj/item/assembly/prox_sensor(Tsec)
- if(specialtiles && tiletype != null)
- empty_tiles()
+ if(tilestack)
+ tilestack.forceMove(drop_location())
if(prob(50))
drop_part(robot_arm, Tsec)