Last active
April 14, 2019 16:12
-
-
Save Baa14453/ecd36628014d3cf875afb02916fcc58d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/proc/get_hat_icon(var/obj/item/hat, var/offset_x = 0, var/offset_y = 0) | |
var/list/mob_hat_cache = SSicon_cache.mob_hat_cache | |
var/t_state = hat.icon_state | |
if(hat.item_state_slots && 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(hat.item_icons && (slot_head_str in hat.item_icons)) | |
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 | |
name = "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 | PASSDOORHATCH | |
braintype = "Robot" | |
lawupdate = 0 | |
density = 0 | |
req_access = list(access_engine, access_robotics) | |
integrated_light_power = 3 | |
local_transmit = 1 | |
possession_candidate = 1 | |
mob_size = 4 | |
can_pull_size = 3 | |
can_pull_mobs = MOB_PULL_SMALLER | |
mob_bump_flag = SIMPLE_ANIMAL | |
//mob_swap_flags = SIMPLE_ANIMAL | |
//mob_push_flags = SIMPLE_ANIMAL | |
//mob_always_swap = 1 | |
//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/range_limit = 1 | |
holder_type = /obj/item/weapon/holder/drone | |
/mob/living/silicon/robot/drone/can_be_possessed_by(var/mob/abstract/observer/possessor) | |
if(!istype(possessor) || !possessor.client || !possessor.ckey) | |
return 0 | |
if(!config.allow_drone_spawn) | |
to_chat(src, "<span class='danger'>Playing as drones is not currently permitted.</span>") | |
return 0 | |
if(too_many_active_drones()) | |
to_chat(src, "<span class='danger'>The maximum number of active drones has been reached..</span>") | |
return 0 | |
if(jobban_isbanned(possessor,"Cyborg")) | |
to_chat(usr, "<span class='danger'>You are banned from playing synthetics and cannot spawn as a drone.</span>") | |
return 0 | |
if(!possessor.MayRespawn(1,MINISYNTH)) | |
return 0 | |
return 1 | |
/mob/living/silicon/robot/drone/do_possession(var/mob/abstract/observer/possessor) | |
if(!(istype(possessor) && possessor.ckey)) | |
return 0 | |
if(src.ckey || src.client) | |
to_chat(possessor, "<span class='warning'>\The [src] already has a player.</span>") | |
return 0 | |
message_admins("<span class='adminnotice'>[key_name_admin(possessor)] has taken control of \the [src].</span>") | |
log_admin("[key_name(possessor)] took control of \the [src].",ckey=key_name(possessor)) | |
transfer_personality(possessor.client) | |
qdel(possessor) | |
return 1 | |
/mob/living/silicon/robot/drone/Destroy() | |
if(hat) | |
hat.forceMove(get_turf(src)) | |
return ..() | |
/mob/living/silicon/robot/drone/construction | |
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_size = 5 | |
can_pull_mobs = MOB_PULL_SAME | |
holder_type = /obj/item/weapon/holder/drone/heavy | |
range_limit = 0 | |
/mob/living/silicon/robot/drone/Initialize() | |
. = ..() | |
verbs += /mob/living/proc/hide | |
remove_language("Robot Talk") | |
add_language("Robot Talk", 0) | |
add_language("Drone Talk", 1) | |
//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 | |
updateicon() | |
density = 0 | |
/mob/living/silicon/robot/drone/init() | |
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: '[current_map.company_name] Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'" | |
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) | |
//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() | |
real_name = "maintenance drone ([rand(100,999)])" | |
name = real_name | |
/mob/living/silicon/robot/drone/updateicon() | |
cut_overlays() | |
if(stat == 0) | |
add_overlay("eyes-[icon_state]") | |
if(hat) // Let the drones wear hats. | |
add_overlay(get_hat_icon(hat, hat_x_offset, hat_y_offset)) | |
/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.forceMove(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) | |
if(user.a_intent == "help" && istype(W, /obj/item/clothing/head)) | |
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("<span class='notice'>\The [user] puts \the [W] on \the [src].</span>") | |
return | |
else if(istype(W, /obj/item/borg/upgrade/)) | |
to_chat(user, "<span class='danger'>\The [src] is not compatible with \the [W].</span>") | |
return | |
else if (W.iscrowbar()) | |
to_chat(user, "<span class='danger'>\The [src] is hermetically sealed. You can't open the case.</span>") | |
return | |
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) | |
if(stat == 2) | |
if(!config.allow_drone_spawn || emagged || health < -maxHealth) //It's dead, Dave. | |
to_chat(user, "<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>") | |
return | |
if(!allowed(usr)) | |
to_chat(user, "<span class='danger'>Access denied.</span>") | |
return | |
user.visible_message("<span class='danger'>\The [user] swipes \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>") | |
request_player() | |
return | |
else | |
user.visible_message("<span class='danger'>\The [user] swipes \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 | |
if(allowed(usr)) | |
shut_down() | |
else | |
to_chat(user, "<span class='danger'>Access denied.</span>") | |
return | |
..() | |
/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>") | |
message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.") | |
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.",ckey=key_name(user),ckey_target=key_name(src)) | |
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 | |
set_zeroth_law("Only [user.real_name] and people \he designates 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 | |
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) | |
var/area/A = get_area(T) | |
if((!T || health <= -maxHealth || (range_limit && !(A in the_station_areas))) && src.stat != DEAD) | |
timeofdeath = world.time | |
death() //Possibly redundant, having trouble making death() cooperate. | |
gib() | |
return | |
..() | |
//DRONE MOVEMENT. | |
/mob/living/silicon/robot/drone/slip_chance(var/prob_slip) | |
return 0 | |
//CONSOLE PROCS | |
/mob/living/silicon/robot/drone/proc/law_resync() | |
if(stat != 2) | |
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 != 2) | |
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() | |
if(too_many_active_drones()) | |
return | |
var/datum/ghosttrap/G = get_ghost_trap("maintenance drone") | |
G.request_player(src, "Someone is attempting to reboot a maintenance drone.", 30 SECONDS) | |
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player) | |
if(!player) return | |
stat = 0 | |
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... <b>loaded</b>.") | |
full_law_reset() | |
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/start_pulling(var/atom/movable/AM) | |
//Redefine start_pulling() from mob.dm so that maintenance drones can pull disposal pipe | |
if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! | |
return | |
if (AM.anchored) | |
to_chat(src, "<span class='warning'>It won't budge!</span>") | |
return | |
var/mob/M = null | |
if(ismob(AM)) | |
M = AM | |
if(!can_pull_mobs || !can_pull_size) | |
to_chat(src, "<span class='warning'>You are too small to pull that.</span>") | |
return | |
if((mob_size < M.mob_size) && (can_pull_mobs != MOB_PULL_LARGER)) | |
to_chat(src, "<span class='warning'>You are too small to pull that.</span>") | |
return | |
if((mob_size == M.mob_size) && (can_pull_mobs == MOB_PULL_SMALLER)) | |
to_chat(src, "<span class='warning'>You are too small to pull that.</span>") | |
return | |
// If your size is larger than theirs and you have some | |
// kind of mob pull value AT ALL, you will be able to pull | |
// them, so don't bother checking that explicitly. | |
if(!iscarbon(src)) | |
M.LAssailant = null | |
else | |
M.LAssailant = usr | |
else if(isobj(AM)) | |
//Let maintenance drones pull disposal pipe | |
if(!(istype(src, /mob/living/silicon/robot/drone) && istype(AM,/obj/structure/disposalconstruct))) | |
var/obj/I = AM | |
if(!can_pull_size || can_pull_size < I.w_class) | |
to_chat(src, "<span class='warning'>You are too small to pull that.</span>") | |
return | |
if(pulling) | |
var/pulling_old = pulling | |
stop_pulling() | |
// Are we pulling the same thing twice? Just stop pulling. | |
if(pulling_old == AM) | |
return | |
src.pulling = AM | |
AM.pulledby = src | |
if(pullin) | |
pullin.icon_state = "pull1" | |
//Attempted fix for people flying away through space when cuffed and dragged. | |
if(M) | |
var/mob/pulled = AM | |
pulled.inertia_dir = 0 | |
/mob/living/silicon/robot/drone/add_robot_verbs() | |
src.verbs |= silicon_subsystems | |
/mob/living/silicon/robot/drone/remove_robot_verbs() | |
src.verbs -= silicon_subsystems | |
/mob/living/silicon/robot/drone/construction/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 NanoTrasen 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>.") | |
/mob/living/silicon/robot/drone/construction/init() | |
..() | |
flavor_text = "It's a bulky construction drone stamped with a NanoTrasen glyph." | |
/mob/living/silicon/robot/drone/construction/updatename() | |
real_name = "construction drone ([rand(100,999)])" | |
name = real_name | |
/proc/too_many_active_drones() | |
var/drones = 0 | |
for(var/mob/living/silicon/robot/drone/D in mob_list) | |
if(D.key && D.client) | |
drones++ | |
return drones >= config.max_maint_drones |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment