diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 5bb4c93bbc..9213765bbc 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -1,10 +1,6 @@ /atom/movable/proc/get_mob() return -/obj/machinery/bot/mulebot/get_mob() - if(load && istype(load,/mob/living)) - return load - /obj/mecha/get_mob() return occupant @@ -14,6 +10,11 @@ /mob/get_mob() return src +/mob/living/bot/mulebot/get_mob() + if(load && istype(load, /mob/living)) + return list(src, load) + return src + /proc/mobs_in_view(var/range, var/source) var/list/mobs = list() for(var/atom/movable/AM in view(range, source)) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 55fe373301..d1c0b7b505 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -20,7 +20,7 @@ return // seems legit. // Things you might plausibly want to follow - if((ismob(A) && A != src) || istype(A,/obj/machinery/bot) || istype(A,/obj/singularity)) + if((ismob(A) && A != src) || istype(A,/obj/singularity)) ManualFollow(A) // Otherwise jump diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index a7b9dc0309..53850a102b 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -278,11 +278,11 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee group = "Miscellaneous" /datum/supply_packs/mule - name = "MULEbot Crate" - contains = list(/obj/machinery/bot/mulebot) + name = "Mulebot Crate" + contains = list() cost = 20 - containertype = /obj/structure/largecrate/mule - containername = "MULEbot Crate" + containertype = /obj/structure/largecrate/animal/mulebot + containername = "Mulebot Crate" group = "Operations" /datum/supply_packs/cargotrain diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm deleted file mode 100644 index 312e6dd7d9..0000000000 --- a/code/datums/wires/mulebot.dm +++ /dev/null @@ -1,65 +0,0 @@ -/datum/wires/mulebot - random = 1 - holder_type = /obj/machinery/bot/mulebot - wire_count = 10 - -var/const/WIRE_POWER1 = 1 // power connections -var/const/WIRE_POWER2 = 2 -var/const/WIRE_AVOIDANCE = 4 // mob avoidance -var/const/WIRE_LOADCHECK = 8 // load checking (non-crate) -var/const/WIRE_MOTOR1 = 16 // motor wires -var/const/WIRE_MOTOR2 = 32 // -var/const/WIRE_REMOTE_RX = 64 // remote recv functions -var/const/WIRE_REMOTE_TX = 128 // remote trans status -var/const/WIRE_BEACON_RX = 256 // beacon ping recv - -/datum/wires/mulebot/CanUse(var/mob/living/L) - var/obj/machinery/bot/mulebot/M = holder - if(M.open) - return 1 - return 0 - -// So the wires do not open a new window, handle the interaction ourselves. -/datum/wires/mulebot/Interact(var/mob/living/user) - if(CanUse(user)) - var/obj/machinery/bot/mulebot/M = holder - M.interact(user) - -/datum/wires/mulebot/UpdatePulsed(var/index) - switch(index) - if(WIRE_POWER1, WIRE_POWER2) - holder.visible_message("\icon[holder] The charge light flickers.") - if(WIRE_AVOIDANCE) - holder.visible_message("\icon[holder] The external warning lights flash briefly.") - if(WIRE_LOADCHECK) - holder.visible_message("\icon[holder] The load platform clunks.") - if(WIRE_MOTOR1, WIRE_MOTOR2) - holder.visible_message("\icon[holder] The drive motor whines briefly.") - else - holder.visible_message("\icon[holder] You hear a radio crackle.") - -// HELPER PROCS - -/datum/wires/mulebot/proc/Motor1() - return !(wires_status & WIRE_MOTOR1) - -/datum/wires/mulebot/proc/Motor2() - return !(wires_status & WIRE_MOTOR2) - -/datum/wires/mulebot/proc/HasPower() - return !(wires_status & WIRE_POWER1) && !(wires_status & WIRE_POWER2) - -/datum/wires/mulebot/proc/LoadCheck() - return !(wires_status & WIRE_LOADCHECK) - -/datum/wires/mulebot/proc/MobAvoid() - return !(wires_status & WIRE_AVOIDANCE) - -/datum/wires/mulebot/proc/RemoteTX() - return !(wires_status & WIRE_REMOTE_TX) - -/datum/wires/mulebot/proc/RemoteRX() - return !(wires_status & WIRE_REMOTE_RX) - -/datum/wires/mulebot/proc/BeaconRX() - return !(wires_status & WIRE_BEACON_RX) diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index f644391bf7..2b54b4ef27 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -422,11 +422,6 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is M << "
" M.add_ion_law("THE STATION IS [who2pref] [who2]") - if(botEmagChance) - for(var/obj/machinery/bot/bot in machines) - if(prob(botEmagChance)) - bot.emag_act(1) - /* var/apcnum = 0 diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm deleted file mode 100644 index 7e03826f05..0000000000 --- a/code/game/machinery/bots/bots.dm +++ /dev/null @@ -1,209 +0,0 @@ -// AI (i.e. game AI, not the AI player) controlled bots - -/obj/machinery/bot - icon = 'icons/obj/aibots.dmi' - layer = MOB_LAYER - light_range = 3 - use_power = 0 - var/obj/item/weapon/card/id/botcard // the ID card that the bot "holds" - var/on = 1 - var/health = 0 //do not forget to set health for your bot! - var/maxhealth = 0 - var/fire_dam_coeff = 1.0 - var/brute_dam_coeff = 1.0 - var/open = 0//Maint panel - var/locked = 1 - //var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots - -/obj/machinery/bot/proc/turn_on() - if(stat) return 0 - on = 1 - set_light(initial(light_range)) - return 1 - -/obj/machinery/bot/proc/turn_off() - on = 0 - set_light(0) - -/obj/machinery/bot/proc/explode() - qdel(src) - -/obj/machinery/bot/proc/healthcheck() - if (src.health <= 0) - src.explode() - -/obj/machinery/bot/emag_act(var/remaining_charges, var/user) - if(locked && !emagged) - locked = 0 - emagged = 1 - user << "You short out [src]'s maintenance hatch lock." - log_and_message_admins("emagged [src]'s maintenance hatch lock") - return 1 - - if(!locked && open && emagged == 1) - emagged = 2 - log_and_message_admins("emagged [src]'s inner circuits") - return 1 - -/obj/machinery/bot/examine(mob/user) - ..(user) - if (src.health < maxhealth) - if (src.health > maxhealth/3) - user << "[src]'s parts look loose." - else - user << "[src]'s parts look very loose!" - return - -/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/screwdriver)) - if(!locked) - open = !open - user << "Maintenance panel is now [src.open ? "opened" : "closed"]." - else if(istype(W, /obj/item/weapon/weldingtool)) - if(health < maxhealth) - if(open) - health = min(maxhealth, health+10) - user.visible_message("[user] repairs [src]!","You repair [src]!") - else - user << "Unable to repair with the maintenance panel closed." - else - user << "[src] does not need a repair." - else - if(hasvar(W,"force") && hasvar(W,"damtype")) - switch(W.damtype) - if("fire") - src.health -= W.force * fire_dam_coeff - if("brute") - src.health -= W.force * brute_dam_coeff - ..() - healthcheck() - else - ..() - -/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj) - if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - return - health -= Proj.damage - ..() - healthcheck() - -/obj/machinery/bot/ex_act(severity) - switch(severity) - if(1.0) - src.explode() - return - if(2.0) - src.health -= rand(5,10)*fire_dam_coeff - src.health -= rand(10,20)*brute_dam_coeff - healthcheck() - return - if(3.0) - if (prob(50)) - src.health -= rand(1,5)*fire_dam_coeff - src.health -= rand(1,5)*brute_dam_coeff - healthcheck() - return - return - -/obj/machinery/bot/emp_act(severity) - var/was_on = on - stat |= EMPED - var/obj/effect/overlay/pulse2 = PoolOrNew(/obj/effect/overlay, src.loc ) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.set_dir(pick(cardinal)) - - spawn(10) - qdel(pulse2) - if (on) - turn_off() - spawn(severity*300) - stat &= ~EMPED - if (was_on) - turn_on() - - -/obj/machinery/bot/attack_ai(mob/user as mob) - src.attack_hand(user) - -/obj/machinery/bot/attack_hand(var/mob/living/carbon/human/user) - - if(!istype(user)) - return ..() - - if(user.species.can_shred(user)) - src.health -= rand(15,30)*brute_dam_coeff - src.visible_message("[user] has slashed [src]!") - playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) - if(prob(10)) - new /obj/effect/decal/cleanable/blood/oil(src.loc) - healthcheck() - -/******************************************************************/ -// Navigation procs -// Used for A-star pathfinding - - -// Returns the surrounding cardinal turfs with open links -// Including through doors openable with the ID -/turf/proc/CardinalTurfsWithAccess(var/obj/item/weapon/card/id/ID) - var/L[] = new() - - // for(var/turf/simulated/t in oview(src,1)) - - for(var/d in cardinal) - var/turf/simulated/T = get_step(src, d) - if(istype(T) && !T.density) - if(!LinkBlockedWithAccess(src, T, ID)) - L.Add(T) - return L - - -// Returns true if a link between A and B is blocked -// Movement through doors allowed if ID has access -/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID) - - if(A == null || B == null) return 1 - var/adir = get_dir(A,B) - var/rdir = get_dir(B,A) - if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal - var/iStep = get_step(A,adir&(NORTH|SOUTH)) - if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID)) - return 0 - - var/pStep = get_step(A,adir&(EAST|WEST)) - if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID)) - return 0 - return 1 - - if(DirBlockedWithAccess(A,adir, ID)) - return 1 - - if(DirBlockedWithAccess(B,rdir, ID)) - return 1 - - for(var/obj/O in B) - if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) - return 1 - - return 0 - -// Returns true if direction is blocked from loc -// Checks doors against access with given ID -/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID) - for(var/obj/structure/window/D in loc) - if(!D.density) continue - if(D.dir == SOUTHWEST) return 1 - if(D.dir == dir) return 1 - - for(var/obj/machinery/door/D in loc) - if(!D.density) continue - if(istype(D, /obj/machinery/door/window)) - if( dir & D.dir ) return !D.check_access(ID) - - //if((dir & SOUTH) && (D.dir & (EAST|WEST))) return !D.check_access(ID) - //if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID) - else return !D.check_access(ID) // it's a real, air blocking door - return 0 diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm deleted file mode 100644 index 27e6cb1a9d..0000000000 --- a/code/game/machinery/bots/mulebot.dm +++ /dev/null @@ -1,887 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -// Mulebot - carries crates around for Quartermaster -// Navigates via floor navbeacons -// Remote Controlled from QM's PDA - - -/obj/machinery/bot/mulebot - name = "Mulebot" - desc = "A Multiple Utility Load Effector bot." - icon_state = "mulebot0" - layer = MOB_LAYER - density = 1 - anchored = 1 - animate_movement=1 - health = 150 //yeah, it's tougher than ed209 because it is a big metal box with wheels --rastaf0 - maxhealth = 150 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 - var/atom/movable/load = null // the loaded crate (usually) - var/beacon_freq = 1400 - var/control_freq = BOT_FREQ - - suffix = "" - - var/turf/target // this is turf to navigate to (location of beacon) - var/loaddir = 0 // this the direction to unload onto/load from - var/new_destination = "" // pending new destination (waiting for beacon response) - var/destination = "" // destination description - var/home_destination = "" // tag of home beacon - req_access = list(access_cargo) // added robotics access so assembly line drop-off works properly -veyveyr //I don't think so, Tim. You need to add it to the MULE's hidden robot ID card. -NEO - var/path[] = new() - - var/mode = 0 //0 = idle/ready - //1 = loading/unloading - //2 = moving to deliver - //3 = returning to home - //4 = blocked - //5 = computing navigation - //6 = waiting for nav computation - //7 = no destination beacon found (or no route) - - var/blockcount = 0 //number of times retried a blocked path - var/reached_target = 1 //true if already reached the target - - var/refresh = 1 // true to refresh dialogue - var/auto_return = 1 // true if auto return to home beacon after unload - var/auto_pickup = 1 // true if auto-pickup at beacon - - var/obj/item/weapon/cell/cell - // the installed power cell - - // constants for internal wiring bitflags - var/datum/wires/mulebot/wires = null - - var/bloodiness = 0 // count of bloodiness - -/obj/machinery/bot/mulebot/New() - ..() - wires = new(src) - botcard = new(src) - botcard.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) - cell = new(src) - cell.charge = 2000 - cell.maxcharge = 2000 - - spawn(5) // must wait for map loading to finish - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - - var/count = 0 - for(var/obj/machinery/bot/mulebot/other in world) - count++ - if(!suffix) - suffix = "#[count]" - name = "Mulebot ([suffix])" - -/obj/machinery/bot/mulebot/Destroy() - unload(0) - qdel(wires) - wires = null - if(radio_controller) - radio_controller.remove_object(src,beacon_freq) - radio_controller.remove_object(src,control_freq) - return ..() - -// attack by item -// emag : lock/unlock, -// screwdriver: open/close hatch -// cell: insert it -// other: chance to knock rider off bot -/obj/machinery/bot/mulebot/attackby(var/obj/item/I, var/mob/user) - if(istype(I,/obj/item/weapon/cell) && open && !cell) - var/obj/item/weapon/cell/C = I - user.drop_item() - C.loc = src - cell = C - updateDialog() - else if(istype(I,/obj/item/weapon/screwdriver)) - if(locked) - user << "The maintenance hatch cannot be opened or closed while the controls are locked." - return - - open = !open - if(open) - src.visible_message("[user] opens the maintenance hatch of [src]", "You open [src]'s maintenance hatch.") - on = 0 - icon_state="mulebot-hatch" - else - src.visible_message("[user] closes the maintenance hatch of [src]", "You close [src]'s maintenance hatch.") - icon_state = "mulebot0" - - updateDialog() - else if (istype(I, /obj/item/weapon/wrench)) - if (src.health < maxhealth) - src.health = min(maxhealth, src.health+25) - user.visible_message( - "\The [user] repairs \the [src]!", - "You repair \the [src]!" - ) - else - user << "[src] does not need a repair!" - else if(load && ismob(load)) // chance to knock off rider - if(prob(1+I.force * 2)) - unload(0) - user.visible_message("[user] knocks [load] off [src] with \the [I]!", "You knock [load] off [src] with \the [I]!") - else - user << "You hit [src] with \the [I] but to no effect." - else - ..() - return - -/obj/machinery/bot/mulebot/emag_act(var/remaining_charges, var/user) - locked = !locked - user << "You [locked ? "lock" : "unlock"] the mulebot's controls!" - flick("mulebot-emagged", src) - playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 0) - return 1 - -/obj/machinery/bot/mulebot/ex_act(var/severity) - unload(0) - switch(severity) - if(2) - BITRESET(wires, rand(0,9)) - BITRESET(wires, rand(0,9)) - BITRESET(wires, rand(0,9)) - if(3) - BITRESET(wires, rand(0,9)) - ..() - return - -/obj/machinery/bot/mulebot/bullet_act() - if(prob(50) && !isnull(load)) - unload(0) - if(prob(25)) - src.visible_message("Something shorts out inside [src]!") - var/index = 1<< (rand(0,9)) - if(wires & index) - wires &= ~index - else - wires |= index - ..() - - -/obj/machinery/bot/mulebot/attack_ai(var/mob/user) - user.set_machine(src) - interact(user, 1) - -/obj/machinery/bot/mulebot/attack_hand(var/mob/user) - . = ..() - if (.) - return - user.set_machine(src) - interact(user, 0) - -/obj/machinery/bot/mulebot/interact(var/mob/user, var/ai=0) - var/dat - dat += "Multiple Utility Load Effector Mk. III

