From 0e05f1ab15a6abb27139943a3fbc5ec7c19b2011 Mon Sep 17 00:00:00 2001 From: Qustinnus Date: Tue, 9 Mar 2021 01:18:27 +0100 Subject: [PATCH] Gives robot tourists a self defense course (#57506) Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com> Co-authored-by: coiax Co-authored-by: ATH1909 <42606352+ATH1909@users.noreply.github.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> --- code/__DEFINES/ai.dm | 2 +- code/datums/ai/generic_actions.dm | 39 +++++++++++ .../robot_customer_behaviors.dm | 4 ++ .../robot_customer_controller.dm | 69 ++++++++++++++++++- .../food_and_drinks/restaurant/_venue.dm | 2 + .../restaurant/customers/_customer.dm | 33 +++++++++ .../simple_animal/friendly/robot_customer.dm | 6 +- 7 files changed, 148 insertions(+), 7 deletions(-) diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index b1bae99bd21..aef18878bf9 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -68,7 +68,7 @@ #define BB_CUSTOMER_EATING "BB_customer_eating" #define BB_CUSTOMER_ATTENDING_VENUE "BB_customer_attending_avenue" #define BB_CUSTOMER_LEAVING "BB_customer_leaving" - +#define BB_CUSTOMER_CURRENT_TARGET "BB_customer_current_target" ///Dog AI controller blackboard keys diff --git a/code/datums/ai/generic_actions.dm b/code/datums/ai/generic_actions.dm index 99b75ae230a..d148a1578bd 100644 --- a/code/datums/ai/generic_actions.dm +++ b/code/datums/ai/generic_actions.dm @@ -22,3 +22,42 @@ /datum/ai_behavior/move_to_target/perform(delta_time, datum/ai_controller/controller) . = ..() finish_action(controller, TRUE) + + +/datum/ai_behavior/break_spine + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT + action_cooldown = 0.7 SECONDS + var/target_key + var/give_up_distance = 10 + + +/datum/ai_behavior/break_spine/perform(delta_time, datum/ai_controller/controller) + var/mob/living/batman = controller.blackboard[target_key] + var/mob/living/big_guy = controller.pawn //he was molded by the darkness + + if(batman.stat) + finish_action(controller, TRUE) + + if(get_dist(batman, big_guy) >= give_up_distance) + finish_action(controller, FALSE) + + big_guy.start_pulling(batman) + big_guy.setDir(get_dir(big_guy, batman)) + + batman.visible_message("[batman] gets a slightly too tight hug from [big_guy]!", "You feel your body break as [big_guy] embraces you!") + + if(iscarbon(batman)) + var/mob/living/carbon/carbon_batman = batman + for(var/obj/item/bodypart/bodypart_to_break in carbon_batman.bodyparts) + if(bodypart_to_break.body_zone == BODY_ZONE_HEAD) + continue + bodypart_to_break.receive_damage(brute = 15, wound_bonus = 35) + else + batman.adjustBruteLoss(150) + + finish_action(controller, TRUE) + +/datum/ai_behavior/break_spine/finish_action(datum/ai_controller/controller, succeeded) + if(succeeded) + controller.blackboard[target_key] = null + return ..() diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm index be4e2c04e68..ebdcda97e4b 100644 --- a/code/datums/ai/robot_customer/robot_customer_behaviors.dm +++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm @@ -110,3 +110,7 @@ . = ..() qdel(controller.pawn) //save the world, my final message, goodbye. finish_action(controller, TRUE) + + +/datum/ai_behavior/break_spine/robot_customer + target_key = BB_CUSTOMER_CURRENT_TARGET diff --git a/code/datums/ai/robot_customer/robot_customer_controller.dm b/code/datums/ai/robot_customer/robot_customer_controller.dm index 7f17974c171..7050cae9ec3 100644 --- a/code/datums/ai/robot_customer/robot_customer_controller.dm +++ b/code/datums/ai/robot_customer/robot_customer_controller.dm @@ -1,6 +1,6 @@ /datum/ai_controller/robot_customer ai_movement = /datum/ai_movement/basic_avoidance - movement_delay = 1 SECONDS + movement_delay = 0.8 SECONDS blackboard = list(BB_CUSTOMER_CURRENT_ORDER = null, BB_CUSTOMER_MY_SEAT = null, BB_CUSTOMER_PATIENCE = 999, @@ -14,10 +14,12 @@ if(!istype(new_pawn, /mob/living/simple_animal/robot_customer)) return AI_CONTROLLER_INCOMPATIBLE RegisterSignal(new_pawn, COMSIG_PARENT_ATTACKBY, .proc/on_attackby) + RegisterSignal(new_pawn, COMSIG_LIVING_GET_PULLED, .proc/on_get_pulled) + RegisterSignal(new_pawn, COMSIG_ATOM_ATTACK_HAND, .proc/on_get_punched) return ..() //Run parent at end /datum/ai_controller/robot_customer/UnpossessPawn(destroy) - UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY)) + UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY, COMSIG_LIVING_GET_PULLED, COMSIG_ATOM_ATTACK_HAND)) return ..() //Run parent at end /datum/ai_controller/robot_customer/SelectBehaviors(delta_time) @@ -28,6 +30,11 @@ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/leave_venue) return + if(blackboard[BB_CUSTOMER_CURRENT_TARGET]) + current_movement_target = blackboard[BB_CUSTOMER_CURRENT_TARGET] + current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/break_spine/robot_customer) + return + var/obj/my_seat = blackboard[BB_CUSTOMER_MY_SEAT] if(!my_seat) //We havn't got a seat yet! find one! @@ -43,13 +50,15 @@ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/wait_for_food) -/datum/ai_controller/robot_customer/proc/on_attackby(datum/source, obj/item/I, mob/user) +/datum/ai_controller/robot_customer/proc/on_attackby(datum/source, obj/item/I, mob/living/user) SIGNAL_HANDLER var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] if(attending_venue.is_correct_order(I, blackboard[BB_CUSTOMER_CURRENT_ORDER])) to_chat(user, "You hand [I] to [pawn]") eat_order(I, attending_venue) return COMPONENT_NO_AFTERATTACK + else + INVOKE_ASYNC(src, .proc/warn_greytider, user) /datum/ai_controller/robot_customer/proc/eat_order(obj/item/order_item, datum/venue/attending_venue) @@ -58,3 +67,57 @@ attending_venue.on_get_order(pawn, order_item) +///Called when +/datum/ai_controller/robot_customer/proc/on_get_pulled(datum/source, mob/living/puller) + SIGNAL_HANDLER + + + INVOKE_ASYNC(src, .proc/async_on_get_pulled, source, puller) + +/datum/ai_controller/robot_customer/proc/async_on_get_pulled(datum/source, mob/living/puller) + var/mob/living/simple_animal/robot_customer/customer = pawn + var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO] + var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] + + var/obj/item/card/id/used_id = puller.get_idcard(TRUE) + + if(used_id && (attending_venue.req_access in used_id?.GetAccess())) + customer.say(customer_data.friendly_pull_line) + return + warn_greytider(puller) + customer.resist() + + + + +/datum/ai_controller/robot_customer/proc/warn_greytider(mob/living/greytider) + var/mob/living/simple_animal/robot_customer/customer = pawn + var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] + var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO] + attending_venue.mob_blacklist[greytider] += 1 + + switch(attending_venue.mob_blacklist[greytider]) + if(1) + customer.say(customer_data.first_warning_line) + return + if(2) + customer.say(customer_data.second_warning_line) + return + if(3) + customer.say(customer_data.self_defense_line) + blackboard[BB_CUSTOMER_CURRENT_TARGET] = greytider + + CancelActions() + +/datum/ai_controller/robot_customer/proc/on_get_punched(datum/source, mob/living/living_hitter) + SIGNAL_HANDLER + + var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] + + var/obj/item/card/id/used_id = living_hitter.get_idcard(hand_first = TRUE) + + if(used_id && (attending_venue.req_access in used_id?.GetAccess())) + return + + if(living_hitter.combat_mode) + INVOKE_ASYNC(src, .proc/warn_greytider, living_hitter) diff --git a/code/modules/food_and_drinks/restaurant/_venue.dm b/code/modules/food_and_drinks/restaurant/_venue.dm index 690b9e0beaa..151c5892594 100644 --- a/code/modules/food_and_drinks/restaurant/_venue.dm +++ b/code/modules/food_and_drinks/restaurant/_venue.dm @@ -20,6 +20,8 @@ var/max_time_between_visitor = 90 SECONDS ///Required access to mess with the venue var/req_access = ACCESS_KITCHEN + ///Blacklist for idiots that attack bots. Key is the mob that did it, and the value is the amount of warnings they've received. + var/list/mob_blacklist = list() ///Seats linked to this venue, assoc list of key holosign of seat position, and value of robot assigned to it, if any. var/list/linked_seats = list() diff --git a/code/modules/food_and_drinks/restaurant/customers/_customer.dm b/code/modules/food_and_drinks/restaurant/customers/_customer.dm index 903d59df455..01474fe5c7a 100644 --- a/code/modules/food_and_drinks/restaurant/customers/_customer.dm +++ b/code/modules/food_and_drinks/restaurant/customers/_customer.dm @@ -19,6 +19,15 @@ var/list/leave_happy_lines = list("Leaving with food") ///Lines the robot says when leaving waiting for food var/list/wait_for_food_lines = list("I'm still waiting for food") + ///Line when pulled by a friendly venue owner + var/friendly_pull_line = "Where are we going?" + ///Line when harrased by someone for the first time + var/first_warning_line = "Don't touch me!" + ///Line when harrased by someone for the second time + var/second_warning_line = "This is your last warning!" + ///Line when harrased by someone for the last time + var/self_defense_line = "Omae wa mo, shinderou." + ///Clothing sets to pick from when dressing the robot. var/list/clothing_sets = list("amerifat_clothes") ///List of prefixes for our robots name @@ -49,6 +58,10 @@ leave_mad_lines = list("NO TIP FOR YOU. GOODBYE!", "At least at SpaceDonalds they serve their food FAST!", "This venue is horrendous!", "I will speak to your manager!", "I'll be sure to leave a bad Yelp review.") leave_happy_lines = list("An extra tip for you my friend.", "Thanks for the great food!", "Diabetes is a myth anyway!") wait_for_food_lines = list("Listen buddy, I'm getting real impatient over here!", "I've been waiting for ages...") + friendly_pull_line = "Where are you taking me? Not to medbay I hope, I don't have insurance." + first_warning_line = "Don't tread on me!" + second_warning_line = "Last chance buddy! Don't tread on me!" + self_defense_line = "CASTLE DOCTRINE ACTIVATED!" /datum/customer_data/italian @@ -62,6 +75,10 @@ leave_mad_lines = list("I have-a not seen-a this much disrespect in years!", "What-a horrendous establishment!") leave_happy_lines = list("That's amoreee!", "Just like momma used to make it!") wait_for_food_lines = list("I'ma so hungry...") + friendly_pull_line = "No-a I'm a hungry! I don't want to go anywhere." + first_warning_line = "Do not-a touch me!" + second_warning_line = "Last warning! Do not touch my spaghet." + self_defense_line = "I'm going to knead you like mama kneaded her delicious meatballs!" orderable_objects = list( /datum/venue/restaurant = list(/obj/item/food/spaghetti/pastatomato = 20, /obj/item/food/spaghetti/copypasta = 6, /obj/item/food/spaghetti/meatballspaghetti = 4, /obj/item/food/pizza/vegetable = 2, /obj/item/food/pizza/mushroom = 2, /obj/item/food/pizza/meat = 2, /obj/item/food/pizza/margherita = 2), /datum/venue/bar = list(/datum/reagent/consumable/ethanol/fanciulli = 5, /datum/reagent/consumable/ethanol/branca_menta = 3, /datum/reagent/consumable/ethanol/beer = 10, /datum/reagent/consumable/lemonade = 8, /datum/reagent/consumable/ethanol/godfather = 5)) @@ -77,6 +94,10 @@ leave_mad_lines = list("Sacre bleu!", "Merde! This place is shittier than the Rhine!") leave_happy_lines = list("Hon hon hon.", "A good effort.") wait_for_food_lines = list("Hon hon hon") + friendly_pull_line = "Your filthy hands on my outfit? Yegh, fine." + first_warning_line = "Get your hands off of me!" + second_warning_line = "Do not touch me you filthy animal, last warning!" + self_defense_line = "I will break you like a baguette!" speech_sound = 'sound/creatures/tourist/tourist_talk_french.ogg' orderable_objects = list( /datum/venue/restaurant = list(/obj/item/food/baguette = 20, /obj/item/food/garlicbread = 5, /obj/item/food/soup/onion = 4, /obj/item/food/pie/berryclafoutis = 2, /obj/item/food/omelette = 15), @@ -101,6 +122,10 @@ leave_mad_lines = list("I can't believe you did this! WAAAAAAAAAAAAAH!!", "I-It's not like I ever wanted your food! B-baka...", "I was gonna give you my tip!") leave_happy_lines = list("Oh NOURISHMENT PROVIDER! This is the happiest day of my life. I love you!", "I take a potato chip.... AND EAT IT!", "Itadakimasuuu~", "Gochisousama desu!") wait_for_food_lines = list("No food yet? I guess it can't be helped.", "I can't wait to finally meet you burger-sama...", "Give me my food, you meanie!") + friendly_pull_line = "O-oh, where are you taking me?" + first_warning_line = "Don't touch me you pervert!" + second_warning_line = "I'm going to go super saiyan if you touch me again! Last warning!" + self_defense_line = "OMAE WA MO, SHINDEROU!" speech_sound = 'sound/creatures/tourist/tourist_talk_japanese1.ogg' orderable_objects = list( /datum/venue/restaurant = list(/obj/item/food/tofu = 5, /obj/item/food/breadslice/plain = 5, /obj/item/food/soup/milo = 10, /obj/item/food/soup/vegetable = 4, /obj/item/food/sashimi = 4, /obj/item/food/chawanmushi = 4, /obj/item/food/muffin/berry = 2, /obj/item/food/beef_stroganoff = 2), @@ -121,6 +146,10 @@ leave_mad_lines = list("This place is just downright shameful, and I'm telling my coworkers.", "What a waste of my time.", "I hope you don't take pride in the operation you run here.") leave_happy_lines = list("Thank you for the hospitality.", "Otsukaresama deshita.", "Business calls.") wait_for_food_lines = list("Zzzzzzzzzz...", "Dame da ne~", "Dame yo dame na no yo~") + friendly_pull_line = "Are we going on a business trip?" + first_warning_line = "Hey, only my employer gets to mess with me like that." + second_warning_line = "Leave me be, I'm trying to focus. Last warning!" + self_defense_line = "I didn't want it to end up like this." speech_sound = 'sound/creatures/tourist/tourist_talk_japanese2.ogg' orderable_objects = list( /datum/venue/restaurant = list(/obj/item/food/tofu = 5, /obj/item/food/soup/milo = 6, /obj/item/food/soup/vegetable = 4, /obj/item/food/sashimi = 4, /obj/item/food/chawanmushi = 4, /obj/item/food/meatbun = 4, /obj/item/food/beef_stroganoff = 2), @@ -142,3 +171,7 @@ leave_mad_lines = list("Aye dios mio, I'm out of here.", "Esto es ridículo! I'm leaving!", "I've seen better cooking at taco campana!", "I though this was a restaurant, pero es porquería!") leave_happy_lines = list("Amigo, era delicio. Thank you!", "Yo tuve el mono, and you friend? You hit the spot.", "Just the right amount of spicy!") wait_for_food_lines = list("Ay ay ay, what's taking so long...", "Are you ready yet, amigo?") + friendly_pull_line = "Amigo, where are we headed?" + first_warning_line = "Amigo! Don't touch me like that." + second_warning_line = "Compadre, enough is enough! Last warning!" + self_defense_line = "Time for you to find out what kind of robot I am, eh?" diff --git a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm index 9363cb1d654..3185461c933 100644 --- a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm +++ b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm @@ -1,8 +1,8 @@ ///Robot customers /mob/living/simple_animal/robot_customer name = "space-tourist bot" - maxHealth = 1000 //go fuck yourself - health = 1000 + maxHealth = 150 + health = 150 desc = "I wonder what they'll order..." gender = NEUTER icon = 'icons/mob/tourists.dmi' @@ -25,6 +25,7 @@ /mob/living/simple_animal/robot_customer/Initialize(mapload, datum/customer_data/customer_data = /datum/customer_data/american, datum/venue/attending_venue = SSrestaurant.all_venues[/datum/venue/restaurant]) ADD_TRAIT(src, TRAIT_NOMOBSWAP, INNATE_TRAIT) //dont push me bitch ADD_TRAIT(src, TRAIT_NO_TELEPORT, INNATE_TRAIT) //dont teleport me bitch + ADD_TRAIT(src, TRAIT_STRONG_GRABBER, INNATE_TRAIT) //strong arms bitch AddComponent(/datum/component/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, vary = TRUE) var/datum/customer_data/customer_info = SSrestaurant.all_customers[customer_data] clothes_set = pick(customer_info.clothing_sets) @@ -84,4 +85,3 @@ if(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]) var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] . += "Their order was: \"[attending_venue.order_food_line(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER])].\"" -