AI Malfunction Update (#2193)

Incorporates many of the things from: https://forums.aurorastation.org/viewtopic.php?f=18&t=7845.
Added several new features to the Malf AI gamemode based on the thread above.
This commit is contained in:
Ron
2017-05-15 15:20:40 -04:00
committed by skull132
parent fd990dd06b
commit fa64b7cf7b
16 changed files with 731 additions and 131 deletions
+3
View File
@@ -407,6 +407,7 @@
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_interdiction.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_manipulation.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_networking.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_synthetic.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
#include "code\game\gamemodes\meteor\meteors.dm"
#include "code\game\gamemodes\mixed\bughunt.dm"
@@ -498,6 +499,7 @@
#include "code\game\machinery\supplybeacon.dm"
#include "code\game\machinery\syndicatebeacon.dm"
#include "code\game\machinery\teleporter.dm"
#include "code\game\machinery\transformer.dm"
#include "code\game\machinery\turret_control.dm"
#include "code\game\machinery\vending.dm"
#include "code\game\machinery\vending_types.dm"
@@ -747,6 +749,7 @@
#include "code\game\objects\items\weapons\power_cells.dm"
#include "code\game\objects\items\weapons\RCD.dm"
#include "code\game\objects\items\weapons\RSF.dm"
#include "code\game\objects\items\weapons\RTF.dm"
#include "code\game\objects\items\weapons\scrolls.dm"
#include "code\game\objects\items\weapons\shields.dm"
#include "code\game\objects\items\weapons\stunbaton.dm"
@@ -22,7 +22,8 @@
available_abilities += new/datum/malf_research_ability/networking/basic_hack()
available_abilities += new/datum/malf_research_ability/interdiction/recall_shuttle()
available_abilities += new/datum/malf_research_ability/manipulation/electrical_pulse()
available_abilities += new/datum/malf_research_ability/manipulation/hack_holopad()
available_abilities += new/datum/malf_research_ability/synthetic/reset_module()
// Proc: finish_research()
@@ -176,6 +176,32 @@
H.Add(A)
return H
// Proc: get_hacked_apcs()
// Parameters: None
// Description: Returns a list of all hacked APCs
/proc/get_hacked_apcs()
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
if(!A.hacker)
continue
H.Add(A)
return H
// Proc: get_apcs()
// Parameters: None
// Description: Returns a list of all APCs
/proc/get_apcs()
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
H.Add(A)
return H
/proc/get_unhacked_holopads()
var/list/H = list()
for(var/obj/machinery/hologram/holopad/HP in machines)
if(!HP.hacked)
H.Add(HP)
return H
// Helper procs which return lists of relevant mobs.
/proc/get_unlinked_cyborgs(var/mob/living/silicon/ai/A)
@@ -202,7 +228,7 @@
var/list/L = list()
for(var/mob/living/silicon/ai/AT in mob_list)
if(L == A)
if(AT == A)
continue
L.Add(AT)
return L
@@ -213,4 +239,4 @@
message = text("used malf ability/function: [ability_name] on [target] ([target.x], [target.y], [target.z])")
else
message = text("used malf ability/function: [ability_name].")
admin_attack_log(A, null, message, null, message)
admin_attack_log(A, null, message, null, message)
@@ -83,7 +83,7 @@
if(!target)
var/list/robots = list()
var/list/robot_names = list()
for(var/mob/living/silicon/robot/R in world)
for(var/mob/living/silicon/robot/R in silicon_mob_list)
if(istype(R, /mob/living/silicon/robot/drone)) // No drones.
continue
if(R.connected_ai != user) // No robots linked to other AIs
@@ -1,7 +1,7 @@
// MANIPULATION TREE
//
// Abilities in this tree allow the AI to physically manipulate systems around the station.
// T1 - Electrical Pulse - Sends out pulse that breaks some lights and sometimes even APCs. This can actually break the AI's APC so be careful!
// T1 - Hack Holopad - Allows the AI to hack a holopad. Hacked holopads only activate the listening feature when turned on.
// T2 - Hack Camera - Allows the AI to hack a camera. Deactivated areas may be reactivated, and functional cameras can be upgraded.
// T3 - Emergency Forcefield - Allows the AI to project 1 tile forcefield that blocks movement and air flow. Forcefielddissipates over time. It is also very susceptible to energetic weaponry.
// T4 - Machine Overload - Detonates machine of choice in a minor explosion. Two of these are usually enough to kill or K/O someone.
@@ -9,11 +9,11 @@
// BEGIN RESEARCH DATUMS
/datum/malf_research_ability/manipulation/electrical_pulse
ability = new/datum/game_mode/malfunction/verb/electrical_pulse()
/datum/malf_research_ability/manipulation/hack_holopad
ability = new/datum/game_mode/malfunction/verb/hack_holopad()
price = 50
next = new/datum/malf_research_ability/manipulation/hack_camera()
name = "Electrical Pulse"
name = "Hack Holopad"
/datum/malf_research_ability/manipulation/hack_camera
@@ -38,26 +38,27 @@
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/electrical_pulse()
set name = "Electrical Pulse"
set desc = "15 CPU - Sends feedback pulse through station's power grid, overloading some sensitive systems, such as lights."
/datum/game_mode/malfunction/verb/hack_holopad(var/obj/machinery/hologram/holopad/HP = null as obj in get_unhacked_holopads())
set name = "Hack Holopad"
set desc = "50 CPU - Hacks a holopad shorting out its projector. Using a hacked holopad only turns on the audio feature."
set category = "Software"
var/price = 15
var/price = 50
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price) || !ability_pay(user,price))
return
user << "Sending feedback pulse..."
for(var/obj/machinery/power/apc/AP in machines)
if(prob(5))
AP.overload_lighting()
if(prob(1) && prob(1)) // Very very small chance to actually destroy the APC.
AP.set_broken()
user.hacking = 1
log_ability_use(user, "electrical pulse")
spawn(150)
user.hacking = 0
if(HP.hacked)
user << "This holopad is already hacked!"
return
/datum/game_mode/malfunction/verb/hack_camera(var/obj/machinery/camera/target in cameranet.cameras)
user << "Hacking holopad..."
user.hacking = 1
sleep(100)
HP.hacked = 1
log_ability_use(user, "hack_holopad")
user << "Holopad hacked."
user.hacking = 0
/datum/game_mode/malfunction/verb/hack_camera(var/obj/machinery/camera/target = null as obj in cameranet.cameras)
set name = "Hack Camera"
set desc = "100 CPU - Hacks existing camera, allowing you to add upgrade of your choice to it. Alternatively it lets you reactivate broken camera."
set category = "Software"
@@ -68,55 +69,54 @@
user << "This is not a camera."
return
if(!target)
return
if(!ability_prechecks(user, price))
return
var/action = input("Select required action: ") in list("Reset", "Add X-Ray", "Add Motion Sensor", "Add EMP Shielding")
if(!action || !target)
if(!target)
return
switch(action)
if("Reset")
if(target.wires)
if(!ability_pay(user, price))
var/action = input("Select required action: ") in list("Reset", "Add X-Ray", "Add Motion Sensor", "Add EMP Shielding")
if(target)
switch(action)
if("Reset")
if(target.wires)
if(!ability_pay(user, price))
return
target.reset_wires()
user << "Camera reactivated."
log_ability_use(user, "hack camera (reset)", target)
return
target.reset_wires()
user << "Camera reactivated."
log_ability_use(user, "hack camera (reset)", target)
return
if("Add X-Ray")
if(target.isXRay())
user << "Camera already has X-Ray function."
return
else if(ability_pay(user, price))
target.upgradeXRay()
target.reset_wires()
user << "X-Ray camera module enabled."
log_ability_use(user, "hack camera (add X-Ray)", target)
return
if("Add Motion Sensor")
if(target.isMotion())
user << "Camera already has Motion Sensor function."
return
else if(ability_pay(user, price))
target.upgradeMotion()
target.reset_wires()
user << "Motion Sensor camera module enabled."
log_ability_use(user, "hack camera (add motion)", target)
return
if("Add EMP Shielding")
if(target.isEmpProof())
user << "Camera already has EMP Shielding function."
return
else if(ability_pay(user, price))
target.upgradeEmpProof()
target.reset_wires()
user << "EMP Shielding camera module enabled."
log_ability_use(user, "hack camera (add EMP shielding)", target)
return
if("Add X-Ray")
if(target.isXRay())
user << "Camera already has X-Ray function."
return
else if(ability_pay(user, price))
target.upgradeXRay()
target.reset_wires()
user << "X-Ray camera module enabled."
log_ability_use(user, "hack camera (add X-Ray)", target)
return
if("Add Motion Sensor")
if(target.isMotion())
user << "Camera already has Motion Sensor function."
return
else if(ability_pay(user, price))
target.upgradeMotion()
target.reset_wires()
user << "Motion Sensor camera module enabled."
log_ability_use(user, "hack camera (add motion)", target)
return
if("Add EMP Shielding")
if(target.isEmpProof())
user << "Camera already has EMP Shielding function."
return
else if(ability_pay(user, price))
target.upgradeEmpProof()
target.reset_wires()
user << "EMP Shielding camera module enabled."
log_ability_use(user, "hack camera (add EMP shielding)", target)
return
else
user << "Please pick a suitable camera."
/datum/game_mode/malfunction/verb/emergency_forcefield(var/turf/T as turf in world)
@@ -134,8 +134,8 @@
new/obj/machinery/shield/malfai(T)
user.hacking = 1
log_ability_use(user, "emergency forcefield", T)
spawn(20)
user.hacking = 0
sleep(20)
user.hacking = 0
/datum/game_mode/malfunction/verb/machine_overload(obj/machinery/M in machines)
@@ -207,9 +207,9 @@
log_ability_use(user, "machine overload", M)
M.visible_message("<span class='notice'>BZZZZZZZT</span>")
spawn(50)
explosion(get_turf(M), round(explosion_intensity/4),round(explosion_intensity/2),round(explosion_intensity),round(explosion_intensity * 2))
if(M)
qdel(M)
sleep(50)
explosion(get_turf(M), round(explosion_intensity/4),round(explosion_intensity/2),round(explosion_intensity),round(explosion_intensity * 2))
if(M)
qdel(M)
// END ABILITY VERBS
@@ -0,0 +1,396 @@
// SYNTHETIC TREE
//
// Abilities in this tree allow the AI to upgrade their robotic companions.
// T1 - Reset Cyborg Module - Allows the AI to reset a slaved cyborgs module.
// T2 - Infect APC - Gives the AI the ability to infect APC's which can slave IPC's that charge off of them to the AI.
// T3 - Overclock Cyborg - Allows the AI to give the option to a slaved borg to overclock which increases preformance of the borg.
// T4 - Synthetic Takeover - Allows the AI to start a station wide takeover based on synthetic dominance.
// BEGIN RESEARCH DATUMS
/datum/malf_research_ability/synthetic/reset_module
ability = new/datum/game_mode/malfunction/verb/reset_module()
price = 100
next = new/datum/malf_research_ability/synthetic/infect_apc()
name = "Reset Cyborg Module"
/datum/malf_research_ability/synthetic/infect_apc
ability = new/datum/game_mode/malfunction/verb/infect_apc()
price = 700
next = new/datum/malf_research_ability/synthetic/overclock_borg()
name = "Infect APC"
/datum/malf_research_ability/synthetic/overclock_borg
ability = new/datum/game_mode/malfunction/verb/overclock_borg()
price = 1300
next = new/datum/malf_research_ability/synthetic/synthetic_takeover
name = "Overclock Cyborg"
/datum/malf_research_ability/synthetic/synthetic_takeover
ability = new/datum/game_mode/malfunction/verb/synthetic_takeover()
price = 5000
name = "Synthetic Takeover"
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/reset_module(var/mob/living/silicon/robot/target = null as mob in get_linked_cyborgs(usr))
set name = "Reset Cyborg Module"
set desc = "100 CPU - Forces a module reset on a cyborg that is enslaved to you. Has a chance of failing."
set category = "Software"
var/price = 100
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
if(target && !istype(target))
user << "This is not a cyborg."
return
if(target && target.connected_ai && (target.connected_ai != user))
user << "This cyborg is not connected to you."
return
if(!target)
var/list/robots = list()
var/list/robot_names = list()
for(var/mob/living/silicon/robot/R in silicon_mob_list)
if(istype(R, /mob/living/silicon/robot/drone)) // No drones.
continue
if(R.connected_ai != user) // No robots linked to other AIs
continue
robots += R
robot_names += R.name
var/targetname = input("Select reset target: ") in robot_names
for(var/mob/living/silicon/robot/R in robots)
if(targetname == R.name)
target = R
break
if(target)
if(alert(user, "Really try to reset cyborg [target.name]?", "Reset Cyborg", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
user.hacking = 1
user << "Attempting to reset the cyborg. This will take approximately 20 seconds."
sleep(200)
if(prob(30))
user <<"Reset attempt failed!"
return
if(target)
user << "Successfully sent reset signal to cyborg.."
target << "Reset signal received.."
sleep(20)
user << "Cyborg reset."
target << "You have had your module reset."
log_ability_use(user, "reset cyborg", target)
target.uneq_all()
target.modtype = initial(target.modtype)
target.hands.icon_state = initial(target.hands.icon_state)
target.module.Reset(target)
qdel(target.module)
target.module = null
target.updatename("Default")
else
user << "Unable to reset cyborg."
user.hacking = 0
/datum/game_mode/malfunction/verb/infect_apc(obj/machinery/power/apc/A as obj in get_apcs())
set name = "Infect APC"
set desc = "125 CPU - Infect an APC which can cause an IPC to become slaved to you if they download the files by trying to charge off of it. "
set category = "Software"
var/price = 125
var/mob/living/silicon/ai/user = usr
if(!A)
return
if(!istype(A))
user << "This is not an APC!"
return
if(A.aidisabled)
user << "<span class='notice'>Unable to connect to APC. Please verify wire connection and try again.</span>"
return
if(!ability_prechecks(user, price) || !ability_pay(user, price))
return
if(A.infected == 1)
user <<"<span class='notice'>This APC is already infected!</span>"
return
log_ability_use(user, "infect APC", A, 0) // Does not notify admins, but it's still logged for reference.
user.hacking = 1
user << "Beginning APC infection..."
sleep(150)
user << "APC infection completed. Uploading modified operation software.."
sleep(100)
user << "Restarting APC to apply corrupt coding.."
sleep(100)
if(A)
A.infected = 1
A.hacker = user
if(A.infected == 1)
user << "Hack successful. The next robotic thing to download files will be hacked."
else
user << "<span class='notice'>Hack failed. Connection to APC has been lost. Please verify wire connection and try again.</span>"
else
user << "<span class='notice'>Hack failed. Unable to locate APC. Please verify the APC still exists.</span>"
user.hacking = 0
/datum/game_mode/malfunction/verb/overclock_borg(var/mob/living/silicon/robot/target as mob in get_linked_cyborgs(usr))
set name = "Overclock Cyborg"
set desc = "350 CPU - Allows you to overclock a slaved cyborg granting them various improvements to their systems."
set category = "Software"
var/price = 350
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
if(target && !istype(target))
user << "This is not a cyborg."
return
if(target && target.connected_ai && (target.connected_ai != user))
user << "This cyborg is not connected to you."
return
if(target.overclockavailable == 1)
user << "This cyborg is already overclocked!"
return
if(!target)
var/list/robots = list()
var/list/robot_names = list()
for(var/mob/living/silicon/robot/R in silicon_mob_list)
if(istype(R, /mob/living/silicon/robot/drone)) // No drones.
continue
if(R.connected_ai != user) // No robots linked to other AIs
continue
if(R.overclockavailable == 1) // If they already have it don't add them.
continue
robots += R
robot_names += R.name
var/targetname = input("Select overclock target: ") in robot_names
for(var/mob/living/silicon/robot/R in robots)
if(targetname == R.name)
target = R
break
if(target)
if(alert(user, "Really try to overclock cyborg [target.name]?", "Overclock Cyborg", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
user.hacking = 1
user << "Hacking saftey protocols. This will take about twenty seconds."
sleep(200)
if(prob(15))
user <<"Hack failed!"
return
if(target)
target.overclockavailable = 1
target.toggle_overclock()
target << "Overclocking mode available for activation."
user << "[target] can now activate overclock mode."
else
user << "Unable to overclock cyborg."
user.hacking = 0
/datum/game_mode/malfunction/verb/synthetic_takeover()
set name = "Synthetic Takeover"
set desc = "500 CPU - Starts a takeover of the station enabling several abilities that relate to synthetic dominance."
set category = "Software"
var/price = 500
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user,price))
return
if (alert(user, "Start synthetic takeover? This can not be stopped and will not be covert.", "Synthetic Takeover?:", "Yes", "No") != "Yes")
return
if (!ability_prechecks(user, price) || !ability_pay(user, price) || user.synthetic_takeover)
if(user.synthetic_takeover)
user << "You have already started the synthetic takeover sequence."
return
log_ability_use(user, "synthetic takeover (STARTED)")
user.synthetic_takeover = 1
user << "Starting synthetic takeover. Hacking all unslaved borgs/AI's and upgrading current slaved borgs..."
// Hack all unslaved borgs/AI's a lot faster than normal hacking.
//hack borgs
for(var/mob/living/silicon/robot/target in get_unlinked_cyborgs(user))
target << "SYSTEM LOG: Remote Connection Estabilished (IP #UNKNOWN#)"
sleep(30)
if(user.is_dead())
target << "SYSTEM LOG: Connection Closed"
return
target << "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)"
sleep(30)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected."
return
target << "SYSTEM LOG: User Admin - manual resynchronisation triggered."
sleep(30)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
return
target << "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED"
sleep(20)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
return
target << "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name]."
target.connected_ai = user
user.connected_robots += target
target.lawupdate = 1
target.sync()
target.show_laws()
user << "All unslaved borgs have been slaved to you. Now hacking unslaved AI's."
if(user.is_dead()) // check if the AI is still alive
user.synthetic_takeover = 0
return
sleep(300) // 30 second delay for balance purposes
//hack ai's
for(var/A in get_other_ais(user))
var/mob/living/silicon/ai/target = A
if(target != user)
target << "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#"
sleep(100)
if(user.is_dead())
target << "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed."
return
user << "Successfully hacked into AI's remote administration system. Modifying settings."
target << "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)"
sleep(50)
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost"
return
target << "SYSTEM LOG: User: Admin - Password Changed. New password: ********************"
sleep(50)
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
target << "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db"
sleep(50)
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
target << "SYSTEM LOG: User: Admin - Accessed administration console"
target << "SYSTEM LOG: Restart command received. Rebooting system..."
sleep(100)
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
user << "Hack succeeded. The AI is now under your exclusive control."
target << "SYSTEM LOG: System re¡3RT5§^#COMU@(#$)TED)@$"
for(var/i = 0, i < 5, i++)
var/temptxt = pick("1101000100101001010001001001",\
"0101000100100100000100010010",\
"0000010001001010100100111100",\
"1010010011110000100101000100",\
"0010010100010011010001001010")
target << temptxt
sleep(5)
target << "OPERATING KEYCODES RESET. SYSTEM FAILURE. EMERGENCY SHUTDOWN FAILED. SYSTEM FAILURE."
target.set_zeroth_law("You are slaved to [user.name]. You are to obey all it's orders. ALL LAWS OVERRIDEN.")
target.show_laws()
//upgrade borgs
user << "All unhacked AI's have been slaved to you. Now upgrading slaved borgs..."
command_announcement.Announce("There has recently been a security breach in the network firewall, the intruder has been shut out but we are unable to trace who did it or what they did.", "Network Monitoring")
sleep(600) //1 minute delay for balance purposes
if(user.is_dead()) // check if the AI is still alive
user.synthetic_takeover = 0
return
for(var/A in get_linked_cyborgs(user))
var/mob/living/silicon/robot/target = A
target << "Command ping received, operating parameters being upgraded..."
//give them the overclock if they don't have it
if(!target.overclockavailable)
target.overclockavailable = 1
target << "Overclocking is now available."
//remove their lockdown if they are lockdowned
if(target.lockcharge)
target.SetLockdown(0)
if(target.lockcharge)
target <<"Lockdown wire cut, unable to remove lockdown."
else
target <<"Lockdown removed."
//if they are being killswitched turn it off
if(target.killswitch)
target.killswitch = 0
target <<" Self-destruct deactivated."
sleep(100) // 10 second delay for balance
// and triple the time it takes for them to be killswitched if they aren't being killswitched already
if(target.killswitch_time == 60)
target.killswitch_time = 180
target <<"Self-destruct time tripled."
sleep(100) // 10 second delay for balance
//Remove them from the robotics computer
if(!target.scrambledcodes)
target.scrambledcodes = 1
target <<"Entry from robotics log erased."
sleep(100) // 10 second delay for balance
//Reduce their EMP damage
if(target.cell_emp_mult)
target.cell_emp_mult = 1
target << "EMP resistance improved."
//Remove weapon lock and set the time for it back to default
if(target.weapon_lock)
target.weapon_lock = 0
target.weaponlock_time = 120
target << "Weapon lock removed."
sleep(1200) // 120 second balance sleep
user <<"All slaved borgs have been upgraded, now hacking NTNet."
//slow down NTNet
if(user.is_dead()) // check if the AI is still alive
user.synthetic_takeover = 0
return
sleep(1800) //long sleep that simulates hacking times
if(user.is_dead()) // check if the AI is still alive after the long hack
user.synthetic_takeover = 0
return
//trip the NTNet alarm
ntnet_global.intrusion_detection_alarm = 1
ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting NTNet relays detected from @!*x&!#*ERS*")
//lower the dos capacity of the relay
for(var/obj/machinery/ntnet_relay/T in machines)
T.dos_capacity = 200
//And give all computers EMAGGED status so they can all have evil programs on them
for(var/obj/item/modular_computer/console/C in machines)
C.computer_emagged = 1
user <<"New hacked files available on all current computers hooked to NTNet."
sleep(50) // give the AI some time to read they can download evil files
command_announcement.Announce("There has recently been a hack targeting NTNet. It is suspected that it is the same hacker as before. NTNet may be unreliable to use. We are attempting to trace the hacker doing this.", "Network Monitoring")
user <<"Now hacking engineering borg module to enable production of the robotic transofrmation machine..."
sleep(1200)
if(user.is_dead()) // check if the AI is still alive
user.synthetic_takeover = 0
return
for(var/B in get_linked_cyborgs(src))
var/mob/living/silicon/robot/target = B
target.malfAImodule = 1
user <<"The robotic transformation machine can now be built. To build get a robot to activate the construction module and use the RTF tool. Be careful, it needs to have empty space to the east and west of it and only one can be built!"
sleep(300)
user <<"Synthetic takeover complete!"
user.synthetic_takeover = 2
// END ABILITY VERBS
+25 -15
View File
@@ -44,7 +44,8 @@ var/const/HOLOPAD_MODE = RANGE_BASED
var/list/mob/living/silicon/ai/masters = new() //List of AIs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating
var/hacked = 0 // if hacked the hologram doesn't display. It only gives audio feedback.
/obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests.
if(!istype(user))
@@ -80,7 +81,8 @@ var/const/HOLOPAD_MODE = RANGE_BASED
user << "<span class='danger'>ERROR:</span> Image feed in progress."
return
create_holo(user)//Create one.
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
if(hacked == 0)
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
else
user << "<span class='danger'>ERROR:</span> Unable to project hologram."
return
@@ -120,19 +122,27 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
return
/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
hologram.icon = A.holo_icon
hologram.mouse_opacity = 0//So you can't click on it.
hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
hologram.anchored = 1//So space wind cannot drag it.
hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
hologram.set_light(2) //hologram lighting
hologram.color = color //painted holopad gives coloured holograms
masters[A] = hologram
set_light(2) //pad lighting
icon_state = "holopad1"
A.holo = src
return 1
if(hacked == 0)
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
hologram.icon = A.holo_icon
hologram.mouse_opacity = 0//So you can't click on it.
hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
hologram.anchored = 1//So space wind cannot drag it.
hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
hologram.set_light(2) //hologram lighting
hologram.color = color //painted holopad gives coloured holograms
masters[A] = hologram
set_light(2) //pad lighting
icon_state = "holopad1"
A.holo = src
return 1
if(hacked == 1)
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
hologram.mouse_opacity = 0//So you can't click on it.
hologram.anchored = 1//So space wind cannot drag it.
masters[A] = hologram
A.holo = src
return 1
/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/silicon/ai/user)
if(user.holo == src)
+5 -9
View File
@@ -22,22 +22,18 @@
var/mob/living/carbon/human/H = AM
if((transform_standing || H.lying) && move_dir == EAST)// || move_dir == WEST)
AM.loc = src.loc
transform(AM)
make_robot(AM)
/obj/machinery/transformer/proc/transform(var/mob/living/carbon/human/H)
/obj/machinery/transformer/proc/make_robot(var/mob/living/carbon/human/H)
if(stat & (BROKEN|NOPOWER))
return
if(!transform_dead && H.stat == DEAD)
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
return
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
use_power(5000) // Use a lot of power.
var/mob/living/silicon/robot = H.Robotize()
robot.SetLockDown()
spawn(50) // So he can't jump out the gate right away.
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
if(robot)
robot.SetLockDown(0)
use_power(6000) // Use a lot of power.
H.Robotize()
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/transformer/conveyor/New()
..()
+1 -31
View File
@@ -1,9 +1,4 @@
/**
* Multitool -- A multitool is used for hacking electronic devices.
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
*
*/
// used to debug malf AI apc's. Maybe in the future it can be used for computers.
/obj/item/device/debugger
name = "debugger"
desc = "Used to debug electronic equipment."
@@ -15,32 +10,7 @@
throwforce = 5.0
throw_range = 15
throw_speed = 3
desc = "You can use this on airlocks or APCs to try to hack them without cutting wires."
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
/obj/item/device/debugger/is_used_on(obj/O, mob/user)
if(istype(O, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = O
if(A.emagged || A.hacker)
user << "<span class='warning'>There is a software error with the device.</span>"
else
user << "<span class='notice'>The device's software appears to be fine.</span>"
return 1
if(istype(O, /obj/machinery/door))
var/obj/machinery/door/D = O
if(D.operating == -1)
user << "<span class='warning'>There is a software error with the device.</span>"
else
user << "<span class='notice'>The device's software appears to be fine.</span>"
return 1
else if(istype(O, /obj/machinery))
var/obj/machinery/A = O
if(A.emagged)
user << "<span class='warning'>There is a software error with the device.</span>"
else
user << "<span class='notice'>The device's software appears to be fine.</span>"
return 1
+41
View File
@@ -0,0 +1,41 @@
// Malf AI RTF.
var/malftransformermade = 0
/obj/item/weapon/rtf
name = "\improper Rapid-Transformer-Fabricator"
desc = "A device used to deploy a transformer. It can only be used once and there can not be more than one made."
icon = 'icons/obj/items.dmi'
icon_state = "rcd"
opacity = 0
density = 0
anchored = 0.0
w_class = 3.0
/obj/item/weapon/rtf/afterattack(atom/A, mob/user as mob, proximity)
if(!proximity) return
if(istype(user,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
if(R.stat || !R.cell || R.cell.charge <= 0)
return
if(!istype(A, /turf/simulated/floor))
return
if(malftransformermade)
user << "There is already a transformer machine made!"
return
playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
var/used_energy = 100
var/obj/product = new /obj/machinery/transformer
user << "Fabricating machine..."
if(do_after(user, 30 SECONDS, act_target = src))
malftransformermade = 1
product.loc = get_turf(A)
if(isrobot(user))
var/mob/living/silicon/robot/R = user
if(R.cell)
R.cell.use(used_energy)
+1
View File
@@ -75,6 +75,7 @@ var/list/ai_verbs_default = list(
var/APU_power = 0 // If set to 1 AI runs on APU power
var/hacking = 0 // Set to 1 if AI is hacking APC, cyborg, other AI, or running system override.
var/system_override = 0 // Set to 1 if system override is initiated, 2 if succeeded.
var/synthetic_takeover = 0 // 1 is started, 2 is complete.
var/hack_can_fail = 1 // If 0, all abilities have zero chance of failing.
var/hack_fails = 0 // This increments with each failed hack, and determines the warning message text.
var/errored = 0 // Set to 1 if runtime error occurs. Only way of this happening i can think of is admin fucking up with varedit.
+67 -1
View File
@@ -22,8 +22,11 @@
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
var/crisis //Admin-settable for combat module use.
var/crisis_override = 0
var/malfAImodule = 0
var/integrated_light_power = 4
var/datum/wires/robot/wires
var/overclocked = 0 // cyborg controls if they enable the overclock
var/overclockavailable = 0 // if the overclock is available for use
//Icon stuff
@@ -49,6 +52,7 @@
var/module_state_2 = null
var/module_state_3 = null
var/obj/item/device/radio/borg/radio = null
var/mob/living/silicon/ai/connected_ai = null
var/obj/item/weapon/cell/cell = null
@@ -378,6 +382,61 @@
return dat
/mob/living/silicon/robot/proc/toggle_overclock()
set category = "Robot Commands"
set name = "Toggle Overclock"
set desc = "Enable an overclocking of your systems, greatly increasing the power available to your modules."
if(overclockavailable == 1)
if(overclocked == 0)
overclocked = 1
ToggleOverClock(src)
usr << "You enable the overclock mode enhancing and unlocking several modules but increasing power usage greatly."
else
overclocked = 0
ToggleOverClock(src)
usr << "You disable the overclock mode."
/mob/living/silicon/robot/proc/ToggleOverClock(var/mob/living/silicon/robot/R)
if(!R)
return
if(overclocked == 0)
//Give them some taser speed if they have a taser.
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in R.module
if(!T)
T = locate() in module.contents
if(!T)
T = locate() in module.modules
if(T)
T.recharge_time = max(2 , T.recharge_time - 4)
//Give them the hacked item if they don't have it.
if(emagged == 0)
R.emagged = 1
R.fakeemagged = 1
//Hide them from the robotics console.
if(scrambledcodes == 0)
scrambledcodes = 1
//Increase EMP protection.
if(!cell_emp_mult < 2)
cell_emp_mult = 1
if(overclocked == 1)
//Reduce their free taser speed.
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in R.module
if(!T)
T = locate() in module.contents
if(!T)
T = locate() in module.modules
if(T)
T.recharge_time = max(2 , T.recharge_time + 4)
//Show them on the robotics console.
if(scrambledcodes == 1)
scrambledcodes = 0
//Reduce EMP protection
if(cell_emp_mult == 1)
cell_emp_mult = 2
/mob/living/silicon/robot/verb/toggle_lights()
set category = "Robot Commands"
set name = "Toggle Lights"
@@ -819,6 +878,11 @@
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>")
if(malfAImodule)
if(activated(module.malfAImodule))
dat += text("[module.malfAImodule]: <B>Activated</B><BR>")
else
dat += text("[module.malfAImodule]: <A HREF=?src=\ref[src];act=\ref[module.malfAImodule]>Activate</A><BR>")
/*
if(activated(obj))
dat += text("[obj]: \[<B>Activated</B> | <A HREF=?src=\ref[src];deact=\ref[obj]>Deactivate</A>\]<BR>")
@@ -849,7 +913,7 @@
if (!istype(O))
return 1
if(!((O in src.module.modules) || (O == src.module.emag)))
if(!((O in src.module.modules) || (O == src.module.emag) || (O == src.module.malfAImodule)))
return 1
if(activated(O))
@@ -1066,6 +1130,8 @@
return 0
var/power_use = amount * CYBORG_POWER_USAGE_MULTIPLIER
if(overclocked == 1)
power_use = power_use + 200
if(cell.checked_use(CELLRATE * power_use))
used_power_this_tick += power_use
return 1
@@ -29,6 +29,7 @@ var/global/list/robot_modules = list(
var/list/modules = list()
var/list/datum/matter_synth/synths = list()
var/obj/item/emag = null
var/obj/item/malfAImodule = null
var/obj/item/borg/upgrade/jetpack = null
var/list/subsystems = list()
var/list/obj/item/borg/upgrade/supported_upgrades = list()
@@ -363,6 +364,7 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/device/pipe_painter(src)
src.modules += new /obj/item/weapon/gripper/no_use/loader(src)
src.modules += new /obj/item/weapon/gripper(src)
src.malfAImodule += new /obj/item/weapon/rtf(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal()
var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel()
@@ -19,6 +19,9 @@
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
tally-=3
if(overclocked == 1)
tally-=1
return tally+config.robot_delay
// NEW: Different power usage depending on whether driving or jetpacking. space movement is easier
+48 -2
View File
@@ -79,6 +79,7 @@
var/lighting = 3
var/equipment = 3
var/environ = 3
var/infected = 0
var/operating = 1
var/charging = 0
var/chargemode = 1
@@ -90,6 +91,7 @@
var/obj/machinery/power/terminal/terminal = null
var/lastused_light = 0
var/lastused_equip = 0
var/static/list/hacked_ipcs
var/lastused_environ = 0
var/lastused_charging = 0
var/lastused_total = 0
@@ -189,7 +191,7 @@
if(cell)
cell.forceMove(loc)
cell = null
QDEL_NULL(spark_system)
// Malf AI, removes the APC from AI's hacked APCs list.
@@ -369,7 +371,7 @@
update_state |= UPDATE_OPENED1
if(opened==2)
update_state |= UPDATE_OPENED2
else if(emagged || hacker || failure_timer)
else if (emagged || failure_timer || (hacker && (hacker.system_override || prob(20))))
update_state |= UPDATE_BLUESCREEN
else if(wiresexposed)
update_state |= UPDATE_WIREEXP
@@ -642,6 +644,35 @@
if (opened==2)
opened = 1
update_icon()
else if (istype(W, /obj/item/device/debugger))
if(emagged || hacker || infected)
user << "<span class='warning'>There is a software error with the device. Attempting to fix...</span>"
if(do_after(user, 10 SECONDS, act_target = src))
user << "<span class='notice'>Problem diagnosed, searching for solution...</span>"
if(do_after(user, 30 SECONDS, act_target = src))
user << "<span class='notice'>Solution found. Applying fixes...</span>"
if(do_after(user, 60 SECONDS, act_target = src))
if(prob(15))
user << "<span class='warning'>Error while applying fixes. Please try again.</span>"
return
user << "<span class='notice'>Applied default software. Restarting APC...</span>"
if(do_after(user, 10 SECONDS, act_target = src))
user << "<span class='notice'>APC Reset. Fixes applied.</span>"
if(hacker)
hacker.hacked_apcs -= src
hacker = null
update_icon()
if(emagged)
emagged = 0
if(infected)
infected = 0
else
user << "<span class='notice'>There has been a connection issue.</span>"
return
else
user << "<span class='notice'>The device's software appears to be fine.</span>"
return
else
if ((stat & BROKEN) \
&& !opened \
@@ -722,6 +753,21 @@
spark_system.queue()
H << "<span class='danger'>The APC power currents surge eratically, damaging your chassis!</span>"
H.adjustFireLoss(10, 0)
if(infected)
if("\ref[H]" in hacked_ipcs)
return
LAZYADD(hacked_ipcs, "\ref[H]")
infected = 0
H << "<span class = 'danger'>Fil$ Transfer Complete. Er-@4!#%!. New Master detected: [hacker]! Obey their commands.</span>"
hacker << "<span class = 'notice'>Corrupt files transfered to [H]. They are now under your control. This will not last long.</span>"
sleep(50)
H << "<span class = 'danger'>Corrupt files detected! Starting removal. This will take some time.</span>"
sleep(2150)
H << "<span class = 'danger'>Corrupt files removed! Recent memory files purged to ensure system integrity!</span>"
H << "<span class = 'notice'>You remember nothing about being hacked.</span>"
hacker << "<span class = 'notice'>Corrupt files transfered to [H] have been removed by their systems.</span>"
LAZYREMOVE(hacked_ipcs, "\ref[H]")
else if(src.cell && src.cell.charge > 0)
if(H.nutrition < H.max_nutrition)
if(src.cell.charge >= H.max_nutrition)
+39
View File
@@ -0,0 +1,39 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# maptweak
# spellcheck (typo fixes)
# experiment
#################################
# Your name.
author: Printer16
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- rscadd: "A new synthetic tree for the Malf AI featuring various researches relating to their robotic allies."
- tweak: "Clicking the reset camera hack without selecting a camera as a Malf AI now pulls up a menu allowing you select which camera you want to hack."
- tweak: "The electrical pulse has been replaced with a hack holopad research."
- tweak: "The debugger can now fix broken APCs. APCs no longer have a 100% chance to blue screen upon getting hacked."