" - dat += "ID: [suffix]
" - dat += "Power: [on ? "On" : "Off"]
" - - if(!open) - - dat += "Status: " - switch(mode) - if(0) - dat += "Ready" - if(1) - dat += "Loading/Unloading" - if(2) - dat += "Navigating to Delivery Location" - if(3) - dat += "Navigating to Home" - if(4) - dat += "Waiting for clear path" - if(5,6) - dat += "Calculating navigation path" - if(7) - dat += "Unable to locate destination" - - - dat += "
Current Load: [load ? load.name : "none"]
" - dat += "Destination: [!destination ? "none" : destination]
" - dat += "Power level: [cell ? cell.percent() : 0]%
" - - if(locked && !ai) - dat += "
Controls are locked (unlock)" - else - dat += "
Controls are unlocked (lock)

" - - dat += "Toggle Power
" - dat += "Stop
" - dat += "Proceed
" - dat += "Return to Home
" - dat += "Set Destination
" - dat += "Set Bot ID
" - dat += "Set Home
" - dat += "Toggle Auto Return Home ([auto_return ? "On":"Off"])
" - dat += "Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
" - - if(load) - dat += "Unload Now
" - dat += "
The maintenance hatch is closed.
" - - else - if(!ai) - dat += "The maintenance hatch is open.

