mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-13 19:52:40 +00:00
* Changes navbeacons to no longer use radios (Doing so was slower and didn't really help anything) Note: var/freq remains for mapping compatibility until all maps are updated. * Fixes navbeacons to actually hide under flooring if you put plating over them. * Changed how navbeacons are mapped in. Don't use the picky "code_txt" variable, instead use appropriate subtype. * Made useful reusable subtypes so you don't have to code in a type for every. single. one. * Updated mulebot to use new navbeacon codes. * Re-activate patrolling! With the new navbeacons, bots with will_patrol can follow the patrol navbeacons. * Note: various "should_patrol" variables on each bot type unified under /mob/living/bot/var/will_patrol * Securitrons (beepsky) got an overhaul to the new patrol routing. * Note: BayStation replaced the snowflake handcuffs code with acutal handcuffs. Polaris handcuffs requiere a grab to work, so are more complicated. Kept our existing attack code. * Behavior procs reorganized to use better movement detection and just be more flexible. * Floorbot fixes & removal of bridgemode * Floorbot will now remove & replace broken floor tiles. * Floorbot will no longer decide its okay to pave over all of SPACE. * For the moment patching hull breaches is disabled, it is too laggy. * Sundry bugfixes to all bots * Use forceMove() instead of setting loc * Use "\The [X]" message strings. * Pass target to do_after() when doing something to a target. * Fixed events that were supposed to emag bots to now do so again.
348 lines
8.6 KiB
Plaintext
348 lines
8.6 KiB
Plaintext
#define MULE_IDLE 0
|
|
#define MULE_MOVING 1
|
|
#define MULE_UNLOAD 2
|
|
#define MULE_LOST 3
|
|
#define MULE_CALC_MIN 4
|
|
#define MULE_CALC_MAX 10
|
|
#define MULE_PATH_DONE 11
|
|
// IF YOU CHANGE THOSE, UPDATE THEM IN pda.tmpl TOO
|
|
|
|
/mob/living/bot/mulebot
|
|
name = "Mulebot"
|
|
desc = "A Multiple Utility Load Effector bot."
|
|
icon_state = "mulebot0"
|
|
anchored = 1
|
|
density = 1
|
|
health = 150
|
|
maxHealth = 150
|
|
mob_bump_flag = HEAVY
|
|
|
|
min_target_dist = 0
|
|
max_target_dist = 250
|
|
target_speed = 3
|
|
max_frustration = 5
|
|
botcard_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
|
|
|
var/atom/movable/load
|
|
|
|
var/paused = 0
|
|
var/crates_only = 1
|
|
var/auto_return = 1
|
|
var/safety = 1
|
|
|
|
var/targetName
|
|
var/turf/home
|
|
var/homeName
|
|
|
|
var/global/amount = 0
|
|
|
|
/mob/living/bot/mulebot/New()
|
|
..()
|
|
|
|
var/turf/T = get_turf(loc)
|
|
var/obj/machinery/navbeacon/N = locate() in T
|
|
if(N)
|
|
home = T
|
|
homeName = N.location
|
|
else
|
|
homeName = "Unset"
|
|
|
|
suffix = num2text(++amount) // Starts from 1
|
|
|
|
name = "Mulebot #[suffix]"
|
|
|
|
/mob/living/bot/mulebot/MouseDrop_T(var/atom/movable/C, var/mob/user)
|
|
if(user.stat)
|
|
return
|
|
|
|
if(!istype(C) || C.anchored || get_dist(user, src) > 1 || get_dist(src, C) > 1 )
|
|
return
|
|
|
|
load(C)
|
|
|
|
/mob/living/bot/mulebot/attack_hand(var/mob/user)
|
|
interact(user)
|
|
|
|
/mob/living/bot/mulebot/proc/interact(var/mob/user)
|
|
var/dat
|
|
dat += "<TT><B>Multiple Utility Load Effector Mk. III</B></TT><BR><BR>"
|
|
dat += "ID: [suffix]<BR>"
|
|
dat += "Power: [on ? "On" : "Off"]<BR>"
|
|
|
|
if(!open)
|
|
dat += "<BR>Current Load: [load ? load.name : "<i>none</i>"]<BR>"
|
|
|
|
if(locked)
|
|
dat += "<HR>Controls are locked"
|
|
else
|
|
dat += "<HR>Controls are unlocked<BR><BR>"
|
|
|
|
if(!locked || issilicon(user))
|
|
dat += "<A href='byond://?src=\ref[src];op=power'>Toggle power</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=stop'>Stop</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=go'>Proceed</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=home'>Return to home</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=destination'>Set destination</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=sethome'>Set home</A><BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=autoret'>Toggle auto return home</A> ([auto_return ? "On" : "Off"])<BR>"
|
|
dat += "<A href='byond://?src=\ref[src];op=cargotypes'>Toggle non-standard cargo</A> ([crates_only ? "Off" : "On"])<BR>"
|
|
|
|
if(load)
|
|
dat += "<A href='byond://?src=\ref[src];op=unload'>Unload now</A><BR>"
|
|
dat += "<HR>The maintenance hatch is closed.<BR>"
|
|
|
|
else
|
|
if(!issilicon(user))
|
|
dat += "The maintenance hatch is open.<BR><BR>"
|
|
|
|
dat += "<A href='byond://?src=\ref[src];op=safety'>Toggle safety</A> ([safety ? "On" : "Off - DANGER"])<BR>"
|
|
else
|
|
dat += "The bot is in maintenance mode and cannot be controlled.<BR>"
|
|
|
|
user << browse("<HEAD><TITLE>Mulebot [suffix ? "([suffix])" : ""]</TITLE></HEAD>[dat]", "window=mulebot;size=350x500")
|
|
onclose(user, "mulebot")
|
|
return
|
|
|
|
/mob/living/bot/mulebot/Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
usr.set_machine(src)
|
|
add_fingerprint(usr)
|
|
switch(href_list["op"])
|
|
if("power")
|
|
if(on)
|
|
turn_off()
|
|
else
|
|
turn_on()
|
|
visible_message("[usr] switches [on ? "on" : "off"] [src].")
|
|
|
|
if("stop")
|
|
obeyCommand("Stop")
|
|
|
|
if("go")
|
|
obeyCommand("GoTD")
|
|
|
|
if("home")
|
|
obeyCommand("Home")
|
|
|
|
if("destination")
|
|
obeyCommand("SetD")
|
|
|
|
if("sethome")
|
|
var/new_dest
|
|
var/list/beaconlist = GetBeaconList()
|
|
if(beaconlist.len)
|
|
new_dest = input("Select new home tag", "Mulebot [suffix ? "([suffix])" : ""]", null) in null|beaconlist
|
|
else
|
|
alert("No destination beacons available.")
|
|
if(new_dest)
|
|
home = get_turf(beaconlist[new_dest])
|
|
homeName = new_dest
|
|
|
|
if("unload")
|
|
unload()
|
|
|
|
if("autoret")
|
|
auto_return = !auto_return
|
|
|
|
if("cargotypes")
|
|
crates_only = !crates_only
|
|
|
|
if("safety")
|
|
safety = !safety
|
|
|
|
interact(usr)
|
|
|
|
/mob/living/bot/mulebot/attackby(var/obj/item/O, var/mob/user)
|
|
..()
|
|
update_icons()
|
|
|
|
/mob/living/bot/mulebot/proc/obeyCommand(var/command)
|
|
switch(command)
|
|
if("Home")
|
|
resetTarget()
|
|
target = home
|
|
targetName = "Home"
|
|
if("SetD")
|
|
var/new_dest
|
|
var/list/beaconlist = GetBeaconList()
|
|
if(beaconlist.len)
|
|
new_dest = input("Select new destination tag", "Mulebot [suffix ? "([suffix])" : ""]") in null|beaconlist
|
|
else
|
|
alert("No destination beacons available.")
|
|
if(new_dest)
|
|
resetTarget()
|
|
target = get_turf(beaconlist[new_dest])
|
|
targetName = new_dest
|
|
if("GoTD")
|
|
paused = 0
|
|
if("Stop")
|
|
paused = 1
|
|
|
|
/mob/living/bot/mulebot/emag_act(var/remaining_charges, var/user)
|
|
locked = !locked
|
|
user << "<span class='notice'>You [locked ? "lock" : "unlock"] the mulebot's controls!</span>"
|
|
flick("mulebot-emagged", src)
|
|
playsound(loc, 'sound/effects/sparks1.ogg', 100, 0)
|
|
return 1
|
|
|
|
/mob/living/bot/mulebot/update_icons()
|
|
if(open)
|
|
icon_state = "mulebot-hatch"
|
|
return
|
|
if(target_path.len && !paused)
|
|
icon_state = "mulebot1"
|
|
return
|
|
icon_state = "mulebot0"
|
|
|
|
/mob/living/bot/mulebot/handleRegular()
|
|
if(!safety && prob(1))
|
|
flick("mulebot-emagged", src)
|
|
update_icons()
|
|
|
|
/mob/living/bot/mulebot/handleFrustrated()
|
|
custom_emote(2, "makes a sighing buzz.")
|
|
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
|
..()
|
|
|
|
/mob/living/bot/mulebot/handleAdjacentTarget()
|
|
if(target == src.loc)
|
|
custom_emote(2, "makes a chiming sound.")
|
|
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
|
|
UnarmedAttack(target)
|
|
resetTarget()
|
|
if(auto_return && home && (loc != home))
|
|
target = home
|
|
targetName = "Home"
|
|
|
|
/mob/living/bot/mulebot/confirmTarget()
|
|
return 1
|
|
|
|
/mob/living/bot/mulebot/calcTargetPath()
|
|
..()
|
|
if(!target_path.len && target != home) // I presume that target is not null
|
|
resetTarget()
|
|
target = home
|
|
targetName = "Home"
|
|
|
|
/mob/living/bot/mulebot/stepToTarget()
|
|
if(paused)
|
|
return
|
|
..()
|
|
|
|
/mob/living/bot/mulebot/UnarmedAttack(var/turf/T)
|
|
if(T == src.loc)
|
|
unload(dir)
|
|
|
|
/mob/living/bot/mulebot/Bump(var/mob/living/M)
|
|
if(!safety && istype(M))
|
|
visible_message("<span class='warning'>[src] knocks over [M]!</span>")
|
|
M.Stun(8)
|
|
M.Weaken(5)
|
|
..()
|
|
|
|
/mob/living/bot/mulebot/proc/runOver(var/mob/living/carbon/human/H)
|
|
if(istype(H)) // No safety checks - WILL run over lying humans. Stop ERPing in the maint!
|
|
visible_message("<span class='warning'>[src] drives over [H]!</span>")
|
|
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
|
|
|
|
var/damage = rand(5, 7)
|
|
H.apply_damage(2 * damage, BRUTE, BP_HEAD)
|
|
H.apply_damage(2 * damage, BRUTE, BP_TORSO)
|
|
H.apply_damage(0.5 * damage, BRUTE, BP_L_LEG)
|
|
H.apply_damage(0.5 * damage, BRUTE, BP_R_LEG)
|
|
H.apply_damage(0.5 * damage, BRUTE, BP_L_ARM)
|
|
H.apply_damage(0.5 * damage, BRUTE, BP_R_ARM)
|
|
|
|
blood_splatter(src, H, 1)
|
|
..()
|
|
|
|
/mob/living/bot/mulebot/relaymove(var/mob/user, var/direction)
|
|
if(load == user)
|
|
unload(direction)
|
|
|
|
/mob/living/bot/mulebot/explode()
|
|
unload(pick(0, 1, 2, 4, 8))
|
|
|
|
visible_message("<span class='danger'>[src] blows apart!</span>")
|
|
|
|
var/turf/Tsec = get_turf(src)
|
|
new /obj/item/device/assembly/prox_sensor(Tsec)
|
|
PoolOrNew(/obj/item/stack/rods, Tsec)
|
|
PoolOrNew(/obj/item/stack/rods, Tsec)
|
|
new /obj/item/stack/cable_coil/cut(Tsec)
|
|
|
|
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
|
s.set_up(3, 1, src)
|
|
s.start()
|
|
|
|
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
|
..()
|
|
|
|
/mob/living/bot/mulebot/proc/GetBeaconList()
|
|
var/list/beaconlist = list()
|
|
for(var/obj/machinery/navbeacon/N in navbeacons)
|
|
if(!N.codes["delivery"])
|
|
continue
|
|
beaconlist.Add(N.location)
|
|
beaconlist[N.location] = N
|
|
return beaconlist
|
|
|
|
/mob/living/bot/mulebot/proc/load(var/atom/movable/C)
|
|
if(busy || load || get_dist(C, src) > 1 || !isturf(C.loc))
|
|
return
|
|
|
|
for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account
|
|
if(!CanPass(C,P))
|
|
return
|
|
|
|
if(crates_only && !istype(C,/obj/structure/closet/crate))
|
|
custom_emote(2, "makes a sighing buzz.")
|
|
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
|
return
|
|
|
|
var/obj/structure/closet/crate/crate = C
|
|
if(istype(crate))
|
|
crate.close()
|
|
|
|
busy = 1
|
|
|
|
C.forceMove(loc)
|
|
sleep(2)
|
|
if(C.loc != loc) //To prevent you from going onto more than one bot.
|
|
return
|
|
C.forceMove(src)
|
|
load = C
|
|
|
|
C.pixel_y += 9
|
|
if(C.layer < layer)
|
|
C.layer = layer + 0.1
|
|
overlays += C
|
|
|
|
busy = 0
|
|
|
|
/mob/living/bot/mulebot/proc/unload(var/dirn = 0)
|
|
if(!load || busy)
|
|
return
|
|
|
|
busy = 1
|
|
overlays.Cut()
|
|
|
|
load.forceMove(loc)
|
|
load.pixel_y -= 9
|
|
load.layer = initial(load.layer)
|
|
|
|
if(dirn)
|
|
step(load, dirn)
|
|
|
|
load = null
|
|
|
|
for(var/atom/movable/AM in src)
|
|
if(AM == botcard || AM == access_scanner)
|
|
continue
|
|
|
|
AM.forceMove(loc)
|
|
AM.layer = initial(AM.layer)
|
|
AM.pixel_y = initial(AM.pixel_y)
|
|
busy = 0
|