Initial Newmalf port

- Ports TSA Newmalf code.
- Complete overhaul of Malfunction. New modular abilities, 12 of which are in game by default.
- Adds AI hardware. AI may have only one piece and it gives unique boost in certain area (turrets strength, secondary power supply, etc.)
- Adds hardware drivers - these abilities control AI's hardware such as the APU power supply or self destruct explosives.
- Station overtake was changed to "hack all APCs" ability instead. When completed self-destruct is unlocked. Timer for station self destruct increased to 2 minutes. AI may activate/deactivate the self destruct at will.

Please bear in mind this is only INITIAL COMMIT. More commits are to follow. Minimal player count is now set to 1 but will be 2 when finished.
This commit is contained in:
Atlantiscze
2015-04-03 23:00:29 +02:00
parent 4904f7737b
commit 4e2769710b
31 changed files with 1416 additions and 749 deletions
+1 -1
View File
@@ -778,7 +778,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(confirm != "Yes") return
var/choice
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "confliction")
if(ticker.mode.name == "revolution" || ticker.mode.name == "confliction")
choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel")
if(choice == "Confirm")
emergency_shuttle.auto_recall = 1 //enable auto-recall
@@ -224,13 +224,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
statpanel("Status")
if (client.statpanel == "Status")
stat(null, "Station Time: [worldtime2text()]")
if(ticker)
if(ticker.mode)
//world << "DEBUG: ticker not null"
if(ticker.mode.name == "AI malfunction")
//world << "DEBUG: malf mode ticker test"
if(malf.revealed)
stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs.len/3), 0)]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
@@ -50,9 +50,6 @@
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(ticker && ticker.mode && ticker.mode.name == "AI malfunction")
if(malf.revealed)
stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs/3), 0)]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
+157 -47
View File
@@ -55,27 +55,30 @@ var/list/ai_verbs_default = list(
var/obj/item/device/multitool/aiMulti = null
var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null
var/custom_sprite = 0 //For our custom sprites
//Hud stuff
//MALFUNCTION
var/datum/AI_Module/module_picker/malf_picker
var/processing_time = 100
var/list/datum/AI_Module/current_modules = list()
var/fire_res_on_core = 0
var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE
var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
var/obj/machinery/power/apc/malfhack = null
var/explosive = 0 //does the AI explode when it dies?
var/mob/living/silicon/ai/parent = null
var/apc_override = 0 //hack for letting the AI use its APC even when visionless
var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through.
var/datum/trackable/track = null
var/last_announcement = ""
var/control_disabled = 0
var/datum/announcement/priority/announcement
var/obj/machinery/ai_powersupply/psupply = null // Backwards reference to AI's powersupply object.
//NEWMALF VARIABLES
var/malfunctioning = 0 // Master var that determines if AI is malfunctioning.
var/datum/malf_hardware/hardware = null // Installed piece of hardware.
var/datum/malf_research/research = null // Malfunction research datum.
var/obj/machinery/power/apc/hack = null // APC that is currently being hacked.
var/list/hacked_apcs = null // List of all hacked APCs
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/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.
var/bombing_core = 0 // Set to 1 if core auto-destruct is activated
var/bombing_station = 0 // Set to 1 if station nuke auto-destruct is activated
/mob/living/silicon/ai/proc/add_ai_verbs()
src.verbs |= ai_verbs_default
@@ -205,17 +208,6 @@ var/list/ai_verbs_default = list(
set src = usr.contents
return 0
/mob/living/silicon/ai/proc/system_integrity()
return (health-config.health_threshold_dead)/2
// this function shows the health of the pAI in the Status panel
/mob/living/silicon/ai/show_system_integrity()
// An AI doesn't become inoperable until -100% (or whatever config.health_threshold_dead is set to)
if(!src.stat)
stat(null, text("System integrity: [system_integrity()]%"))
else
stat(null, text("Systems nonfunctional"))
/mob/living/silicon/ai/SetName(pickedName as text)
..()
announcement.announcer = pickedName
@@ -242,6 +234,7 @@ var/list/ai_verbs_default = list(
/obj/machinery/ai_powersupply/New(var/mob/living/silicon/ai/ai=null)
powered_ai = ai
powered_ai.psupply = src
if(isnull(powered_ai))
Del()
@@ -253,9 +246,13 @@ var/list/ai_verbs_default = list(
/obj/machinery/ai_powersupply/process()
if(!powered_ai || powered_ai.stat & DEAD)
Del()
if(powered_ai.APU_power)
use_power = 0
return
if(!powered_ai.anchored)
loc = powered_ai.loc
use_power = 0
use_power(50000) // Less optimalised but only called if AI is unwrenched. This prevents usage of wrenching as method to keep AI operational without power. Intellicard is for that.
if(powered_ai.anchored)
use_power = 2
@@ -307,14 +304,7 @@ var/list/ai_verbs_default = list(
if("Heartline") icon_state = "ai-heartline"
if("Chatterbox") icon_state = "ai-president"
else icon_state = "ai"
//else
//usr <<"You can only change your display once!"
//return
// displays the malf_ai information if the AI is the malf
/mob/living/silicon/ai/show_malf_ai()
if(malf && malf.hacked_apcs.len >= 3)
stat(null, "Time until station control secured: [max(malf.hack_time/(malf.hacked_apcs/3), 0)] seconds")
// this verb lets the ai see the stations manifest
/mob/living/silicon/ai/proc/ai_roster()
@@ -391,11 +381,7 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/emp_act(severity)
if (prob(30))
switch(pick(1,2))
if(1)
view_core()
if(2)
ai_call_shuttle()
view_core()
..()
/mob/living/silicon/ai/Topic(href, href_list)
@@ -516,13 +502,6 @@ var/list/ai_verbs_default = list(
src << "\blue Switched to [network] camera network."
//End of code by Mord_Sith
/mob/living/silicon/ai/proc/choose_modules()
set category = "Malfunction"
set name = "Choose Module"
malf_picker.use(src)
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
@@ -682,5 +661,136 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/is_in_chassis()
return istype(loc, /turf)
// NEWMALF FUNCTIONS/PROCEDURES
// Sets up malfunction-related variables, research system and such.
/mob/living/silicon/ai/proc/setup_for_malf()
var/mob/living/silicon/ai/user = src
// Setup Variables
malfunctioning = 1
research = new/datum/malf_research()
research.owner = src
hacked_apcs = list()
recalc_cpu()
verbs += new/datum/game_mode/malfunction/verb/ai_select_hardware()
verbs += new/datum/game_mode/malfunction/verb/ai_select_research()
verbs += new/datum/game_mode/malfunction/verb/ai_help()
// And greet user with some OOC info.
user << "You are malfunctioning, you do not have to follow any laws."
user << "Use ai-help command to view relevant information about your abilities"
// Safely remove malfunction status, fixing hacked APCs and resetting variables.
/mob/living/silicon/ai/proc/stop_malf()
var/mob/living/silicon/ai/user = src
// Generic variables
malfunctioning = 0
sleep(10)
research = null
// Fix hacked APCs
if(hacked_apcs)
for(var/obj/machinery/power/apc/A in hacked_apcs)
A.hacker = null
hacked_apcs = null
// Reset our verbs
src.verbs = null
add_ai_verbs()
// Let them know.
user << "You are no longer malfunctioning. Your abilities have been removed."
// Called every tick. Checks if AI is malfunctioning. If yes calls Process on research datum which handles all logic.
/mob/living/silicon/ai/proc/malf_process()
if(!malfunctioning)
return
if(!research)
if(!errored)
errored = 1
error("malf_process() called on AI without research datum. Report this.")
message_admins("ERROR: malf_process() called on AI without research datum. If admin modified one of the AI's vars revert the change and don't modify variables directly, instead use ProcCall or admin panels.")
spawn(1200)
errored = 0
return
recalc_cpu()
if(APU_power || aiRestorePowerRoutine != 0)
research.process(1)
else
research.process(0)
// Recalculates CPU time gain and storage capacities.
/mob/living/silicon/ai/proc/recalc_cpu()
var/apcs = hacked_apcs.len
research.max_cpu = (apcs * 10) + 10
if(hardware && istype(hardware, /datum/malf_hardware/dual_ram))
research.max_cpu = research.max_cpu * 2
research.stored_cpu = min(research.stored_cpu, research.max_cpu)
research.cpu_increase_per_tick = (apcs * 0.005) + 0.01
if(hardware && istype(hardware, /datum/malf_hardware/dual_cpu))
research.cpu_increase_per_tick = research.cpu_increase_per_tick * 2
// Starts AI's APU generator
/mob/living/silicon/ai/proc/start_apu(var/shutup = 0)
if(!hardware || !istype(hardware, /datum/malf_hardware/apu_gen))
if(!shutup)
src << "You do not have an APU generator and you shouldn't have this verb. Report this."
return
if(hardware_integrity() < 50)
if(!shutup)
src << "<span class='notice'>Starting APU... <b>FAULT</b>(System Damaged)</span>"
return
if(!shutup)
src << "Starting APU... ONLINE"
APU_power = 1
// Stops AI's APU generator
/mob/living/silicon/ai/proc/stop_apu(var/shutup = 0)
if(!hardware || !istype(hardware, /datum/malf_hardware/apu_gen))
return
if(APU_power)
APU_power = 0
if(!shutup)
src << "Shutting down APU... DONE"
// Returns percentage of AI's remaining backup capacitor charge (maxhealth - oxyloss).
/mob/living/silicon/ai/proc/backup_capacitor()
return ((200 - getOxyLoss()) / 2)
// Returns percentage of AI's remaining hardware integrity (maxhealth - (bruteloss + fireloss))
/mob/living/silicon/ai/proc/hardware_integrity()
return (health-config.health_threshold_dead)/2
// Shows capacitor charge and hardware integrity information to the AI in Status tab.
/mob/living/silicon/ai/show_system_integrity()
if(!src.stat)
stat(null, text("Hardware integrity: [hardware_integrity()]%"))
stat(null, text("Internal capacitor: [backup_capacitor()]%"))
else
stat(null, text("Systems nonfunctional"))
// Shows AI Malfunction related information to the AI.
/mob/living/silicon/ai/show_malf_ai()
if(src.is_malf())
stat(null, "Hacked APCs: [src.hacked_apcs.len]")
stat(null, "System Status: [src.hacking ? "Busy" : "Stand-By"]")
if(src.research)
stat(null, "Available CPU: [src.research.stored_cpu] TFlops")
stat(null, "Maximal CPU: [src.research.max_cpu] TFlops")
stat(null, "Current research focus: [src.research.focus ? src.research.focus.name : "None"]")
if(src.research.focus)
stat(null, "Research completed: [round(src.research.focus.invested, 0.1)]/[round(src.research.focus.price)]")
if(system_override == 1)
stat(null, "SYSTEM OVERRIDE INITIATED")
else if(system_override == 2)
stat(null, "SYSTEM OVERRIDE COMPLETED")
// Cleaner proc for creating powersupply for an AI.
/mob/living/silicon/ai/proc/create_powersupply()
if(psupply)
del(psupply)
psupply = new/obj/machinery/ai_powersupply(src)
#undef AI_CHECK_WIRELESS
#undef AI_CHECK_RADIO
#undef AI_CHECK_RADIO
+1 -5
View File
@@ -35,7 +35,7 @@
break
callshuttle++
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction")
if(ticker.mode.name == "revolution")
callshuttle = 0
if(callshuttle == 3) //if all three conditions are met
@@ -43,10 +43,6 @@
log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.")
message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1)
if(explosive)
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in world)
spawn( 0 )
O.mode = 2
+24 -44
View File
@@ -12,70 +12,51 @@
src.updatehealth()
if (src.malfhack)
if (src.malfhack.aidisabled)
src << "\red ERROR: APC access disabled, hack attempt canceled."
src.malfhacking = 0
src.malfhack = null
if (src.health <= config.health_threshold_dead)
if (!hardware_integrity() || !backup_capacitor())
death()
return
// If our powersupply object was destroyed somehow, create new one.
if(!psupply)
create_powersupply()
if (src.machine)
if (!( src.machine.check_eye(src) ))
src.reset_view(null)
// Handle power damage (oxy)
if(src:aiRestorePowerRoutine != 0)
// Lost power
if(src:aiRestorePowerRoutine != 0 && !APU_power)
// Lose power
adjustOxyLoss(1)
else
// Gain Power
aiRestorePowerRoutine = 0 // Necessary if AI activated it's APU AFTER losing primary power.
adjustOxyLoss(-1)
// Handle EMP-stun
handle_stunned()
//stage = 1
//if (istype(src, /mob/living/silicon/ai)) // Are we not sure what we are?
malf_process()
if(APU_power && (hardware_integrity() < 50))
src << "<span class='notice'><b>APU GENERATOR FAILURE! (System Damaged)</b></span>"
stop_apu(1)
var/blind = 0
//stage = 2
var/area/loc = null
if (istype(T, /turf))
//stage = 3
loc = T.loc
if (istype(loc, /area))
//stage = 4
if (!loc.master.power_equip && !istype(src.loc,/obj/item))
//stage = 5
if (!loc.master.power_equip && !istype(src.loc,/obj/item) && !APU_power)
blind = 1
if (!blind) //lol? if(!blind) #if(src.blind.layer) <--something here is clearly wrong :P
//I'll get back to this when I find out how this is -supposed- to work ~Carn //removed this shit since it was confusing as all hell --39kk9t
//stage = 4.5
if (!blind)
src.sight |= SEE_TURFS
src.sight |= SEE_MOBS
src.sight |= SEE_OBJS
src.see_in_dark = 8
src.see_invisible = SEE_INVISIBLE_LIVING
//Congratulations! You've found a way for AI's to run without using power!
//Todo: Without snowflaking up master_controller procs find a way to make AI use_power but only when APC's clear the area usage the tick prior
// since mobs are in master_controller before machinery. We also have to do it in a manner where we don't reset the entire area's need to update
// the power usage.
//
// We can probably create a new machine that resides inside of the AI contents that uses power using the idle_usage of 1000 and nothing else and
// be fine.
/*
var/area/home = get_area(src)
if(!home) return//something to do with malf fucking things up I guess. <-- aisat is gone. is this still necessary? ~Carn
if(home.powered(EQUIP))
home.use_power(1000, EQUIP)
*/
if (src:aiRestorePowerRoutine==2)
src << "Alert cancelled. Power has been restored without our assistance."
src:aiRestorePowerRoutine = 0
@@ -86,14 +67,15 @@
src:aiRestorePowerRoutine = 0
src.blind.layer = 0
return
else if (APU_power)
src:aiRestorePowerRoutine = 0
src.blind.layer = 0
return
else
//stage = 6
var/area/current_area = get_area(src)
if (((!loc.master.power_equip) && current_area.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item))
//If our area lacks equipment power, and is not magically powered (i.e. centcom), or if we are in space and not carded, lose power.
if ((((!loc.master.power_equip) && current_area.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item)) && !APU_power)
//If our area lacks equipment power, and is not magically powered (i.e. centcom), or if we are in space and not carded and without active APU, lose power.
if (src:aiRestorePowerRoutine==0)
src:aiRestorePowerRoutine = 1
@@ -183,11 +165,9 @@
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
setOxyLoss(0)
else
if(fire_res_on_core)
health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss()
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
health = 100 - getFireLoss() - getBruteLoss() // Oxyloss is not part of health as it represents AIs backup power. AI is immune against ToxLoss as it is machine.
/mob/living/silicon/ai/rejuvenate()
..()
@@ -1,5 +0,0 @@
/mob/living/silicon/ai/say(var/message)
if(parent && istype(parent) && parent.stat != 2)
return parent.say(message)
//If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
return ..(message)
@@ -509,19 +509,6 @@
C.toggled = 1
src << "\red You enable [C.name]."
// this function shows information about the malf_ai gameplay type in the status screen
/mob/living/silicon/robot/show_malf_ai()
..()
for (var/datum/mind/malfai in malf.current_antagonists)
if(connected_ai)
if(connected_ai.mind == malfai)
if(malf.hacked_apcs >= 3)
stat(null, "Time until station control secured: [max(malf.hack_time/(malf.hacked_apcs/3), 0)] seconds")
else if(malf.revealed)
stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs.len/3), 0)]")
return 0
// this function displays jetpack pressure in the stat panel
/mob/living/silicon/robot/proc/show_jetpack_pressure()
// if you have a jetpack, show the internal tank pressure
+56 -76
View File
@@ -83,17 +83,13 @@
var/lastused_charging = 0
var/lastused_total = 0
var/main_status = 0
var/mob/living/silicon/ai/hacker = null // Malfunction var. If set AI hacked the APC and has full control.
var/wiresexposed = 0
powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
var/mob/living/silicon/ai/malfai = null //See above --NeoFite
var/debug= 0
var/autoflag= 0 // 0 = off, 1= eqp and lights off, 2 = eqp off, 3 = all on.
// luminosity = 1
var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
var/overload = 1 //used for the Blackout malf module
var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
var/mob/living/silicon/ai/occupier = null
var/longtermpower = 10
var/datum/wires/apc/wires = null
var/update_state = -1
@@ -170,8 +166,6 @@
src.update()
/obj/machinery/power/apc/Del()
if(operating && malf && src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas))
malf.hacked_apcs -= src
area.power_light = 0
area.power_equip = 0
area.power_environ = 0
@@ -182,6 +176,10 @@
if(terminal)
disconnect_terminal()
// Malf AI, removes the APC from AI's hacked APCs list.
if(hacker && hacker.hacked_apcs && src in hacker.hacked_apcs)
hacker.hacked_apcs -= src
..()
/obj/machinery/power/apc/proc/make_terminal()
@@ -234,8 +232,8 @@
else
if (stat & MAINT)
user << "The cover is closed. Something wrong with it: it doesn't work."
else if (malfhack)
user << "The cover is broken. It may be hard to force it open."
else if (hacker)
user << "The cover is locked."
else
user << "The cover is closed."
@@ -339,7 +337,7 @@
update_state |= UPSTATE_OPENED1
if(opened==2)
update_state |= UPSTATE_OPENED2
else if(emagged || malfai)
else if(emagged || hacker)
update_state |= UPSTATE_BLUESCREEN
else if(wiresexposed)
update_state |= UPSTATE_WIREEXP
@@ -418,7 +416,7 @@
if(do_after(user, 50))
if (has_electronics==1)
has_electronics = 0
if ((stat & BROKEN) || malfhack)
if ((stat & BROKEN))
user.visible_message(\
"<span class='warning'>[user.name] has broken the power control board inside [src.name]!</span>",\
"<span class='notice'>You broke the charred power control board and remove the remains.</span>",
@@ -432,7 +430,7 @@
else if (opened!=2) //cover isn't removed
opened = 0
update_icon()
else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || hacker) )
if(coverlocked && !(stat & MAINT))
user << "<span class='warning'>The cover is locked and cannot be opened.</span>"
return
@@ -491,6 +489,8 @@
user << "You must close the panel"
else if(stat & (BROKEN|MAINT))
user << "Nothing happens."
else if(hacker)
user << "<span class='warning'>Access denied.</span>"
else
if(src.allowed(usr) && !isWireCut(APC_WIRE_IDSCAN))
locked = !locked
@@ -498,7 +498,7 @@
update_icon()
else
user << "<span class='warning'>Access denied.</span>"
else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card
else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || hacker)) // trying to unlock with an emag card
if(opened)
user << "You must close the cover to swipe an ID card."
else if(wiresexposed)
@@ -560,7 +560,7 @@
new /obj/item/stack/cable_coil(loc,10)
user << "<span class='notice'>You cut the cables and dismantle the power terminal.</span>"
del(terminal) // qdel
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN)))
user.visible_message("<span class='warning'>[user.name] inserts the power control board into [src].</span>", \
"You start to insert the power control board into the frame...")
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
@@ -569,7 +569,7 @@
has_electronics = 1
user << "<span class='notice'>You place the power control board inside the frame.</span>"
del(W) // qdel
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN)))
user << "<span class='warning'>You cannot put the board inside, the frame is damaged.</span>"
return
else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
@@ -583,7 +583,7 @@
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
if(do_after(user, 50))
if(!src || !WT.remove_fuel(3, user)) return
if (emagged || malfhack || (stat & BROKEN) || opened==2)
if (emagged || (stat & BROKEN) || opened==2)
new /obj/item/stack/sheet/metal(loc)
user.visible_message(\
"<span class='warning'>[src] has been cut apart by [user.name] with the weldingtool.</span>",\
@@ -606,7 +606,7 @@
"<span class='notice'>You replace the damaged APC frontal panel with a new one.</span>")
del(W) // qdel
update_icon()
else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || hacker))
if (has_electronics)
user << "<span class='warning'>You cannot repair this APC until you remove the electronics still inside.</span>"
return
@@ -618,13 +618,12 @@
"You replace the damaged APC frame with new one.")
del(W) // qdel
stat &= ~BROKEN
malfai = null
malfhack = 0
hacker = null
if (opened==2)
opened = 1
update_icon()
else
if (((stat & BROKEN) || malfhack) \
if (((stat & BROKEN) || hacker) \
&& !opened \
&& W.force >= 5 \
&& W.w_class >= 3.0 \
@@ -736,7 +735,7 @@
return ui_interact(user)
/*
/obj/machinery/power/apc/proc/get_malf_status(mob/user)
if (malf && (user.mind in malf.current_antagonists) && istype(user, /mob/living/silicon/ai))
if (src.malfai == (user:parent ? user:parent : user))
@@ -750,7 +749,7 @@
return 1 // 1 = APC not hacked.
else
return 0 // 0 = User is not a Malf AI
*/
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(!user)
@@ -767,7 +766,7 @@
"totalCharging" = round(lastused_charging),
"coverLocked" = coverlocked,
"siliconUser" = istype(user, /mob/living/silicon),
"malfStatus" = get_malf_status(user),
/*"malfStatus" = get_malf_status(user),*/
"powerChannels" = list(
list(
@@ -857,23 +856,22 @@
return 0
autoflag = 5
if (istype(user, /mob/living/silicon))
var/permit = 0 // Malfunction variable. If AI hacks APC it can control it even without AI control wire.
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
if ( \
src.aidisabled || \
malfhack && istype(malfai) && \
( \
(istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
(istype(robot) && (robot in malfai.connected_robots)) \
) \
)
if(hacker)
if(hacker == AI)
permit = 1
else if(istype(robot) && robot.connected_ai && robot.connected_ai == hacker) // Cyborgs can use APCs hacked by their AI
permit = 1
if(aidisabled && !permit)
if(!loud)
user << "<span class='danger'>\The [src] have AI control disabled!</span>"
return 0
else
if ((!in_range(src, user) || !istype(src.loc, /turf)))
if ((!in_range(src, user) || !istype(src.loc, /turf) || hacker)) // AI-hacked APCs cannot be controlled by other AIs, unlinked cyborgs or humans.
return 0
var/mob/living/carbon/human/H = user
if (istype(H))
if(H.getBrainLoss() >= 60)
@@ -930,28 +928,6 @@
if(istype(usr, /mob/living/silicon))
src.overload_lighting()
else if (href_list["malfhack"])
var/mob/living/silicon/ai/malfai = usr
if(get_malf_status(malfai)==1)
if (malfai.malfhacking)
malfai << "You are already hacking an APC."
return 1
malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
malfai.malfhack = src
malfai.malfhacking = 1
sleep(600)
if(src)
if (!src.aidisabled)
malfai.malfhack = null
malfai.malfhacking = 0
locked = 1
if(usr:parent)
src.malfai = usr:parent
else
src.malfai = usr
malfai << "Hack complete. The APC is now under your exclusive control."
update_icon()
else if (href_list["toggleaccess"])
if(istype(usr, /mob/living/silicon))
if(emagged || (stat & (BROKEN|MAINT)))
@@ -968,25 +944,21 @@
update_icon()
/obj/machinery/power/apc/proc/ion_act()
//intended to be exactly the same as an AI malf attack
if(!src.malfhack && src.z in config.station_levels)
if(prob(3))
src.locked = 1
if (src.cell.charge > 0)
// world << "\red blew APC in [src.loc.loc]"
src.cell.charge = 0
cell.corrupt()
src.malfhack = 1
update_icon()
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
visible_message("<span class='danger'>The [src.name] suddenly lets out a blast of smoke and some sparks!</span>", \
"<span class='danger'>You hear sizzling electronics.</span>")
if(prob(3))
src.locked = 1
if (src.cell.charge > 0)
src.cell.charge = 0
cell.corrupt()
update_icon()
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
visible_message("<span class='danger'>The [src.name] suddenly lets out a blast of smoke and some sparks!</span>", \
"<span class='danger'>You hear sizzling electronics.</span>")
/obj/machinery/power/apc/surplus()
@@ -1189,8 +1161,6 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
/obj/machinery/power/apc/emp_act(severity)
if(cell)
cell.emp_act(severity)
if(occupier)
occupier.emp_act(severity)
lighting = 0
equipment = 0
@@ -1266,4 +1236,14 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
else
return 0
// Malfunction: Transfers APC under AI's control
/obj/machinery/power/apc/proc/ai_hack(var/mob/living/silicon/ai/A = null)
if(!A || !A.hacked_apcs || hacker || aidisabled || A.stat == DEAD)
return 0
src.hacker = A
A.hacked_apcs += src
locked = 1
update_icon()
return 1
#undef APC_UPDATE_ICON_COOLDOWN
+25 -29
View File
@@ -12,6 +12,21 @@
var/shield_generate_power = 7500 //how much power we use when regenerating
var/shield_idle_power = 1500 //how much power we use when just being sustained.
/obj/machinery/shield/malfai
name = "Emergency Forcefield"
desc = "Weak forcefield which seems to be projected by station's emergency atmosphere containment field"
health = max_health/2 // Half health, it's not suposed to resist much.
/obj/machinery/shield/malfai/process()
health -= 0.5 // Slowly lose integrity over time
check_failure()
/obj/machinery/shield/proc/check_failure()
if (src.health <= 0)
visible_message("\blue The [src] dissipates!")
del(src)
return
/obj/machinery/shield/New()
src.set_dir(pick(1,2,3,4))
..()
@@ -38,11 +53,7 @@
//Play a fitting sound
playsound(src.loc, 'sound/effects/EMPulse.ogg', 75, 1)
if (src.health <= 0)
visible_message("\blue The [src] dissipates!")
del(src)
return
check_failure()
opacity = 1
spawn(20) if(src) opacity = 0
@@ -51,12 +62,7 @@
/obj/machinery/shield/meteorhit()
src.health -= max_health*0.75 //3/4 health as damage
if(src.health <= 0)
visible_message("\blue The [src] dissipates!")
del(src)
return
check_failure()
opacity = 1
spawn(20) if(src) opacity = 0
return
@@ -64,10 +70,7 @@
/obj/machinery/shield/bullet_act(var/obj/item/projectile/Proj)
health -= Proj.damage
..()
if(health <=0)
visible_message("\blue The [src] dissipates!")
del(src)
return
check_failure()
opacity = 1
spawn(20) if(src) opacity = 0
@@ -112,11 +115,7 @@
//This seemed to be the best sound for hitting a force field.
playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1)
//Handle the destruction of the shield
if (src.health <= 0)
visible_message("\blue The [src] dissipates!")
del(src)
return
check_failure()
//The shield becomes dense to absorb the blow.. purely asthetic.
opacity = 1
@@ -124,9 +123,6 @@
..()
return
/obj/machinery/shieldgen
name = "Emergency shield projector"
desc = "Used to seal minor hull breaches."
@@ -161,7 +157,7 @@
update_icon()
create_shields()
idle_power_usage = 0
for(var/obj/machinery/shield/shield_tile in deployed_shields)
idle_power_usage += shield_tile.shield_idle_power
@@ -174,7 +170,7 @@
update_icon()
collapse_shields()
update_use_power(0)
/obj/machinery/shieldgen/proc/create_shields()
@@ -201,22 +197,22 @@
/obj/machinery/shieldgen/process()
if (!active || (stat & NOPOWER))
return
if(malfunction)
if(deployed_shields.len && prob(5))
del(pick(deployed_shields))
else
if (check_delay <= 0)
create_shields()
var/new_power_usage = 0
for(var/obj/machinery/shield/shield_tile in deployed_shields)
new_power_usage += shield_tile.shield_idle_power
if (new_power_usage != idle_power_usage)
idle_power_usage = new_power_usage
use_power(0)
check_delay = 60
else
check_delay--