" - dat += "Power cell: " - if(cell) - dat += "Installed
" - else - dat += "Removed
" - - dat += wires.GetInteractWindow() - else - dat += "The bot is in maintenance mode and cannot be controlled.
" - - user << browse("Mulebot [suffix ? "([suffix])" : ""][dat]", "window=mulebot;size=350x500") - onclose(user, "mulebot") - return - -/obj/machinery/bot/mulebot/Topic(href, href_list) - if(..()) - return - if (usr.stat) - return - if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - switch(href_list["op"]) - if("lock", "unlock") - if(src.allowed(usr)) - locked = !locked - updateDialog() - else - usr << "Access denied." - return - if("power") - if (src.on) - turn_off() - else if (cell && !open) - if (!turn_on()) - usr << "You can't switch on [src]." - return - else - return - visible_message("[usr] switches [on ? "on" : "off"] [src].") - updateDialog() - - - if("cellremove") - if(open && cell && !usr.get_active_hand()) - cell.update_icon() - usr.put_in_active_hand(cell) - cell.add_fingerprint(usr) - cell = null - - usr.visible_message("[usr] removes the power cell from [src].", "You remove the power cell from [src].") - updateDialog() - - if("cellinsert") - if(open && !cell) - var/obj/item/weapon/cell/C = usr.get_active_hand() - if(istype(C)) - usr.drop_item() - cell = C - C.loc = src - C.add_fingerprint(usr) - - usr.visible_message("[usr] inserts a power cell into [src].", "You insert the power cell into [src].") - updateDialog() - - - if("stop") - if(mode >=2) - mode = 0 - updateDialog() - - if("go") - if(mode == 0) - start() - updateDialog() - - if("home") - if(mode == 0 || mode == 2) - start_home() - updateDialog() - - if("destination") - refresh=0 - var/new_dest - var/list/beaconlist = new() - for(var/obj/machinery/navbeacon/N in navbeacons) - beaconlist.Add(N.location) - if(beaconlist.len) - new_dest = input("Select new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", destination) in beaconlist - else - alert("No destination beacons available.") - refresh=1 - if(new_dest) - set_destination(new_dest) - - - if("setid") - refresh=0 - var/new_id = sanitize(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", suffix) as text|null, MAX_NAME_LEN) - refresh=1 - if(new_id) - suffix = new_id - name = "Mulebot ([suffix])" - updateDialog() - - if("sethome") - refresh=0 - var/new_home = input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", home_destination) as text|null - refresh=1 - if(new_home) - home_destination = new_home - updateDialog() - - if("unload") - if(load && mode !=1) - if(loc == target) - unload(loaddir) - else - unload(0) - - if("autoret") - auto_return = !auto_return - - if("autopick") - auto_pickup = !auto_pickup - - if("close") - usr.unset_machine() - usr << browse(null,"window=mulebot") - - updateDialog() - //src.updateUsrDialog() - else - usr << browse(null, "window=mulebot") - usr.unset_machine() - return - - - -// returns true if the bot has power -/obj/machinery/bot/mulebot/proc/has_power() - return !open && cell && cell.charge>0 && wires.HasPower() - -// mousedrop a crate to load the bot -// can load anything if emagged - -/obj/machinery/bot/mulebot/MouseDrop_T(var/atom/movable/C, mob/user) - - if(user.stat) - return - - if (!on || !istype(C)|| C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 ) - return - - if(load) - return - - load(C) - - -// called to load a crate -/obj/machinery/bot/mulebot/proc/load(var/atom/movable/C) - if(wires.LoadCheck() && !istype(C,/obj/structure/closet/crate)) - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - return // if not emagged, only allow crates to be loaded - - //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool. - //So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below. - if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C)) - return - if(!isturf(C.loc)) //To prevent the loading from stuff from someone's inventory, which wouldn't get handled properly. - return - - if(get_dist(C, src) > 1 || load || !on) - return - for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account - if(!CanPass(C,P)) - return - mode = 1 - - // if a create, close before loading - var/obj/structure/closet/crate/crate = C - if(istype(crate)) - crate.close() - - C.loc = src.loc - sleep(2) - if(C.loc != src.loc) //To prevent you from going onto more thano ne bot. - return - C.loc = src - load = C - - C.pixel_y += 9 - if(C.layer < layer) - C.layer = layer + 0.1 - overlays += C - - if(ismob(C)) - var/mob/M = C - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - mode = 0 - send_status() - -// called to unload the bot -// argument is optional direction to unload -// if zero, unload at bot's location -/obj/machinery/bot/mulebot/proc/unload(var/dirn = 0) - if(!load) - return - - mode = 1 - overlays.Cut() - - load.loc = src.loc - load.pixel_y -= 9 - load.layer = initial(load.layer) - if(ismob(load)) - var/mob/M = load - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - - - if(dirn) - var/turf/T = src.loc - T = get_step(T,dirn) - if(CanPass(load,T))//Can't get off onto anything that wouldn't let you pass normally - step(load, dirn) - else - load.loc = src.loc//Drops you right there, so you shouldn't be able to get yourself stuck - - load = null - - // in case non-load items end up in contents, dump every else too - // this seems to happen sometimes due to race conditions - // with items dropping as mobs are loaded - - for(var/atom/movable/AM in src) - if(AM == cell || AM == botcard) continue - - AM.loc = src.loc - AM.layer = initial(AM.layer) - AM.pixel_y = initial(AM.pixel_y) - if(ismob(AM)) - var/mob/M = AM - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - mode = 0 - - -/obj/machinery/bot/mulebot/process() - if(!has_power()) - on = 0 - return - if(on) - var/speed = (wires.Motor1() ? 1:0) + (wires.Motor2() ? 2:0) - //world << "speed: [speed]" - switch(speed) - if(0) - // do nothing - if(1) - process_bot() - spawn(2) - process_bot() - sleep(2) - process_bot() - sleep(2) - process_bot() - sleep(2) - process_bot() - if(2) - process_bot() - spawn(4) - process_bot() - if(3) - process_bot() - - if(refresh) updateDialog() - -/obj/machinery/bot/mulebot/proc/process_bot() - //if(mode) world << "Mode: [mode]" - switch(mode) - if(0) // idle - icon_state = "mulebot0" - return - if(1) // loading/unloading - return - if(2,3,4) // navigating to deliver,home, or blocked - - if(loc == target) // reached target - at_target() - return - - else if(path.len > 0 && target) // valid path - - var/turf/next = path[1] - reached_target = 0 - if(next == loc) - path -= next - return - - - if(istype( next, /turf/simulated)) - //world << "at ([x],[y]) moving to ([next.x],[next.y])" - - - if(bloodiness) - var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) - var/newdir = get_dir(next, loc) - if(newdir == dir) - B.set_dir(newdir) - else - newdir = newdir | dir - if(newdir == 3) - newdir = 1 - else if(newdir == 12) - newdir = 4 - B.set_dir(newdir) - bloodiness-- - - - - var/moved = step_towards(src, next) // attempt to move - if(cell) cell.use(1) - if(moved) // successful move - //world << "Successful move." - blockcount = 0 - path -= loc - - - if(mode==4) - spawn(1) - send_status() - - if(destination == home_destination) - mode = 3 - else - mode = 2 - - else // failed to move - - //world << "Unable to move." - - - - blockcount++ - mode = 4 - if(blockcount == 3) - src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.") - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - - spawn(2) - calc_path(next) - if(path.len > 0) - src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - mode = 4 - mode =6 - return - return - else - src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.") - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) - //world << "Bad turf." - mode = 5 - return - else - //world << "No path." - mode = 5 - return - - if(5) // calculate new path - //world << "Calc new path." - mode = 6 - spawn(0) - - calc_path() - - if(path.len > 0) - blockcount = 0 - mode = 4 - src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - - else - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - - mode = 7 - //if(6) - //world << "Pending path calc." - //if(7) - //world << "No dest / no route." - return - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id=botcard, exclude=avoid) - if(!src.path) - src.path = list() - - -// sets the current destination -// signals all beacons matching the delivery code -// beacons will return a signal giving their locations -/obj/machinery/bot/mulebot/proc/set_destination(var/new_dest) - spawn(0) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "delivery") - updateDialog() - -// starts bot moving to current destination -/obj/machinery/bot/mulebot/proc/start() - if(destination == home_destination) - mode = 3 - else - mode = 2 - icon_state = "mulebot[wires.MobAvoid()]" - -// starts bot moving to home -// sends a beacon query to find -/obj/machinery/bot/mulebot/proc/start_home() - spawn(0) - set_destination(home_destination) - mode = 4 - icon_state = "mulebot[wires.MobAvoid()]" - -// called when bot reaches current target -/obj/machinery/bot/mulebot/proc/at_target() - if(!reached_target) - src.visible_message("[src] makes a chiming sound!", "You hear a chime.") - playsound(src.loc, 'sound/machines/chime.ogg', 50, 0) - reached_target = 1 - - if(load) // if loaded, unload at target - unload(loaddir) - else - // not loaded - if(auto_pickup) // find a crate - var/atom/movable/AM - if(!wires.LoadCheck()) // if emagged, load first unanchored thing we find - for(var/atom/movable/A in get_step(loc, loaddir)) - if(!A.anchored) - AM = A - break - else // otherwise, look for crates only - AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir) - if(AM) - load(AM) - // whatever happened, check to see if we return home - - if(auto_return && destination != home_destination) - // auto return set and not at home already - start_home() - mode = 4 - else - mode = 0 // otherwise go idle - - send_status() // report status to anyone listening - - return - -// called when bot bumps into anything -/obj/machinery/bot/mulebot/Bump(var/atom/obs) - if(!wires.MobAvoid()) //usually just bumps, but if avoidance disabled knock over mobs - var/mob/M = obs - if(ismob(M)) - if(istype(M,/mob/living/silicon/robot)) - src.visible_message("[src] bumps into [M]!") - else - src.visible_message("[src] knocks over [M]!") - M.stop_pulling() - M.Stun(8) - M.Weaken(5) - M.lying = 1 - ..() - -// called from mob/living/carbon/human/Crossed() -// when mulebot is in the same loc -/obj/machinery/bot/mulebot/proc/RunOver(var/mob/living/carbon/human/H) - src.visible_message("[src] drives over [H]!") - playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) - - var/damage = rand(5,15) - 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) - bloodiness += 4 - -// player on mulebot attempted to move -/obj/machinery/bot/mulebot/relaymove(var/mob/user) - if(user.stat) - return - if(load == user) - unload(0) - return - -// receive a radio signal -// used for control and beacon reception - -/obj/machinery/bot/mulebot/receive_signal(datum/signal/signal) - - if(!on) - return - - var/recv = signal.data["command"] - // process all-bot input - if(recv=="bot_status" && wires.RemoteRX()) - send_status() - - - recv = signal.data["command [suffix]"] - if(wires.RemoteRX()) - // process control input - switch(recv) - if("stop") - mode = 0 - return - - if("go") - start() - return - - if("target") - set_destination(signal.data["destination"] ) - return - - if("unload") - if(loc == target) - unload(loaddir) - else - unload(0) - return - - if("home") - start_home() - return - - if("bot_status") - send_status() - return - - if("autoret") - auto_return = text2num(signal.data["value"]) - return - - if("autopick") - auto_pickup = text2num(signal.data["value"]) - return - - // receive response from beacon - recv = signal.data["beacon"] - if(wires.BeaconRX()) - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - target = signal.source.loc - var/direction = signal.data["dir"] // this will be the load/unload dir - if(direction) - loaddir = text2num(direction) - else - loaddir = 0 - icon_state = "mulebot[wires.MobAvoid()]" - calc_path() - updateDialog() - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/mulebot/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/mulebot/proc/post_signal_multiple(var/freq, var/list/keyval) - - if(freq == beacon_freq && !wires.BeaconRX()) - return - if(freq == control_freq && !wires.RemoteTX()) - return - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - - - var/datum/signal/signal = new() - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval - //world << "sent [key],[keyval[key]] on [freq]" - if (signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else if (signal.data["type"] == "mulebot") - frequency.post_signal(src, signal, filter = RADIO_MULEBOT) - else - frequency.post_signal(src, signal) - -// signals bot status etc. to controller -/obj/machinery/bot/mulebot/proc/send_status() - var/list/kv = list( - "type" = "mulebot", - "name" = suffix, - "loca" = (loc ? loc.loc : "Unknown"), // somehow loc can be null and cause a runtime - Quarxink - "mode" = mode, - "powr" = (cell ? cell.percent() : 0), - "dest" = destination, - "home" = home_destination, - "load" = load, - "retn" = auto_return, - "pick" = auto_pickup, - ) - post_signal_multiple(control_freq, kv) - -/obj/machinery/bot/mulebot/emp_act(severity) - if (cell) - cell.emp_act(severity) - if(load) - load.emp_act(severity) - ..() - - -/obj/machinery/bot/mulebot/explode() - src.visible_message("[src] blows apart!", 1) - 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) - if (cell) - cell.loc = Tsec - cell.update_icon() - cell = null - - 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(src.loc) - unload(0) - qdel(src) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index f583b620a4..c605ed3644 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -103,13 +103,6 @@ bumpopen(M) return - if(istype(AM, /obj/machinery/bot)) - var/obj/machinery/bot/bot = AM - if(src.check_access(bot.botcard)) - if(density) - open() - return - if(istype(AM, /mob/living/bot)) var/mob/living/bot/bot = AM if(src.check_access(bot.botcard)) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 6b423f1309..0d304a1e07 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -420,8 +420,8 @@ var/global/list/obj/item/device/pda/PDAs = list() cartdata["radio"] = 1 if(istype(cartridge.radio, /obj/item/radio/integrated/signal)) cartdata["radio"] = 2 - if(istype(cartridge.radio, /obj/item/radio/integrated/mule)) - cartdata["radio"] = 3 + //if(istype(cartridge.radio, /obj/item/radio/integrated/mule)) + // cartdata["radio"] = 3 if(mode == 2) cartdata["charges"] = cartridge.charges ? cartridge.charges : 0 diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 2c91285e08..24a2db67d7 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -124,10 +124,6 @@ icon_state = "cart-q" access_quartermaster = 1 -/obj/item/weapon/cartridge/quartermaster/initialize() - radio = new /obj/item/radio/integrated/mule(src) - ..() - /obj/item/weapon/cartridge/head name = "\improper Easy-Record DELUXE" icon_state = "cart-h" @@ -141,9 +137,6 @@ access_janitor = 1 access_security = 1 -/obj/item/weapon/cartridge/hop/initialize() - radio = new /obj/item/radio/integrated/mule(src) - /obj/item/weapon/cartridge/hos name = "\improper R.O.B.U.S.T. DELUXE" icon_state = "cart-hos" @@ -351,40 +344,26 @@ /* MULEBOT Control (Mode: 48) */ if(mode==48) - var/muleData[0] var/mulebotsData[0] - if(istype(radio,/obj/item/radio/integrated/mule)) - var/obj/item/radio/integrated/mule/QC = radio - muleData["active"] = QC.active - if(QC.active && !isnull(QC.botstatus)) - var/area/loca = QC.botstatus["loca"] - var/loca_name = sanitize(loca.name) - muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"])) + var/count = 0 - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) + for(var/mob/living/bot/mulebot/M in living_mob_list) + if(!M.on) + continue + ++count + var/muleData[0] + muleData["name"] = M.suffix + muleData["location"] = get_area(M) + muleData["mode"] = M.mode + muleData["home"] = M.homeName + muleData["target"] = M.targetName + muleData["ref"] = "\ref[M]" + muleData["load"] = M.load ? M.load.name : "Nothing" + + mulebotsData[++mulebotsData.len] = muleData.Copy() - - var/mulebotsCount=0 - for(var/obj/machinery/bot/B in QC.botlist) - mulebotsCount++ - if(B.loc) - mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") - - if(!mulebotsData.len) - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - - muleData["bots"] = mulebotsData - muleData["count"] = mulebotsCount - - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) - muleData["active"] = 0 - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - muleData["bots"] = mulebotsData - muleData["count"] = 0 - - values["mulebot"] = muleData + values["mulebotcount"] = count + values["mulebots"] = mulebotsData @@ -575,5 +554,9 @@ loc:mode = 43 mode = 43 + if("MULEbot") + var/mob/living/bot/mulebot/M = locate(href_list["ref"]) + if(istype(M)) + M.obeyCommand(href_list["command"]) return 1 diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm index 7ad2b00200..5e7d63e1e9 100644 --- a/code/game/objects/items/devices/PDA/radio.dm +++ b/code/game/objects/items/devices/PDA/radio.dm @@ -105,107 +105,6 @@ radio_controller.remove_object(src, control_freq) ..() -/obj/item/radio/integrated/mule - var/list/botlist = null // list of bots - var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list - var/list/botstatus // the status signal sent by the bot - var/list/beacons - - var/beacon_freq = 1400 - var/control_freq = BOT_FREQ - - // create a new QM cartridge, and register to receive bot control & beacon message - New() - ..() - spawn(5) - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - spawn(10) - post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS) - - // receive radio signals - // can detect bot status signals - // and beacon locations - // create/populate lists as they are recvd - - receive_signal(datum/signal/signal) -// var/obj/item/device/pda/P = src.loc - - /* - world << "recvd:[P] : [signal.source]" - for(var/d in signal.data) - world << "- [d] = [signal.data[d]]" - */ - if(signal.data["type"] == "mulebot") - if(!botlist) - botlist = new() - - if(!(signal.source in botlist)) - botlist += signal.source - - if(active == signal.source) - var/list/b = signal.data - botstatus = b.Copy() - - else if(signal.data["beacon"]) - if(!beacons) - beacons = new() - - beacons[signal.data["beacon"] ] = signal.source - - -// if(istype(P)) P.updateSelfDialog() - - Topic(href, href_list) - ..() - var/cmd = "command" - if(active) cmd = "command [active.suffix]" - - switch(href_list["op"]) - - if("control") - active = locate(href_list["bot"]) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("scanbots") // find all bots - botlist = null - post_signal(control_freq, "command", "bot_status", s_filter = RADIO_MULEBOT) - - if("botlist") - active = null - - - if("unload") - post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("setdest") - if(beacons) - var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons - if(dest) - post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("retoff") - post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("reton") - post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("pickoff") - post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("pickon") - post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("stop", "go", "home") - post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - - /* * Radio Cartridge, essentially a signaler. */ diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 17204e77c8..b9c9a1b797 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -51,6 +51,10 @@ for(var/i = 1;i<=held_count;i++) new held_type(src) +/obj/structure/largecrate/animal/mulebot + name = "Mulebot crate" + held_type = /mob/living/bot/mulebot + /obj/structure/largecrate/animal/corgi name = "corgi carrier" held_type = /mob/living/simple_animal/corgi diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index e98d59528f..cc91ee49a2 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -49,6 +49,7 @@ var/list/mechtoys = list( layer = 4 explosion_resistance = 5 var/list/mobs_can_pass = list( + /mob/living/bot, /mob/living/carbon/slime, /mob/living/simple_animal/mouse, /mob/living/silicon/robot/drone diff --git a/code/modules/blob/blob.dm b/code/modules/blob/blob.dm index 7db20fe1ce..88f04e1924 100644 --- a/code/modules/blob/blob.dm +++ b/code/modules/blob/blob.dm @@ -90,10 +90,6 @@ if(V) V.ex_act(2) return - var/obj/machinery/bot/B = locate() in T - if(B) - B.ex_act(2) - return var/obj/mecha/M = locate() in T if(M) M.visible_message("The blob attacks \the [M]!") diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index cf6318638f..f8334dacb0 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -86,12 +86,6 @@ "admin","ponies","heresy","meow","Pun Pun","monkey","Ian","moron","pizza","message","spam",\ "director", "Hello", "Hi!"," ","nuke","crate","dwarf","xeno") -/datum/event/ionstorm/tick() - if(botEmagChance) - for(var/obj/machinery/bot/bot in world) - if(prob(botEmagChance)) - bot.emag_act(1) - /datum/event/ionstorm/end() spawn(rand(5000,8000)) if(prob(50)) diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 4505c666fd..cd2dbb8642 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -29,6 +29,8 @@ access_scanner.req_access = req_access.Copy() access_scanner.req_one_access = req_one_access.Copy() + turn_on() + /mob/living/bot/Life() ..() if(health <= 0) @@ -125,3 +127,70 @@ /mob/living/bot/attack_throat() return + +/******************************************************************/ +// Navigation procs +// Used for A-star pathfinding + + +// Returns the surrounding cardinal turfs with open links +// Including through doors openable with the ID +/turf/proc/CardinalTurfsWithAccess(var/obj/item/weapon/card/id/ID) + var/L[] = new() + + // for(var/turf/simulated/t in oview(src,1)) + + for(var/d in cardinal) + var/turf/simulated/T = get_step(src, d) + if(istype(T) && !T.density) + if(!LinkBlockedWithAccess(src, T, ID)) + L.Add(T) + return L + + +// Returns true if a link between A and B is blocked +// Movement through doors allowed if ID has access +/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID) + + if(A == null || B == null) return 1 + var/adir = get_dir(A,B) + var/rdir = get_dir(B,A) + if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal + var/iStep = get_step(A,adir&(NORTH|SOUTH)) + if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID)) + return 0 + + var/pStep = get_step(A,adir&(EAST|WEST)) + if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID)) + return 0 + return 1 + + if(DirBlockedWithAccess(A,adir, ID)) + return 1 + + if(DirBlockedWithAccess(B,rdir, ID)) + return 1 + + for(var/obj/O in B) + if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) + return 1 + + return 0 + +// Returns true if direction is blocked from loc +// Checks doors against access with given ID +/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID) + for(var/obj/structure/window/D in loc) + if(!D.density) continue + if(D.dir == SOUTHWEST) return 1 + if(D.dir == dir) return 1 + + for(var/obj/machinery/door/D in loc) + if(!D.density) continue + if(istype(D, /obj/machinery/door/window)) + if( dir & D.dir ) return !D.check_access(ID) + + //if((dir & SOUTH) && (D.dir & (EAST|WEST))) return !D.check_access(ID) + //if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID) + else return !D.check_access(ID) // it's a real, air blocking door + return 0 diff --git a/code/modules/mob/living/bot/mulebot.dm b/code/modules/mob/living/bot/mulebot.dm new file mode 100644 index 0000000000..29dc665246 --- /dev/null +++ b/code/modules/mob/living/bot/mulebot.dm @@ -0,0 +1,431 @@ +#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 + + botcard_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station) + + var/busy = 0 + var/mode = MULE_IDLE + var/atom/movable/load + + var/crates_only = 1 + var/auto_return = 1 + var/safety = 1 + + var/list/path = list() + var/frustration = 0 + var/turf/target + var/targetName + var/turf/home + var/homeName + var/turf/obstacle + + var/global/amount = 0 + +/mob/living/bot/mulebot/New() + ..() + + var/turf/T = get_turf(loc) + var/obj/machinery/navbeacon/N = locate() in home + 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 += "Multiple Utility Load Effector Mk. III

" + dat += "ID: [suffix]
" + dat += "Power: [on ? "On" : "Off"]
" + + if(!open) + dat += "Status: " + switch(mode) + if(MULE_IDLE) + dat += "Ready" + if(MULE_MOVING, MULE_UNLOAD, MULE_PATH_DONE) + dat += "Navigating" + if(MULE_UNLOAD) + dat += "Unloading" + if(MULE_LOST) + dat += "Processing commands" + if(MULE_CALC_MIN to MULE_CALC_MAX) + dat += "Calculating navigation path" + + dat += "
Current Load: [load ? load.name : "none"]
" + + if(locked) + dat += "
Controls are locked" + else + dat += "
Controls are unlocked

" + + if(!locked || issilicon(user)) + dat += "Toggle power
" + dat += "Stop
" + dat += "Proceed
" + dat += "Return to home
" + dat += "Set destination
" + dat += "Set home
" + dat += "Toggle auto return home ([auto_return ? "On" : "Off"])
" + dat += "Toggle non-standard cargo ([crates_only ? "Off" : "On"])
" + + if(load) + dat += "Unload now
" + dat += "
The maintenance hatch is closed.
" + + else + if(!issilicon(user)) + dat += "The maintenance hatch is open.

" + + dat += "Toggle safety ([safety ? "On" : "Off - DANGER"])
" + else + dat += "The bot is in maintenance mode and cannot be controlled.
" + + user << browse("Mulebot [suffix ? "([suffix])" : ""][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 = new() + for(var/obj/machinery/navbeacon/N in navbeacons) + beaconlist.Add(N.location) + beaconlist[N.location] = N + 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") + mode = MULE_IDLE + target = home + targetName = "Home" + mode = MULE_LOST + if("SetD") + var/new_dest + var/list/beaconlist = new() + for(var/obj/machinery/navbeacon/N in navbeacons) + beaconlist.Add(N.location) + beaconlist[N.location] = N + 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) + target = get_turf(beaconlist[new_dest]) + targetName = new_dest + if("GoTD") + if(mode == MULE_IDLE) + mode = MULE_LOST + if("Stop") + mode = MULE_IDLE + +/mob/living/bot/mulebot/emag_act(var/remaining_charges, var/user) + locked = !locked + user << "You [locked ? "lock" : "unlock"] the mulebot's controls!" + 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(mode == MULE_MOVING || mode == MULE_UNLOAD) + icon_state = "mulebot1" + return + icon_state = "mulebot0" + +/mob/living/bot/mulebot/Life() + ..() + + if(busy) + return + + if(!safety && prob(1)) + flick("mulebot-emagged", src) + + switch(mode) + if(MULE_IDLE) // Idle + return + if(MULE_MOVING) // Moving to target + if(!target) // Return home + if(auto_return && home) + target = home + targetName = "Home" + mode = MULE_LOST + else + mode = MULE_IDLE + update_icons() + return + if(loc == target) // Unload or stop + custom_emote(2, "makes a chiming sound.") + playsound(loc, 'sound/machines/chime.ogg', 50, 0) + mode = MULE_UNLOAD + update_icons() + return + if(path.len) // Move + var/turf/next = path[1] + if(next == loc) + path -= next + return + + var/moved = step_towards(src, next) + if(moved) + frustration = 0 + path -= next + else if(frustration < 6) + if(frustration == 3) + custom_emote(2, "makes an annoyed buzzing sound") + playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0) + ++frustration + else + custom_emote(2, "makes a sighing buzz.") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + obstacle = next + + mode = MULE_LOST + else + mode = MULE_LOST + update_icons() + return + if(MULE_UNLOAD) + unload(dir) + + if(auto_return && home && (loc != home)) + target = home + targetName = "Home" + mode = MULE_LOST + else + mode = MULE_IDLE + update_icons() + return + if(MULE_LOST) // Lost my way + if(target) + spawn(0) + calc_path(obstacle) + mode = MULE_CALC_MIN + else + mode = MULE_IDLE + update_icons() + return + if(MULE_CALC_MIN to MULE_CALC_MAX) // Calcing path + if(path.len) + mode = MULE_PATH_DONE + update_icons() + else + ++mode + return + if(MULE_PATH_DONE) // Done with path + obstacle = null + if(path.len) + frustration = 0 + mode = MULE_MOVING + else + if(home) + target = home + targetName = "Home" + mode = MULE_LOST + else + mode = MULE_IDLE + update_icons() + +/mob/living/bot/mulebot/Bump(var/mob/living/M) + if(!safety && istype(M)) + visible_message("[src] knocks over [M]!") + 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("[src] drives over [H]!") + 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("[src] blows apart!") + + 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/calc_path(var/turf/avoid = null) + path = AStar(loc, target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id = botcard, exclude = avoid) + if(!path) + path = list() + +/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() + + //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool. + //So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below. + //if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C)) + // return + busy = 1 + + C.loc = loc + sleep(2) + if(C.loc != loc) //To prevent you from going onto more than one bot. + return + C.loc = 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.loc = 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.loc = loc + AM.layer = initial(AM.layer) + AM.pixel_y = initial(AM.pixel_y) + busy = 0 + +#undef MULE_IDLE +#undef MULE_MOVING +#undef MULE_UNLOAD +#undef MULE_LOST +#undef MULE_CALC_MIN +#undef MULE_CALC_MAX +#undef MULE_PATH_DONE diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f77be45d56..b4d2289f69 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -235,9 +235,9 @@ // called when something steps onto a human // this handles mulebots and vehicles /mob/living/carbon/human/Crossed(var/atom/movable/AM) - if(istype(AM, /obj/machinery/bot/mulebot)) - var/obj/machinery/bot/mulebot/MB = AM - MB.RunOver(src) + if(istype(AM, /mob/living/bot/mulebot)) + var/mob/living/bot/mulebot/MB = AM + MB.runOver(src) if(istype(AM, /obj/vehicle)) var/obj/vehicle/V = AM diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index e80c1becff..33fb8acd24 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -50,13 +50,6 @@ stance = HOSTILE_STANCE_ATTACK T = M break - - if(istype(A, /obj/machinery/bot)) - var/obj/machinery/bot/B = A - if (B.health > 0) - stance = HOSTILE_STANCE_ATTACK - T = B - break return T @@ -101,9 +94,6 @@ var/obj/mecha/M = target_mob M.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext) return M - if(istype(target_mob,/obj/machinery/bot)) - var/obj/machinery/bot/B = target_mob - B.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext) /mob/living/simple_animal/hostile/proc/LoseTarget() stance = HOSTILE_STANCE_IDLE diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index a66f6b772c..06daf72260 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -359,10 +359,6 @@ var/obj/mecha/M = target_mob if (M.occupant) return (0) - if (istype(target_mob,/obj/machinery/bot)) - var/obj/machinery/bot/B = target_mob - if(B.health > 0) - return (0) return 1 /mob/living/simple_animal/say(var/message) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 7a66deb3c4..e3ab63bdfe 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -507,17 +507,6 @@ namecounts[name] = 1 creatures[name] = O - if(istype(O, /obj/machinery/bot)) - var/name = "BOT: [O.name]" - if (names.Find(name)) - namecounts[name]++ - name = "[name] ([namecounts[name]])" - else - names.Add(name) - namecounts[name] = 1 - creatures[name] = O - - for(var/mob/M in sortAtom(mob_list)) var/name = M.name if (names.Find(name)) diff --git a/maps/polaris-1.dmm b/maps/polaris-1.dmm index 692f067fae..be0624cd23 100644 --- a/maps/polaris-1.dmm +++ b/maps/polaris-1.dmm @@ -6544,8 +6544,8 @@ "cvS" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled,/area/quartermaster/storage) "cvT" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/quartermaster/storage) "cvU" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=8"; freq = 1400; location = "QM #3"},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage) -"cvV" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=8"; freq = 1400; location = "QM #2"},/obj/machinery/bot/mulebot{home_destination = "QM #2"; suffix = "#2"},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage) -"cvW" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=8"; freq = 1400; location = "QM #1"},/obj/machinery/bot/mulebot{beacon_freq = 1400; home_destination = "QM #1"; suffix = "#1"},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage) +"cvV" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=8"; freq = 1400; location = "QM #2"},/mob/living/bot/mulebot,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage) +"cvW" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=8"; freq = 1400; location = "QM #1"},/mob/living/bot/mulebot,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/quartermaster/storage) "cvX" = (/obj/machinery/status_display/supply_display,/turf/simulated/wall,/area/quartermaster/qm) "cvY" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/turf/simulated/floor/tiled,/area/quartermaster/qm) "cvZ" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/quartermaster/qm) @@ -9608,7 +9608,7 @@ "dCO" = (/obj/structure/bed/chair/wood{dir = 8},/obj/effect/floor_decal/corner/green{dir = 10},/turf/simulated/floor/tiled,/area/hydroponics/garden) "dCP" = (/obj/structure/table/woodentable,/obj/effect/floor_decal/corner/green{dir = 10},/turf/simulated/floor/tiled,/area/hydroponics/garden) "dCQ" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area/hallway/primary/central_three) - + (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 37ac74f7e0..756f6edce0 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -128,7 +128,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm
{{:helper.link('Supply Records', 'gear', {'choice' : "47"}, null, 'fixedLeftWide')}} - {{if data.cartridge.radio == 3}} {{:helper.link('Delivery Bot Control', 'gear', {'choice' : "48"}, null, 'fixedLeftWide')}} {{/if}} + {{:helper.link('Delivery Bot Control', 'gear', {'choice' : "48"}, null, 'fixedLeftWide')}}
@@ -762,128 +762,38 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm {{else data.mode == 48}} -

Mule Control

- {{if data.records.mulebot.active == null || data.records.mulebot.active == 0}} - {{if data.records.mulebot.count == 0}} -

No bots found.

- {{else}} -

Mule List

-
- Select A Mulebot -
-
- {{for data.records.mulebot.bots}} -
- {{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, null)}} (Location: {{:value.Location}}) -
- {{/for}} - {{/if}} -
- {{:helper.link('Scan for Bots','gear', {'radiomenu' : "1", 'op' : "scanbots"}, null, null)}} - {{else}} - {{if data.records.mulebot.botstatus.mode == -1}} -

