diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm
index f6cbab25230..293657dff5f 100644
--- a/code/game/machinery/bots/cleanbot.dm
+++ b/code/game/machinery/bots/cleanbot.dm
@@ -37,12 +37,28 @@
var/oldloc = null
req_access = list(access_janitor)
var/path[] = new()
+ var/patrol_path[] = null
+ var/beacon_freq = 1445 // navigation beacon frequency
+ var/closest_dist
+ var/closest_loc
+ var/failed_steps
+ var/should_patrol
+ var/next_dest
+ var/next_dest_loc
/obj/machinery/bot/cleanbot/New()
..()
src.get_targets()
src.icon_state = "cleanbot[src.on]"
+ should_patrol = 0
+
+ src.botcard = new /obj/item/weapon/card/id(src)
+ src.botcard.access = get_access("Detective")
+
+ if(radio_controller)
+ radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
+
/obj/machinery/bot/cleanbot/turn_on()
. = ..()
@@ -70,12 +86,12 @@
dat += text({"
Automatic Station Cleaner v1.0
Status: []
-Behaviour controls are [src.locked ? "locked" : "unlocked"]""},
+Behaviour controls are [src.locked ? "locked" : "unlocked"]"},
text("[src.on ? "On" : "Off"]"))
if(!src.locked)
- dat += text({"
-Cleans Blood: []
"},
-text("[src.blood ? "Yes" : "No"]"))
+ dat += text({"
Cleans Blood: []
"}, text("[src.blood ? "Yes" : "No"]"))
+ dat += text({"
Patrol station: []
"}, text("[src.should_patrol ? "Yes" : "No"]"))
+ // dat += text({"
Beacon frequency: []
"}, text("[src.beacon_freq]"))
if(src.panelopen && !src.locked)
dat += text({"
Odd looking screw twiddled: []
@@ -102,6 +118,15 @@ text("[src.oddbutton ? "Yes" : "No"
src.blood =!src.blood
src.get_targets()
src.updateUsrDialog()
+ if("patrol")
+ src.should_patrol =!src.should_patrol
+ src.patrol_path = null
+ src.updateUsrDialog()
+ if("freq")
+ var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10
+ if (freq > 0)
+ src.beacon_freq = freq
+ src.updateUsrDialog()
if("screw")
src.screwloose = !src.screwloose
usr << "You twiddle the screw."
@@ -185,6 +210,35 @@ text("[src.oddbutton ? "Yes" : "No"
if(!src.target || src.target == null)
if(src.loc != src.oldloc)
src.oldtarget = null
+
+ if (!should_patrol)
+ return
+
+ if (!patrol_path || patrol_path.len < 1)
+ var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
+
+ if(!frequency) return
+
+ closest_dist = 9999
+ closest_loc = null
+ next_dest_loc = null
+
+ var/datum/signal/signal = new()
+ signal.source = src
+ signal.transmission_method = 1
+ signal.data = list("findbeacon" = "patrol")
+ frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
+ spawn(5)
+ if (!next_dest_loc)
+ next_dest_loc = closest_loc
+ if (next_dest_loc)
+ src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=null)
+ src.patrol_path = reverselist(src.patrol_path)
+ else
+ patrol_move()
+ spawn(5)
+ patrol_move()
+
return
if(src.target && (src.target != null) && src.path.len == 0)
@@ -202,6 +256,7 @@ text("[src.oddbutton ? "Yes" : "No"
step_to(src, target)
if(src.target && (src.target != null))
+ patrol_path = null
if(src.loc == src.target.loc)
clean(src.target)
src.path = new()
@@ -210,17 +265,54 @@ text("[src.oddbutton ? "Yes" : "No"
src.oldloc = src.loc
+/obj/machinery/bot/cleanbot/proc/patrol_move()
+ if (src.patrol_path.len <= 0)
+ return
+
+ var/next = src.patrol_path[1]
+ src.patrol_path -= next
+ if (next == src.loc)
+ return
+
+ var/moved = step_towards(src, next)
+ if (!moved)
+ failed_steps++
+ if (failed_steps > 4)
+ patrol_path = null
+ next_dest = null
+ failed_steps = 0
+ else
+ failed_steps = 0
+
+/obj/machinery/bot/cleanbot/receive_signal(datum/signal/signal)
+ var/recv = signal.data["beacon"]
+ var/valid = signal.data["patrol"]
+ if(!recv || !valid)
+ return
+
+ var/dist = get_dist(src, signal.source.loc)
+ if (dist < closest_dist && signal.source.loc != src.loc)
+ closest_dist = dist
+ closest_loc = signal.source.loc
+ next_dest = signal.data["next_patrol"]
+
+ if (recv == next_dest)
+ next_dest_loc = signal.source.loc
+ next_dest = signal.data["next_patrol"]
+
/obj/machinery/bot/cleanbot/proc/get_targets()
src.target_types = new/list()
- if(src.blood)
+ target_types += /obj/effect/decal/cleanable/oil
+ target_types += /obj/effect/decal/cleanable/vomit
+ target_types += /obj/effect/decal/cleanable/robot_debris
+ target_types += /obj/effect/decal/cleanable/crayon
+
+ if(src.blood)
target_types += /obj/effect/decal/cleanable/xenoblood/
target_types += /obj/effect/decal/cleanable/xenoblood/xgibs
target_types += /obj/effect/decal/cleanable/blood/
target_types += /obj/effect/decal/cleanable/blood/gibs/
- target_types += /obj/effect/decal/cleanable/oil
- target_types += /obj/effect/decal/cleanable/robot_debris
- target_types += /obj/effect/decal/cleanable/crayon
/obj/machinery/bot/cleanbot/proc/clean(var/obj/effect/decal/cleanable/target)
src.anchored = 1
@@ -274,10 +366,4 @@ text("[src.oddbutton ? "Yes" : "No"
if (!in_range(src, usr) && src.loc != usr)
return
- src.created_name = t
-
-
-
-
-
-
+ src.created_name = t
\ No newline at end of file
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index bc0d07d57e8..6774671f16c 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -40,7 +40,7 @@ display round(lastgen) and plasmatank amount
//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power).
/obj/machinery/power/port_gen
- name = "protable generator"
+ name = "Portable Generator"
desc = "A portable generator for emergency backup power"
icon = 'power.dmi'
icon_state = "portgen0"
@@ -48,11 +48,13 @@ display round(lastgen) and plasmatank amount
anchored = 0
directwired = 1
use_power = 0
+
var
active = 0
power_gen = 5000
open = 0
recent_fault = 0
+ power_output = 1
proc
HasFuel() //Placeholder for fuel check.
@@ -61,15 +63,25 @@ display round(lastgen) and plasmatank amount
UseFuel() //Placeholder for fuel use.
return
+ handleInactive()
+ return
+
process()
- if(active && HasFuel() && !crit_fail && powernet)
- if(prob(reliability)) add_avail(power_gen)
- else if(!recent_fault) recent_fault = 1
+ if(active && HasFuel() && !crit_fail && anchored)
+ if(prob(reliability))
+ add_avail(power_gen * power_output)
+ else if(!recent_fault)
+ recent_fault = 1
else crit_fail = 1
UseFuel()
+ for(var/mob/M in viewers(1, src))
+ if (M.client && M.machine == src)
+ src.updateUsrDialog()
+
else
active = 0
icon_state = initial(icon_state)
+ handleInactive()
attack_hand(mob/user as mob)
if(..())
@@ -88,9 +100,13 @@ display round(lastgen) and plasmatank amount
name = "P.A.C.M.A.N.-type Portable Generator"
var
coins = 0
- max_coins = 120
+ max_coins = 1000
coin_path = "/obj/item/weapon/coin/plasma"
board_path = "/obj/item/weapon/circuitboard/pacman"
+ coin_left = 0 // How much is left of the coin
+ time_per_coin = 1
+ emagged = 0
+ heat = 0
New()
..()
@@ -108,7 +124,7 @@ display round(lastgen) and plasmatank amount
var/temp_reliability = 0
for(var/obj/item/weapon/stock_parts/SP in component_parts)
if(istype(SP, /obj/item/weapon/stock_parts/matter_bin))
- max_coins = SP.rating * SP.rating * 120
+ max_coins = SP.rating * SP.rating * 1000
else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor))
temp_rating += SP.rating
for(var/obj/item/weapon/CP in component_parts)
@@ -122,15 +138,54 @@ display round(lastgen) and plasmatank amount
if(crit_fail) usr << "\red The generator seems to have broken down."
HasFuel()
- if(coins)
+ if(coins >= 1 / (time_per_coin / power_output) - coin_left)
return 1
return 0
UseFuel()
- if(coins)
+ var/needed_coins = 1 / (time_per_coin / power_output)
+ var/temp = min(needed_coins, coin_left)
+ needed_coins -= temp
+ coin_left -= temp
+ coins -= round(needed_coins)
+ needed_coins -= round(needed_coins)
+ if (coin_left <= 0 && coins > 0)
+ coin_left = 1 - needed_coins
coins--
+
+ var/lower_limit = 56 + power_output * 10
+ var/upper_limit = 76 + power_output * 10
+ var/bias = 0
+ if (power_output > 4)
+ upper_limit = 400
+ bias = power_output * 3
+ if (heat < lower_limit)
+ heat += 3
+ else
+ heat += rand(-7 + bias, 7 + bias)
+ if (heat < lower_limit)
+ heat = lower_limit
+ if (heat > upper_limit)
+ heat = upper_limit
+
+ if (heat > 300)
+ overheat()
+ del(src)
return
+ handleInactive()
+ heat -= 2
+ if (heat < 0)
+ heat = 0
+ else
+ for(var/mob/M in viewers(1, src))
+ if (M.client && M.machine == src)
+ src.updateUsrDialog()
+
+ proc
+ overheat()
+ explosion(src.loc, 2, 5, 2, -1)
+
attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, text2path(coin_path)))
if(coins >= max_coins)
@@ -140,17 +195,25 @@ display round(lastgen) and plasmatank amount
user.drop_item()
del(O)
user << "\blue You add a coin to the generator."
-
+ else if (istype(O, /obj/item/weapon/card/emag))
+ emagged = 1
+ emp_act(1)
else if(!active)
if(istype(O, /obj/item/weapon/wrench))
anchored = !anchored
+ playsound(src.loc, 'Deconstruct.ogg', 50, 1)
if(anchored)
- user << "\blue The generator is locked into place."
+ user << "\blue You secure the generator to the floor."
else
- user << "\blue The generator is unbolted from the floor."
+ user << "\blue You unsecure the generator from the floor."
makepowernets()
else if(istype(O, /obj/item/weapon/screwdriver))
open = !open
+ playsound(src.loc, 'Screwdriver.ogg', 50, 1)
+ if(open)
+ user << "\blue You open the access panel."
+ else
+ user << "\blue You close the access panel."
else if(istype(O, /obj/item/weapon/crowbar) && !open)
var/obj/machinery/constructable_frame/machine_frame/new_frame = new /obj/machinery/constructable_frame/machine_frame(src.loc)
for(var/obj/item/I in component_parts)
@@ -163,25 +226,105 @@ display round(lastgen) and plasmatank amount
attack_hand(mob/user as mob)
..()
- if(!active && HasFuel() && !crit_fail && powernet)
- active = 1
- icon_state = "portgen1"
- user << "\blue The generator is on."
- else if(active)
- active = 0
- icon_state = "portgen0"
- user << "\blue The generator is off."
+
+ if (istype(user.pulling,/obj/item/weapon/moneybag))
+ var/new_coins = 0
+ var/target_coins = text2num(input("How many coins do you wish to transfer?", "Generator", "0"))
+ for (var/obj/item/weapon/coin/C in user.pulling.contents)
+ if(istype(C, text2path(coin_path)))
+ if (coins >= max_coins)
+ user << "\blue The generator is full!"
+ break
+ if (new_coins >= target_coins)
+ break
+ coins++
+ new_coins++
+ del(C)
+ if (user.pulling.contents.len < 1)
+ del(user.pulling)
+
+ user << "\blue You move [new_coins] coins from the money bag to the generator."
+ src.add_fingerprint(usr)
+ return
+
+ if (!anchored)
+ return
+
+ interact(user)
+
+ attack_ai(mob/user as mob)
+ interact(user)
+
+ attack_paw(mob/user as mob)
+ interact(user)
+
+ proc
+ interact(mob/user)
+ if (get_dist(src, user) > 1 )
+ if (!istype(user, /mob/living/silicon/ai))
+ user.machine = null
+ user << browse(null, "window=port_gen")
+ return
+
+ user.machine = src
+
+ var/dat = text("[name]
")
+ if (active)
+ dat += text("Generator: On
")
+ else
+ dat += text("Generator: Off
")
+ dat += text("Coins: [coins]
")
+ var/coin_percent = round(coin_left * 100, 1)
+ dat += text("Current coin: [coin_percent]%
")
+ dat += text("Power output: - [power_gen * power_output] +
")
+ dat += text("Heat: [heat]
")
+ dat += "
Close"
+ user << browse("[dat]", "window=port_gen")
+
+ Topic(href, href_list)
+ if(..())
+ return
+
+ src.add_fingerprint(usr)
+ if(href_list["action"])
+ if(href_list["action"] == "enable")
+ if(!active && HasFuel() && !crit_fail)
+ active = 1
+ icon_state = "portgen1"
+ src.updateUsrDialog()
+ if(href_list["action"] == "disable")
+ if (active)
+ active = 0
+ icon_state = "portgen0"
+ src.updateUsrDialog()
+ if(href_list["action"] == "lower_power")
+ if (power_output > 1)
+ power_output--
+ src.updateUsrDialog()
+ if (href_list["action"] == "higher_power")
+ if (power_output < 4 || emagged)
+ power_output++
+ src.updateUsrDialog()
+ if (href_list["action"] == "close")
+ usr << browse(null, "window=port_gen")
+ usr.machine = null
/obj/machinery/power/port_gen/pacman/super
name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator"
icon_state = "portgen1"
coin_path = "/obj/item/weapon/coin/uranium"
- power_gen = 10000
+ power_gen = 15000
+ time_per_coin = 5
board_path = "/obj/item/weapon/circuitboard/pacman/super"
+ overheat()
+ explosion(src.loc, 3, 3, 3, -1)
/obj/machinery/power/port_gen/pacman/mrs
name = "M.R.S.P.A.C.M.A.N.-type Portable Generator"
icon_state = "portgen2"
coin_path = "/obj/item/weapon/coin/diamond"
- power_gen = 20000
+ power_gen = 40000
+ time_per_coin = 60
board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
+ overheat()
+ explosion(src.loc, 4, 4, 4, -1)
\ No newline at end of file