mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-17 10:03:50 +01:00
Merge pull request #6286 from uraniummeltdown/aimech
AI control beacons for mechs
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#define PLANT_TOXIN_HUD "20"// Toxin level
|
||||
#define PLANT_PEST_HUD "21"// Pest level
|
||||
#define PLANT_WEED_HUD "22"// Weed level
|
||||
#define DIAG_TRACK_HUD "23"// Mech tracking beacon
|
||||
|
||||
//data HUD (medhud, sechud) defines
|
||||
//Don't forget to update human/New() if you change these!
|
||||
|
||||
+12
-1
@@ -44,7 +44,7 @@
|
||||
hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD, WANTED_HUD)
|
||||
|
||||
/datum/atom_hud/data/diagnostic
|
||||
hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD)
|
||||
hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
/datum/atom_hud/data/hydroponic
|
||||
hud_icons = list (PLANT_NUTRIENT_HUD, PLANT_WATER_HUD, PLANT_STATUS_HUD, PLANT_HEALTH_HUD, PLANT_TOXIN_HUD, PLANT_PEST_HUD, PLANT_WEED_HUD)
|
||||
@@ -287,6 +287,17 @@
|
||||
if(internal_damage)
|
||||
holder.icon_state = "hudwarn"
|
||||
|
||||
/obj/mecha/proc/diag_hud_set_mechtracking() //Shows tracking beacons on the mech
|
||||
var/image/holder = hud_list[DIAG_TRACK_HUD]
|
||||
var/new_icon_state //This var exists so that the holder's icon state is set only once in the event of multiple mech beacons.
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/T in trackers)
|
||||
if(T.ai_beacon) //Beacon with AI uplink
|
||||
new_icon_state = "hudtrackingai"
|
||||
break //Immediately terminate upon finding an AI beacon to ensure it is always shown over the normal one, as mechs can have several trackers.
|
||||
else
|
||||
new_icon_state = "hudtracking"
|
||||
holder.icon_state = new_icon_state
|
||||
|
||||
/*~~~~~~~~~
|
||||
Bots!
|
||||
~~~~~~~~~~*/
|
||||
|
||||
+62
-27
@@ -50,6 +50,7 @@
|
||||
var/obj/machinery/atmospherics/unary/portables_connector/connected_port = null
|
||||
|
||||
var/obj/item/device/radio/radio = null
|
||||
var/list/trackers = list()
|
||||
|
||||
var/max_temperature = 25000
|
||||
var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
|
||||
@@ -74,7 +75,7 @@
|
||||
var/melee_cooldown = 10
|
||||
var/melee_can_hit = 1
|
||||
|
||||
hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD)
|
||||
hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
/obj/mecha/New()
|
||||
..()
|
||||
@@ -102,6 +103,7 @@
|
||||
diag_hud_set_mechhealth()
|
||||
diag_hud_set_mechcell()
|
||||
diag_hud_set_mechstat()
|
||||
diag_hud_set_mechtracking()
|
||||
|
||||
////////////////////////
|
||||
////// Helpers /////////
|
||||
@@ -165,7 +167,7 @@
|
||||
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
|
||||
return
|
||||
|
||||
/obj/mecha/hear_talk(mob/M as mob, text)
|
||||
/obj/mecha/hear_talk(mob/M, text)
|
||||
if(M == occupant && radio.broadcasting)
|
||||
radio.talk_into(M, text)
|
||||
|
||||
@@ -465,7 +467,7 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/mecha/attack_hand(mob/living/user as mob)
|
||||
/obj/mecha/attack_hand(mob/living/user)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src)
|
||||
log_message("Attack by hand/paw. Attacker - [user].",1)
|
||||
@@ -481,7 +483,7 @@
|
||||
return
|
||||
|
||||
|
||||
/obj/mecha/attack_alien(mob/living/user as mob)
|
||||
/obj/mecha/attack_alien(mob/living/user)
|
||||
log_message("Attack by alien. Attacker - [user].",1)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src)
|
||||
@@ -500,7 +502,7 @@
|
||||
return
|
||||
|
||||
|
||||
/obj/mecha/attack_animal(mob/living/simple_animal/user as mob)
|
||||
/obj/mecha/attack_animal(mob/living/simple_animal/user)
|
||||
log_message("Attack by simple animal. Attacker - [user].",1)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src)
|
||||
@@ -513,7 +515,7 @@
|
||||
take_damage(damage)
|
||||
check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
|
||||
visible_message("<span class='danger'>[user]</span> [user.attacktext] [src]!")
|
||||
user.create_attack_log("<font color='red'>attacked [src.name]</font>")
|
||||
user.create_attack_log("<font color='red'>attacked [name]</font>")
|
||||
else
|
||||
log_append_to_last("Armor saved.")
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1)
|
||||
@@ -798,7 +800,9 @@
|
||||
to_chat(user, "<span class='notice'>\the [W] is stuck to your hand, you cannot put it in \the [src]</span>")
|
||||
return
|
||||
W.forceMove(src)
|
||||
trackers += W
|
||||
user.visible_message("[user] attaches [W] to [src].", "<span class='notice'>You attach [W] to [src].</span>")
|
||||
diag_hud_set_mechtracking()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weapon/paintkit))
|
||||
@@ -866,20 +870,35 @@
|
||||
//////////// AI piloting ////////////
|
||||
/////////////////////////////////////
|
||||
|
||||
/obj/mecha/attack_ai(var/mob/living/silicon/ai/user as mob)
|
||||
/obj/mecha/attack_ai(mob/living/silicon/ai/user)
|
||||
if(!isAI(user))
|
||||
return
|
||||
//Allows the Malf to scan a mech's status and loadout, helping it to decide if it is a worthy chariot.
|
||||
if(user.can_dominate_mechs)
|
||||
examine(user) //Get diagnostic information!
|
||||
var/obj/item/mecha_parts/mecha_tracking/B = locate(/obj/item/mecha_parts/mecha_tracking) in src
|
||||
if(B) //Beacons give the AI more detailed mech information.
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/B in trackers)
|
||||
to_chat(user, "<span class='danger'>Warning: Tracking Beacon detected. Enter at your own risk. Beacon Data:")
|
||||
to_chat(user, "[B.get_mecha_info()]")
|
||||
to_chat(user, "[B.get_mecha_info_text()]")
|
||||
break
|
||||
//Nothing like a big, red link to make the player feel powerful!
|
||||
to_chat(user, "<a href='?src=[user.UID()];ai_take_control=\ref[src]'><span class='userdanger'>ASSUME DIRECT CONTROL?</span></a><br>")
|
||||
else
|
||||
examine(user)
|
||||
if(occupant)
|
||||
user << "<span class='warning'>This exosuit has a pilot and cannot be controlled.</span>"
|
||||
return
|
||||
var/can_control_mech = FALSE
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in trackers)
|
||||
can_control_mech = TRUE
|
||||
to_chat(user, "<span class='notice'>[bicon(src)] Status of [name]:</span>\n\
|
||||
[A.get_mecha_info_text()]")
|
||||
break
|
||||
if(!can_control_mech)
|
||||
to_chat(user, "<span class='warning'>You cannot control exosuits without AI control beacons installed.</span>")
|
||||
return
|
||||
to_chat(user, "<a href='?src=[user.UID()];ai_take_control=\ref[src]'><span class='boldnotice'>Take control of exosuit?</span></a><br>")
|
||||
|
||||
/obj/mecha/transfer_ai(var/interaction, mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card)
|
||||
/obj/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
@@ -907,12 +926,13 @@
|
||||
to_chat(AI, "You have been downloaded to a mobile storage device. Wireless connection offline.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
|
||||
|
||||
if(AI_MECH_HACK) //Called by Malf AI mob on the mech.
|
||||
new /obj/structure/AIcore/deactivated(AI.loc)
|
||||
if(occupant) //Oh, I am sorry, were you using that?
|
||||
to_chat(AI, "<span class='warning'>Pilot detected! Forced ejection initiated!")
|
||||
to_chat(occupant, "<span class='danger'>You have been forcibly ejected!</span>")
|
||||
go_out(1) //IT IS MINE, NOW. SUCK IT, RD!
|
||||
if(AI_MECH_HACK) //Called by AIs on the mech
|
||||
AI.linked_core = new /obj/structure/AIcore/deactivated(AI.loc)
|
||||
if(AI.can_dominate_mechs)
|
||||
if(occupant) //Oh, I am sorry, were you using that?
|
||||
to_chat(AI, "<span class='warning'>Pilot detected! Forced ejection initiated!")
|
||||
to_chat(occupant, "<span class='danger'>You have been forcibly ejected!</span>")
|
||||
go_out(1) //IT IS MINE, NOW. SUCK IT, RD!
|
||||
ai_enter_mech(AI, interaction)
|
||||
|
||||
if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech.
|
||||
@@ -932,7 +952,7 @@
|
||||
ai_enter_mech(AI, interaction)
|
||||
|
||||
//Hack and From Card interactions share some code, so leave that here for both to use.
|
||||
/obj/mecha/proc/ai_enter_mech(var/mob/living/silicon/ai/AI, var/interaction)
|
||||
/obj/mecha/proc/ai_enter_mech(mob/living/silicon/ai/AI, interaction)
|
||||
AI.aiRestorePowerRoutine = 0
|
||||
AI.loc = src
|
||||
occupant = AI
|
||||
@@ -945,7 +965,7 @@
|
||||
AI.remote_control = src
|
||||
AI.canmove = 1 //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow.
|
||||
AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES.
|
||||
to_chat(AI, "[interaction == AI_MECH_HACK ? "<span class='announce'>Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector!</span>" \
|
||||
to_chat(AI, "[AI.can_dominate_mechs ? "<span class='announce'>Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector!</span>" \
|
||||
: "<span class='notice'>You have been uploaded to a mech's onboard computer."]")
|
||||
to_chat(AI, "<span class='boldnotice'>Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.</span>")
|
||||
|
||||
@@ -1172,7 +1192,7 @@
|
||||
to_chat(user, "<span class='notice'>You stop inserting the MMI.</span>")
|
||||
return 0
|
||||
|
||||
/obj/mecha/proc/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob)
|
||||
/obj/mecha/proc/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
|
||||
if(mmi_as_oc && user in range(1))
|
||||
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
|
||||
to_chat(user, "Consciousness matrix not detected.")
|
||||
@@ -1239,7 +1259,7 @@
|
||||
if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
|
||||
go_out(1, newloc)
|
||||
|
||||
/obj/mecha/proc/go_out(var/forced, var/atom/newloc = loc)
|
||||
/obj/mecha/proc/go_out(forced, atom/newloc = loc)
|
||||
if(!occupant)
|
||||
return
|
||||
var/atom/movable/mob_container
|
||||
@@ -1248,15 +1268,29 @@
|
||||
if(ishuman(occupant))
|
||||
mob_container = occupant
|
||||
//RemoveActions(occupant, human_occupant=1)
|
||||
else if(istype(occupant, /mob/living/carbon/brain))
|
||||
else if(isbrain(occupant))
|
||||
var/mob/living/carbon/brain/brain = occupant
|
||||
//RemoveActions(brain)
|
||||
mob_container = brain.container
|
||||
else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf.
|
||||
//RemoveActions(occupant)
|
||||
occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
|
||||
occupant = null
|
||||
return
|
||||
else if(isAI(occupant))
|
||||
var/mob/living/silicon/ai/AI = occupant
|
||||
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
|
||||
//RemoveActions(occupant)
|
||||
occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
|
||||
occupant = null
|
||||
return
|
||||
else
|
||||
if(!AI.linked_core || qdeleted(AI.linked_core))
|
||||
to_chat(AI, "<span class='userdanger'>Inactive core destroyed. Unable to return.</span>")
|
||||
AI.linked_core = null
|
||||
return
|
||||
to_chat(AI, "<span class='notice'>Returning to core...</span>")
|
||||
AI.controlled_mech = null
|
||||
AI.remote_control = null
|
||||
//RemoveActions(occupant, 1)
|
||||
mob_container = AI
|
||||
newloc = get_turf(AI.linked_core)
|
||||
qdel(AI.linked_core)
|
||||
else
|
||||
return
|
||||
var/mob/living/L = occupant
|
||||
@@ -1439,6 +1473,7 @@
|
||||
diag_hud_set_mechhealth()
|
||||
diag_hud_set_mechcell()
|
||||
diag_hud_set_mechstat()
|
||||
diag_hud_set_mechtracking()
|
||||
|
||||
|
||||
/obj/mecha/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
var/screen = 0
|
||||
var/stored_data
|
||||
|
||||
/obj/machinery/computer/mecha/attack_ai(var/mob/user as mob)
|
||||
/obj/machinery/computer/mecha/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/mecha/attack_hand(var/mob/user as mob)
|
||||
/obj/machinery/computer/mecha/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/mecha/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
@@ -73,11 +73,12 @@
|
||||
icon_state = "motion2"
|
||||
w_class = 2
|
||||
origin_tech = "programming=2;magnets=2"
|
||||
var/ai_beacon = FALSE //If this beacon allows for AI control. Exists to avoid using istype() on checking.
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
|
||||
if(!in_mecha())
|
||||
return 0
|
||||
var/obj/mecha/M = src.loc
|
||||
return FALSE
|
||||
var/obj/mecha/M = loc
|
||||
var/list/answer[0]
|
||||
answer["reference"] = "\ref[src]"
|
||||
answer["name"] = sanitize(replacetext(M.name,"\"","'")) // Double apostrophes break JSON
|
||||
@@ -101,6 +102,25 @@
|
||||
|
||||
return answer
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info_text()
|
||||
if(!in_mecha())
|
||||
return FALSE
|
||||
var/obj/mecha/M = loc
|
||||
var/cell_charge = M.get_charge()
|
||||
var/area/A = get_area(M)
|
||||
var/answer = {"<b>Name:</b> [M.name]
|
||||
<b>Integrity:</b> [M.health/initial(M.health)*100]%
|
||||
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
|
||||
<b>Airtank:</b> [M.return_pressure()]kPa
|
||||
<b>Pilot:</b> [M.occupant||"None"]
|
||||
<b>Location:</b> [sanitize(A.name)||"Unknown"]
|
||||
<b>Active equipment:</b> [M.selected||"None"]<br>"}
|
||||
if(istype(M, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = M
|
||||
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
|
||||
|
||||
return answer
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/emp_act()
|
||||
qdel(src)
|
||||
return
|
||||
@@ -110,9 +130,9 @@
|
||||
return
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
|
||||
if(istype(src.loc, /obj/mecha))
|
||||
return src.loc
|
||||
return 0
|
||||
if(istype(loc, /obj/mecha))
|
||||
return loc
|
||||
return FALSE
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/shock()
|
||||
var/obj/mecha/M = in_mecha()
|
||||
@@ -121,19 +141,26 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
|
||||
if(!src.in_mecha())
|
||||
if(!in_mecha())
|
||||
return 0
|
||||
var/obj/mecha/M = src.loc
|
||||
var/obj/mecha/M = loc
|
||||
return M.get_log_html()
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/ai_control
|
||||
name = "exosuit AI control beacon"
|
||||
desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit."
|
||||
origin_tech = "programming=3;magnets=2;engineering=2"
|
||||
ai_beacon = TRUE
|
||||
|
||||
/obj/item/weapon/storage/box/mechabeacons
|
||||
name = "Exosuit Tracking Beacons"
|
||||
New()
|
||||
..()
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
|
||||
/obj/item/weapon/storage/box/mechabeacons/New()
|
||||
..()
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
/obj/mecha/medical/New()
|
||||
..()
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
|
||||
@@ -110,10 +110,10 @@
|
||||
//Add ore box to cargo
|
||||
cargo.Add(new /obj/structure/ore_box(src))
|
||||
|
||||
//Attach hydrolic clamp
|
||||
//Attach hydraulic clamp
|
||||
var/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp
|
||||
HC.attach(src)
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/B in contents)//Deletes the beacon so it can't be found easily
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/B in trackers)//Deletes the beacon so it can't be found easily
|
||||
qdel(B)
|
||||
|
||||
var/obj/item/mecha_parts/mecha_equipment/mining_scanner/scanner = new /obj/item/mecha_parts/mecha_equipment/mining_scanner
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/obj/mecha/working/New()
|
||||
..()
|
||||
new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
|
||||
@@ -99,6 +99,8 @@ var/list/ai_verbs_default = list(
|
||||
|
||||
var/obj/machinery/camera/portable/builtInCamera
|
||||
|
||||
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
|
||||
|
||||
var/arrivalmsg = "$name, $rank, has arrived on the station."
|
||||
|
||||
/mob/living/silicon/ai/proc/add_ai_verbs()
|
||||
@@ -535,7 +537,16 @@ var/list/ai_verbs_default = list(
|
||||
if(href_list["ai_take_control"]) //Mech domination
|
||||
var/obj/mecha/M = locate(href_list["ai_take_control"])
|
||||
if(controlled_mech)
|
||||
to_chat(src, "You are already loaded into an onboard computer!")
|
||||
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
|
||||
return
|
||||
if(!cameranet.checkCameraVis(M))
|
||||
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
|
||||
return
|
||||
if(lacks_power())
|
||||
to_chat(src, "<span class='warning'>You're depowered!</span>")
|
||||
return
|
||||
if(!isturf(loc))
|
||||
to_chat(src, "<span class='warning'>You aren't in your core!</span>")
|
||||
return
|
||||
if(M)
|
||||
M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
|
||||
|
||||
@@ -1078,6 +1078,16 @@
|
||||
construction_time = 50
|
||||
category = list("Misc")
|
||||
|
||||
/datum/design/mecha_tracking_ai_control
|
||||
name = "AI Control Beacon"
|
||||
id = "mecha_tracking_ai_control"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/mecha_tracking/ai_control
|
||||
materials = list(MAT_METAL = 1000, MAT_GLASS = 500, MAT_SILVER = 200)
|
||||
req_tech = list("programming" = 3, "magnets" = 2, "engineering" = 2)
|
||||
construction_time = 50
|
||||
category = list("Misc")
|
||||
|
||||
/datum/design/ipc_head
|
||||
name = "IPC Head"
|
||||
id = "ipc_head"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Reference in New Issue
Block a user