Waiting for response...

- {{else}} -

Status:

-
-
-
- Location: -
-
- {{:data.records.mulebot.botstatus.loca}} -
-
-
-
- Mode: -
-
- - {{if data.records.mulebot.botstatus.mode ==0}} - Ready - {{else data.records.mulebot.botstatus.mode == 1}} - Loading/Unloading - {{else data.records.mulebot.botstatus.mode ==2}} - Navigating to Delivery Location - {{else data.records.mulebot.botstatus.mode == 3}} - Navigating to Home - {{else data.records.mulebot.botstatus.mode ==4}} - Waiting for Clear Path - {{else data.records.mulebot.botstatus.mode ==5 || data.records.mulebot.botstatus.mode == 6}} - Calculating navigation Path - {{else data.records.mulebot.botstatus.mode ==7}} - Unable to locate destination - {{/if}} - -
-
-
-
- Current Load: -
-
- - {{:helper.link(data.records.mulebot.botstatus.load == null ? 'None (Unload)' : data.records.mulebot.botstatus.load + ' (Unload)', 'gear', {'radiomenu' : "1", 'op' : "unload"},data.records.mulebot.botstatus.load == null ? 'disabled' : null, null)}} - -
-
-
-
- Power: -
-
- - {{:data.records.mulebot.botstatus.powr}}% - -
-
-
-
- Destination: -
-
- {{:helper.link(data.records.mulebot.botstatus.dest == null || data.records.mulebot.botstatus.dest == "" ? 'None (Set)': data.records.mulebot.botstatus.dest+ ' (Set)', 'gear', {'radiomenu' : "1", 'op' : "setdest"}, null, null)}} -
-
-
-
- Home: -
-
- {{if data.records.mulebot.botstatus.home == null}} None {{else}} {{:data.records.mulebot.botstatus.home}} {{/if}} -
-
-
-
- Auto Return: -
-
- {{:helper.link(data.records.mulebot.botstatus.retn == 1 ? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : data.records.mulebot.botstatus.retn==1 ? "retoff" : "reton"}, null, null)}} -
-
-
-
- Auto Pickup: -
-
- {{:helper.link(data.records.mulebot.botstatus.pick==1? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : data.records.mulebot.botstatus.pick==1 ? "pickoff" : "pickon"}, null, null)}} -
-
-
-
- Functions: -
-
- {{:helper.link('Stop', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, null)}} - {{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, null)}} - {{:helper.link('Return Home', 'gear', {'radiomenu' : "1", 'op' : "home"}, null, null)}} -
-
-

