# Bodyzone Targeting Check Changes The way that bodyzone targeting is checked has changed. https://github.com/BeeStation/BeeStation-Hornet/pull/9845 Introduced a new mode for selecting bodyzone targeting and PRs using the old method for checking will now fail the checks. ## Methods added: `is_zone_selected`: Check if the user is targeting a specific area in **combat**, used for special after attack effects. `get_combat_bodyzone`: Gets the zone that the user is targeting in **combat**, used for non-special attacks such as melee attacks or gun zones. `select_bodyzone`: Gets the limb that the user wants to target in **non-combat** contexts. ## Checking if a user has a certain bodyzone selected **Usage** - Use for combat actions (baton attacks), or actions where the outcome is the same regardless of limbs (injections). **Function** - Simplified: `get_combat_bodyzone` will determine which limb to attack based on context. `is_zone_selected` will return true if the user is targeting a body group that contains the requested zone. - Standard: `get_combat_bodyzone` will return the limb that the user has selected. `is_zone_selected` will return true if the user is targeting the requested zone. **Example** A police baton that performs different actions depending on the group hit: ``` if(M.is_zone_selected(BODY_ZONE_CHEST)) chest_action() else if(M.is_zone_selected(BODY_ZONE_HEAD)) head_action() else if((M.is_zone_selected(BODY_ZONE_L_ARM)) || (M.is_zone_selected(BODY_ZONE_R_ARM))) arm_action() else if(M.is_zone_selected(BODY_ZONE_PRECISE_GROIN, precise_only = TRUE)) groin_action() ``` In this example, users on the simplified targeting mode will be unable to access the `head_action()` because the head and chest are in a single bodygroup, meaning that the first conditional will always pass first. **Make sure that if this is the case, the impossible action is not an important function and provides flavour only.** Simplified targeting users will also be unable to access `groin_action` as precise_only has been set to true. When this variable is true, only traditional bodyzone targeting will be able to pass that check. **Also only use this for flavour.** Determining which limb should be hit by an attack: ``` var/combat_zone = user.get_combat_bodyzone(target, precise = FALSE, zone_context = BODYZONE_CONTEXT_COMBAT) if (combat_zone == BODY_ZONE_L_ARM) attack_left_arm() ``` Get combat bodyzone returns the zone that the user should target. The second parameter (`precise`) determines if precise limbs should be allowed. This only affects traditional bodyzone targeting, and users on simplified targeting will never return a precise zone (mouth, eyes or groin). The third parameter (`zone_context`) determines how simplified targeting should determine which bodyzone should be targeted. There are 3 options: `BODYZONE_CONTEXT_COMBAT`: Prioritise arms in the group that the user is actively using or pick randomly if not targeting the arms, use for combat. `BODYZONE_CONTEXT_INJECTION`: Prioritise limbs in the group that are not protected by anti-injection clothing. `BODYZONE_CONTEXT_ROBOTIC_LIMB_HEALING`: Prioritise robotic limbs that have non-zero amounts of damage. **Note** - Be careful if you have different actions for 2 limbs that are in the same group, as `is_zone_selected` may return true for both of them (Eyes and mouth, for example). ## Requesting the selected zone from a user **Usage** - Use for non-combat actions such as applying chemical patches to a specific bodypart. **Function** - Simplified: A wheel will be displayed to the user which allows them to select the area of the body that they want to target. - Standard: The user's selected zone will be used to determine which bodypart they want to target. **Example** A basic example, allowing the user to select any bodyparts. ``` var/datum/task/select_bodyzone_task = user.select_bodyzone(M, FALSE, BODYZONE_STYLE_MEDICAL) select_bodyzone_task.continue_with(CALLBACK(src, PROC_REF(perform_action_on_bodypart), M, user)) ``` The select_bodyzone function returns a task, which can be assigned a callback to continue with. This continuation callback has the parameters: ``` /example/proc/perform_action_on_bodypart(mob/living/M, mob/user, zone_selected) ``` The third parameter (`BODYZONE_STYLE_MEDICAL`) describes the context of the interaction. `BODYZONE_STYLE_DEFAULT` will display the bodyzone wheel as normal, while `BODYZONE_STYLE_MEDICAL` will colour the bodyparts according to their health, which is useful for interactions that involve healing. The second parameter is precise. If you set this to true, then the user can select specific areas such as eyes, groin or mouth. If you only want to allow specific bodyzones to be selectable, then you may pass in an override_zones parameter. ``` var/datum/task/select_bodyzone = user.select_bodyzone(M, TRUE, BODYZONE_STYLE_DEFAULT, override_zones = list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH)) select_bodyzone.continue_with(CALLBACK(src, PROC_REF(razor_action), H, user, mirror)) ``` It is important to note that the zone_selected passed to the continue_with function might not be in the list of selectable zones as the default bodyzone targeting preference will instantly return whatever zone the user has selected regardless of acceptability.