mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 14:08:31 +01:00
Adds a syndicate AI card for nuke ops (#76546)
## About The Pull Request Adds a syndicate AI card for nuke ops. Costs 12 TC, can be refunded. Activating it in-hand opens up a ghost poll like normal reinforcements. ## Why It's Good For The Game > Adds a syndicate AI card for nuke ops. Costs 12 TC, can be refunded. Activating it in-hand opens up a ghost poll. It'll be fun to have a lil modsuit pal with you who can maybe help if you get stunned, in critical condition, or else. With an injector module they can even save your life, if it's loaded with medicine! Unless they can't actually inject, but oh well, out of scope. 12 TC seems fair to me, not so expensive that nobody's going to bother with something that's not really useful in the vast majority of circumstances, but not so cheap that everyone will get one. There are also doubtless a huge amount of gimmicks that savvy nukies can get up to, having a pocket AI. **Since this needs two players to be fully tested, I wasn't able to do so. Please testmerge this before merging so we can confirm it works ingame!** ## Changelog 🆑 add: Adds a syndicate AI card for nuke ops. Costs 12 TC, can be refunded. Activating it in-hand opens up a ghost poll like normal reinforcements. Base interaction range for syndicate AIs is one, which means they can handle electronics only in proximity. add: Adds a syndicate AI interaction range upgrade for nuke ops, costs 4 TC and can be applied onto a syndicate AI (inside any container) to increase its interaction range by two per. (Three purchases are recommended for seven tiles of range!) /🆑
This commit is contained in:
+11
-11
@@ -109,7 +109,7 @@
|
||||
CtrlShiftClick(user)
|
||||
|
||||
/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/living/silicon/robot/user) // Sets/Unsets Emergency Access Override Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlShiftClick(user)
|
||||
else
|
||||
..()
|
||||
@@ -118,7 +118,7 @@
|
||||
ShiftClick(user)
|
||||
|
||||
/obj/machinery/door/airlock/BorgShiftClick(mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AIShiftClick(user)
|
||||
else
|
||||
..()
|
||||
@@ -128,44 +128,44 @@
|
||||
CtrlClick(user)
|
||||
|
||||
/obj/machinery/door/airlock/BorgCtrlClick(mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/power/apc/BorgCtrlShiftClick(mob/living/silicon/robot/user)
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlShiftClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/power/apc/BorgShiftClick(mob/living/silicon/robot/user)
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AIShiftClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/power/apc/BorgAltClick(mob/living/silicon/robot/user)
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AIAltClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/power/apc/attack_robot_secondary(mob/living/silicon/user, list/modifiers)
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
return attack_ai_secondary(user, modifiers)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlClick(user)
|
||||
else
|
||||
..()
|
||||
@@ -175,13 +175,13 @@
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AIAltClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
|
||||
if(get_dist(src, user) <= user.interaction_range)
|
||||
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
|
||||
AIAltClick(user)
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -471,7 +471,7 @@
|
||||
|
||||
// Allows Silicons to disable thermal sensor
|
||||
/obj/machinery/firealarm/BorgCtrlClick(mob/living/silicon/robot/user)
|
||||
if(get_dist(src,user) <= user.interaction_range)
|
||||
if(get_dist(src,user) <= user.interaction_range && !(user.control_disabled))
|
||||
AICtrlClick(user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -18,6 +18,88 @@
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_CASTABLE_LOC, INNATE_TRAIT)
|
||||
|
||||
/obj/item/computer_disk/syndie_ai_upgrade
|
||||
name = "AI interaction range upgrade"
|
||||
desc = "A NT data chip containing information that a syndiCard AI can utilize to improve its wireless interfacing abilities. Simply slap it on top of an intelliCard, MODsuit, or AI core and watch it do its work! It's rumoured that there's something 'pretty awful' in it."
|
||||
icon = 'icons/obj/antags/syndicate_tools.dmi'
|
||||
icon_state = "something_awful"
|
||||
max_capacity = 1000
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/computer_disk/syndie_ai_upgrade/pre_attack(atom/A, mob/living/user, params)
|
||||
var/mob/living/silicon/ai/AI
|
||||
if(isAI(A))
|
||||
AI = A
|
||||
else
|
||||
AI = locate() in A
|
||||
if(!AI || AI.interaction_range == INFINITY)
|
||||
playsound(src,'sound/machines/buzz-sigh.ogg',50,FALSE)
|
||||
to_chat(user, span_notice("Error! Incompatible object!"))
|
||||
return ..()
|
||||
AI.interaction_range += 2
|
||||
if(AI.interaction_range > 7)
|
||||
AI.interaction_range = INFINITY
|
||||
playsound(src,'sound/machines/twobeep.ogg',50,FALSE)
|
||||
to_chat(user, span_notice("You insert [src] into [AI]'s compartment, and it beeps as it processes the data."))
|
||||
to_chat(AI, span_notice("You process [src], and find yourself able to manipulate electronics from up to [AI.interaction_range] meters!"))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/aicard/syndie
|
||||
name = "syndiCard"
|
||||
desc = "A storage device for AIs. Nanotrasen forgot to make the patent, so the Syndicate made their own version!"
|
||||
icon = 'icons/obj/aicards.dmi'
|
||||
icon_state = "syndicard"
|
||||
base_icon_state = "syndicard"
|
||||
item_flags = null
|
||||
force = 7
|
||||
|
||||
/obj/item/aicard/syndie/loaded
|
||||
var/being_or_was_used = FALSE
|
||||
|
||||
/obj/item/aicard/syndie/loaded/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
. += span_notice("This one has a little S.E.L.F. insignia on the back, and a label next to it that says 'Activate for one FREE aligned AI! Please attempt uplink reintegration or ask your employers for reimbursal if AI is unavailable or belligerent.")
|
||||
|
||||
/obj/item/aicard/syndie/loaded/attack_self(mob/user, modifiers)
|
||||
if(AI || being_or_was_used)
|
||||
return ..()
|
||||
being_or_was_used = TRUE
|
||||
to_chat(user, span_notice("Connecting to S.E.L.F. dispatch..."))
|
||||
being_or_was_used = procure_ai(user)
|
||||
|
||||
/obj/item/aicard/syndie/loaded/proc/procure_ai(mob/user)
|
||||
var/datum/antagonist/nukeop/creator_op = user.mind?.has_antag_datum(/datum/antagonist/nukeop,TRUE)
|
||||
if(!creator_op)
|
||||
return FALSE
|
||||
var/list/nuke_candidates = poll_ghost_candidates("Do you want to play as a syndicate artifical intelligence inside an intelliCard?", ROLE_OPERATIVE, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE)
|
||||
if(QDELETED(src))
|
||||
return FALSE
|
||||
if(!LAZYLEN(nuke_candidates))
|
||||
to_chat(user, span_warning("Unable to connect to S.E.L.F. dispatch. Please wait and try again later or use the intelliCard on your uplink to get your points refunded."))
|
||||
return FALSE
|
||||
// pick ghost, create AI and transfer
|
||||
var/mob/dead/observer/ghos = pick(nuke_candidates)
|
||||
var/mob/living/silicon/ai/weak_syndie/new_ai = new /mob/living/silicon/ai/weak_syndie(get_turf(src), null, ghos) // wow so cool i love how laws go before the mob to insert for no reason this definitely didnt delay this pr for weeks
|
||||
new_ai.key = ghos.key
|
||||
// create and apply syndie datum
|
||||
var/datum/antagonist/nukeop/nuke_datum = new()
|
||||
nuke_datum.send_to_spawnpoint = FALSE
|
||||
new_ai.mind.add_antag_datum(nuke_datum, creator_op.nuke_team)
|
||||
new_ai.mind.special_role = "Syndicate AI"
|
||||
new_ai.faction |= ROLE_SYNDICATE
|
||||
// Make it look evil!!!
|
||||
new_ai.hologram_appearance = mutable_appearance('icons/mob/silicon/ai.dmi',"xeno_queen") //good enough
|
||||
new_ai.icon_state = resolve_ai_icon("hades") // evli
|
||||
pre_attack(new_ai, user) // i love shitcode!
|
||||
AI.control_disabled = FALSE // re-enable wireless activity
|
||||
AI.radio_enabled = TRUE // ditto
|
||||
var/obj/structure/ai_core/deactivated/detritus = locate() in get_turf(src)
|
||||
qdel(detritus)
|
||||
do_sparks(4, TRUE, src)
|
||||
playsound(src, 'sound/machines/chime.ogg', 25, TRUE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/aicard/Destroy(force)
|
||||
if(AI)
|
||||
AI.ghostize(can_reenter_corpse = FALSE)
|
||||
@@ -142,10 +224,6 @@
|
||||
. = TRUE
|
||||
if("wireless")
|
||||
AI.control_disabled = !AI.control_disabled
|
||||
if(!AI.control_disabled)
|
||||
AI.interaction_range = INFINITY
|
||||
else
|
||||
AI.interaction_range = 0
|
||||
to_chat(AI, span_warning("[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!"))
|
||||
. = TRUE
|
||||
if("radio")
|
||||
|
||||
@@ -190,5 +190,13 @@
|
||||
/obj/item/encryptionkey/ai //ported from NT, this goes 'inside' the AI.
|
||||
channels = list(RADIO_CHANNEL_COMMAND = 1, RADIO_CHANNEL_SECURITY = 1, RADIO_CHANNEL_ENGINEERING = 1, RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_MEDICAL = 1, RADIO_CHANNEL_SUPPLY = 1, RADIO_CHANNEL_SERVICE = 1, RADIO_CHANNEL_AI_PRIVATE = 1)
|
||||
|
||||
/obj/item/encryptionkey/ai/evil //ported from NT, this goes 'inside' the AI.
|
||||
name = "syndicate binary encryption key"
|
||||
icon_state = "cypherkey_syndicate"
|
||||
channels = list(RADIO_CHANNEL_SYNDICATE = 1)
|
||||
syndie = TRUE
|
||||
greyscale_config = /datum/greyscale_config/encryptionkey_syndicate
|
||||
greyscale_colors = "#171717#990000"
|
||||
|
||||
/obj/item/encryptionkey/secbot
|
||||
channels = list(RADIO_CHANNEL_AI_PRIVATE = 1, RADIO_CHANNEL_SECURITY = 1)
|
||||
|
||||
@@ -356,6 +356,15 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
keyslot2 = new /obj/item/encryptionkey/ai
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/silicon/ai/evil
|
||||
name = "\proper Evil Integrated Subspace Transceiver "
|
||||
keyslot2 = new /obj/item/encryptionkey/ai/evil
|
||||
command = FALSE
|
||||
|
||||
/obj/item/radio/headset/silicon/ai/evil/Initialize(mapload)
|
||||
. = ..()
|
||||
make_syndie()
|
||||
|
||||
/obj/item/radio/headset/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
user.set_machine(src)
|
||||
if(keyslot || keyslot2)
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
var/can_dominate_mechs = FALSE
|
||||
var/shunted = FALSE //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead
|
||||
var/obj/machinery/ai_voicechanger/ai_voicechanger = null // reference to machine that holds the voicechanger
|
||||
var/control_disabled = FALSE // Set to 1 to stop AI from interacting via Click()
|
||||
var/malfhacking = FALSE // 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, stores a worldtime + cooldown
|
||||
|
||||
@@ -79,7 +78,7 @@
|
||||
var/mob/camera/ai_eye/eyeobj
|
||||
var/sprint = 10
|
||||
var/cooldown = 0
|
||||
var/acceleration = 1
|
||||
var/acceleration = TRUE
|
||||
|
||||
var/obj/structure/ai_core/deactivated/linked_core //For exosuit control
|
||||
var/mob/living/silicon/robot/deployed_shell = null //For shell control
|
||||
@@ -200,6 +199,16 @@
|
||||
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
|
||||
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, PROC_REF(alarm_cleared))
|
||||
|
||||
/mob/living/silicon/ai/weak_syndie
|
||||
radio = /obj/item/radio/headset/silicon/ai/evil
|
||||
radio_enabled = TRUE
|
||||
interaction_range = 1
|
||||
sprint = 5
|
||||
|
||||
/mob/living/silicon/ai/weak_syndie/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
. = ..()
|
||||
laws = new /datum/ai_laws/syndicate_override
|
||||
|
||||
/mob/living/silicon/ai/key_down(_key, client/user)
|
||||
if(findtext(_key, "numpad")) //if it's a numpad number, we can convert it to just the number
|
||||
_key = _key[7] //strings, lists, same thing really
|
||||
@@ -870,7 +879,6 @@
|
||||
new_core.circuit.battery = battery
|
||||
ai_restore_power()//So the AI initially has power.
|
||||
control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
|
||||
interaction_range = 0
|
||||
radio_enabled = FALSE //No talking on the built-in radio for you either!
|
||||
forceMove(card)
|
||||
card.AI = src
|
||||
@@ -990,7 +998,7 @@
|
||||
update_sight()
|
||||
if(client.eye != src)
|
||||
var/atom/AT = client.eye
|
||||
AT.get_remote_view_fullscreens(src)
|
||||
AT?.get_remote_view_fullscreens(src)
|
||||
else
|
||||
clear_fullscreen("remote_view", 0)
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
var/emagged = FALSE
|
||||
var/hack_software = FALSE //Will be able to use hacking actions
|
||||
interaction_range = 7 //wireless control range
|
||||
var/control_disabled = FALSE // Set to 1 to stop AI from interacting via Click()
|
||||
|
||||
var/obj/item/modular_computer/pda/silicon/modularInterface
|
||||
|
||||
|
||||
@@ -597,6 +597,24 @@
|
||||
cost = 2
|
||||
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
|
||||
|
||||
/datum/uplink_item/suits/syndi_intellicard
|
||||
name = "Pre-Loaded Syndicate Intellicard"
|
||||
desc = "A syndicate intellicard that can be activated to download a captured Nanotrasen AI, modified with the standard syndicate lawset. You can slot it into your modsuit for a conversational partner! It can additionally control the MODsuit's modules at will, and move your body around even if you're in critical condition or dead. \
|
||||
However, due to failsafes activated during the extraction process, the AI is unable to interact with electronics from anywhere but direct proximity..."
|
||||
item = /obj/item/aicard/syndie/loaded
|
||||
cost = 12
|
||||
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
|
||||
refundable = TRUE
|
||||
|
||||
/datum/uplink_item/suits/synd_ai_upgrade
|
||||
name = "Syndicate AI Upgrade"
|
||||
desc = "...unless you buy the Syndicate Upgrade! This data chip allows the captured AI to increase its interaction range by two tiles per application. The Syndicate recommends three or four purchases at most, for a total of seven or infinite meters of range."
|
||||
item = /obj/item/computer_disk/syndie_ai_upgrade
|
||||
cost = 4
|
||||
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
|
||||
cant_discount = TRUE
|
||||
refundable = TRUE
|
||||
|
||||
// Devices
|
||||
|
||||
/datum/uplink_item/device_tools/assault_pod
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.5 KiB |
Reference in New Issue
Block a user