- {{:helper.link('Return to Bot list', 'gear', {'radiomenu' : "1", 'op' : "botlist"}, null, null)}} - {{/if}} - {{/if}} +

Mule Control

+ {{if data.records.mulebotcount == 0}} +

No bots found.

+ {{else}} +

Mule List

+ {{for data.records.mulebots}} +
+
Mulebot #{{:value.name}}
+
Location: {{:value.location}}
Home: {{:value.home}}
Target: {{:value.target}}
Load: {{:value.load}}
+
+
+
Status:
+
+ {{if value.mode == 0}} + Idle + {{else value.mode == 1}} + Moving + {{else value.mode == 2}} + Unloading + {{else}} + Calculating path + {{/if}} +
+
+
+ {{:helper.link('Go home', null, {'cartmenu' : "1", 'choice' : "MULEbot", 'ref' : value.ref, 'command' : "Home"})}} + {{:helper.link('Set destination', null, {'cartmenu' : "1", 'choice' : "MULEbot", 'ref' : value.ref, 'command' : "SetD"})}} + {{:helper.link('Go', null, {'cartmenu' : "1", 'choice' : "MULEbot", 'ref' : value.ref, 'command' : "GoTD"})}} + {{:helper.link('Stop', null, {'cartmenu' : "1", 'choice' : "MULEbot", 'ref' : value.ref, 'command' : "Stop"})}} +
+ {{/for}} + {{/if}} {{else data.mode == 49}} diff --git a/polaris.dme b/polaris.dme index 378700623c..f77cd664f1 100644 --- a/polaris.dme +++ b/polaris.dme @@ -215,7 +215,6 @@ #include "code\datums\wires\autolathe.dm" #include "code\datums\wires\camera.dm" #include "code\datums\wires\explosive.dm" -#include "code\datums\wires\mulebot.dm" #include "code\datums\wires\particle_accelerator.dm" #include "code\datums\wires\radio.dm" #include "code\datums\wires\robot.dm" @@ -456,8 +455,6 @@ #include "code\game\machinery\atmoalter\portable_atmospherics.dm" #include "code\game\machinery\atmoalter\pump.dm" #include "code\game\machinery\atmoalter\scrubber.dm" -#include "code\game\machinery\bots\bots.dm" -#include "code\game\machinery\bots\mulebot.dm" #include "code\game\machinery\camera\camera.dm" #include "code\game\machinery\camera\camera_assembly.dm" #include "code\game\machinery\camera\motion.dm" @@ -1310,6 +1307,7 @@ #include "code\modules\mob\living\bot\farmbot.dm" #include "code\modules\mob\living\bot\floorbot.dm" #include "code\modules\mob\living\bot\medbot.dm" +#include "code\modules\mob\living\bot\mulebot.dm" #include "code\modules\mob\living\bot\secbot.dm" #include "code\modules\mob\living\carbon\breathe.dm" #include "code\modules\mob\living\carbon\carbon.dm"