mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 09:05:11 +01:00
7763db34a1
## About The Pull Request this PR refactors beepskies and ED209s into basic mobs. ive also added a few features for the ed209 because i cant keep my hands to myself: ED bots can now wear hats! a few hats give them some new unique dialogue. Putting a cowboy's hat on an ED will have it acting like a town Sherrif EDs are now rideable when emagged. theyll still be shooting people while ridden. youll also have the ability to charge at people full throttle running them over ive also added a new Nukie variant, purchasable from the uplink. These versions come fitted with an LMG and will patrol the station and shoot all walks of life. If emagged, theyll blow up people with (weaker) rockets (im still working on balancing this). they are rideable but i highly suggest against it; youll be caught in the crossfire. (i understand if ud prefer i atomize this feature) ## Why It's Good For The Game gives some personality to EDs, as well as updating all these bots to the cool new ai system ## Changelog 🆑 refactor: beepskies, and ed209s have been refactored. please report any bugs add: ed209s can now wear hats! some hats give them new dialogue add: emagged ed209s are now rideable! add: added evil versions of the ed209s to the syndie uplink /🆑 --------- Co-authored-by: san7890 <the@san7890.com>
264 lines
10 KiB
Plaintext
264 lines
10 KiB
Plaintext
/mob/living/basic/bot/secbot
|
|
name = "\improper Securitron"
|
|
desc = "A little security robot. He looks less than thrilled."
|
|
icon = 'icons/mob/silicon/aibots.dmi'
|
|
icon_state = "secbot"
|
|
base_icon_state = "secbot"
|
|
light_color = "#f56275"
|
|
light_power = 0.8
|
|
gender = MALE
|
|
density = FALSE
|
|
anchored = FALSE
|
|
health = 25
|
|
maxHealth = 25
|
|
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, STAMINA = 0, OXY = 0)
|
|
pass_flags = PASSMOB | PASSFLAPS
|
|
combat_mode = TRUE
|
|
can_buckle_to = FALSE
|
|
|
|
req_one_access = list(ACCESS_SECURITY)
|
|
radio_key = /obj/item/encryptionkey/secbot //AI Priv + Security
|
|
radio_channel = RADIO_CHANNEL_SECURITY //Security channel
|
|
bot_type = SEC_BOT
|
|
bot_mode_flags = ~BOT_MODE_CAN_BE_SAPIENT
|
|
data_hud_type = TRAIT_SECURITY_HUD
|
|
hackables = "target identification systems"
|
|
path_image_color = COLOR_RED
|
|
possessed_message = "You are a securitron! Guard the station to the best of your ability!"
|
|
additional_access = /datum/id_trim/job/detective
|
|
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.2, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 3.2)
|
|
ai_controller = /datum/ai_controller/basic_controller/bot/secbot
|
|
///Whether this secbot is considered 'commissioned' and given the trait on Initialize.
|
|
var/commissioned = FALSE
|
|
///The type of baton this Secbot will use
|
|
var/baton_type = /obj/item/melee/baton/security
|
|
///The weapon (from baton_type) that will be used to make arrests.
|
|
var/obj/item/weapon
|
|
///The threat level of the BOT, will arrest anyone at threatlevel 4 or above
|
|
var/threatlevel = 0
|
|
|
|
///Flags SecBOTs use on what to check on targets when arresting, and whether they should announce it to security/handcuff their target
|
|
/// Look at the security_mode_flags bitfield for more information on what's togglable here.
|
|
var/security_mode_flags = SECBOT_DECLARE_ARRESTS | SECBOT_CHECK_RECORDS | SECBOT_HANDCUFF_TARGET
|
|
|
|
/// On arrest, charges the violator this much.
|
|
/// If they don't have that much in their account, they will get beaten instead
|
|
var/price_arrest = 0
|
|
/// Charged each time the violator is stunned on detain
|
|
var/price_detain = 0
|
|
///The department the secbot will deposit collected money into
|
|
var/payment_department = ACCOUNT_SEC
|
|
///what sound we play when stunning
|
|
var/stun_sound = 'sound/items/weapons/egloves.ogg'
|
|
///The type of cuffs we use on criminals after making arrests
|
|
var/cuff_type = /obj/item/restraints/handcuffs/cable/zipties/used
|
|
|
|
/mob/living/basic/bot/secbot/Initialize(mapload)
|
|
. = ..()
|
|
weapon = new baton_type(src)
|
|
update_appearance(UPDATE_ICON)
|
|
if(commissioned)
|
|
ADD_TRAIT(src, TRAIT_COMMISSIONED, INNATE_TRAIT)
|
|
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
|
)
|
|
|
|
AddElement(/datum/element/connect_loc, loc_connections)
|
|
AddComponent(/datum/component/security_vision, judgement_criteria = NONE, update_judgement_criteria = CALLBACK(src, PROC_REF(judgement_criteria)))
|
|
add_arrest_component()
|
|
|
|
/mob/living/basic/bot/secbot/Destroy()
|
|
QDEL_NULL(weapon)
|
|
return ..()
|
|
|
|
/mob/living/basic/bot/secbot/update_icon_state()
|
|
if(mode == BOT_HUNT)
|
|
icon_state = "[base_icon_state]-c"
|
|
return ..()
|
|
|
|
/mob/living/basic/bot/secbot/turn_off()
|
|
..()
|
|
update_bot_mode(new_mode = BOT_IDLE)
|
|
|
|
/mob/living/basic/bot/secbot/on_saboteur(datum/source, disrupt_duration)
|
|
. = ..()
|
|
if(!(security_mode_flags & SECBOT_SABOTEUR_AFFECTED))
|
|
security_mode_flags |= SECBOT_SABOTEUR_AFFECTED
|
|
addtimer(CALLBACK(src, PROC_REF(remove_saboteur_effect)), disrupt_duration)
|
|
return TRUE
|
|
|
|
/mob/living/basic/bot/secbot/proc/remove_saboteur_effect()
|
|
security_mode_flags &= ~SECBOT_SABOTEUR_AFFECTED
|
|
|
|
/mob/living/basic/bot/secbot/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)//shocks only make him angry
|
|
if(speed >= initial(speed) + 3)
|
|
return
|
|
speed += 3
|
|
addtimer(VARSET_CALLBACK(src, speed, speed - 3), 6 SECONDS)
|
|
playsound(src, 'sound/machines/defib/defib_zap.ogg', 50)
|
|
visible_message(span_warning("[src] shakes and speeds up!"))
|
|
|
|
/mob/living/basic/bot/secbot/Exited(atom/movable/gone, direction)
|
|
. = ..()
|
|
if(gone == weapon)
|
|
weapon = null
|
|
update_appearance()
|
|
|
|
// Variables sent to TGUI
|
|
/mob/living/basic/bot/secbot/ui_data(mob/user)
|
|
var/list/data = ..()
|
|
if(!(bot_access_flags & BOT_COVER_LOCKED) || HAS_SILICON_ACCESS(user))
|
|
data["custom_controls"]["check_id"] = security_mode_flags & SECBOT_CHECK_IDS
|
|
data["custom_controls"]["check_weapons"] = security_mode_flags & SECBOT_CHECK_WEAPONS
|
|
data["custom_controls"]["check_warrants"] = security_mode_flags & SECBOT_CHECK_RECORDS
|
|
data["custom_controls"]["handcuff_targets"] = security_mode_flags & SECBOT_HANDCUFF_TARGET
|
|
data["custom_controls"]["arrest_alert"] = security_mode_flags & SECBOT_DECLARE_ARRESTS
|
|
return data
|
|
|
|
// Actions received from TGUI
|
|
/mob/living/basic/bot/secbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
var/mob/user = ui.user
|
|
if(. || (bot_access_flags & BOT_COVER_LOCKED && !HAS_SILICON_ACCESS(user)))
|
|
return
|
|
|
|
switch(action)
|
|
if("check_id")
|
|
security_mode_flags ^= SECBOT_CHECK_IDS
|
|
return TRUE
|
|
if("check_weapons")
|
|
security_mode_flags ^= SECBOT_CHECK_WEAPONS
|
|
return TRUE
|
|
if("check_warrants")
|
|
security_mode_flags ^= SECBOT_CHECK_RECORDS
|
|
return TRUE
|
|
if("handcuff_targets")
|
|
security_mode_flags ^= SECBOT_HANDCUFF_TARGET
|
|
return TRUE
|
|
if("arrest_alert")
|
|
security_mode_flags ^= SECBOT_DECLARE_ARRESTS
|
|
return TRUE
|
|
|
|
|
|
/mob/living/basic/bot/secbot/attack_hand(mob/living/carbon/human/user, list/modifiers)
|
|
|
|
// Turns an oversight into a feature. Beepsky will now announce when pacifists taunt him over sec comms.
|
|
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
|
user.visible_message(span_notice("[user] taunts [src], daring [p_them()] to give chase!"), \
|
|
span_notice("You taunt [src], daring [p_them()] to chase you!"), span_hear("You hear someone shout a daring taunt!"), DEFAULT_MESSAGE_RANGE, user)
|
|
speak("Taunted by pacifist scumbag [RUNECHAT_BOLD("[user]")] in [get_area(src)].", radio_channel)
|
|
|
|
// Interrupt the attack chain. We've already handled this scenario for pacifists.
|
|
return
|
|
|
|
return ..()
|
|
|
|
/mob/living/basic/bot/secbot/proc/retrieve_emag_message()
|
|
audible_message(span_danger("[src] buzzes oddly!"))
|
|
|
|
/mob/living/basic/bot/secbot/emag_act(mob/user, obj/item/card/emag/emag_card)
|
|
. = ..()
|
|
if(!(bot_access_flags & BOT_COVER_EMAGGED))
|
|
return
|
|
if(user)
|
|
balloon_alert(user, "target assessment circuits shorted")
|
|
|
|
retrieve_emag_message()
|
|
security_mode_flags &= ~SECBOT_DECLARE_ARRESTS
|
|
update_appearance()
|
|
return TRUE
|
|
|
|
/mob/living/basic/bot/secbot/proc/post_arrest(mob/living/carbon/current_target)
|
|
playsound(src, SFX_LAW, 50, FALSE)
|
|
|
|
/mob/living/basic/bot/secbot/proc/post_stun(mob/living/carbon/current_target, harm = FALSE)
|
|
flick("[base_icon_state]-c", src)
|
|
var/threat = 5 || ai_controller.blackboard[BB_CURRENT_CRIMINAL_ASSESSMENT]
|
|
if(security_mode_flags & SECBOT_DECLARE_ARRESTS)
|
|
var/area/location = get_area(src)
|
|
speak("[security_mode_flags & SECBOT_HANDCUFF_TARGET ? "Arresting" : "Detaining"] level [threat] scumbag [RUNECHAT_BOLD("[current_target]")] in [location].", radio_channel)
|
|
payment_check(current_target)
|
|
update_bot_mode(new_mode = BOT_PREP_ARREST)
|
|
|
|
/mob/living/basic/bot/secbot/explode()
|
|
var/atom/drop_location = drop_location()
|
|
retrieve_secbot_drops(drop_location)
|
|
new /obj/effect/decal/cleanable/blood/oil(loc)
|
|
return ..()
|
|
|
|
/mob/living/basic/bot/secbot/proc/retrieve_secbot_drops(atom/drop_location)
|
|
var/obj/item/bot_assembly/secbot/secbot_assembly = new(drop_location)
|
|
secbot_assembly.build_step = ASSEMBLY_FIRST_STEP
|
|
secbot_assembly.add_overlay("hs_hole")
|
|
secbot_assembly.created_name = name
|
|
new /obj/item/assembly/prox_sensor(drop_location)
|
|
drop_part(weapon, drop_location)
|
|
|
|
/mob/living/basic/bot/secbot/proc/on_entered(datum/source, atom/movable/to_be_tripped)
|
|
SIGNAL_HANDLER
|
|
var/mob/living/possible_target = ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]
|
|
if(!has_gravity() || !ismob(to_be_tripped) || !possible_target)
|
|
return
|
|
var/mob/living/carbon/tripped_mob = to_be_tripped
|
|
if(istype(tripped_mob) && !in_range(src, possible_target))
|
|
knockOver(tripped_mob)
|
|
|
|
/// Returns true if the current target is unable to pay to be detained/arrested
|
|
/mob/living/basic/bot/secbot/proc/payment_check(mob/living/carbon/human/human_target)
|
|
var/fair_market_price = (security_mode_flags & SECBOT_HANDCUFF_TARGET) ? price_arrest : price_detain
|
|
if(fair_market_price <= 0)
|
|
return FALSE
|
|
if(!ishuman(human_target))
|
|
return FALSE
|
|
var/obj/item/card/id/target_id = human_target.get_idcard()
|
|
if(!target_id)
|
|
say("Unable to pay fine: No ID card found.")
|
|
return TRUE
|
|
var/datum/bank_account/insurance = target_id.registered_account
|
|
if(!insurance)
|
|
say("Unable to pay fine: No bank account found.")
|
|
return TRUE
|
|
if(!insurance.adjust_money(-fair_market_price, "Securitron fine"))
|
|
say("Unable to pay fine: Not enough funds in account.")
|
|
return TRUE
|
|
|
|
SSeconomy.get_dep_account(payment_department)?.adjust_money(fair_market_price)
|
|
say("Fine paid: Thank you for your compliance. Your account been charged [fair_market_price] [MONEY_NAME].")
|
|
return FALSE
|
|
|
|
/mob/living/basic/bot/secbot/generate_speak_list()
|
|
var/static/list/secbot_lines = list(
|
|
BEEPSKY_VOICED_CRIMINAL_DETECTED = 'sound/mobs/non-humanoids/beepsky/criminal.ogg',
|
|
BEEPSKY_VOICED_FREEZE = 'sound/mobs/non-humanoids/beepsky/freeze.ogg',
|
|
BEEPSKY_VOICED_JUSTICE = 'sound/mobs/non-humanoids/beepsky/justice.ogg',
|
|
BEEPSKY_VOICED_YOUR_MOVE = 'sound/mobs/non-humanoids/beepsky/creep.ogg',
|
|
BEEPSKY_VOICED_I_AM_THE_LAW = 'sound/mobs/non-humanoids/beepsky/iamthelaw.ogg',
|
|
BEEPSKY_VOICED_SECURE_DAY = 'sound/mobs/non-humanoids/beepsky/secureday.ogg',
|
|
)
|
|
return secbot_lines
|
|
|
|
|
|
/mob/living/basic/bot/secbot/proc/judgement_criteria()
|
|
var/final = FALSE
|
|
if(bot_access_flags & BOT_COVER_EMAGGED)
|
|
final |= JUDGE_EMAGGED
|
|
if(security_mode_flags & SECBOT_CHECK_IDS)
|
|
final |= JUDGE_IDCHECK
|
|
if(security_mode_flags & SECBOT_CHECK_RECORDS)
|
|
final |= JUDGE_RECORDCHECK
|
|
if(security_mode_flags & SECBOT_CHECK_WEAPONS)
|
|
final |= JUDGE_WEAPONCHECK
|
|
if(security_mode_flags & SECBOT_SABOTEUR_AFFECTED)
|
|
final |= JUDGE_CHILLOUT
|
|
return final
|
|
|
|
/mob/living/basic/bot/secbot/proc/add_arrest_component()
|
|
AddComponent(/datum/component/stun_n_cuff,\
|
|
stun_sound = stun_sound,\
|
|
post_stun_callback = CALLBACK(src, PROC_REF(post_stun)),\
|
|
post_arrest_callback = CALLBACK(src, PROC_REF(post_arrest)),\
|
|
handcuff_type = cuff_type,\
|
|
)
|