From ce7c7f98850b9cff3b5f19120a16965c52d1de8a Mon Sep 17 00:00:00 2001
From: Deniz <66401072+Oyu07@users.noreply.github.com>
Date: Wed, 6 Mar 2024 15:05:39 +0000
Subject: [PATCH] Yet another Bot refactor. 2.0 (#23900)
* test 1
claim_job
comment spaces
start
* yay, its BROKE
* Update bot.dm
* alcohol is the only escape
* static
* it works
* spacing
* cleanbot list cleanup
* comments
* space AREA
This is what insanity looks like.
Every bot PR breaks something, without fail.
fixed replace tiles? broke hull breach
fixed hullbreach? broke cleanbots
fixed hullbreach? well also broke it
* Comment Sorting
* comments 2/2
* comments 3/?
* comments 4/?
* autodoc 1/?
* maketile doesnt drop
* maketile update
* floor - snake_case + if else
* Floor - comments
* floor - snake_case 2/?
* cleanbot turf reservation comment
* floorbot ignore list
* comments
* var/atom/A
* target check. null runtime
* tile clean comment removal
* again
* reviews. final_result removal
* comment block
* avoid bot TRUE
* comments ?/?
I lost track of how manny comment commits there are
* autodocs
* autodoc
* autodocs
* ignore_job -= target.UID() additions
* anchored
Noticed that, if a tile is in space, they will dance around it as they do not anchor. Now they do
* runtime fix
* ignore_job edits. clean after 30
* typo
* fix before replace, DUH
* ignore job clearing
* Time Dilation 106% no more
* eat tile fix, oops
* replace plating
* comment shift
* lets try again
* mode !
* process_type = null + to_chat cleanup + ignore_job bot_reset
* remove extra ignore_job
* target.loc
* TRUE
* ignore job and revert loc
* move speed and such
* comment with proc
* God I hate myself
* TRUE / FALSE
* comments :)
* else if
* pesky comment
* mods are asleep, rename the vars
* small edits
* Make ignore_job culling based on amount of bots alive. 1 job per bot
* Revert move speed changes. Bots move slower than security on cere
* Emag fixes oof
* ++
* + 1?
* ++
* comment
* dropped metal amount
* paranthesis
* no need for absolute
* Thanks VSC conflict resolver for duplicating this here
* Emag is a bool now, self remind comment removed
* Documentation
* move speed null nulled
* replace_tile lag / freeze fix + removed extra job stuff
* clarification about which list is being used in comment
---
.../mob/living/simple_animal/bot/bot.dm | 352 ++++++++++--------
.../mob/living/simple_animal/bot/cleanbot.dm | 5 +-
.../mob/living/simple_animal/bot/floorbot.dm | 110 +++---
3 files changed, 265 insertions(+), 202 deletions(-)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 7445fed15fd..1dbf4a1c62f 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -15,7 +15,7 @@
minbodytemp = 0
has_unlimited_silicon_privilege = TRUE
sentience_type = SENTIENCE_ARTIFICIAL
- status_flags = 0 //no default canpush
+ status_flags = 0 // No default canpush
can_strip = FALSE
speak_emote = list("states")
@@ -23,66 +23,104 @@
bubble_icon = "machine"
faction = list("neutral", "silicon")
- var/list/users = list() //for dialog updates
+ var/list/users = list() // For dialog updates
var/window_id = "bot_control"
- var/window_name = "Protobot 1.0" //Popup title
- var/window_width = 0 //0 for default size
+ var/window_name = "Protobot 1.0" // Popup title
+ var/window_width = 0 // 0 for default size
var/window_height = 0
- var/obj/item/paicard/paicard // Inserted pai card.
- var/allow_pai = TRUE // Are we even allowed to insert a pai card.
+ var/obj/item/paicard/paicard // Inserted pai card.
+ var/allow_pai = TRUE // Are we even allowed to insert a pai card.
var/bot_name
var/disabling_timer_id = null
var/list/player_access = list()
var/emagged = FALSE
- var/obj/item/card/id/access_card // the ID card that the bot "holds"
+ /// The ID card that the bot "holds"
+ var/obj/item/card/id/access_card
var/list/prev_access = list()
var/on = TRUE
- var/open = FALSE //Maint panel
+ /// Maint panel
+ var/open = FALSE
var/locked = TRUE
- var/hacked = FALSE //Used to differentiate between being hacked by silicons and emagged by humans.
+ /// Used to differentiate between being hacked by silicons and emagged by humans.
+ var/hacked = FALSE
/// Is currently hijacked by a pulse demon?
var/hijacked = FALSE
- var/text_hack = "" //Custom text returned to a silicon upon hacking a bot.
- var/text_dehack = "" //Text shown when resetting a bots hacked status to normal.
- var/text_dehack_fail = "" //Shown when a silicon tries to reset a bot emagged with the emag item, which cannot be reset.
- var/declare_message = "" //What the bot will display to the HUD user.
- var/frustration = 0 //Used by some bots for tracking failures to reach their target.
- var/base_speed = 2 //The speed at which the bot moves, or the number of times it moves per process() tick.
- var/turf/ai_waypoint //The end point of a bot's path, or the target location.
- var/list/path = list() //List of turfs through which a bot 'steps' to reach the waypoint
+ /// Custom text returned to a silicon upon hacking a bot.
+ var/text_hack = ""
+ /// Text shown when resetting a bots hacked status to normal.
+ var/text_dehack = ""
+ /// Shown when a silicon tries to reset a bot emagged with the emag item, which cannot be reset.
+ var/text_dehack_fail = ""
+ /// What the bot will display to the HUD user.
+ var/declare_message = ""
+ /// Used by some bots for tracking failures to reach their target.
+ var/frustration = 0
+ /// The speed at which the bot moves, or the number of times it moves per process() tick.
+ var/base_speed = 2
+ /// The end point of a bot's path, or the target location.
+ var/turf/ai_waypoint
+ /// List of turfs through which a bot 'steps' to reach the waypoint
+ var/list/path = list()
var/pathset = FALSE
- var/list/ignore_list = list() //List of unreachable targets for an ignore-list enabled bot to ignore.
- var/mode = BOT_IDLE //Standardizes the vars that indicate the bot is busy with its function.
- var/tries = 0 //Number of times the bot tried and failed to move.
- var/remote_disabled = FALSE //If enabled, the AI cannot *Remotely* control a bot. It can still control it through cameras.
- var/mob/living/silicon/ai/calling_ai //Links a bot to the AI calling it.
- var/obj/item/radio/Radio //The bot's radio, for speaking to people.
- var/list/radio_config = null //which channels can the bot listen to
- var/radio_channel = "Common" //The bot's default radio channel
- var/auto_patrol = FALSE // set to make bot automatically patrol
- var/turf/patrol_target // this is turf to navigate to (location of beacon)
- var/turf/summon_target // The turf of a user summoning a bot.
- var/new_destination // pending new destination (waiting for beacon response)
- var/destination // destination description tag
- var/next_destination // the next destination in the patrol route
- var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list
+ /// List of unreachable targets for an ignore-list enabled bot to ignore.
+ var/list/ignore_list = list()
+ /// List of jobs claimed by bot
+ var/static/list/ignore_job = list()
+ /// Standardizes the vars that indicate the bot is busy with its function.
+ var/mode = BOT_IDLE
+ /// Number of times the bot tried and failed to move.
+ var/tries = 0
+ /// If enabled, the AI cannot *Remotely* control a bot. It can still control it through cameras.
+ var/remote_disabled = FALSE
+ /// Links a bot to the AI calling it.
+ var/mob/living/silicon/ai/calling_ai
+ /// The bot's radio, for speaking to people.
+ var/obj/item/radio/Radio
+ /// Which channels can the bot listen to
+ var/list/radio_config = null
+ /// The bot's default radio channel
+ var/radio_channel = "Common"
+ /// Set to make bot automatically patrol
+ var/auto_patrol = FALSE
+ /// This is turf to navigate to (location of beacon)
+ var/turf/patrol_target
+ /// The turf of a user summoning a bot.
+ var/turf/summon_target
+ /// Pending new destination (waiting for beacon response)
+ var/new_destination
+ /// Destination description tag
+ var/destination
+ /// The next destination in the patrol route
+ var/next_destination
+ /// This ticks up every automated action, at 300 we clean the ignore list
+ var/ignore_list_cleanup_timer = 1
var/robot_arm = /obj/item/robot_parts/r_arm
- var/blockcount = 0 //number of times retried a blocked path
- var/awaiting_beacon = 0 // count of pticks awaiting a beacon response
+ /// Number of times retried a blocked path
+ var/blockcount = 0
+ /// Count of pticks awaiting a beacon response
+ var/awaiting_beacon = 0
- var/nearest_beacon // the nearest beacon's tag
- var/turf/nearest_beacon_loc // the nearest beacon's location
+ /// The nearest beacon's tag
+ var/nearest_beacon
+ /// The nearest beacon's location
+ var/turf/nearest_beacon_loc
- var/model = "" //The type of bot it is.
+ ///The type of bot it is.
+ var/model = ""
+ /// Bot Purpose under Show Laws
var/bot_purpose = "improve the station to the best of your ability"
- var/control_freq = BOT_FREQ // bot control frequency
- var/bot_filter // The radio filter the bot uses to identify itself on the network.
- var/bot_type = 0 //The type of bot it is, for radio control.
+ /// Bot control frequency
+ var/control_freq = BOT_FREQ
+
+ /// The radio filter the bot uses to identify itself on the network.
+ var/bot_filter
+ /// The type of bot it is, for radio control.
+ var/bot_type = 0
/// The type of data HUD the bot uses. Diagnostic by default.
var/data_hud_type = DATA_HUD_DIAGNOSTIC_BASIC
- //This holds text for what the bot is mode doing, reported on the remote bot control interface.
+ // This holds text for what the bot is mode doing, reported on the remote bot control interface.
var/list/mode_name = list("In Pursuit","Preparing to Arrest", "Arresting", \
"Beginning Patrol", "Patrolling", "Summoned by PDA", \
"Cleaning", "Repairing", "Proceeding to work site", "Healing", \
@@ -94,11 +132,11 @@
/// List of access values you can have to access the bot. Consider this as req_one_access
var/list/req_access = list()
- hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD)//Diagnostic HUD views
+ hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD) // Diagnostic HUD views
- /// storing last chased target known location
+ /// Storing last chased target known location
var/turf/last_target_location
- /// will be true if we lost target we were chasing
+ /// Will be true if we lost target we were chasing
var/lost_target = FALSE
/obj/item/radio/headset/bot
@@ -110,7 +148,7 @@
if(istype(B))
if(!B.radio_config)
B.radio_config = list("AI Private" = 1)
- if(!(B.radio_channel in B.radio_config)) // put it first so it's the :h channel
+ if(!(B.radio_channel in B.radio_config)) // Put it first so it's the :h channel
B.radio_config.Insert(1, "[B.radio_channel]")
B.radio_config["[B.radio_channel]"] = 1
config(B.radio_config)
@@ -146,7 +184,7 @@
frustration++
/mob/living/simple_animal/bot/proc/get_mode()
- if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
+ if(client) // Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
if(paicard)
return "pAI Controlled"
else
@@ -164,20 +202,20 @@
if(disabling_timer_id)
return FALSE
if(stat)
- return 0
+ return FALSE
on = TRUE
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, "depowered")
set_light(initial(light_range))
update_icon(UPDATE_ICON_STATE | UPDATE_OVERLAYS)
update_controls()
diag_hud_set_botstat()
- return 1
+ return TRUE
/mob/living/simple_animal/bot/proc/turn_off()
on = FALSE
ADD_TRAIT(src, TRAIT_IMMOBILIZED, "depowered")
set_light(0)
- bot_reset() //Resets an AI's call, should it exist.
+ bot_reset() // Resets an AI's call, should it exist.
update_icon(UPDATE_ICON_STATE | UPDATE_OVERLAYS)
update_controls()
@@ -187,7 +225,7 @@
icon_living = icon_state
icon_dead = icon_state
access_card = new /obj/item/card/id(src)
- //This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
+ // This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
access_card.access += ACCESS_ROBOTICS
set_custom_texts()
Radio = new/obj/item/radio/headset/bot(src)
@@ -210,10 +248,10 @@
/mob/living/simple_animal/bot/med_hud_set_health()
- return //we use a different hud
+ return // We use a different hud
/mob/living/simple_animal/bot/med_hud_set_status()
- return //we use a different hud
+ return // We use a different hud
/mob/living/simple_animal/bot/Destroy()
@@ -250,21 +288,23 @@
qdel(src)
/mob/living/simple_animal/bot/emag_act(mob/user)
- if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
+ if(locked) // First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
locked = FALSE
to_chat(user, "You bypass [src]'s controls.")
return TRUE
+
if(!locked && open) //Bot panel is unlocked by ID or emag, and the panel is screwed open. Ready for emagging.
emagged = TRUE
- remote_disabled = TRUE //Manually emagging the bot locks out the AI built in panel.
- locked = TRUE //Access denied forever!
+ remote_disabled = TRUE // Manually emagging the bot locks out the AI built in panel.
+ locked = TRUE // Access denied forever!
bot_reset()
- turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
+ turn_on() // The bot automatically turns on when emagged, unless recently hit with EMP.
to_chat(src, "(#$*#$^^( OVERRIDE DETECTED")
show_laws()
if(user)
add_attack_logs(user, src, "Emagged")
return TRUE
+
else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet.
to_chat(user, "You need to open maintenance panel first!")
@@ -290,14 +330,14 @@
/mob/living/simple_animal/bot/handle_automated_action()
diag_hud_set_botmode()
- if(ignorelistcleanuptimer % 300 == 0) // Every 300 actions, clean up the ignore list from old junk
+ if(++ignore_list_cleanup_timer == 300) // Every 300 actions, clean up the ignore list from old junk
for(var/uid in ignore_list)
- var/atom/referredatom = locateUID(uid)
- if(!referredatom || QDELETED(referredatom))
+ var/atom/referred_atom = locateUID(uid)
+ if(!referred_atom || QDELETED(referred_atom))
ignore_list -= uid
- ignorelistcleanuptimer = 1
+ ignore_list_cleanup_timer = 0
else
- ignorelistcleanuptimer++
+ ignore_list_cleanup_timer++
if(!on)
return
@@ -305,14 +345,14 @@
if(hijacked)
return
- switch(mode) //High-priority overrides are processed first. Bots can do nothing else while under direct command.
- if(BOT_RESPONDING) //Called by the AI.
+ switch(mode) // High-priority overrides are processed first. Bots can do nothing else while under direct command.
+ if(BOT_RESPONDING) // Called by the AI.
call_mode()
return
- if(BOT_SUMMON) //Called by PDA
+ if(BOT_SUMMON) // Called by PDA
bot_summon()
return
- return 1 //Successful completion. Used to prevent child process() continuing if this one is ended early.
+ return TRUE // Successful completion. Used to prevent child process() continuing if this one is ended early.
/mob/living/simple_animal/bot/attack_alien(mob/living/carbon/alien/user)
user.changeNext_move(CLICK_CD_MELEE)
@@ -407,7 +447,7 @@
return ..()
if(locked)
to_chat(user, "The maintenance panel is locked.")
- return TRUE // must be true or we attempt to stab the bot
+ return TRUE // Must be true or we attempt to stab the bot
open = !open
I.play_tool_sound(src)
@@ -418,7 +458,7 @@
/mob/living/simple_animal/bot/welder_act(mob/user, obj/item/I)
if(user.a_intent != INTENT_HELP)
return
- if(user == src) //No self-repair dummy
+ if(user == src) // No self-repair dummy
return
. = TRUE
if(health >= maxHealth)
@@ -467,7 +507,7 @@
/mob/living/simple_animal/bot/proc/disable(time)
if(disabling_timer_id)
- deltimer(disabling_timer_id) // if we already have disabling timer, lets replace it with new one
+ deltimer(disabling_timer_id) // If we already have disabling timer, lets replace it with new one
if(on)
turn_off()
disabling_timer_id = addtimer(CALLBACK(src, PROC_REF(enable)), time, TIMER_STOPPABLE)
@@ -486,12 +526,12 @@
set_custom_texts()
return TRUE
-/mob/living/simple_animal/bot/proc/set_custom_texts() //Superclass for setting hack texts. Appears only if a set is not given to a bot locally.
+/mob/living/simple_animal/bot/proc/set_custom_texts() // Superclass for setting hack texts. Appears only if a set is not given to a bot locally.
text_hack = "You hack [name]."
text_dehack = "You reset [name]."
text_dehack_fail = "You fail to reset [name]."
-/mob/living/simple_animal/bot/proc/speak(message, channel) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio.
+/mob/living/simple_animal/bot/proc/speak(message, channel) // Pass a message to have the bot say() it. Pass a frequency to say it on the radio.
if((!on) || (!message))
return
if(channel)
@@ -500,74 +540,73 @@
say(message)
return
-//Generalized behavior code, override where needed!
+// Generalized behavior code, override where needed!
/*
scan() will search for a given type (such as turfs, human mobs, or objects) in the bot's view range, and return a single result.
Arguments: The object type to be searched (such as "/mob/living/carbon/human"), the old scan result to be ignored, if one exists,
and the view range, which defaults to 7 (full screen) if an override is not passed.
If the bot maintains an ignore list, it is also checked here.
-If the bot has avoid_bot, which inserts its own path, it will ignore turfs with the same bot type
-
+If avoid_bot = TRUE, it will claim it's target. List of bots that use it: Cleanbot and Floorbot
Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1)
The proc would return a human next to the bot to be set to the patient var.
Pass the desired type path itself, declaring a temporary var beforehand is not required.
*/
/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE, avoid_bot)
- var/final_result
- for(var/scan in view(scan_range, src)) //Search for something in range!
- var/atom/A = scan
- if(!istype(A, scan_type)) //Check that the thing we found is the type we want!
- continue //If not, keep searching!
- if((A.UID() in ignore_list) || (A == old_target)) //Filter for blacklisted elements, usually unreachable or previously processed oness
+ for(var/atom/A in view(scan_range, src)) // Search for something in range!
+ if(!istype(A, scan_type)) // Check that the thing we found is the type we want!
+ continue // If not, keep searching!
+ if((A.UID() in ignore_list) || (A == old_target)) // Filter for blacklisted elements, usually unreachable or previously processed oness
continue
- if(turf_has_bot(avoid_bot, get_turf(A))) //Ignores targets that already have a bot of the same type on it, meant for cleanbot and floorbot seperation
+ var/scan_result = process_scan(A) // Some bots may require additional processing when a result is selected.
+ if(!scan_result)
+ continue // The current element failed assessment, move on to the next.
+ if(assign_bot(A, avoid_bot)) // Is the target claimed by a bot
continue
- var/scan_result = process_scan(A) //Some bots may require additional processing when a result is selected.
- if(scan_result)
- final_result = scan_result
- else
- continue //The current element failed assessment, move on to the next.
- return final_result
+ return scan_result
-/mob/living/simple_animal/bot/proc/turf_has_bot(avoid_bot, turf/turf_to_search)
- if(!avoid_bot)
+/mob/living/simple_animal/bot/proc/assign_bot(atom/A, avoid_bot)
+ if(!avoid_bot) // Only bots with avoid bot should be considered
return FALSE
- for(var/bot in turf_to_search)
- if(istype(bot, avoid_bot))
- return TRUE
- return FALSE
+ if(A.UID() in ignore_job) // Is this target already claimed by a bot
+ return TRUE
+ claim_job(A) // Claim the job so other bots don't come
-//When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
+/mob/living/simple_animal/bot/proc/claim_job(atom/A) // Adds the target to ignore_job list
+ var/ignore_amount = length(GLOB.bots_list) // 1 claim per bot
+ if(length(ignore_job) >= ++ignore_amount) // Something went wrong, cull the herd
+ ignore_job.Cut()
+ ignore_job |= A.UID()
+
+// When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
/mob/living/simple_animal/bot/proc/process_scan(atom/scan_target)
return scan_target
/mob/living/simple_animal/bot/proc/add_to_ignore(atom/A)
- if(ignore_list.len < 50) //This will help keep track of them, so the bot is always trying to reach a blocked spot.
- ignore_list |= A.UID()
- else //If the list is full, insert newest, delete oldest.
- ignore_list.Cut(1, 2)
- ignore_list |= A.UID()
+ if(length(ignore_list) >= 50) // This will help keep track of them, so the bot is always trying to reach a blocked spot.
+ ignore_list.Cut(1, 2) // If the list is full, insert newest, delete oldest.
+ ignore_list |= A.UID()
+
/*
Movement proc for stepping a bot through a path generated through A-star.
Pass a positive integer as an argument to override a bot's default speed.
*/
/mob/living/simple_animal/bot/proc/bot_move(dest, move_speed)
- if(!dest || !path || !length(path)) //A-star failed or a path/destination was not set.
+ if(!dest || !path || !length(path)) // A-star failed or a path/destination was not set.
set_path(null)
return FALSE
- dest = get_turf(dest) //We must always compare turfs, so get the turf of the dest var if dest was originally something else.
- var/turf/last_node = get_turf(path[length(path)]) //This is the turf at the end of the path, it should be equal to dest.
- if(get_turf(src) == dest) //We have arrived, no need to move again.
+ dest = get_turf(dest) // We must always compare turfs, so get the turf of the dest var if dest was originally something else.
+ var/turf/last_node = get_turf(path[length(path)]) // This is the turf at the end of the path, it should be equal to dest.
+ if(get_turf(src) == dest) // We have arrived, no need to move again.
return TRUE
- else if(dest != last_node) //The path should lead us to our given destination. If this is not true, we must stop.
+ else if(dest != last_node) // The path should lead us to our given destination. If this is not true, we must stop.
set_path(null)
return FALSE
- var/step_count = move_speed ? move_speed : base_speed //If a value is passed into move_speed, use that instead of the default speed var.
+ var/step_count = move_speed ? move_speed : base_speed // If a value is passed into move_speed, use that instead of the default speed var.
if(step_count >= 1 && tries < BOT_STEP_MAX_RETRIES)
for(var/step_number in 1 to step_count)
@@ -578,7 +617,7 @@ Pass a positive integer as an argument to override a bot's default speed.
return TRUE
-/mob/living/simple_animal/bot/proc/bot_step() //Step,increase tries if failed
+/mob/living/simple_animal/bot/proc/bot_step() // Step,increase tries if failed
if(!length(path))
return FALSE
@@ -596,19 +635,19 @@ Pass a positive integer as an argument to override a bot's default speed.
access_card.access = prev_access
/mob/living/simple_animal/bot/proc/call_bot(caller, turf/waypoint, message=TRUE)
- bot_reset() //Reset a bot before setting it to call mode.
+ bot_reset() // Reset a bot before setting it to call mode.
var/area/end_area = get_area(waypoint)
var/datum/job/captain/All = new/datum/job/captain
access_card.access = All.get_access() // Give the bot temporary all access
set_path(get_path_to(src, waypoint, 200, id = access_card))
- calling_ai = caller //Link the AI to the bot!
+ calling_ai = caller // Link the AI to the bot!
ai_waypoint = waypoint
- if(path && length(path)) //Ensures that a valid path is calculated!
+ if(path && length(path)) // Ensures that a valid path is calculated!
if(!on)
- turn_on() //Saves the AI the hassle of having to activate a bot manually.
+ turn_on() // Saves the AI the hassle of having to activate a bot manually.
if(client)
reset_access_timer_id = addtimer(CALLBACK(src, PROC_REF(bot_reset)), 600, TIMER_OVERRIDE|TIMER_STOPPABLE) //if the bot is player controlled, they get the extra access for a limited time
to_chat(src, "Priority waypoint set by [calling_ai] [caller]. Proceed to [end_area.name].
[length(path)-1] meters to destination. You have been granted additional door access for 60 seconds.")
@@ -624,8 +663,8 @@ Pass a positive integer as an argument to override a bot's default speed.
access_card.access = prev_access // Don't forget to reset it
set_path(null)
-/mob/living/simple_animal/bot/proc/call_mode() //Handles preparing a bot for a call, as well as calling the move proc.
-//Handles the bot's movement during a call.
+/mob/living/simple_animal/bot/proc/call_mode() // Handles preparing a bot for a call, as well as calling the move proc.
+// Handles the bot's movement during a call.
var/success = bot_move(ai_waypoint, 3)
if(!success)
if(calling_ai)
@@ -634,13 +673,14 @@ Pass a positive integer as an argument to override a bot's default speed.
bot_reset()
/mob/living/simple_animal/bot/proc/bot_reset()
- if(calling_ai) //Simple notification to the AI if it called a bot. It will not know the cause or identity of the bot.
+ if(calling_ai) // Simple notification to the AI if it called a bot. It will not know the cause or identity of the bot.
to_chat(calling_ai, "Call command to a bot has been reset.")
calling_ai = null
if(reset_access_timer_id)
deltimer(reset_access_timer_id)
reset_access_timer_id = null
set_path(null)
+ ignore_job.Cut()
last_target_location = null
lost_target = FALSE
summon_target = null
@@ -668,21 +708,21 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/start_patrol()
set_path(null)
- if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol.
+ if(tries >= BOT_STEP_MAX_RETRIES) // Bot is trapped, so stop trying to patrol.
auto_patrol = FALSE
tries = 0
speak("Unable to start patrol.")
return
- if(!auto_patrol) //A bot not set to patrol should not be patrolling.
+ if(!auto_patrol) // A bot not set to patrol should not be patrolling.
mode = BOT_IDLE
return
if(patrol_target) // has patrol target
INVOKE_ASYNC(src, PROC_REF(target_patrol))
- else // no patrol target, so need a new one
+ else // No patrol target, so need a new one
speak("Engaging patrol mode.")
find_patrol_target()
tries++
@@ -694,30 +734,30 @@ Pass a positive integer as an argument to override a bot's default speed.
return
mode = BOT_PATROL
-// perform a single patrol step
+// Perform a single patrol step
/mob/living/simple_animal/bot/proc/patrol_step()
if(client) // In use by player, don't actually move.
return
- if(loc == patrol_target) // reached target
- //Find the next beacon matching the target.
+ if(loc == patrol_target) // Reached target
+ // Find the next beacon matching the target.
if(!get_next_patrol_target())
- find_patrol_target() //If it fails, look for the nearest one instead.
+ find_patrol_target() // If it fails, look for the nearest one instead.
return
- else if(length(path) && patrol_target) // valid path
+ else if(length(path) && patrol_target) // Valid path
if(path[1] == loc)
increment_path()
return
- var/moved = bot_move(patrol_target)//step_towards(src, next) // attempt to move
- if(!moved) //Couldn't proceed the next step of the path BOT_STEP_MAX_RETRIES times
+ var/moved = bot_move(patrol_target) // step_towards(src, next) // attempt to move
+ if(!moved) // Couldn't proceed the next step of the path BOT_STEP_MAX_RETRIES times
addtimer(CALLBACK(src, PROC_REF(patrol_step_not_moved)), 2)
- else // no path, so calculate new one
+ else // No path, so calculate new one
mode = BOT_START_PATROL
/mob/living/simple_animal/bot/proc/patrol_step_not_moved()
@@ -726,7 +766,7 @@ Pass a positive integer as an argument to override a bot's default speed.
find_patrol_target()
tries = 0
-// finds the nearest beacon to self
+// Finds the nearest beacon to self
/mob/living/simple_animal/bot/proc/find_patrol_target()
nearest_beacon = null
new_destination = null
@@ -740,13 +780,13 @@ Pass a positive integer as an argument to override a bot's default speed.
speak("Disengaging patrol mode.")
/mob/living/simple_animal/bot/proc/get_next_patrol_target()
- // search the beacon list for the next target in the list.
+ // Search the beacon list for the next target in the list.
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
- if(NB.location == next_destination) //Does the Beacon location text match the destination?
- destination = new_destination //We now know the name of where we want to go.
- patrol_target = NB.loc //Get its location and set it as the target.
- next_destination = NB.codes["next_patrol"] //Also get the name of the next beacon in line.
- return 1
+ if(NB.location == next_destination) // Does the Beacon location text match the destination?
+ destination = new_destination // We now know the name of where we want to go.
+ patrol_target = NB.loc // Get its location and set it as the target.
+ next_destination = NB.codes["next_patrol"] // Also get the name of the next beacon in line.
+ return TRUE
/mob/living/simple_animal/bot/proc/find_nearest_beacon()
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
@@ -786,17 +826,17 @@ Pass a positive integer as an argument to override a bot's default speed.
if(!on)
return FALSE
- // check to see if we are the commanded bot
- if(emagged || remote_disabled || hijacked) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands.
+ // Check to see if we are the commanded bot
+ if(emagged || remote_disabled || hijacked) // Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands.
return FALSE
if(client)
bot_control_message(command, user, params["target"] ? params["target"] : "Unknown")
- // process control input
+ // Process control input
switch(command)
if("stop")
- bot_reset() //HOLD IT!!
+ bot_reset() // HOLD IT!!
auto_patrol = FALSE
if("go")
@@ -808,7 +848,7 @@ Pass a positive integer as an argument to override a bot's default speed.
summon_target = params["target"] // Location of the user
if(length(user_access))
- access_card.access = user_access + prev_access //Adds the user's access, if any.
+ access_card.access = user_access + prev_access // Adds the user's access, if any.
mode = BOT_SUMMON
calc_summon_path()
@@ -817,11 +857,11 @@ Pass a positive integer as an argument to override a bot's default speed.
return TRUE
-/mob/living/simple_animal/bot/proc/bot_summon() // summoned to PDA
+/mob/living/simple_animal/bot/proc/bot_summon() // Summoned to PDA
summon_step()
-// calculates a path to the current destination
-// given an optional turf to avoid
+// Calculates a path to the current destination
+// Given an optional turf to avoid
/mob/living/simple_animal/bot/proc/calc_path(turf/avoid)
check_bot_access()
set_path(get_path_to(src, patrol_target, 120, id=access_card, exclude=avoid))
@@ -830,7 +870,7 @@ Pass a positive integer as an argument to override a bot's default speed.
set waitfor = FALSE
check_bot_access()
set_path(get_path_to(src, summon_target, 150, id=access_card, exclude=avoid))
- if(!length(path)) //Cannot reach target. Give up and announce the issue.
+ if(!length(path)) // Cannot reach target. Give up and announce the issue.
speak("Summon command failed, destination unreachable.",radio_channel)
bot_reset()
@@ -854,7 +894,7 @@ Pass a positive integer as an argument to override a bot's default speed.
addtimer(CALLBACK(src, PROC_REF(try_calc_path)), 2)
- else // no path, so calculate new one
+ else // No path, so calculate new one
calc_summon_path()
/mob/living/simple_animal/bot/proc/try_calc_path()
@@ -886,22 +926,22 @@ Pass a positive integer as an argument to override a bot's default speed.
return "PROTOBOT - NOT FOR USE"
/mob/living/simple_animal/bot/proc/allowed(mob/M)
- var/acc = M.get_access() //see mob.dm
+ var/acc = M.get_access() // See mob.dm
if(acc == IGNORE_ACCESS || M.can_admin_interact())
- return TRUE //Mob ignores access
+ return TRUE // Mob ignores access
return has_access(list(), req_access, acc)
/mob/living/simple_animal/bot/Topic(href, href_list)
- if(href_list["close"])// HUE HUE
+ if(href_list["close"]) // HUE HUE
if(usr in users)
users.Remove(usr)
- return 1
+ return TRUE
if(topic_denied(usr))
to_chat(usr, "[src]'s interface is not responding!")
- return 1
+ return TRUE
add_fingerprint(usr)
if((href_list["power"]) && (allowed(usr) || !locked || usr.can_admin_interact()))
@@ -927,7 +967,7 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/canhack(mob/M)
return ((issilicon(M) && (!emagged || hacked)) || M.can_admin_interact())
-/mob/living/simple_animal/bot/proc/handle_hacking(mob/M) // refactored out of Topic/ to allow re-use by TGUIs
+/mob/living/simple_animal/bot/proc/handle_hacking(mob/M) // Refactored out of Topic/ to allow re-use by TGUIs
if(!canhack(M))
return
if(!emagged)
@@ -951,15 +991,15 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/update_icon_state()
icon_state = "[initial(icon_state)][on]"
-/mob/living/simple_animal/bot/proc/topic_denied(mob/user) //Access check proc for bot topics! Remember to place in a bot's individual Topic if desired.
+/mob/living/simple_animal/bot/proc/topic_denied(mob/user) // Access check proc for bot topics! Remember to place in a bot's individual Topic if desired.
if(user.can_admin_interact())
return FALSE
if(user.incapacitated() || !(issilicon(user) || in_range(src, user)))
return TRUE
- if(emagged) //An emagged bot cannot be controlled by humans, silicons can if one hacked it.
- if(!hacked) //Manually emagged by a human - access denied to all.
+ if(emagged) // An emagged bot cannot be controlled by humans, silicons can if one hacked it.
+ if(!hacked) // Manually emagged by a human - access denied to all.
return TRUE
- else if(!(issilicon(user) || ispulsedemon(user))) //Bot is hacked, so only silicons are allowed access.
+ else if(!(issilicon(user) || ispulsedemon(user))) // Bot is hacked, so only silicons are allowed access.
return TRUE
if(hijacked && !ispulsedemon(user))
return FALSE
@@ -969,10 +1009,10 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/hack(mob/user)
var/hack
- if(issilicon(user) || user.can_admin_interact()) //Allows silicons or admins to toggle the emag status of a bot.
+ if(issilicon(user) || user.can_admin_interact()) // Allows silicons or admins to toggle the emag status of a bot.
hack += "[emagged ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]
"
hack += "Harm Prevention Safety System: [emagged ? "DANGER" : "Engaged"]
"
- else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control.
+ else if(!locked) // Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control.
hack += "Remote network control radio: [remote_disabled ? "Disconnected" : "Connected"]
"
return hack
@@ -1095,7 +1135,7 @@ Pass a positive integer as an argument to override a bot's default speed.
used_radios += Radio
/mob/living/simple_animal/bot/is_mechanical()
- return 1
+ return TRUE
/mob/living/simple_animal/bot/proc/set_path(list/newpath)
path = newpath ? newpath : list()
@@ -1112,13 +1152,13 @@ Pass a positive integer as an argument to override a bot's default speed.
// Common data shared among all the bots, used by BotStatus.js
/mob/living/simple_animal/bot/ui_data(mob/user)
var/list/data = list()
- data["locked"] = locked // controls, locked or not
- data["noaccess"] = topic_denied(user) // does the current user have access? admins, silicons etc can still access bots with locked controls
+ data["locked"] = locked // Controls, locked or not
+ data["noaccess"] = topic_denied(user) // Does the current user have access? admins, silicons etc can still access bots with locked controls
data["maintpanel"] = open
data["on"] = on
data["autopatrol"] = auto_patrol
data["painame"] = paicard ? paicard.pai.name : null
data["canhack"] = canhack(user)
- data["emagged"] = emagged // this is an int, NOT a boolean
+ data["emagged"] = emagged
data["remote_disabled"] = remote_disabled
return data
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index cba5965884b..10090833b57 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -124,7 +124,7 @@
audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
- target = scan(/obj/effect/decal/cleanable, avoid_bot = /mob/living/simple_animal/bot/cleanbot)
+ target = scan(/obj/effect/decal/cleanable, avoid_bot = TRUE)
if(!target && auto_patrol) //Search for cleanables it can see.
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
@@ -143,12 +143,14 @@
//Try to produce a path to the target, and ignore airlocks to which it has access.
path = get_path_to(src, target, 30, id=access_card)
if(!bot_move(target))
+ ignore_job -= target.UID()
add_to_ignore(target)
target = null
path = list()
return
mode = BOT_MOVING
else if(!bot_move(target))
+ ignore_job -= target.UID()
target = null
mode = BOT_IDLE
return
@@ -164,6 +166,7 @@
/mob/living/simple_animal/bot/cleanbot/proc/do_clean(obj/effect/decal/cleanable/target)
if(mode == BOT_CLEANING)
+ ignore_job -= target.UID()
QDEL_NULL(target)
anchored = FALSE
mode = BOT_IDLE
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index bfbbcc18702..a8e7e3d0653 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -1,4 +1,4 @@
-//Floorbot
+// Floorbot
/mob/living/simple_animal/bot/floorbot
name = "\improper Floorbot"
desc = "A little floor repairing robot, he looks so excited!"
@@ -167,37 +167,37 @@
if(prob(5))
audible_message("[src] makes an excited booping beeping sound!")
- //Normal scanning procedure. We have tiles loaded, are not emagged.
+ // Normal scanning procedure. We have tiles loaded, are not emagged.
if(!target && !emagged && amount)
if(!target)
- process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones.
- target = scan(/turf/space, avoid_bot = /mob/living/simple_animal/bot/floorbot)
+ process_type = HULL_BREACH // Ensures the floorbot does not try to "fix" space areas or shuttle docking zones.
+ target = scan(/turf/space, avoid_bot = TRUE)
- if(!target && replace_tiles) //Finds a floor without a tile and gives it one.
- process_type = REPLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile.
- target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot)
-
- if(!target && fix_floor) //Repairs damaged floors and tiles.
+ if(!target && fix_floor) // Repairs damaged floors and tiles.
process_type = FIX_TILE
- target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot)
+ target = scan(/turf/simulated/floor, avoid_bot = TRUE)
- if(!target && emagged) //We are emagged! Time to rip up the floors!
+ if(!target && replace_tiles) // Finds a floor without a tile and gives it one.
+ process_type = REPLACE_TILE // The target must be the floor and not a tile. The floor must not already have a floortile.
+ target = scan(/turf/simulated/floor/plating, avoid_bot = TRUE)
+
+ if(!target && emagged) // We are emagged! Time to rip up the floors!
process_type = TILE_EMAG
- target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot)
+ target = scan(/turf/simulated/floor, avoid_bot = TRUE)
- if(amount < MAX_AMOUNT && !target) //Out of tiles! We must refill!
- if(eat_tiles) //Configured to find and consume floortiles!
+ if(amount < MAX_AMOUNT && !target) // Out of tiles! We must refill!
+
+ if(!target && eat_tiles) // Configured to find and consume floortiles!
process_type = null
target = scan(/obj/item/stack/tile/plasteel)
- if(!target && make_tiles) //We did not manage to find any floor tiles! Scan for metal stacks and make our own!
+ if(!target && make_tiles) // We did not manage to find any floor tiles! Scan for metal stacks and make our own!
process_type = null
target = scan(/obj/item/stack/sheet/metal)
- if(!target && nag_on_empty) //Floorbot is empty and cannot acquire more tiles, nag the engineers for more!
+ if(!target && nag_on_empty) // Floorbot is empty and cannot acquire more tiles, nag the engineers for more!
nag()
-
if(!target)
if(auto_patrol)
@@ -211,10 +211,10 @@
if(loc == target || loc == target.loc)
if(istype(target, /obj/item/stack/tile/plasteel))
- start_eattile(target)
+ start_eat_tile(target)
if(istype(target, /obj/item/stack/sheet/metal))
- start_maketile(target)
+ start_make_tile(target)
if(isturf(target) && !emagged)
repair(target)
@@ -232,7 +232,7 @@
path = list()
return
- if(!length(path))
+ if(!length(path)) // No path, need a new one
if(!isturf(target))
var/turf/TL = get_turf(target)
path = get_path_to(src, TL, 30, id = access_card, simulated_only = 0)
@@ -241,10 +241,12 @@
if(!bot_move(target))
add_to_ignore(target)
+ ignore_job -= target.UID()
target = null
mode = BOT_IDLE
return
else if(!bot_move(target))
+ ignore_job -= target.UID()
target = null
mode = BOT_IDLE
return
@@ -255,45 +257,50 @@
amount ++
anchored = FALSE
mode = BOT_IDLE
+ ignore_job -= target.UID()
target = null
-/mob/living/simple_animal/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us!
+/mob/living/simple_animal/bot/floorbot/proc/nag() // Annoy everyone on the channel to refill us!
if(!nagged)
speak("Requesting refill [MAX_AMOUNT - amount] at [get_area(src)]!", radio_channel)
nagged = TRUE
-/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
+/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) // Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
return !istype(get_area(t), /area/space)
-//Floorbots, having several functions, need sort out special conditions here.
+// Floorbots, having several functions, need sort out special conditions here.
/mob/living/simple_animal/bot/floorbot/process_scan(atom/scan_target)
var/result
var/turf/simulated/floor/F
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.
+ 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
- anchored = TRUE //Prevent the floorbot being blown off-course while trying to reach a hull breach.
+ anchored = TRUE // Prevent the floorbot being blown off-course while trying to reach a hull breach.
if(REPLACE_TILE)
F = scan_target
- if(istype(F, /turf/simulated/floor/plating)) //The floor must not already have a tile.
+ if(istype(F, /turf/simulated/floor/plating)) // The floor must not already have a tile.
+ if(locate(/obj/structure/window) in get_turf(F)) // Targeting plating under window
+ add_to_ignore(scan_target)
+ return FALSE
result = F
- if(FIX_TILE) //Selects only damaged floors.
+ if(FIX_TILE) // Selects only damaged floors.
F = scan_target
if(istype(F) && (F.broken || F.burnt))
result = F
- if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space!
+ if(TILE_EMAG) // Emag mode! Rip up the floor and cause breaches to space!
F = scan_target
if(!istype(F, /turf/simulated/floor/plating))
result = F
- else //If no special processing is needed, simply return the result.
+ else // If no special processing is needed, simply return the result.
result = scan_target
return result
/mob/living/simple_animal/bot/floorbot/proc/repair(turf/target_turf)
if(isspaceturf(target_turf))
- //Must be a hull breach to continue.
+ // Must be a hull breach to continue.
if(!is_hull_breach(target_turf))
+ ignore_job -= target.UID()
target = null
return
@@ -302,12 +309,13 @@
if(amount <= 0)
mode = BOT_IDLE
+ ignore_job -= target.UID()
target = null
return
anchored = TRUE
- if(isspaceturf(target_turf)) //If we are fixing an area not part of pure space, it is
+ if(isspaceturf(target_turf)) // If we are fixing an area not part of pure space, it is
visible_message("[src] begins to repair the hole.")
mode = BOT_REPAIRING
update_icon(UPDATE_OVERLAYS)
@@ -326,6 +334,8 @@
if(mode != BOT_REPAIRING)
return
+ ignore_job -= target_turf.UID() // If called after the tile fix, turf changes and the UID with it
+
if(autotile || replace_tiles)
if(process_type != HULL_BREACH)
F.break_tile_to_plating()
@@ -339,15 +349,16 @@
anchored = FALSE
target = null
-/mob/living/simple_animal/bot/floorbot/proc/start_eattile(obj/item/stack/tile/plasteel/T)
+/mob/living/simple_animal/bot/floorbot/proc/start_eat_tile(obj/item/stack/tile/plasteel/T)
if(!istype(T, /obj/item/stack/tile/plasteel))
return
+ anchored = TRUE
visible_message("[src] begins to collect tiles.")
mode = BOT_EAT_TILE
update_icon(UPDATE_OVERLAYS)
- addtimer(CALLBACK(src, PROC_REF(do_eattile), T), 2 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(do_eat_tile), T), 2 SECONDS)
-/mob/living/simple_animal/bot/floorbot/proc/do_eattile(obj/item/stack/tile/plasteel/T)
+/mob/living/simple_animal/bot/floorbot/proc/do_eat_tile(obj/item/stack/tile/plasteel/T)
if(isnull(T))
target = null
mode = BOT_IDLE
@@ -359,30 +370,39 @@
else
amount += T.amount
qdel(T)
+ anchored = FALSE
target = null
mode = BOT_IDLE
update_icon(UPDATE_OVERLAYS)
-/mob/living/simple_animal/bot/floorbot/proc/start_maketile(obj/item/stack/sheet/metal/M)
+/mob/living/simple_animal/bot/floorbot/proc/start_make_tile(obj/item/stack/sheet/metal/M)
if(!istype(M, /obj/item/stack/sheet/metal))
return
+ anchored = TRUE
visible_message("[src] begins to create tiles.")
mode = BOT_MAKE_TILE
update_icon(UPDATE_OVERLAYS)
- addtimer(CALLBACK(src, PROC_REF(do_maketile), M), 2 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(do_make_tile), M), 2 SECONDS)
-/mob/living/simple_animal/bot/floorbot/proc/do_maketile(obj/item/stack/sheet/metal/M)
+/mob/living/simple_animal/bot/floorbot/proc/do_make_tile(obj/item/stack/sheet/metal/M)
if(isnull(M))
target = null
mode = BOT_IDLE
return
- var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
- T.amount = 4
- T.forceMove(M.loc)
+
+ if((amount + 4) > MAX_AMOUNT) // 1 metal = 4 tiles, hence + 4
+ var/missing_amount = MAX_AMOUNT - amount
+ var/extra = amount + 4 - MAX_AMOUNT
+ amount += missing_amount
+ new /obj/item/stack/tile/plasteel(get_turf(src), extra)
+ else
+ amount += 4
+
if(M.amount > 1)
- M.amount--
+ M.amount --
else
qdel(M)
+ anchored = FALSE
target = null
mode = BOT_IDLE
update_icon(UPDATE_OVERLAYS)
@@ -408,7 +428,7 @@
if(prob(50))
drop_part(robot_arm, Tsec)
- while(amount)//Dumps the tiles into the appropriate sized stacks
+ while(amount)// Dumps the tiles into the appropriate sized stacks
if(amount >= 16)
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = 16
@@ -425,9 +445,9 @@
if(isturf(A))
repair(A)
else if(istype(A,/obj/item/stack/tile/plasteel))
- start_eattile(A)
+ start_eat_tile(A)
else if(istype(A,/obj/item/stack/sheet/metal))
- start_maketile(A)
+ start_make_tile(A)
else
..()