mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-01-05 15:04:21 +00:00
Move drones to modular + changes
Moves drones into the modular folder to allow for more violent changes without having to worry about upstreams potentially adding something to regular drones. Restructures some of drone code a bit to be nicer in my oppinion Still needs a second pass at some point but hey if you never start
This commit is contained in:
@@ -0,0 +1,401 @@
|
||||
//Modified copy of regula drone folder
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "maintenance drone"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "repairbot"
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
cell_emp_mult = 1
|
||||
universal_speak = 0
|
||||
universal_understand = 1
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
braintype = "Drone"
|
||||
lawupdate = 0
|
||||
density = TRUE
|
||||
req_access = list(access_engine, access_robotics)
|
||||
integrated_light_power = 3
|
||||
local_transmit = 1
|
||||
|
||||
can_pull_size = ITEMSIZE_NO_CONTAINER
|
||||
can_pull_mobs = MOB_PULL_SMALLER
|
||||
can_enter_vent_with = list(
|
||||
/obj,
|
||||
/atom/movable/emissive_blocker)
|
||||
|
||||
mob_bump_flag = SIMPLE_ANIMAL
|
||||
mob_swap_flags = SIMPLE_ANIMAL
|
||||
mob_push_flags = SIMPLE_ANIMAL
|
||||
mob_always_swap = 1
|
||||
|
||||
mob_size = MOB_LARGE // Small mobs can't open doors, it's a huge pain for drones.
|
||||
|
||||
//Used for self-mailing.
|
||||
var/mail_destination = ""
|
||||
var/obj/machinery/drone_fabricator/master_fabricator
|
||||
var/law_type = /datum/ai_laws/drone
|
||||
var/module_type = /obj/item/weapon/robot_module/drone
|
||||
var/obj/item/hat
|
||||
var/hat_x_offset = 0
|
||||
var/hat_y_offset = -13
|
||||
var/serial_number = 0
|
||||
var/name_override = 0
|
||||
|
||||
var/foreign_droid = FALSE
|
||||
|
||||
holder_type = /obj/item/weapon/holder/drone
|
||||
|
||||
can_be_antagged = FALSE
|
||||
|
||||
var/static/list/shell_types = list("Classic" = "repairbot", "Eris" = "maintbot")
|
||||
var/can_pick_shell = TRUE
|
||||
var/list/shell_accessories
|
||||
var/can_blitz = FALSE
|
||||
//vore addition
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
|
||||
|
||||
var/list/mob_hat_cache = list()
|
||||
/proc/get_hat_icon(var/obj/item/hat, var/offset_x = 0, var/offset_y = 0)
|
||||
var/t_state = hat.icon_state
|
||||
if(LAZYACCESS(hat.item_state_slots, slot_head_str))
|
||||
t_state = hat.item_state_slots[slot_head_str]
|
||||
else if(hat.item_state)
|
||||
t_state = hat.item_state
|
||||
var/key = "[t_state]_[offset_x]_[offset_y]"
|
||||
if(!mob_hat_cache[key]) // Not ideal as there's no guarantee all hat icon_states
|
||||
var/t_icon = INV_HEAD_DEF_ICON // are unique across multiple dmis, but whatever.
|
||||
if(hat.icon_override)
|
||||
t_icon = hat.icon_override
|
||||
else if(LAZYACCESS(hat.item_icons, slot_head_str))
|
||||
t_icon = hat.item_icons[slot_head_str]
|
||||
var/image/I = image(icon = t_icon, icon_state = t_state)
|
||||
I.pixel_x = offset_x
|
||||
I.pixel_y = offset_y
|
||||
mob_hat_cache[key] = I
|
||||
return mob_hat_cache[key]
|
||||
|
||||
/mob/living/silicon/robot/drone/Destroy()
|
||||
if(hat)
|
||||
hat.loc = get_turf(src)
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/drone/is_sentient()
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/robot/drone/New()
|
||||
..()
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
verbs += /mob/living/proc/hide
|
||||
remove_language("Robot Talk")
|
||||
add_language("Robot Talk", 0)
|
||||
add_language("Drone Talk", 1)
|
||||
serial_number = rand(0,999)
|
||||
|
||||
//They are unable to be upgraded, so let's give them a bit of a better battery.
|
||||
cell.maxcharge = 10000
|
||||
cell.charge = 10000
|
||||
|
||||
// NO BRAIN.
|
||||
mmi = null
|
||||
|
||||
//We need to screw with their HP a bit. They have around one fifth as much HP as a full borg.
|
||||
for(var/V in components) if(V != "power cell")
|
||||
var/datum/robot_component/C = components[V]
|
||||
C.max_damage = 10
|
||||
|
||||
verbs -= /mob/living/silicon/robot/verb/Namepick
|
||||
|
||||
if(can_pick_shell)
|
||||
var/random = pick(shell_types)
|
||||
icon_state = shell_types[random]
|
||||
shell_accessories = list("[icon_state]-eyes-blue")
|
||||
|
||||
updateicon()
|
||||
updatename()
|
||||
|
||||
/mob/living/silicon/robot/drone/init()
|
||||
if(!scrambledcodes && !foreign_droid)
|
||||
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
|
||||
additional_law_channels["Drone"] = ":d"
|
||||
if(!laws) laws = new law_type
|
||||
if(!module) module = new module_type(src)
|
||||
|
||||
flavor_text = "It's a tiny little repair drone. The casing is stamped with an corporate logo and the subscript: '[using_map.company_name] Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
|
||||
|
||||
/mob/living/silicon/robot/drone/Login()
|
||||
. = ..()
|
||||
if(can_pick_shell)
|
||||
to_chat(src, "<b>You can select a shell using the 'Robot Commands' > 'Customize Appearance'</b>")
|
||||
|
||||
//Redefining some robot procs...
|
||||
/mob/living/silicon/robot/drone/SetName(pickedName as text)
|
||||
// Would prefer to call the grandparent proc but this isn't possible, so..
|
||||
real_name = pickedName
|
||||
name = real_name
|
||||
|
||||
/mob/living/silicon/robot/drone/updatename()
|
||||
if(name_override)
|
||||
return
|
||||
|
||||
real_name = "[initial(name)] ([serial_number])"
|
||||
name = real_name
|
||||
|
||||
/mob/living/silicon/robot/drone/updateicon()
|
||||
cut_overlays()
|
||||
|
||||
if(islist(shell_accessories))
|
||||
add_overlay(shell_accessories)
|
||||
|
||||
if(hat) // Let the drones wear hats.
|
||||
add_overlay(get_hat_icon(hat, hat_x_offset, hat_y_offset))
|
||||
|
||||
/mob/living/silicon/robot/drone/verb/pick_shell()
|
||||
set name = "Customize Appearance"
|
||||
set category = "Robot Commands"
|
||||
|
||||
if(!can_pick_shell)
|
||||
to_chat(src, "<span class='warning'>You already selected a shell or this drone type isn't customizable.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = shell_types.Copy()
|
||||
|
||||
if(can_blitz)
|
||||
choices["Blitz"] = "blitzshell"
|
||||
|
||||
var/shell_choice = tgui_input_list(src, "Select a shell. NOTE: You can only do this once during this drone-lifetime.", "Customize Shell", choices)
|
||||
if(!shell_choice)
|
||||
return
|
||||
|
||||
icon_state = choices[shell_choice]
|
||||
|
||||
// If you add more, datumize these. Having 'basically two' is not enough to make me bother though.
|
||||
shell_accessories = null
|
||||
if(icon_state in list("repairbot", "maintbot"))
|
||||
var/eye_color = tgui_input_list(src, "Select eye color:", "Eye Color", list("blue", "red", "orange", "green", "violet"))
|
||||
if(eye_color)
|
||||
LAZYADD(shell_accessories, "[icon_state]-eyes-[eye_color]")
|
||||
if(icon_state == "maintbot")
|
||||
var/armor_color = tgui_input_list(src, "Select plating color:", "Eye Color", list("blue", "red", "orange", "green", "brown"))
|
||||
if(armor_color)
|
||||
LAZYADD(shell_accessories, "[icon_state]-shell-[armor_color]")
|
||||
|
||||
can_pick_shell = FALSE
|
||||
updateicon()
|
||||
|
||||
/mob/living/silicon/robot/drone/choose_icon()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/wear_hat(var/obj/item/new_hat)
|
||||
if(hat)
|
||||
return
|
||||
hat = new_hat
|
||||
new_hat.loc = src
|
||||
updateicon()
|
||||
|
||||
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
|
||||
/mob/living/silicon/robot/drone/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
|
||||
//Early return handler
|
||||
if(handle_attackby_return(W,user))
|
||||
return
|
||||
if(user.a_intent == "help" && istype(W, /obj/item/clothing/head))
|
||||
equip_hat(W,user)
|
||||
..()
|
||||
|
||||
//Denesting for the above code
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/equip_hat(var/obj/item/clothing/head/W, var/mob/user)
|
||||
if(hat)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already wearing \the [hat].</span>")
|
||||
return
|
||||
user.unEquip(W)
|
||||
wear_hat(W)
|
||||
user.visible_message("<b>\The [user]</b> puts \the [W] on \the [src].")
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/handle_attackby_return(var/obj/item/W, var/mob/user)
|
||||
var/hint
|
||||
if(W.is_crowbar())
|
||||
hint = "<span class='danger'>\The [src] is hermetically sealed. You can't open the case.</span>"
|
||||
else if(istype(W, /obj/item/borg/upgrade/))
|
||||
hint = "<span class='danger'>\The [src] is not compatible with \the [W].</span>"
|
||||
else if(stat == 2)
|
||||
hint = handle_try_reboot(W,user) //ugly as shit nesting otherwise
|
||||
|
||||
if(hint!="MSG-SKIP")
|
||||
to_chat(usr,hint)
|
||||
return hint //null if we dont handle early return
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/handle_try_reboot(var/obj/item/W,var/mob/user)
|
||||
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
|
||||
if(!istype(W, /obj/item/weapon/card/id)&&!istype(W, /obj/item/device/pda))
|
||||
return handle_try_shutdown(user, TU)
|
||||
|
||||
if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
|
||||
return "<span class='danger'>The interface is fried, and a distressing burned smell wafts from the robot's interior. You're not rebooting this one.</span>"
|
||||
|
||||
if(!allowed(usr))
|
||||
return "<span class='danger'>Access denied.</span>"
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] swipes [TU.his] ID card through \the [src], attempting to reboot it.</span>", "<span class='danger'>>You swipe your ID card through \the [src], attempting to reboot it.</span>")
|
||||
var/drones = 0
|
||||
for(var/mob/living/silicon/robot/drone/D in player_list)
|
||||
drones++
|
||||
if(drones < config.max_maint_drones)
|
||||
request_player()
|
||||
return "MSG-SKIP"
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/handle_try_shutdown(var/mob/user, var/datum/gender/TU)
|
||||
user.visible_message("<span class='danger'>\The [user] swipes [TU.his] ID card through \the [src], attempting to shut it down.</span>", "<span class='danger'>You swipe your ID card through \the [src], attempting to shut it down.</span>")
|
||||
if(emagged)
|
||||
return "MSG-SKIP"
|
||||
|
||||
if(allowed(usr))
|
||||
shut_down()
|
||||
return "MSG-SKIP"
|
||||
else
|
||||
return "<span class='danger'>Access denied.</span>"
|
||||
|
||||
|
||||
//ATTACKBY HANDLERS END
|
||||
|
||||
|
||||
/mob/living/silicon/robot/drone/emag_act(var/remaining_charges, var/mob/user)
|
||||
if(!client || stat == 2)
|
||||
to_chat(user, "<span class='danger'>There's not much point subverting this heap of junk.</span>")
|
||||
return
|
||||
|
||||
if(emagged)
|
||||
to_chat(src, "<span class='danger'>\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.</span>")
|
||||
to_chat(user, "<span class='danger'>You attempt to subvert [src], but the sequencer has no effect.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='danger'>You swipe the sequencer across [src]'s interface and watch its eyes flicker.</span>")
|
||||
|
||||
to_chat(src, "<span class='danger'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.</span>")
|
||||
|
||||
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
|
||||
emagged = 1
|
||||
lawupdate = 0
|
||||
connected_ai = null
|
||||
clear_supplied_laws()
|
||||
clear_inherent_laws()
|
||||
laws = new /datum/ai_laws/syndicate_override
|
||||
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
|
||||
set_zeroth_law("Only [user.real_name] and people [TU.he] designate[TU.s] as being such are operatives.")
|
||||
|
||||
to_chat(src, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(src)
|
||||
to_chat(src, "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.</span>")
|
||||
return 1
|
||||
|
||||
//DRONE LIFE/DEATH
|
||||
|
||||
//For some goddamn reason robots have this hardcoded. Redefining it for our fragile friends here.
|
||||
/mob/living/silicon/robot/drone/updatehealth()
|
||||
if(status_flags & GODMODE)
|
||||
health = maxHealth
|
||||
set_stat(CONSCIOUS)
|
||||
return
|
||||
health = maxHealth - (getBruteLoss() + getFireLoss())
|
||||
return
|
||||
|
||||
//Easiest to check this here, then check again in the robot proc.
|
||||
//Standard robots use config for crit, which is somewhat excessive for these guys.
|
||||
//Drones killed by damage will gib.
|
||||
/mob/living/silicon/robot/drone/handle_regular_status_updates()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T || health <= -35 )
|
||||
timeofdeath = world.time
|
||||
death() //Possibly redundant, having trouble making death() cooperate.
|
||||
gib()
|
||||
return
|
||||
..()
|
||||
|
||||
//DRONE MOVEMENT.
|
||||
/mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip)
|
||||
return 0
|
||||
|
||||
//CONSOLE PROCS
|
||||
/mob/living/silicon/robot/drone/proc/law_resync()
|
||||
if(stat == DEAD)
|
||||
return //opting for an early return here to remove unneeded nesting
|
||||
if(emagged)
|
||||
to_chat(src, "<span class='danger'>You feel something attempting to modify your programming, but your hacked subroutines are unaffected.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it.</span>")
|
||||
full_law_reset()
|
||||
show_laws()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/shut_down()
|
||||
if(stat == DEAD)
|
||||
return //opting for an early return here to remove unneeded nesting
|
||||
if(emagged)
|
||||
to_chat(src, "<span class='danger'>You feel a system kill order percolate through your tiny brain, but it doesn't seem like a good idea to you.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>You feel a system kill order percolate through your tiny brain, and you obediently destroy yourself.</span>")
|
||||
death()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/full_law_reset()
|
||||
clear_supplied_laws(1)
|
||||
clear_inherent_laws(1)
|
||||
clear_ion_laws(1)
|
||||
laws = new law_type
|
||||
|
||||
//Reboot procs.
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/request_player()
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(jobban_isbanned(O, "Cyborg") || !O.client || !O.client.prefs.be_special & BE_PAI)
|
||||
continue
|
||||
question(O.client)
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/question(var/client/C)
|
||||
spawn(0)
|
||||
if(!C || jobban_isbanned(C,"Cyborg")) return
|
||||
var/response = tgui_alert(C, "Someone is attempting to reboot a maintenance drone. Would you like to play as one?", "Maintenance drone reboot", list("Yes", "No", "Never for this round"))
|
||||
if(!C || ckey)
|
||||
return
|
||||
if(response == "Yes")
|
||||
transfer_personality(C)
|
||||
else if (response == "Never for this round")
|
||||
C.prefs.be_special ^= BE_PAI
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player)
|
||||
|
||||
if(!player) return
|
||||
|
||||
src.ckey = player.ckey
|
||||
|
||||
if(player.mob && player.mob.mind)
|
||||
player.mob.mind.transfer_to(src)
|
||||
|
||||
lawupdate = 0
|
||||
to_chat(src, "<b>Systems rebooted</b>. Loading base pattern maintenance protocol...")
|
||||
spawn(3 SECONDS)
|
||||
full_law_reset()
|
||||
to_chat(src,"<b>Loaded</b>.")
|
||||
spawn(4 SECONDS)
|
||||
welcome_drone()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/welcome_drone()
|
||||
to_chat(src, "<b>You are a maintenance drone, a tiny-brained robotic repair machine</b>.")
|
||||
to_chat(src, "You have no individual will, no personality, and no drives or urges other than your laws.")
|
||||
to_chat(src, "Remember, you are <b>lawed against interference with the crew</b>. Also remember, <b>you DO NOT take orders from the AI.</b>")
|
||||
to_chat(src, "Use <b>say ;Hello</b> to talk to other drones and <b>say Hello</b> to speak silently to your nearby fellows.")
|
||||
|
||||
/mob/living/silicon/robot/drone/add_robot_verbs()
|
||||
src.verbs |= silicon_subsystems
|
||||
|
||||
/mob/living/silicon/robot/drone/remove_robot_verbs()
|
||||
src.verbs -= silicon_subsystems
|
||||
@@ -0,0 +1,36 @@
|
||||
//Modified copy of regula drone folder
|
||||
// DRONE ABILITIES
|
||||
/mob/living/silicon/robot/drone/verb/set_mail_tag()
|
||||
set name = "Set Mail Tag"
|
||||
set desc = "Tag yourself for delivery through the disposals system."
|
||||
set category = "Robot Commands"
|
||||
|
||||
var/new_tag = tgui_input_list(usr, "Select the desired destination.", "Set Mail Tag", GLOB.tagger_locations)
|
||||
|
||||
if(!new_tag)
|
||||
mail_destination = ""
|
||||
return
|
||||
|
||||
to_chat(src, "<span class='notice'>You configure your internal beacon, tagging yourself for delivery to '[new_tag]'.</span>")
|
||||
mail_destination = new_tag
|
||||
|
||||
//Auto flush if we use this verb inside a disposal chute.
|
||||
var/obj/machinery/disposal/D = src.loc
|
||||
if(istype(D))
|
||||
to_chat(src, "<span class='notice'>\The [D] acknowledges your signal.</span>")
|
||||
D.flush_count = D.flush_every_ticks
|
||||
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/drone/MouseDrop(var/atom/over_object)
|
||||
var/mob/living/carbon/human/H = over_object
|
||||
if(!istype(H) || !Adjacent(H))
|
||||
return ..()
|
||||
if(H.a_intent == "grab" && hat && !(H.l_hand && H.r_hand))
|
||||
H.put_in_hands(hat)
|
||||
H.visible_message("<span class='danger'>\The [H] removes \the [src]'s [hat].</span>")
|
||||
hat = null
|
||||
updateicon()
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
@@ -0,0 +1,124 @@
|
||||
//Modified copy of regula drone folder
|
||||
/obj/machinery/computer/drone_control
|
||||
name = "Maintenance Drone Control"
|
||||
desc = "Used to monitor the station's drone population and the assembler that services them."
|
||||
icon_keyboard = "power_key"
|
||||
icon_screen = "generic" //VOREStation Edit
|
||||
req_access = list(access_engine_equip)
|
||||
circuit = /obj/item/weapon/circuitboard/drone_control
|
||||
|
||||
//Used when pinging drones.
|
||||
var/drone_call_area = "Engineering"
|
||||
//Used to enable or disable drone fabrication.
|
||||
var/obj/machinery/drone_fabricator/dronefab
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/tgui_status(mob/user)
|
||||
if(!allowed(user))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob)
|
||||
if(..())
|
||||
return
|
||||
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "DroneConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/drone_control/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/drones = list()
|
||||
for(var/mob/living/silicon/robot/drone/D in mob_list)
|
||||
//VOREStation Edit - multiz lol
|
||||
if(!(D.z in using_map.get_map_levels(z, TRUE, 0)))
|
||||
continue
|
||||
//VOREStation Edit - multiz lol
|
||||
if(D.foreign_droid)
|
||||
continue
|
||||
|
||||
drones.Add(list(list(
|
||||
"name" = D.real_name,
|
||||
"active" = D.stat != 2,
|
||||
"charge" = D.cell.charge,
|
||||
"maxCharge" = D.cell.maxcharge,
|
||||
"loc" = "[get_area(D)]",
|
||||
"ref" = "\ref[D]",
|
||||
)))
|
||||
data["drones"] = drones
|
||||
|
||||
data["fabricator"] = dronefab
|
||||
data["fabPower"] = dronefab?.produce_drones
|
||||
|
||||
data["areas"] = GLOB.tagger_locations
|
||||
data["selected_area"] = "[drone_call_area]"
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/drone_control/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
switch(action)
|
||||
if("set_dcall_area")
|
||||
var/t_area = params["area"]
|
||||
if(!t_area || !(t_area in GLOB.tagger_locations))
|
||||
return
|
||||
|
||||
drone_call_area = t_area
|
||||
to_chat(usr, "<span class='notice'>You set the area selector to [drone_call_area].</span>")
|
||||
|
||||
if("ping")
|
||||
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
|
||||
for(var/mob/living/silicon/robot/drone/D in player_list)
|
||||
if(D.stat == 0)
|
||||
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
|
||||
|
||||
if("resync")
|
||||
var/mob/living/silicon/robot/drone/D = locate(params["ref"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='danger'>You issue a law synchronization directive for the drone.</span>")
|
||||
D.law_resync()
|
||||
|
||||
if("shutdown")
|
||||
var/mob/living/silicon/robot/drone/D = locate(params["ref"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='danger'>You issue a kill command for the unfortunate drone.</span>")
|
||||
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
|
||||
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
|
||||
D.shut_down()
|
||||
|
||||
if("search_fab")
|
||||
if(dronefab)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/drone_fabricator/fab in oview(3,src))
|
||||
if(fab.stat & NOPOWER)
|
||||
continue
|
||||
|
||||
dronefab = fab
|
||||
to_chat(usr, "<span class='notice'>Drone fabricator located.</span>")
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='danger'>Unable to locate drone fabricator.</span>")
|
||||
|
||||
if("toggle_fab")
|
||||
if(!dronefab)
|
||||
return
|
||||
|
||||
if(get_dist(src,dronefab) > 3)
|
||||
dronefab = null
|
||||
to_chat(usr, "<span class='danger'>Unable to locate drone fabricator.</span>")
|
||||
return
|
||||
|
||||
dronefab.produce_drones = !dronefab.produce_drones
|
||||
to_chat(usr, "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>")
|
||||
@@ -0,0 +1,25 @@
|
||||
//Modified copy of regula drone folder
|
||||
//Redefining some robot procs, since drones can't be repaired and really shouldn't take component damage.
|
||||
/mob/living/silicon/robot/drone/take_overall_damage(var/brute = 0, var/burn = 0, var/sharp = FALSE, var/used_weapon = null)
|
||||
bruteloss += brute
|
||||
fireloss += burn
|
||||
|
||||
/mob/living/silicon/robot/drone/heal_overall_damage(var/brute, var/burn)
|
||||
|
||||
bruteloss -= brute
|
||||
fireloss -= burn
|
||||
|
||||
if(bruteloss<0) bruteloss = 0
|
||||
if(fireloss<0) fireloss = 0
|
||||
|
||||
/mob/living/silicon/robot/drone/take_organ_damage(var/brute = 0, var/burn = 0, var/sharp = FALSE, var/emp = 0)
|
||||
take_overall_damage(brute,burn)
|
||||
|
||||
/mob/living/silicon/robot/drone/heal_organ_damage(var/brute, var/burn)
|
||||
heal_overall_damage(brute,burn)
|
||||
|
||||
/mob/living/silicon/robot/drone/getFireLoss()
|
||||
return fireloss
|
||||
|
||||
/mob/living/silicon/robot/drone/getBruteLoss()
|
||||
return bruteloss
|
||||
@@ -1,3 +1,603 @@
|
||||
//Modified copy of regula drone folder
|
||||
//Simple borg hand.
|
||||
//Limited use.
|
||||
/obj/item/weapon/gripper
|
||||
name = "magnetic gripper"
|
||||
desc = "A simple grasping tool specialized in construction and engineering work."
|
||||
description_info = "Ctrl-Clicking on the gripper will drop whatever it is holding.<br>\
|
||||
Using an object on the gripper will interact with the item inside it, if it exists, instead."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gripper"
|
||||
flags = NOBLUDGEON
|
||||
|
||||
//Has a list of items that it can hold.
|
||||
var/list/can_hold = list(
|
||||
/obj/item/weapon/cell,
|
||||
/obj/item/weapon/airlock_electronics,
|
||||
/obj/item/weapon/tracker_electronics,
|
||||
/obj/item/weapon/module/power_control,
|
||||
/obj/item/weapon/stock_parts,
|
||||
/obj/item/frame,
|
||||
/obj/item/weapon/camera_assembly,
|
||||
/obj/item/weapon/tank,
|
||||
/obj/item/weapon/circuitboard,
|
||||
/obj/item/weapon/smes_coil,
|
||||
/obj/item/weapon/fuel_assembly,
|
||||
/obj/item/weapon/ore/bluespace_crystal
|
||||
) // CHOMPEdit - Buffing the gripper to allow bluespace crystal use for telesci building.
|
||||
|
||||
var/obj/item/wrapped = null // Item currently being held.
|
||||
|
||||
var/force_holder = null //
|
||||
|
||||
/obj/item/weapon/gripper/examine(mob/user)
|
||||
. = ..()
|
||||
if(wrapped)
|
||||
. += "<span class='notice'>\The [src] is holding \the [wrapped].</span>"
|
||||
. += wrapped.examine(user)
|
||||
|
||||
/obj/item/weapon/gripper/CtrlClick(mob/user)
|
||||
drop_item()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gripper/AltClick(mob/user)
|
||||
drop_item()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gripper/omni
|
||||
name = "omni gripper"
|
||||
desc = "A strange grasping tool that can hold anything a human can, but still maintains the limitations of application its more limited cousins have."
|
||||
icon_state = "gripper-omni"
|
||||
|
||||
can_hold = list(/obj/item) // Testing and Event gripper.
|
||||
|
||||
// VEEEEERY limited version for mining borgs. Basically only for swapping cells and upgrading the drills.
|
||||
/obj/item/weapon/gripper/miner
|
||||
name = "drill maintenance gripper"
|
||||
desc = "A simple grasping tool for the maintenance of heavy drilling machines."
|
||||
icon_state = "gripper-mining"
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/cell,
|
||||
/obj/item/weapon/stock_parts
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/security
|
||||
name = "security gripper"
|
||||
desc = "A simple grasping tool for corporate security work."
|
||||
icon_state = "gripper-sec"
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/paper,
|
||||
/obj/item/weapon/paper_bundle,
|
||||
/obj/item/weapon/pen,
|
||||
/obj/item/weapon/sample,
|
||||
/obj/item/weapon/forensics/sample_kit,
|
||||
/obj/item/device/taperecorder,
|
||||
/obj/item/device/tape,
|
||||
/obj/item/device/uv_light
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/paperwork
|
||||
name = "paperwork gripper"
|
||||
desc = "A simple grasping tool for clerical work."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/clipboard,
|
||||
/obj/item/weapon/paper,
|
||||
/obj/item/weapon/paper_bundle,
|
||||
/obj/item/weapon/card/id,
|
||||
/obj/item/weapon/book,
|
||||
/obj/item/weapon/newspaper
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/medical
|
||||
name = "medical gripper"
|
||||
desc = "A simple grasping tool for medical work."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/reagent_containers/glass,
|
||||
/obj/item/weapon/storage/pill_bottle,
|
||||
/obj/item/weapon/reagent_containers/pill,
|
||||
/obj/item/weapon/reagent_containers/blood,
|
||||
/obj/item/device/nif, //Chompedit Add Nif handling
|
||||
/obj/item/stack/material/phoron,
|
||||
/obj/item/weapon/tank/anesthetic,
|
||||
/obj/item/weapon/disk/body_record //Vorestation Edit: this lets you get an empty sleeve or help someone else
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc
|
||||
name = "scientific gripper"
|
||||
icon_state = "gripper-sci"
|
||||
desc = "A simple grasping tool suited to assist in a wide array of research applications."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/cell,
|
||||
/obj/item/weapon/stock_parts,
|
||||
/obj/item/device/mmi,
|
||||
/obj/item/robot_parts,
|
||||
/obj/item/borg/upgrade,
|
||||
/obj/item/device/flash, //to build borgs,
|
||||
/obj/item/weapon/disk,
|
||||
/obj/item/weapon/circuitboard,
|
||||
/obj/item/weapon/reagent_containers/glass,
|
||||
/obj/item/device/assembly/prox_sensor,
|
||||
/obj/item/device/healthanalyzer, //to build medibots,
|
||||
/obj/item/slime_cube,
|
||||
/obj/item/slime_crystal,
|
||||
/obj/item/weapon/disposable_teleporter/slime,
|
||||
/obj/item/slimepotion,
|
||||
/obj/item/slime_extract,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/monkeycube
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/circuit
|
||||
name = "circuit assembly gripper"
|
||||
icon_state = "gripper-circ"
|
||||
desc = "A complex grasping tool used for working with circuitry."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/cell/device,
|
||||
/obj/item/device/electronic_assembly,
|
||||
/obj/item/device/assembly/electronic_assembly,
|
||||
/obj/item/clothing/under/circuitry,
|
||||
/obj/item/clothing/gloves/circuitry,
|
||||
/obj/item/clothing/glasses/circuitry,
|
||||
/obj/item/clothing/shoes/circuitry,
|
||||
/obj/item/clothing/head/circuitry,
|
||||
/obj/item/clothing/ears/circuitry,
|
||||
/obj/item/clothing/suit/circuitry,
|
||||
/obj/item/weapon/implant/integrated_circuit,
|
||||
/obj/item/integrated_circuit
|
||||
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/service //Used to handle food, drinks, and seeds.
|
||||
name = "service gripper"
|
||||
icon_state = "gripper"
|
||||
desc = "A simple grasping tool used to perform tasks in the service sector, such as handling food, drinks, and seeds."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/weapon/reagent_containers/glass,
|
||||
/obj/item/weapon/reagent_containers/food,
|
||||
/obj/item/seeds,
|
||||
/obj/item/weapon/grown,
|
||||
/obj/item/trash,
|
||||
/obj/item/weapon/reagent_containers/cooking_container
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/gravekeeper //Used for handling grave things, flowers, etc.
|
||||
name = "grave gripper"
|
||||
icon_state = "gripper"
|
||||
desc = "A specialized grasping tool used in the preparation and maintenance of graves."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/seeds,
|
||||
/obj/item/weapon/grown,
|
||||
/obj/item/weapon/material/gravemarker
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ
|
||||
name = "organ gripper"
|
||||
icon_state = "gripper-flesh"
|
||||
desc = "A specialized grasping tool used to preserve and manipulate organic material."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/organ,
|
||||
/obj/item/device/nif //NIFs can be slapped in during surgery
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ/Entered(var/atom/movable/AM)
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 1
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 1
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ/Exited(var/atom/movable/AM)
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 0
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ/robotics
|
||||
name = "robotics organ gripper"
|
||||
icon_state = "gripper-flesh"
|
||||
desc = "A specialized grasping tool used in robotics work."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/organ/external,
|
||||
/obj/item/organ/internal/brain, //to insert into MMIs,
|
||||
/obj/item/organ/internal/cell,
|
||||
/obj/item/organ/internal/eyes/robot,
|
||||
/obj/item/device/nif //NIFs can be slapped in during surgery
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/mech
|
||||
name = "exosuit gripper"
|
||||
icon_state = "gripper-mech"
|
||||
desc = "A large, heavy-duty grasping tool used in construction of mechs."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/mecha_parts/part,
|
||||
//obj/item/mecha_parts/micro/part, //VOREStation Edit: Allow construction of micromechs //CHOMPedit commented micromech stuff, because fuck this trash
|
||||
/obj/item/mecha_parts/mecha_equipment,
|
||||
/obj/item/mecha_parts/mecha_tracking,
|
||||
/obj/item/mecha_parts/component
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use //Used when you want to hold and put items in other things, but not able to 'use' the item
|
||||
|
||||
/obj/item/weapon/gripper/no_use/attack_self(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/weapon/gripper/no_use/loader //This is used to disallow building with metal.
|
||||
name = "sheet loader"
|
||||
desc = "A specialized loading device, designed to pick up and insert sheets of materials inside machines."
|
||||
icon_state = "gripper-sheet"
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/stack/material
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/attack_self(mob/user as mob)
|
||||
if(wrapped)
|
||||
return wrapped.attack_self(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gripper/attackby(var/obj/item/O, var/mob/user)
|
||||
if(wrapped) // We're interacting with the item inside. If you can hold a cup with 2 fingers and stick a straw in it, you could do that with a gripper and another robotic arm.
|
||||
wrapped.loc = src.loc
|
||||
var/resolved = wrapped.attackby(O, user)
|
||||
if(QDELETED(wrapped) || wrapped.loc != src.loc) //Juuuust in case.
|
||||
wrapped = null
|
||||
if(!resolved && wrapped && O)
|
||||
O.afterattack(wrapped,user,1)
|
||||
if(QDELETED(wrapped) || wrapped.loc != src.loc) // I don't know of a nicer way to do this.
|
||||
wrapped = null
|
||||
if(wrapped)
|
||||
wrapped.loc = src
|
||||
return resolved
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gripper/verb/drop_gripper_item()
|
||||
|
||||
set name = "Drop Item"
|
||||
set desc = "Release an item from your magnetic gripper."
|
||||
set category = "Robot Commands"
|
||||
|
||||
drop_item()
|
||||
|
||||
/obj/item/weapon/gripper/proc/drop_item()
|
||||
if(!wrapped)
|
||||
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
|
||||
for(var/obj/item/thing in src.contents)
|
||||
thing.loc = get_turf(src)
|
||||
return
|
||||
|
||||
if(wrapped.loc != src)
|
||||
wrapped = null
|
||||
return
|
||||
|
||||
to_chat(src.loc, "<span class='notice'>You drop \the [wrapped].</span>")
|
||||
wrapped.loc = get_turf(src)
|
||||
wrapped = null
|
||||
//update_icon()
|
||||
|
||||
/obj/item/weapon/gripper/proc/drop_item_nm()
|
||||
|
||||
if(!wrapped)
|
||||
for(var/obj/item/thing in src.contents)
|
||||
thing.loc = get_turf(src)
|
||||
return
|
||||
|
||||
if(wrapped.loc != src)
|
||||
wrapped = null
|
||||
return
|
||||
|
||||
wrapped.loc = get_turf(src)
|
||||
wrapped = null
|
||||
//update_icon()
|
||||
|
||||
/obj/item/weapon/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||
if(wrapped) //The force of the wrapped obj gets set to zero during the attack() and afterattack().
|
||||
force_holder = wrapped.force
|
||||
wrapped.force = 0.0
|
||||
if(QDELETED(wrapped) || wrapped.loc != src.loc) //qdel check here so it doesn't duplicate/spawn ghost items
|
||||
wrapped = null
|
||||
else
|
||||
wrapped.loc = src.loc //To ensure checks pass.
|
||||
wrapped.attack(M,user)
|
||||
M.attackby(wrapped, user) //attackby reportedly gets procced by being clicked on, at least according to Anewbe.
|
||||
if(QDELETED(wrapped) || wrapped.loc != src.loc)
|
||||
wrapped = null
|
||||
if(wrapped) //In the event nothing happened to wrapped, go back into the gripper.
|
||||
wrapped.loc = src
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params)
|
||||
|
||||
if(!proximity)
|
||||
return // This will prevent them using guns at range but adminbuse can add them directly to modules, so eh.
|
||||
|
||||
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
|
||||
if(!wrapped)
|
||||
for(var/obj/item/thing in src.contents)
|
||||
wrapped = thing
|
||||
break
|
||||
|
||||
if(wrapped) //Already have an item.
|
||||
//Temporary put wrapped into user so target's attackby() checks pass.
|
||||
wrapped.loc = user
|
||||
|
||||
//Pass the attack on to the target. This might delete/relocate wrapped.
|
||||
var/resolved = target.attackby(wrapped,user)
|
||||
if(!resolved && wrapped && target)
|
||||
wrapped.afterattack(target,user,1)
|
||||
|
||||
//wrapped's force was set to zero. This resets it to the value it had before.
|
||||
if(wrapped)
|
||||
wrapped.force = force_holder
|
||||
force_holder = null
|
||||
//If wrapped was neither deleted nor put into target, put it back into the gripper.
|
||||
if(wrapped && user && (wrapped.loc == user))
|
||||
wrapped.loc = src
|
||||
else
|
||||
wrapped = null
|
||||
return
|
||||
|
||||
else if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
|
||||
|
||||
//...and that the item is not in a container.
|
||||
if(!isturf(target.loc))
|
||||
return
|
||||
|
||||
var/obj/item/I = target
|
||||
|
||||
if(I.anchored)
|
||||
to_chat(user,"<span class='notice'>You are unable to lift \the [I] from \the [I.loc].</span>")
|
||||
return
|
||||
|
||||
//Check if the item is blacklisted.
|
||||
var/grab = 0
|
||||
for(var/typepath in can_hold)
|
||||
if(istype(I,typepath))
|
||||
grab = 1
|
||||
break
|
||||
|
||||
//We can grab the item, finally.
|
||||
if(grab)
|
||||
to_chat(user, "You collect \the [I].")
|
||||
I.loc = src
|
||||
wrapped = I
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Your gripper cannot hold \the [target].</span>")
|
||||
|
||||
else if(istype(target,/obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = target
|
||||
if(A.opened)
|
||||
if(A.cell)
|
||||
|
||||
wrapped = A.cell
|
||||
|
||||
A.cell.add_fingerprint(user)
|
||||
A.cell.update_icon()
|
||||
A.cell.loc = src
|
||||
A.cell = null
|
||||
|
||||
A.charging = 0
|
||||
A.update_icon()
|
||||
|
||||
user.visible_message("<span class='danger'>[user] removes the power cell from [A]!</span>", "You remove the power cell.")
|
||||
|
||||
else if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/A = target
|
||||
if(A.opened)
|
||||
if(A.cell)
|
||||
|
||||
wrapped = A.cell
|
||||
|
||||
A.cell.add_fingerprint(user)
|
||||
A.cell.update_icon()
|
||||
A.updateicon()
|
||||
A.cell.loc = src
|
||||
A.cell = null
|
||||
|
||||
user.visible_message("<span class='danger'>[user] removes the power cell from [A]!</span>", "You remove the power cell.")
|
||||
|
||||
//TODO: Matter decompiler.
|
||||
/obj/item/weapon/matter_decompiler
|
||||
|
||||
name = "matter decompiler"
|
||||
desc = "Eating trash, bits of glass, or other debris will replenish your stores."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "decompiler"
|
||||
|
||||
//Metal, glass, wood, plastic.
|
||||
var/datum/matter_synth/metal = null
|
||||
var/datum/matter_synth/glass = null
|
||||
var/datum/matter_synth/wood = null
|
||||
var/datum/matter_synth/plastic = null
|
||||
|
||||
/obj/item/weapon/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/weapon/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
|
||||
|
||||
if(!proximity) return //Not adjacent.
|
||||
|
||||
//We only want to deal with using this on turfs. Specific items aren't important.
|
||||
var/turf/T = get_turf(target)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
//Used to give the right message.
|
||||
var/grabbed_something = 0
|
||||
|
||||
for(var/mob/M in T)
|
||||
if(istype(M,/mob/living/simple_mob/animal/passive/lizard) || istype(M,/mob/living/simple_mob/animal/passive/mouse))
|
||||
src.loc.visible_message("<span class='danger'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='danger'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
|
||||
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
|
||||
qdel(M)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(2000)
|
||||
return
|
||||
|
||||
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
|
||||
|
||||
var/mob/living/silicon/robot/D = src.loc
|
||||
|
||||
if(!istype(D))
|
||||
return
|
||||
|
||||
to_chat(D, "<span class='danger'>You begin decompiling [M].</span>")
|
||||
|
||||
if(!do_after(D,50))
|
||||
to_chat(D, "<span class='danger'>You need to remain still while decompiling such a large object.</span>")
|
||||
return
|
||||
|
||||
if(!M || !D) return
|
||||
|
||||
to_chat(D, "<span class='danger'>You carefully and thoroughly decompile [M], storing as much of its resources as you can within yourself.</span>")
|
||||
qdel(M)
|
||||
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
|
||||
if(metal)
|
||||
metal.add_charge(15000)
|
||||
if(glass)
|
||||
glass.add_charge(15000)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(1000)
|
||||
return
|
||||
else
|
||||
continue
|
||||
|
||||
for(var/obj/W in T)
|
||||
//Different classes of items give different commodities.
|
||||
if(istype(W,/obj/item/trash/cigbutt))
|
||||
if(plastic)
|
||||
plastic.add_charge(500)
|
||||
else if(istype(W,/obj/effect/spider/spiderling))
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(2000)
|
||||
else if(istype(W,/obj/item/weapon/light))
|
||||
var/obj/item/weapon/light/L = W
|
||||
if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
|
||||
if(metal)
|
||||
metal.add_charge(250)
|
||||
if(glass)
|
||||
glass.add_charge(250)
|
||||
else
|
||||
continue
|
||||
else if(istype(W,/obj/effect/decal/remains/robot))
|
||||
if(metal)
|
||||
metal.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(2000)
|
||||
if(glass)
|
||||
glass.add_charge(1000)
|
||||
else if(istype(W,/obj/item/trash))
|
||||
if(metal)
|
||||
metal.add_charge(1000)
|
||||
if(plastic)
|
||||
plastic.add_charge(3000)
|
||||
else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
|
||||
if(metal)
|
||||
metal.add_charge(2000)
|
||||
if(glass)
|
||||
glass.add_charge(2000)
|
||||
else if(istype(W,/obj/item/ammo_casing))
|
||||
if(metal)
|
||||
metal.add_charge(1000)
|
||||
else if(istype(W,/obj/item/weapon/material/shard/shrapnel))
|
||||
if(metal)
|
||||
metal.add_charge(1000)
|
||||
else if(istype(W,/obj/item/weapon/material/shard))
|
||||
if(glass)
|
||||
glass.add_charge(1000)
|
||||
else if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown))
|
||||
if(wood)
|
||||
wood.add_charge(4000)
|
||||
else if(istype(W,/obj/item/pipe))
|
||||
// This allows drones and engiborgs to clear pipe assemblies from floors.
|
||||
else
|
||||
continue
|
||||
|
||||
qdel(W)
|
||||
grabbed_something = 1
|
||||
|
||||
if(grabbed_something)
|
||||
to_chat(user, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Nothing on \the [T] is useful to you.</span>")
|
||||
return
|
||||
|
||||
//PRETTIER TOOL LIST.
|
||||
/mob/living/silicon/robot/drone/installed_modules()
|
||||
|
||||
if(weapon_lock)
|
||||
to_chat(src, "<span class='danger'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
|
||||
return
|
||||
|
||||
if(!module)
|
||||
module = new /obj/item/weapon/robot_module/drone(src)
|
||||
|
||||
var/dat = "<HEAD><TITLE>Drone modules</TITLE></HEAD><BODY>\n"
|
||||
dat += {"
|
||||
<B>Activated Modules</B>
|
||||
<BR>
|
||||
Module 1: [module_state_1 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]<BR>
|
||||
Module 2: [module_state_2 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]<BR>
|
||||
Module 3: [module_state_3 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]<BR>
|
||||
<BR>
|
||||
<B>Installed Modules</B><BR><BR>"}
|
||||
|
||||
|
||||
var/tools = "<B>Tools and devices</B><BR>"
|
||||
var/resources = "<BR><B>Resources</B><BR>"
|
||||
|
||||
for (var/O in module.modules)
|
||||
|
||||
var/module_string = ""
|
||||
|
||||
if (!O)
|
||||
module_string += text("<B>Resource depleted</B><BR>")
|
||||
else if(activated(O))
|
||||
module_string += text("[O]: <B>Activated</B><BR>")
|
||||
else
|
||||
module_string += text("[O]: <A HREF=?src=\ref[src];act=\ref[O]>Activate</A><BR>")
|
||||
|
||||
if((istype(O,/obj/item/weapon) || istype(O,/obj/item/device)) && !(istype(O,/obj/item/stack/cable_coil)))
|
||||
tools += module_string
|
||||
else
|
||||
resources += module_string
|
||||
|
||||
dat += tools
|
||||
|
||||
if (emagged)
|
||||
if (!module.emag)
|
||||
dat += text("<B>Resource depleted</B><BR>")
|
||||
else if(activated(module.emag))
|
||||
dat += text("[module.emag]: <B>Activated</B><BR>")
|
||||
else
|
||||
dat += text("[module.emag]: <A HREF=?src=\ref[src];act=\ref[module.emag]>Activate</A><BR>")
|
||||
|
||||
dat += resources
|
||||
|
||||
src << browse(dat, "window=robotmod")
|
||||
|
||||
//CHOMPADDITIONS
|
||||
/obj/item/weapon/gripper/scene
|
||||
name = "misc gripper"
|
||||
desc = "A simple grasping tool that can hold a variety of 'general' objects..."
|
||||
@@ -10,4 +610,4 @@
|
||||
/obj/item/weapon/handcuffs,
|
||||
/obj/item/toy,
|
||||
/obj/item/petrifier
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,42 @@
|
||||
//Defines the extra laws drones have
|
||||
/datum/ai_laws/jani_drone
|
||||
name = "Maintence Protocols"
|
||||
law_header = "Maintenance Protocols"
|
||||
|
||||
/datum/ai_laws/drone/New()
|
||||
add_inherent_law("Do not interfere with the maintenance work of non-drones whenever possible.")
|
||||
add_inherent_law("Preserve, repair and improve the station to the best of your abilities.")
|
||||
add_inherent_law("Cause no harm to the station or any crew on it.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/construction_drone
|
||||
name = "Construction Protocols"
|
||||
law_header = "Construction Protocols"
|
||||
|
||||
/datum/ai_laws/construction_drone/New()
|
||||
add_inherent_law("Do not interfere with the construction work of non-drones whenever possible.")
|
||||
add_inherent_law("Repair, refit and upgrade your assigned vessel.")
|
||||
add_inherent_law("Prevent unplanned damage to your assigned vessel wherever possible.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/mining_drone
|
||||
name = "Excavation Protocols"
|
||||
law_header = "Excavation Protocols"
|
||||
|
||||
/datum/ai_laws/mining_drone/New()
|
||||
add_inherent_law("Do not interfere with the excavation work of non-drones whenever possible.")
|
||||
add_inherent_law("Provide materials for repairing, refitting, and upgrading your assigned vessel.")
|
||||
add_inherent_law("Prevent unplanned damage to your assigned excavation equipment wherever possible.")
|
||||
..()
|
||||
|
||||
/datum/ai_laws/security_drone
|
||||
name = "Security Protocols"
|
||||
law_header = "Security Protocols"
|
||||
|
||||
/datum/ai_laws/security_drone/New()
|
||||
add_inherent_law("Do not interfere with the security work of non-drones whenever possible.")
|
||||
add_inherent_law("Provide protection to the crew and eliminate hostile lifeforms on your assigned vessel.")
|
||||
add_inherent_law("Obey orders by security personnel except if they violate law 4.")
|
||||
add_inherent_law("Lethal force requires a code higher than green AND orders by security to use it to authorize it.")
|
||||
add_inherent_law("You must outfit yourself with a security beret.")
|
||||
..()
|
||||
@@ -0,0 +1,182 @@
|
||||
//Modified copy of regula drone folder
|
||||
/proc/count_drones()
|
||||
var/drones = 0
|
||||
for(var/mob/living/silicon/robot/drone/D in player_list)
|
||||
drones++
|
||||
return drones
|
||||
|
||||
/obj/machinery/drone_fabricator
|
||||
name = "drone fabricator"
|
||||
desc = "A large automated factory for producing maintenance drones."
|
||||
appearance_flags = 0
|
||||
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
|
||||
var/fabricator_tag = "Upper Level"
|
||||
var/drone_progress = 0
|
||||
var/produce_drones = 2
|
||||
var/time_last_drone = 500
|
||||
var/drone_type = /mob/living/silicon/robot/drone
|
||||
|
||||
icon = 'icons/obj/machines/drone_fab.dmi'
|
||||
icon_state = "drone_fab_idle"
|
||||
var/list/possible_drones = list("Maintenance Module" = /mob/living/silicon/robot/drone)
|
||||
|
||||
/obj/machinery/drone_fabricator/derelict
|
||||
name = "construction drone fabricator"
|
||||
fabricator_tag = "Upper Level Construction"
|
||||
drone_type = /mob/living/silicon/robot/drone/construction
|
||||
possible_drones = list("Construction Module" = /mob/living/silicon/robot/drone/construction)
|
||||
|
||||
/obj/machinery/drone_fabricator/mining
|
||||
name = "mining drone fabricator"
|
||||
fabricator_tag = "Upper Level Mining"
|
||||
drone_type = /mob/living/silicon/robot/drone/mining
|
||||
possible_drones = list("Mining Module" = /mob/living/silicon/robot/drone/mining)
|
||||
|
||||
/obj/machinery/drone_fabricator/New()
|
||||
..()
|
||||
|
||||
/obj/machinery/drone_fabricator/power_change()
|
||||
..()
|
||||
if (stat & NOPOWER)
|
||||
icon_state = "drone_fab_nopower"
|
||||
|
||||
/obj/machinery/drone_fabricator/process()
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
return
|
||||
|
||||
if(stat & NOPOWER || !produce_drones)
|
||||
if(icon_state != "drone_fab_nopower") icon_state = "drone_fab_nopower"
|
||||
return
|
||||
|
||||
if(drone_progress >= 100)
|
||||
icon_state = "drone_fab_idle"
|
||||
return
|
||||
|
||||
icon_state = "drone_fab_active"
|
||||
var/elapsed = world.time - time_last_drone
|
||||
drone_progress = round((elapsed/config.drone_build_time)*100)
|
||||
|
||||
if(drone_progress >= 100)
|
||||
visible_message("\The [src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
. = ..()
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/observer/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
. += "<br><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
choose_dronetype(possible_drones) //Call Drone choice before executing create_drone
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
return
|
||||
|
||||
if(player && !istype(player.mob,/mob/observer/dead))
|
||||
return
|
||||
|
||||
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
flick("h_lathe_leave",src)
|
||||
drone_progress = 0
|
||||
|
||||
time_last_drone = world.time
|
||||
|
||||
var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
|
||||
if(player)
|
||||
announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
|
||||
if(player.mob && player.mob.mind) player.mob.mind.reset()
|
||||
new_drone.transfer_personality(player)
|
||||
|
||||
return new_drone
|
||||
|
||||
/mob/observer/dead/verb/join_as_drone()
|
||||
|
||||
set category = "Ghost"
|
||||
set name = "Join As Drone"
|
||||
set desc = "If there is a powered, enabled fabricator in the game world with a prepared chassis, join as a maintenance drone."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if(!(config.allow_drone_spawn))
|
||||
to_chat(src, "<span class='danger'>That verb is not currently permitted.</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return 0 //something is terribly wrong
|
||||
|
||||
if(jobban_isbanned(src,"Cyborg"))
|
||||
to_chat(usr, "<span class='danger'>You are banned from playing synthetics and cannot spawn as a drone.</span>")
|
||||
return
|
||||
|
||||
// VOREStation Addition Start
|
||||
if(config.use_age_restriction_for_jobs && isnum(src.client.player_age))
|
||||
var/time_till_play = max(0, 3 - src.client.player_age)
|
||||
if(time_till_play)
|
||||
to_chat(usr, "<span class='danger'>You have not been playing on the server long enough to join as drone.</span>")
|
||||
return
|
||||
// VOREStation Addition End
|
||||
|
||||
if(!MayRespawn(1))
|
||||
return
|
||||
|
||||
var/deathtime = world.time - src.timeofdeath
|
||||
var/deathtimeminutes = round(deathtime / (1 MINUTE))
|
||||
var/pluralcheck = "minute"
|
||||
if(deathtimeminutes == 0)
|
||||
pluralcheck = ""
|
||||
else if(deathtimeminutes == 1)
|
||||
pluralcheck = " [deathtimeminutes] minute and"
|
||||
else if(deathtimeminutes > 1)
|
||||
pluralcheck = " [deathtimeminutes] minutes and"
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 1 MINUTE) / 10,1)
|
||||
|
||||
if (deathtime < 5 MINUTES)
|
||||
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
|
||||
to_chat(usr, "You must wait 5 minutes to respawn as a drone!")
|
||||
return
|
||||
|
||||
var/list/all_fabricators = list()
|
||||
for(var/obj/machinery/drone_fabricator/DF in machines)
|
||||
if(DF.stat & NOPOWER || !DF.produce_drones)
|
||||
continue
|
||||
if(DF.drone_progress >= 100)
|
||||
all_fabricators[DF.fabricator_tag] = DF
|
||||
|
||||
if(!all_fabricators.len)
|
||||
to_chat(src, "<span class='danger'>There are no available drone spawn points, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src, "Which fabricator do you wish to use?", "Fabricator Choice", all_fabricators)
|
||||
if(choice)
|
||||
var/obj/machinery/drone_fabricator/chosen_fabricator = all_fabricators[choice]
|
||||
chosen_fabricator.create_drone(src.client)
|
||||
|
||||
|
||||
//UNIFY, sub fabricator that can handle more than one type
|
||||
/obj/machinery/drone_fabricator/unify //Non-Specific dronetype
|
||||
drone_type = null //var filled by drone choice.
|
||||
fabricator_tag = "Unified Drone Fabricator"
|
||||
possible_drones = list("Construction Module" = /mob/living/silicon/robot/drone/construction,
|
||||
"Maintenance Module" = /mob/living/silicon/robot/drone,
|
||||
) //List of drone types to choose from.//Changeable in mapping.
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/choose_dronetype(possible_drones)
|
||||
if(!LAZYLEN(possible_drones)-1)
|
||||
drone_type = possible_drones[1]
|
||||
return
|
||||
var/choice
|
||||
choice = input(usr,"What module would you like to use?") as null|anything in possible_drones
|
||||
if(!choice) return
|
||||
drone_type = possible_drones[choice]
|
||||
@@ -0,0 +1,39 @@
|
||||
//Modified copy of regula drone folder
|
||||
/mob/living/silicon/robot/drone/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
|
||||
if(local_transmit)
|
||||
if (src.client && client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "You cannot send IC messages (muted).")
|
||||
return 0
|
||||
|
||||
message = sanitize(message)
|
||||
|
||||
if (stat == DEAD)
|
||||
return say_dead(message)
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
if(copytext(message,1,2) == ";")
|
||||
var/datum/language/L = GLOB.all_languages["Drone Talk"]
|
||||
if(istype(L))
|
||||
return L.broadcast(src,trim(copytext(message,2)))
|
||||
|
||||
//Must be concious to speak
|
||||
if (stat)
|
||||
return 0
|
||||
|
||||
var/list/listeners = hearers(5,src)
|
||||
listeners |= src
|
||||
|
||||
for(var/mob/living/silicon/D in listeners)
|
||||
if(D.client && D.local_transmit)
|
||||
to_chat(D, "<b>[src]</b> transmits, \"[message]\"")
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(M.client)
|
||||
to_chat(M, "<b>[src]</b> transmits, \"[message]\"")
|
||||
return 1
|
||||
return ..()
|
||||
@@ -0,0 +1,53 @@
|
||||
//All of the different types of drones
|
||||
|
||||
/mob/living/silicon/robot/drone/construction
|
||||
name = "construction drone"
|
||||
icon_state = "constructiondrone"
|
||||
law_type = /datum/ai_laws/construction_drone
|
||||
module_type = /obj/item/weapon/robot_module/drone/construction
|
||||
hat_x_offset = 1
|
||||
hat_y_offset = -12
|
||||
can_pull_mobs = MOB_PULL_SAME
|
||||
can_pick_shell = FALSE
|
||||
shell_accessories = list("eyes-constructiondrone")
|
||||
//These are short overrides dont do this for long shit
|
||||
welcome_drone()
|
||||
to_chat(src, "<b>You are a construction drone, an autonomous engineering and fabrication system.</b>.")
|
||||
to_chat(src, "You are assigned to a Sol Central construction project. The name is irrelevant. Your task is to complete construction and subsystem integration as soon as possible.")
|
||||
to_chat(src, "Use <b>:d</b> to talk to other drones and <b>say</b> to speak silently to your nearby fellows.")
|
||||
to_chat(src, "<b>You do not follow orders from anyone; not the AI, not humans, and not other synthetics.</b>.")
|
||||
//These are short overrides dont do this for long shit
|
||||
init()
|
||||
..()
|
||||
flavor_text = "It's a bulky construction drone stamped with a Sol Central glyph."
|
||||
|
||||
/mob/living/silicon/robot/drone/mining
|
||||
icon_state = "miningdrone"
|
||||
item_state = "constructiondrone"
|
||||
law_type = /datum/ai_laws/mining_drone
|
||||
module_type = /obj/item/weapon/robot_module/drone/mining
|
||||
hat_x_offset = 1
|
||||
hat_y_offset = -12
|
||||
can_pull_mobs = MOB_PULL_SAME
|
||||
can_pick_shell = FALSE
|
||||
shell_accessories = list("eyes-miningdrone")
|
||||
//These are short overrides dont do this for long shit
|
||||
init()
|
||||
..()
|
||||
flavor_text = "It's a bulky mining drone stamped with a Grayson logo."
|
||||
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "unified drone" //Maintenance drones can be a Jani specific shell now, the normal drone will be a blank shell not really intended for use
|
||||
law_type = /datum/ai_laws/drone
|
||||
|
||||
/mob/living/silicon/robot/drone/jan
|
||||
name = "maintenance drone"
|
||||
law_type = /datum/ai_laws/jani_drone
|
||||
|
||||
/mob/living/silicon/robot/drone/sec
|
||||
name = "security drone"
|
||||
law_type = /datum/ai_laws/security_drone
|
||||
|
||||
/mob/living/silicon/robot/drone/min
|
||||
name = "mining drone"
|
||||
law_type = /datum/ai_laws/mining_drone
|
||||
@@ -0,0 +1,72 @@
|
||||
//Modified copy of regula drone folder
|
||||
/mob/living/silicon/robot/drone/swarm
|
||||
name = "swarm drone"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer"
|
||||
item_state = "repairbot"
|
||||
faction = "swarmer"
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
cell_emp_mult = 0.5
|
||||
universal_speak = 0
|
||||
universal_understand = 1
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
braintype = "Drone"
|
||||
lawupdate = 0
|
||||
density = TRUE
|
||||
idcard_type = /obj/item/weapon/card/id/syndicate
|
||||
req_access = list(999)
|
||||
integrated_light_power = 3
|
||||
local_transmit = 0
|
||||
|
||||
can_pull_size = ITEMSIZE_NO_CONTAINER
|
||||
can_pull_mobs = MOB_PULL_SMALLER
|
||||
can_enter_vent_with = list(
|
||||
/obj,
|
||||
/atom/movable/emissive_blocker)
|
||||
|
||||
mob_always_swap = 1
|
||||
|
||||
speed = 3
|
||||
|
||||
softfall = TRUE
|
||||
|
||||
mob_size = MOB_LARGE
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm
|
||||
|
||||
hat_x_offset = 0
|
||||
hat_y_offset = -10
|
||||
|
||||
foreign_droid = TRUE
|
||||
scrambledcodes = TRUE
|
||||
|
||||
holder_type = /obj/item/weapon/holder/drone
|
||||
|
||||
can_be_antagged = TRUE
|
||||
|
||||
var/spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/conjure/zeropointwell,
|
||||
/spell/aoe_turf/conjure/zeropointbarricade,
|
||||
/spell/aoe_turf/blink/swarm,
|
||||
/spell/aoe_turf/conjure/swarmer/gunner,
|
||||
/spell/aoe_turf/conjure/swarmer/melee
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/Initialize()
|
||||
. = ..()
|
||||
|
||||
add_language(LANGUAGE_SWARMBOT, 1)
|
||||
|
||||
for(var/spell in spell_setup)
|
||||
src.add_spell(new spell, "nano_spell_ready", /obj/screen/movable/spell_master/swarm)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/init()
|
||||
..()
|
||||
QDEL_NULL(aiCamera)
|
||||
flavor_text = "Some form of ancient machine."
|
||||
@@ -0,0 +1,117 @@
|
||||
//Modified copy of regula drone folder
|
||||
/spell/aoe_turf/conjure/swarmer
|
||||
name = "Self Replication"
|
||||
desc = "This ability constructs a standard swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 5 MINUTES
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
|
||||
animation.icon_state = "deflect_static"
|
||||
flick("shield2",animation)
|
||||
spawn(1 SECOND)
|
||||
qdel(animation)
|
||||
|
||||
/spell/aoe_turf/conjure/forcewall/swarm
|
||||
name = "Null-Field"
|
||||
desc = "Create a bubble of null-point energy."
|
||||
summon_type = list(/obj/effect/forcefield/swarm)
|
||||
duration = 30 SECONDS
|
||||
charge_max = 60 SECONDS
|
||||
|
||||
school = "conjuration"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
hud_state = "wiz_shield"
|
||||
|
||||
/obj/effect/forcefield/swarm
|
||||
desc = "A pocket of strange energy."
|
||||
name = "Null-Field"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "shield-old"
|
||||
invisibility = 0
|
||||
|
||||
/spell/aoe_turf/conjure/zeropointwell
|
||||
name = "Zero-Point Well"
|
||||
desc = "This ability constructs a standard zero-point energy well, capable of charging nearby swarmers."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 120 SECONDS
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/cult/pylon/swarm/zp_well)
|
||||
|
||||
hud_state = "swarm_zeropoint"
|
||||
|
||||
/spell/aoe_turf/conjure/zeropointbarricade
|
||||
name = "Zero-Point Barricade"
|
||||
desc = "This ability constructs a standard zero-point energy wall, used to create a secure passageway for allies, and a bastion for defense."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 120 SECONDS
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/cult/pylon/swarm/defender)
|
||||
|
||||
hud_state = "swarm_barricade"
|
||||
|
||||
/spell/aoe_turf/blink/swarm
|
||||
name = "Warp"
|
||||
desc = "Your null-point drive jaunts you to a new location."
|
||||
|
||||
school = "abjuration"
|
||||
charge_max = 5 MINUTES
|
||||
spell_flags = Z2NOCAST | IGNOREDENSE
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 10
|
||||
inner_radius = 5
|
||||
hud_state = "swarm_warp"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/gunner
|
||||
name = "Generate Gunner"
|
||||
desc = "This spell constructs a gunner swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_type = Sp_CHARGES
|
||||
charge_max = 1
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/gunner)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
|
||||
/spell/aoe_turf/conjure/swarmer/melee
|
||||
name = "Generate Impaler"
|
||||
desc = "This spell constructs an impaler swarmer shell that may activate at some point."
|
||||
|
||||
school = "conjuration"
|
||||
charge_type = Sp_CHARGES
|
||||
charge_max = 1
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/melee)
|
||||
|
||||
hud_state = "swarm_replicate"
|
||||
@@ -0,0 +1,162 @@
|
||||
//Modified copy of regula drone folder
|
||||
//Swarm Assimilator / Breacher
|
||||
/obj/item/weapon/matter_decompiler/swarm
|
||||
name = "matter assimilator"
|
||||
desc = "Used to eat some forms of simple machinery; and large, wall-shaped blocks of metal with energetic fields."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "decompiler_swarm"
|
||||
|
||||
var/field_cooldown = 1 MINUTE
|
||||
var/last_field = 0
|
||||
|
||||
/obj/item/weapon/matter_decompiler/swarm/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
|
||||
|
||||
if(!proximity) return //Not adjacent.
|
||||
|
||||
//We only want to deal with using this on turfs. Specific items aren't important.
|
||||
var/turf/T = get_turf(target)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
//Used to give the right message.
|
||||
var/grabbed_something = FALSE
|
||||
|
||||
for(var/mob/M in T)
|
||||
if(istype(M,/mob/living/simple_mob/animal/passive/lizard) || istype(M,/mob/living/simple_mob/animal/passive/mouse))
|
||||
src.loc.visible_message("<span class='danger'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='danger'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
|
||||
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
|
||||
qdel(M)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(2000)
|
||||
return
|
||||
|
||||
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
|
||||
|
||||
var/mob/living/silicon/robot/D = src.loc
|
||||
|
||||
if(!istype(D))
|
||||
return
|
||||
|
||||
to_chat(D, "<span class='danger'>You begin decompiling [M].</span>")
|
||||
|
||||
if(!do_after(D,50))
|
||||
to_chat(D, "<span class='danger'>You need to remain still while decompiling such a large object.</span>")
|
||||
return
|
||||
|
||||
if(!M || !D) return
|
||||
|
||||
to_chat(D, "<span class='danger'>You carefully and thoroughly decompile [M], storing as much of its resources as you can within yourself.</span>")
|
||||
qdel(M)
|
||||
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
|
||||
if(metal)
|
||||
metal.add_charge(15000)
|
||||
if(glass)
|
||||
glass.add_charge(15000)
|
||||
if(wood)
|
||||
wood.add_charge(2000)
|
||||
if(plastic)
|
||||
plastic.add_charge(1000)
|
||||
return
|
||||
else
|
||||
continue
|
||||
|
||||
for(var/obj/W in T)
|
||||
//Different classes of items give different commodities.
|
||||
if(istype(W,/obj/structure/girder))
|
||||
if(metal)
|
||||
metal.add_charge(500)
|
||||
else if(istype(W,/obj/machinery/power/emitter))
|
||||
if(metal)
|
||||
metal.add_charge(3000)
|
||||
if(plastic)
|
||||
plastic.add_charge(1000)
|
||||
else if(istype(W,/obj/machinery/space_heater))
|
||||
if(metal)
|
||||
metal.add_charge(1500)
|
||||
if(plastic)
|
||||
plastic.add_charge(750)
|
||||
else if(istype(W,/obj/structure/closet))
|
||||
var/obj/structure/closet/C = W
|
||||
if(!C.opened)
|
||||
continue
|
||||
if(istype(W,/obj/structure/closet/coffin))
|
||||
if(wood)
|
||||
wood.add_charge(1000)
|
||||
else if(istype(W,/obj/structure/closet/crate/plastic))
|
||||
if(plastic)
|
||||
plastic.add_charge(750)
|
||||
else
|
||||
if(metal)
|
||||
metal.add_charge(1000)
|
||||
else
|
||||
continue
|
||||
|
||||
qdel(W)
|
||||
grabbed_something = TRUE
|
||||
|
||||
if(istype(T,/turf/simulated/wall) && (last_field < world.time + field_cooldown))
|
||||
if(!(locate(/obj/effect/temporary_effect/pulse/disintegrate)))
|
||||
last_field = world.time
|
||||
to_chat(user, "<span class='alien'>You deploy an energetic field through \the [T], beginning its deconstruction.</span>")
|
||||
to_chat(user, "<span class='warning'>You should stand back.</span>")
|
||||
new /obj/effect/temporary_effect/pulse/disintegrate(T)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There is already a disintigration field affecting \the [T].</span>")
|
||||
|
||||
if(grabbed_something)
|
||||
to_chat(user, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Nothing on \the [T] is useful to you.</span>")
|
||||
return
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate
|
||||
name = "molecular debonding field"
|
||||
desc = "This is something you do not want to near."
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "disintegrate_pulse"
|
||||
light_range = 4
|
||||
light_power = 5
|
||||
light_color = "#00B4D9"
|
||||
pulses_remaining = 5
|
||||
pulse_delay = 2 SECONDS
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/emp_act()
|
||||
visible_message("<span class='warning'>\The [src] flickers, before dispersing energetically.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/on_pulse()
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T,/turf/simulated/wall))
|
||||
T.take_damage(rand(20, 50))
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/temporary_effect/pulse/disintegrate/Destroy()
|
||||
if(istype(get_turf(src), /turf/simulated/wall))
|
||||
explosion(get_turf(src), -1, 1, 2, 5, adminlog = 1)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/xray/swarm
|
||||
name = "spectral projector"
|
||||
desc = "A high-power laser gun capable of expelling concentrated gamma blasts, which are able to penetrate matter easier than \
|
||||
standard xray beams, resulting in an effective 'anti-everything' energy weapon."
|
||||
icon_state = "xray"
|
||||
item_state = "xray"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2)
|
||||
projectile_type = /obj/item/projectile/beam/shock
|
||||
charge_cost = 175
|
||||
|
||||
self_recharge = TRUE
|
||||
use_external_power = TRUE
|
||||
|
||||
firemodes = list(
|
||||
list(mode_name="kill", projectile_type=/obj/item/projectile/beam/gamma, charge_cost = 300),
|
||||
list(mode_name="deter", projectile_type=/obj/item/projectile/beam/shock, charge_cost = 175),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/xray/swarm/Initialize()
|
||||
. = ..()
|
||||
adjust_scale(-1, 1)
|
||||
@@ -0,0 +1,41 @@
|
||||
/mob/living/silicon/robot/drone/swarm/gunner
|
||||
name = "swarm gunner"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer_ranged"
|
||||
faction = "swarmer"
|
||||
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
speed = 4
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone/soldier
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm/ranged
|
||||
|
||||
spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/blink/swarm
|
||||
)
|
||||
|
||||
/mob/living/silicon/robot/drone/swarm/melee
|
||||
name = "swarm melee"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/swarmbot.dmi'
|
||||
icon_state = "swarmer_melee"
|
||||
faction = "swarmer"
|
||||
|
||||
maxHealth = 70
|
||||
health = 70
|
||||
|
||||
speed = 2
|
||||
|
||||
law_type = /datum/ai_laws/swarm_drone/soldier
|
||||
module_type = /obj/item/weapon/robot_module/drone/swarm/melee
|
||||
|
||||
spell_setup = list(
|
||||
/spell/aoe_turf/conjure/swarmer,
|
||||
/spell/aoe_turf/conjure/forcewall/swarm,
|
||||
/spell/aoe_turf/blink/swarm
|
||||
)
|
||||
Reference in New Issue
Block a user