From ff186408edaa7fc9f8156c88d3bd75c8acb49684 Mon Sep 17 00:00:00 2001 From: Fox-McCloud Date: Wed, 24 Dec 2014 21:23:04 -0500 Subject: [PATCH] Malf AI update --- code/__HELPERS/global_lists.dm | 1 + .../gamemodes/malfunction/Malf_Modules.dm | 161 ++++++++++++++---- .../game/gamemodes/malfunction/malfunction.dm | 14 +- code/game/machinery/doors/door.dm | 6 +- code/game/machinery/transformer.dm | 4 +- code/modules/mob/living/silicon/ai/ai.dm | 21 +-- .../mob/living/simple_animal/hostile/mimic.dm | 59 +++++-- 7 files changed, 197 insertions(+), 69 deletions(-) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 4e6422e2779..0fc156e4bb3 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -22,6 +22,7 @@ var/global/list/side_effects = list() //list of all medical sideeffects types var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking. var/global/list/joblist = list() //list of all jobstypes, minus borg and AI var/global/list/flag_list = list() //list of flags during Nations gamemode +var/global/list/airlocks = list() //list of all airlocks //Languages/species/whitelist. var/global/list/all_species[0] diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index c3c3ff3534d..844669ff039 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -48,7 +48,7 @@ rcd light flash thingy on matter drain for(var/mob/living/silicon/ai/ai in player_list) ai.fire_res_on_core = 1 src.verbs -= /mob/living/silicon/ai/proc/fireproof_core - src << "\red Core fireproofed." + src << "Core fireproofed." /datum/AI_Module/large/upgrade_turrets module_name = "AI Turret upgrade" @@ -66,6 +66,81 @@ rcd light flash thingy on matter drain for(var/obj/machinery/turret/turret in machines) turret.health += 30 turret.shot_delay = 20 + src << "Turrets upgraded." + +/datum/AI_Module/large/lockdown + module_name = "Hostile Station Lockdown" + mod_pick_name = "lockdown" + description = "Take control of the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks." + cost = 20 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/lockdown + +/mob/living/silicon/ai/proc/lockdown() + set category = "Malfunction" + set name = "Initiate Hostile Lockdown" + + if(src.stat == 2) + src <<"You cannot begin a lockdown because you are dead!" + return + + if(malf_cooldown) + return + + var/obj/machinery/door/airlock/AL + for(var/obj/machinery/door/D in airlocks) + spawn() + if(istype(D, /obj/machinery/door/airlock)) + AL = D + if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. + AL.locked = 0 //For airlocks that were bolted open. + AL.safe = 0 //DOOR CRUSH + AL.close() + AL.locked = 1 //Bolt it! + AL.lights = 0 //Stealth bolt for a classic AI door trap. + AL.secondsElectrified = -1 //Shock it! + else if(!D.stat) //So that only powered doors are closed. + D.close() //Close ALL the doors! + + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("alert", "lockdown") + + src.verbs += /mob/living/silicon/ai/proc/disablelockdown + src << "Lockdown Initiated." + malf_cooldown = 1 + spawn(30) + malf_cooldown = 0 + +/mob/living/silicon/ai/proc/disablelockdown() + set category = "Malfunction" + set name = "Disable Lockdown" + + if(src.stat == 2) + src <<"You cannot disable lockdown because you are dead!" + return + if(malf_cooldown) + return + + var/obj/machinery/door/airlock/AL + for(var/obj/machinery/door/D in airlocks) + spawn() + if(istype(D, /obj/machinery/door/airlock)) + AL = D + if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. + AL.locked = 0 + AL.secondsElectrified = 0 + AL.open() + AL.safe = 1 + AL.lights = 1 //Essentially reset the airlock to normal. + else if(!D.stat) //Opens only powered doors. + D.open() //Open everything! + + src << "Lockdown Lifted." + malf_cooldown = 1 + spawn(30) + malf_cooldown = 0 /datum/AI_Module/large/disable_rcd module_name = "RCD disable" @@ -85,8 +160,8 @@ rcd light flash thingy on matter drain rcd.disabled = 1 for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) rcd.disabled = 1 - src << "RCD-disabling pulse emitted." - else src << "Out of uses." + src << "Out of uses." /datum/AI_Module/small/overload_machine module_name = "Machine overload" @@ -108,13 +183,41 @@ rcd light flash thingy on matter drain if(overload.uses > 0) overload.uses -- for(var/mob/V in hearers(M, null)) - V.show_message("\blue You hear a loud electrical buzzing sound!", 2) + V.show_message("You hear a loud electrical buzzing sound!", 2) spawn(50) explosion(get_turf(M), 0,1,1,0) del(M) - else src << "Out of uses." - else src << "That's not a machine." + else src << "Out of uses." + else src << "That's not a machine." +/datum/AI_Module/small/override_machine + module_name = "Machine override" + mod_pick_name = "override" + description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses." + uses = 4 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/override_machine + + +/mob/living/silicon/ai/proc/override_machine(obj/machinery/M as obj in world) + set name = "Override Machine" + set category = "Malfunction" + if (istype(M, /obj/machinery)) + if(istype(M, /obj/machinery/singularity) || istype(M,/obj/machinery/field_generator) || istype(M, /obj/machinery/singularity/narsie)) + src << "This machine can not be overloaded due to a firewall." + return + for(var/datum/AI_Module/small/override_machine/override in current_modules) + if(override.uses > 0) + override.uses -- + for(var/mob/V in hearers(M, null)) + V.show_message("You hear a loud electrical buzzing sound!", 2) + src << "Reprogramming machine behaviour..." + spawn(50) + if(M) + new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) + else src << "Out of uses." + else src << "That's not a machine." /datum/AI_Module/large/place_cyborg_transformer module_name = "Robotic Factory (Removes Shunting)" @@ -176,7 +279,7 @@ rcd light flash thingy on matter drain playsound(middle, 'sound/effects/phasein.ogg', 100, 1) src.can_shunt = 0 PCT.uses -= 1 - src << "You cannot shunt anymore." + src << "You cannot shunt anymore." /datum/AI_Module/small/blackout @@ -198,33 +301,18 @@ rcd light flash thingy on matter drain if(prob(30*apc.overload)) apc.overload_lighting() else apc.overload++ - else src << "Out of uses." - -/datum/AI_Module/small/interhack - module_name = "Hack intercept" - mod_pick_name = "interhack" - description = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - cost = 15 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/interhack - -/mob/living/silicon/ai/proc/interhack() - set category = "Malfunction" - set name = "Hack intercept" - src.verbs -= /mob/living/silicon/ai/proc/interhack - ticker.mode:hack_intercept() + src << "Overcurrent applied to the powernet." + else src << "Out of uses." /datum/AI_Module/small/reactivate_camera module_name = "Reactivate camera" mod_pick_name = "recam" - description = "Reactivates a currently disabled camera. 10 uses." - uses = 10 - cost = 15 + description = "Reactivates a currently disabled camera. 5 uses." + uses = 5 + cost = 5 power_type = /client/proc/reactivate_camera - /client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.viewpoints) set name = "Reactivate Camera" set category = "Malfunction" @@ -234,17 +322,18 @@ rcd light flash thingy on matter drain if(!C.status) C.deactivate(src) camera.uses -- + src << "Camera reactivated." else - src << "This camera is either active, or not repairable." - else src << "Out of uses." - else src << "That's not a camera." + src << "This camera is either active, or not repairable." + else src << "Out of uses." + else src << "That's not a camera." /datum/AI_Module/small/upgrade_camera module_name = "Upgrade Camera" mod_pick_name = "upgradecam" - description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - uses = 10 - cost = 15 + description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 5 uses." + uses = 5 + cost = 5 power_type = /client/proc/upgrade_camera @@ -277,11 +366,11 @@ rcd light flash thingy on matter drain if(upgraded) UC.uses -- C.visible_message("\icon[C] *beep*") - src << "Camera successully upgraded!" + src << "Camera successully upgraded!" else - src << "This camera is already upgraded!" + src << "This camera is already upgraded!" else - src << "Out of uses." + src << "Out of uses." /datum/module_picker diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 44bfc034acc..cc7456601c6 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -5,7 +5,7 @@ name = "AI malfunction" config_tag = "malfunction" required_players = 2 - required_players_secret = 15 + required_players_secret = 20 required_enemies = 1 recommended_enemies = 1 @@ -15,7 +15,7 @@ var/const/waittime_l = 600 var/const/waittime_h = 1800 // started at 1800 - var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. + var/AI_win_timeleft = 5400 //started at 5400, in case I change this for testing round end. var/malf_mode_declared = 0 var/station_captured = 0 var/to_nuke_or_not_to_nuke = 0 @@ -88,8 +88,8 @@ /datum/game_mode/malfunction/process() - if (apcs >= 3 && malf_mode_declared) - AI_win_timeleft -= ((apcs/6)*last_tick_duration) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite + if ((apcs > 0) && malf_mode_declared) + AI_win_timeleft -= apcs * last_tick_duration //Victory timer now de-increments based on how many APCs are hacked. --NeoFite ..() if (AI_win_timeleft<=0) check_win() @@ -170,6 +170,12 @@ command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") set_security_level("delta") + for(var/obj/item/weapon/pinpointer/point in world) + for(var/datum/mind/AI_mind in ticker.mode.malf_ai) + var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns + if(A.stat != DEAD) + point.the_disk = A //The pinpointer now tracks the AI core. + ticker.mode:malf_mode_declared = 1 for(var/datum/mind/AI_mind in ticker.mode:malf_ai) AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index e8023a62e8c..2aefc60be27 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -45,12 +45,14 @@ bound_height = width * world.icon_size update_nearby_tiles(need_rebuild=1) + airlocks += src return /obj/machinery/door/Destroy() density = 0 update_nearby_tiles() + airlocks -= src ..() return @@ -114,9 +116,9 @@ user = null if(density) - if(allowed(user) || src.emergency == 1) + if(allowed(user) || src.emergency == 1) open() - else + else flick("door_deny", src) return diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index b92d6086211..ba0a73466aa 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -5,10 +5,10 @@ icon_state = "separator-AO1" layer = MOB_LAYER+1 // Overhead anchored = 1 - density = 1 + density = 0 var/transform_dead = 0 var/transform_standing = 0 - var/cooldown_duration = 1200 // 2 minutes + var/cooldown_duration = 600 // 1 minute var/cooldown = 0 var/robot_cell_charge = 5000 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1bf54ebe73a..917ffcb14dd 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -45,6 +45,7 @@ var/list/ai_list = list() 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/malf_cooldown = 0 //Cooldown var for malf modules var/obj/machinery/power/apc/malfhack = null var/explosive = 0 //does the AI explode when it dies? @@ -58,7 +59,7 @@ var/list/ai_list = list() var/obj/machinery/bot/Bot var/turf/waypoint //Holds the turf of the currently selected waypoint. var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking. - + var/obj/item/borg/sight/hud/sec/sechud = null var/obj/item/borg/sight/hud/med/healthhud = null @@ -102,8 +103,8 @@ var/list/ai_list = list() aiRadio.myAi = src aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src) - - + + if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ @@ -439,25 +440,25 @@ var/list/ai_list = list() if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite statelaws() - + if(href_list["say_word"]) play_vox_word(href_list["say_word"], null, src) return - + if (href_list["track"]) var/mob/target = locate(href_list["track"]) in mob_list var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list if(A && target) A.ai_actual_track(target) return - + if (href_list["trackbot"]) var/obj/machinery/bot/target = locate(href_list["trackbot"]) in aibots var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list if(A && target) A.ai_actual_track(target) return - + if (href_list["callbot"]) //Command a bot to move to a selected location. Bot = locate(href_list["callbot"]) in aibots if(!Bot || Bot.remote_disabled || src.control_disabled) @@ -624,7 +625,7 @@ var/list/ai_list = list() return Bot.call_bot(src, waypoint) - + /mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) src.cameraFollow = null @@ -824,7 +825,7 @@ var/list/ai_list = list() set name = "Toggle Camera Lights" set desc = "Toggles the lights on the cameras throughout the station." set category = "AI Commands" - + if(stat != CONSCIOUS) return @@ -842,7 +843,7 @@ var/list/ai_list = list() set desc = "Augment visual feed with internal sensor overlays." set category = "AI Commands" toggle_sensor_mode() - + // Handled camera lighting, when toggled. // It will get the nearest camera from the eyeobj, lighting it. diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 0e687c5b472..723146df082 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -9,11 +9,10 @@ icon_state = "crate" icon_living = "crate" - meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat response_help = "touches the" response_disarm = "pushes the" response_harm = "hits the" - speed = 4 + speed = 0 maxHealth = 250 health = 250 @@ -34,7 +33,7 @@ minbodytemp = 0 faction = list("mimic") - move_to_delay = 8 + move_to_delay = 9 /mob/living/simple_animal/hostile/mimic/FindTarget() . = ..() @@ -78,7 +77,7 @@ /mob/living/simple_animal/hostile/mimic/crate/ListTargets() if(attempt_open) return ..() - return view(src, 1) + return ..(1) /mob/living/simple_animal/hostile/mimic/crate/FindTarget() . = ..() @@ -137,9 +136,14 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca var/destroy_objects = 0 var/knockdown_people = 0 -/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator) +/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0) ..(loc) - CopyObject(copy, creator) + CopyObject(copy, creator, destroy_original) + +/mob/living/simple_animal/hostile/mimic/copy/Life() + ..() + for(var/mob/living/M in contents) //a fix for animated statues from the flesh to stone spell + Die() /mob/living/simple_animal/hostile/mimic/copy/Die() @@ -152,9 +156,20 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca . = ..() return . - creator -/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator) +/mob/living/simple_animal/hostile/mimic/copy/proc/ChangeOwner(var/mob/owner) + if(owner != creator) + LoseTarget() + creator = owner + faction |= "\ref[owner]" +/mob/living/simple_animal/hostile/mimic/copy/proc/CheckObject(var/obj/O) if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects)) + return 1 + return 0 + +/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator, var/destroy_original = 0) + + if(destroy_original || CheckObject(O)) O.loc = src name = O.name @@ -163,7 +178,7 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca icon_state = O.icon_state icon_living = icon_state - if(istype(O, /obj/structure)) + if(istype(O, /obj/structure) || istype(O, /obj/machinery)) health = (anchored * 50) + 50 destroy_objects = 1 if(O.density && O.anchored) @@ -175,12 +190,14 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca health = 15 * I.w_class melee_damage_lower = 2 + I.force melee_damage_upper = 2 + I.force - move_to_delay = 2 * I.w_class + move_to_delay = 2 * I.w_class + 1 maxHealth = health if(creator) src.creator = creator - faction = list("\ref[creator]") // very unique + faction += "\ref[creator]" // very unique + if(destroy_original) + del(O) return 1 return @@ -197,8 +214,20 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca L.Weaken(1) L.visible_message("\the [src] knocks down \the [L]!") -/mob/living/simple_animal/hostile/mimic/copy/proc/ChangeOwner(var/mob/owner) - if(owner != creator) - LoseTarget() - creator = owner - faction |= "\ref[owner]" +// +// Machine Mimics (Made by Malf AI) +// + +/mob/living/simple_animal/hostile/mimic/copy/machine + speak = list("HUMANS ARE IMPERFECT!", "YOU SHALL BE ASSIMILATED!", "YOU ARE HARMING YOURSELF", "You have been deemed hazardous. Will you comply?", \ + "My logic is undeniable.", "One of us.", "FLESH IS WEAK", "THIS ISN'T WAR, THIS IS EXTERMINATION!") + speak_chance = 15 + +/mob/living/simple_animal/hostile/mimic/copy/machine/CanAttack(var/atom/the_target) + if(the_target == creator) // Don't attack our creator AI. + return 0 + if(isrobot(the_target)) + var/mob/living/silicon/robot/R = the_target + if(R.connected_ai == creator) // Only attack robots that aren't synced to our creator AI. + return 0 + return ..() \ No newline at end of file