diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 11ba7db35483..4d56058225f0 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -387,6 +387,16 @@ var/list/default_onmob_icons = list( WEAR_ACCESSORIES = 'icons/mob/humans/onmob/ties.dmi' ) +var/list/default_xeno_onmob_icons = list( + /mob/living/carbon/Xenomorph/Runner = 'icons/mob/xenos/onmob/runner.dmi', + /mob/living/carbon/Xenomorph/Praetorian = 'icons/mob/xenos/onmob/praetorian.dmi', + /mob/living/carbon/Xenomorph/Drone = 'icons/mob/xenos/onmob/drone.dmi', + /mob/living/carbon/Xenomorph/Warrior = 'icons/mob/xenos/onmob/warrior.dmi', + /mob/living/carbon/Xenomorph/Defender = 'icons/mob/xenos/onmob/defender.dmi', + /mob/living/carbon/Xenomorph/Sentinel = 'icons/mob/xenos/onmob/sentinel.dmi', + /mob/living/carbon/Xenomorph/Spitter = 'icons/mob/xenos/onmob/spitter.dmi' + ) + // species names #define SPECIES_HUMAN "Human" #define SPECIES_YAUTJA "Yautja" diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm index 52bbee8b9e61..2a0a33be14cf 100644 --- a/code/_onclick/adjacent.dm +++ b/code/_onclick/adjacent.dm @@ -100,7 +100,10 @@ Quick adjacency (to turf): if(recurse > 0) return loc.Adjacent(neighbor, recurse - 1) return FALSE + else if(isXeno(loc)) //Xenos don't count as storage depth. + return loc.Adjacent(neighbor, recurse) return ..() + /* Special case: This allows you to reach a door when it is visally on top of, but technically behind, a fire door diff --git a/code/_onclick/human.dm b/code/_onclick/human.dm index 27515a07e4a0..5d78f737902c 100644 --- a/code/_onclick/human.dm +++ b/code/_onclick/human.dm @@ -92,6 +92,36 @@ if(user != src) return . = ..() + if(isXeno(dropping)) + var/mob/living/carbon/Xenomorph/xeno = dropping + if(xeno.back) + var/obj/item/back_item = xeno.back + if(xeno.stat != DEAD) // If the Xeno is alive, fight back + var/mob/living/carbon/carbon_user = user + if(!carbon_user || !carbon_user.ally_of_hivenumber(xeno.hivenumber)) + user.KnockDown(rand(xeno.caste.tacklestrength_min, xeno.caste.tacklestrength_max)) + playsound(user.loc, 'sound/weapons/pierce.ogg', 25, TRUE) + user.visible_message(SPAN_WARNING("\The [user] tried to unstrap \the [back_item] from [xeno] but instead gets a tail swipe to the head!")) + return + if(user.get_active_hand()) + to_chat(user, SPAN_WARNING("You can't unstrap \the [back_item] from [xeno] with your hands full.")) + return + user.visible_message(SPAN_NOTICE("\The [user] starts unstrapping \the [back_item] from [xeno]"), \ + SPAN_NOTICE("You start unstrapping \the [back_item] from [xeno]."), null, 5, CHAT_TYPE_FLUFF_ACTION) + if(!do_after(user, HUMAN_STRIP_DELAY * user.get_skill_duration_multiplier(), INTERRUPT_ALL, BUSY_ICON_GENERIC, xeno, INTERRUPT_MOVED, BUSY_ICON_GENERIC)) + to_chat(user, SPAN_WARNING("You were interrupted!")) + return + + if(user.get_active_hand()) + return + if(!user.Adjacent(xeno)) + return + xeno.drop_inv_item_on_ground(back_item) + if(!back_item || QDELETED(back_item)) //Might be self-deleted? + return + user.put_in_active_hand(back_item) + return + if(pulling != dropping || grab_level != GRAB_AGGRESSIVE || !ishuman(dropping) || !(a_intent & INTENT_GRAB)) return . = ..() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 0f5bed2b5c26..ccf6badf019f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -97,7 +97,7 @@ var/mob/living/carbon/human/locked_to_mob = null // If the item uses flag MOB_LOCK_ON_PICKUP, this is the mob owner reference. - var/list/equip_sounds//Sounds played when this item is equipped + var/list/equip_sounds //Sounds played when this item is equipped var/list/unequip_sounds //Same but when unequipped ///Vision impairing effect if worn on head/mask/glasses. diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index f71a121164b5..01f27772932b 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -16,6 +16,8 @@ var/obj/item/card/id/locking_id = null var/is_id_lockable = FALSE var/lock_overridable = TRUE + var/xeno_icon_state = null //the icon_state for xeno's wearing this (using the dmi defined in default_xeno_onmob_icons list) + var/list/xeno_types = null //what xeno types can equip this backpack /obj/item/storage/backpack/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/card/id/) && is_id_lockable && ishuman(user)) @@ -27,6 +29,51 @@ if (..() && use_sound) playsound(loc, use_sound, 15, TRUE, 6) +/obj/item/storage/backpack/attack(mob/living/target_mob, mob/living/user) + if(!xeno_icon_state) + return ..() + if(target_mob.back) + return ..() + if(user.a_intent != INTENT_HELP) + return ..() + if(!xeno_types || !(target_mob.type in xeno_types)) + return ..() + if(!isXeno(target_mob)) + return ..() + if(HAS_TRAIT(target_mob, TRAIT_XENONID)) + return ..() // We don't have backpack sprites for xenoids (yet?) + var/mob/living/carbon/Xenomorph/xeno = target_mob + if(target_mob.stat != DEAD) // If the Xeno is alive, fight back + var/mob/living/carbon/carbon_user = user + if(!carbon_user || !carbon_user.ally_of_hivenumber(xeno.hivenumber)) + user.KnockDown(rand(xeno.caste.tacklestrength_min, xeno.caste.tacklestrength_max)) + playsound(user.loc, 'sound/weapons/pierce.ogg', 25, TRUE) + user.visible_message(SPAN_WARNING("\The [user] tried to strap \the [src] onto [target_mob] but instead gets a tail swipe to the head!")) + return FALSE + + user.visible_message(SPAN_NOTICE("\The [user] starts strapping \the [src] onto [target_mob]."), \ + SPAN_NOTICE("You start strapping \the [src] onto [target_mob]."), null, 5, CHAT_TYPE_FLUFF_ACTION) + if(!do_after(user, HUMAN_STRIP_DELAY * user.get_skill_duration_multiplier(), INTERRUPT_ALL, BUSY_ICON_GENERIC, target_mob, INTERRUPT_MOVED, BUSY_ICON_GENERIC)) + to_chat(user, SPAN_WARNING("You were interrupted!")) + return FALSE + + // Ensure conditions still valid + if(src != user.get_active_hand()) + return FALSE + if(!user.Adjacent(target_mob)) + return FALSE + user.drop_inv_item_on_ground(src) + if(!src || QDELETED(src)) //Might be self-deleted? + return FALSE + + // Create their vis object if needed + if(!xeno.backpack_icon_carrier) + xeno.backpack_icon_carrier = new(null, xeno) + xeno.vis_contents += xeno.backpack_icon_carrier + + target_mob.put_in_back(src) + return FALSE + /obj/item/storage/backpack/proc/toggle_lock(obj/item/card/id/card, mob/living/carbon/human/H) if(QDELETED(locking_id)) to_chat(H, SPAN_NOTICE("You lock \the [src]!")) @@ -48,6 +95,12 @@ storage_close(user) ..() +/obj/item/storage/unequipped(mob/user, slot, silent) + if(slot == WEAR_BACK) + if(use_sound && !silent) + playsound(loc, use_sound, 15, TRUE, 6) + ..() + /obj/item/storage/backpack/dropped(mob/user) mouse_opacity = initial(mouse_opacity) ..() @@ -312,18 +365,24 @@ obj/item/storage/backpack/proc/compare_id(var/mob/living/carbon/human/H) icon_state = "marinepack" item_state = "marinepack" has_gamemode_skin = TRUE //replace this with the atom_flag NO_SNOW_TYPE at some point, just rename it to like, NO_MAP_VARIANT_SKIN + xeno_icon_state = "marinepack" + xeno_types = list(/mob/living/carbon/Xenomorph/Runner, /mob/living/carbon/Xenomorph/Praetorian, /mob/living/carbon/Xenomorph/Drone, /mob/living/carbon/Xenomorph/Warrior, /mob/living/carbon/Xenomorph/Defender, /mob/living/carbon/Xenomorph/Sentinel, /mob/living/carbon/Xenomorph/Spitter) /obj/item/storage/backpack/marine/medic name = "\improper USCM corpsman backpack" desc = "A standard-issue backpack worn by USCM medics." icon_state = "marinepack_medic" item_state = "marinepack_medic" + xeno_icon_state = "medicpack" + xeno_types = list(/mob/living/carbon/Xenomorph/Runner, /mob/living/carbon/Xenomorph/Praetorian, /mob/living/carbon/Xenomorph/Drone, /mob/living/carbon/Xenomorph/Warrior, /mob/living/carbon/Xenomorph/Defender, /mob/living/carbon/Xenomorph/Sentinel, /mob/living/carbon/Xenomorph/Spitter) /obj/item/storage/backpack/marine/tech name = "\improper USCM technician backpack" desc = "A standard-issue backpack worn by USCM technicians." icon_state = "marinepack_techi" item_state = "marinepack_techi" + xeno_icon_state = "marinepack" + xeno_types = list(/mob/living/carbon/Xenomorph/Runner, /mob/living/carbon/Xenomorph/Praetorian, /mob/living/carbon/Xenomorph/Drone, /mob/living/carbon/Xenomorph/Warrior, /mob/living/carbon/Xenomorph/Defender, /mob/living/carbon/Xenomorph/Sentinel, /mob/living/carbon/Xenomorph/Spitter) /obj/item/storage/backpack/marine/satchel/intel name = "\improper USCM lightweight expedition pack" @@ -338,6 +397,7 @@ obj/item/storage/backpack/proc/compare_id(var/mob/living/carbon/human/H) worn_accessible = TRUE storage_slots = null max_storage_space = 15 + xeno_types = null /obj/item/storage/backpack/marine/satchel/big //wacky squad marine loadout item, its the IO backpack. name = "\improper USCM logistics IMP backpack" @@ -347,7 +407,6 @@ obj/item/storage/backpack/proc/compare_id(var/mob/living/carbon/human/H) storage_slots = null max_storage_space = 21 //backpack size - /obj/item/storage/backpack/marine/satchel/medic name = "\improper USCM corpsman satchel" desc = "A heavy-duty satchel used by USCM medics. It sacrifices capacity for usability. A small patch is sewn to the top flap." @@ -490,6 +549,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r desc = "A specially-designed smock with pockets for all your sniper needs." icon_state = "smock" worn_accessible = TRUE + xeno_types = null /obj/item/storage/backpack/marine/marsoc name = "\improper USCM SOF IMP tactical rucksack" @@ -497,6 +557,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r desc = "With a backpack like this, you'll forget you're on a hell march designed to kill you." worn_accessible = TRUE has_gamemode_skin = FALSE + xeno_types = null /obj/item/storage/backpack/marine/rocketpack name = "\improper USCM IMP M22 rocket bags" @@ -504,6 +565,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r icon_state = "rocketpack" worn_accessible = TRUE has_gamemode_skin = FALSE //monkeysfist101 never sprited a snowtype but included duplicate icons. Why?? Recolor and touch up sprite at a later date. + xeno_types = null /obj/item/storage/backpack/marine/grenadepack name = "\improper USCM IMP M63A1 grenade satchel" @@ -516,6 +578,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r can_hold = list(/obj/item/explosive/grenade) is_id_lockable = TRUE has_gamemode_skin = FALSE + xeno_types = null /obj/item/storage/backpack/marine/grenadepack/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/storage/box/nade_box) || istype(W, /obj/item/storage/backpack/marine/grenadepack) || istype(W, /obj/item/storage/belt/grenade)) @@ -530,6 +593,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r max_w_class = SIZE_HUGE storage_slots = 8 can_hold = list(/obj/item/mortar_shell) + xeno_types = null /// G-8-a general pouch belt /obj/item/storage/backpack/general_belt @@ -708,7 +772,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r max_storage_space = 18 storage_slots = null has_gamemode_skin = TRUE - + xeno_types = null /obj/item/storage/backpack/marine/engineerpack/Initialize() . = ..() diff --git a/code/game/objects/items/storage/smartpack.dm b/code/game/objects/items/storage/smartpack.dm index 64bc74e47758..040d078f2a37 100644 --- a/code/game/objects/items/storage/smartpack.dm +++ b/code/game/objects/items/storage/smartpack.dm @@ -12,6 +12,7 @@ max_storage_space = 14 worn_accessible = TRUE actions_types = list(/datum/action/item_action/toggle) + xeno_types = null var/show_exoskeleton = FALSE diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index f388b62852d8..4aac5c342e94 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -523,6 +523,16 @@ W is always an item. stop_warning prevents messaging. user may be null.**/ return attempt_item_insertion(W, FALSE, user) +/obj/item/storage/equipped(mob/user, slot, silent) + if ((storage_flags & STORAGE_ALLOW_EMPTY)) + if(!isXeno(user)) + verbs |= /obj/item/storage/verb/empty_verb + verbs |= /obj/item/storage/verb/toggle_click_empty + else + verbs -= /obj/item/storage/verb/empty_verb + verbs -= /obj/item/storage/verb/toggle_click_empty + ..() + /obj/item/storage/proc/attempt_item_insertion(obj/item/W as obj, prevent_warning = FALSE, mob/user as mob) if(!can_be_inserted(W)) return @@ -608,6 +618,61 @@ W is always an item. stop_warning prevents messaging. user may be null.**/ remove_from_storage(I, T) user.visible_message(SPAN_NOTICE("[user] empties \the [src]."), SPAN_NOTICE("You empty \the [src].")) + if (use_sound) + playsound(loc, use_sound, 25, TRUE, 3) + +/obj/item/storage/verb/shake_verb() + set name = "Shake" + set category = "Object" + set src in usr + var/mob/user_mob = usr + shake(user_mob, get_turf(user_mob)) + +/obj/item/storage/proc/shake(var/mob/user, var/turf/tile) + if(!(storage_flags & STORAGE_ALLOW_EMPTY)) + return + + if(user.l_hand != src && user.r_hand != src && user.back != src) + return + + if(user.is_mob_incapacitated()) + return + + if (!isturf(tile) || get_dist(src, tile) > 1) + tile = get_turf(src) + + if (use_sound) + playsound(loc, use_sound, 25, TRUE, 3) + + if(!length(contents)) + if(prob(25) && isXeno(user)) + user.drop_inv_item_to_loc(src, tile) + user.visible_message(SPAN_NOTICE("[user] shakes \the [src] off."), + SPAN_NOTICE("You shake \the [src] off.")) + else + user.visible_message(SPAN_NOTICE("[user] shakes \the [src] but nothing falls out."), + SPAN_NOTICE("You shake \the [src] but nothing falls out. It feels empty.")) + return + + if(!allowed(user)) + user.visible_message(SPAN_NOTICE("[user] shakes \the [src] but nothing falls out."), + SPAN_NOTICE("You shake \the [src] but nothing falls out. Access denied.")) + return + + if(!prob(75)) + user.visible_message(SPAN_NOTICE("[user] shakes \the [src] but nothing falls out."), + SPAN_NOTICE("You shake \the [src] but nothing falls out.")) + return + + storage_close(user) + var/obj/item/item_obj + if(storage_flags & STORAGE_USING_FIFO_DRAWING) + item_obj = contents[1] + else + item_obj = contents[contents.len] + remove_from_storage(item_obj, tile) + user.visible_message(SPAN_NOTICE("[user] shakes \the [src] and \a [item_obj] falls out."), + SPAN_NOTICE("You shake \the [src] and \a [item_obj] falls out.")) /obj/item/storage/proc/dump_ammo_to(obj/item/ammo_magazine/ammo_dumping, mob/user, var/amount_to_dump = 5) //amount_to_dump should never actually need to be used as default value if(user.action_busy) @@ -674,6 +739,7 @@ W is always an item. stop_warning prevents messaging. user may be null.**/ if (!(storage_flags & STORAGE_ALLOW_EMPTY)) verbs -= /obj/item/storage/verb/empty_verb verbs -= /obj/item/storage/verb/toggle_click_empty + verbs -= /obj/item/storage/verb/shake_verb boxes = new boxes.name = "storage" diff --git a/code/modules/cm_aliens/structures/fruit.dm b/code/modules/cm_aliens/structures/fruit.dm index c0fec23ad153..1be7326de78c 100644 --- a/code/modules/cm_aliens/structures/fruit.dm +++ b/code/modules/cm_aliens/structures/fruit.dm @@ -323,7 +323,8 @@ desc = "A strange fruit that you could eat.. if you REALLY wanted to. Its roots seem to twitch every so often." icon = 'icons/mob/xenos/fruits.dmi' icon_state = "fruit_lesser_item" - w_class = SIZE_LARGE + w_class = SIZE_MEDIUM + storage_cost = SIZE_LARGE bitesize = 2 var/mob/living/carbon/Xenomorph/bound_xeno //Drone linked to this fruit var/fruit_type = /obj/effect/alien/resin/fruit diff --git a/code/modules/cm_marines/Donor_Items.dm b/code/modules/cm_marines/Donor_Items.dm index db9be2a089bf..5df3537dc0cc 100644 --- a/code/modules/cm_marines/Donor_Items.dm +++ b/code/modules/cm_marines/Donor_Items.dm @@ -1309,6 +1309,8 @@ desc = "Black gloves, favored by Special Operations teams. DONOR ITEM" name = "Black Ops Black Gloves" +/obj/item/storage/backpack/marine/fluff + xeno_types = null /obj/item/storage/backpack/marine/fluff/Sado name = "Tanya's Backpack" diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 900aca69b070..7308c6ce1341 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -60,7 +60,7 @@ if(hand) return put_in_r_hand(W) else return put_in_l_hand(W) -//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. +//Puts the item into our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. //If both fail it drops it on the floor and returns 0. //This is probably the main one you need to know :) /mob/proc/put_in_hands(var/obj/item/W) @@ -76,7 +76,24 @@ W.dropped(src) return FALSE - +//Puts the item into our back if possible. Returns 1 on success. +/mob/proc/put_in_back(var/obj/item/item) + if(!item) + return FALSE + if(!istype(item)) + return FALSE + if(back) + return FALSE + if(item.loc == src && !(item.flags_item & DELONDROP)) + item.dropped(src) + item.pickup(src) + item.forceMove(src) + back = item + item.layer = ABOVE_HUD_LAYER + item.plane = ABOVE_HUD_PLANE + item.equipped(src, WEAR_BACK) + update_inv_back() + return TRUE /mob/proc/drop_item_v() //this is dumb. if(stat == CONSCIOUS && isturf(loc)) @@ -366,3 +383,5 @@ return WEAR_L_HAND if(I == r_hand) return WEAR_R_HAND + if(I == back) + return WEAR_BACK diff --git a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm index 40fc79ec4ee3..9c64fd843df1 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm @@ -27,6 +27,27 @@ switch(M.a_intent) if(INTENT_HELP) + if(back && Adjacent(M)) + back.add_fingerprint(M) + var/obj/item/storage/backpack = back + if(backpack && !M.action_busy) + if(stat != DEAD) // If the Xeno is alive, fight back + if(!M.ally_of_hivenumber(hivenumber)) + M.KnockDown(rand(caste.tacklestrength_min, caste.tacklestrength_max)) + playsound(M.loc, 'sound/weapons/pierce.ogg', 25, TRUE) + M.visible_message(SPAN_WARNING("\The [M] tried to open \the [backpack] on [src] but instead gets a tail swipe to the head!")) + return FALSE + + M.visible_message(SPAN_NOTICE("\The [M] starts opening \the [backpack] on [src]"), \ + SPAN_NOTICE("You begin to open \the [backpack] on [src], so you can check its contents."), null, 5, CHAT_TYPE_FLUFF_ACTION) + if(!do_after(M, 1 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_GENERIC, src, INTERRUPT_MOVED, BUSY_ICON_GENERIC)) //Timed opening. + to_chat(M, SPAN_WARNING("You were interrupted!")) + return FALSE + if(!Adjacent(M)) + to_chat(M, SPAN_WARNING("You were interrupted!")) + return FALSE + backpack.open(M) + return if(stat == DEAD) M.visible_message(SPAN_WARNING("\The [M] pokes \the [src], but nothing happens."), \ SPAN_WARNING("You poke \the [src], but nothing happens."), null, 5, CHAT_TYPE_FLUFF_ACTION) diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index efec85009651..330c1c504939 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -332,6 +332,7 @@ var/list/overlays_standing[X_TOTAL_LAYERS] var/atom/movable/vis_obj/xeno_wounds/wound_icon_carrier + var/atom/movable/vis_obj/xeno_pack/backpack_icon_carrier /mob/living/carbon/Xenomorph/Initialize(mapload, mob/living/carbon/Xenomorph/oldXeno, h_number) var/area/A = get_area(src) @@ -697,6 +698,9 @@ vis_contents -= wound_icon_carrier QDEL_NULL(wound_icon_carrier) + if(backpack_icon_carrier) + vis_contents -= backpack_icon_carrier + QDEL_NULL(backpack_icon_carrier) QDEL_NULL(iff_tag) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm index 3719330d3e4a..a24e83a3b36f 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm @@ -63,6 +63,13 @@ if(crest_defense) return "Defender_crest_[severity]" +/mob/living/carbon/Xenomorph/Defender/handle_special_backpack_states() + . = ..() + if(fortify) + return " Fortify" + if(crest_defense) + return " Crest" + /datum/behavior_delegate/defender_base name = "Base Defender Behavior Delegate" diff --git a/code/modules/mob/living/carbon/xenomorph/update_icons.dm b/code/modules/mob/living/carbon/xenomorph/update_icons.dm index ad7874b9f1f8..cfab5e191332 100644 --- a/code/modules/mob/living/carbon/xenomorph/update_icons.dm +++ b/code/modules/mob/living/carbon/xenomorph/update_icons.dm @@ -2,15 +2,17 @@ //Abby //Xeno Overlays Indexes////////// -#define X_HEAD_LAYER 8 -#define X_SUIT_LAYER 7 -#define X_L_HAND_LAYER 6 -#define X_R_HAND_LAYER 5 +#define X_BACK_LAYER 10 +#define X_HEAD_LAYER 9 +#define X_SUIT_LAYER 8 +#define X_L_HAND_LAYER 7 +#define X_R_HAND_LAYER 6 +#define X_BACK_FRONT_LAYER 5 #define X_RESOURCE_LAYER 4 #define X_TARGETED_LAYER 3 #define X_LEGCUFF_LAYER 2 #define X_FIRE_LAYER 1 -#define X_TOTAL_LAYERS 8 +#define X_TOTAL_LAYERS 10 ///////////////////////////////// @@ -45,8 +47,10 @@ if(!caste) return - update_fire() //the fire overlay depends on the xeno's stance, so we must update it. + //These also depend on the xeno's stance, so we must update them + update_fire() update_wounds() + update_inv_back() if(behavior_delegate?.on_update_icons()) return @@ -74,10 +78,10 @@ ..() update_inv_r_hand() update_inv_l_hand() + update_inv_back() update_inv_resource() update_icons() - /mob/living/carbon/Xenomorph/update_inv_pockets() var/datum/custom_hud/alien/ui_datum = GLOB.custom_huds_list[HUD_ALIEN] if(l_store) @@ -115,6 +119,32 @@ overlays_standing[X_L_HAND_LAYER] = l_hand.get_mob_overlay(src, WEAR_L_HAND) apply_overlay(X_L_HAND_LAYER) +/mob/living/carbon/Xenomorph/update_inv_back() + if(!backpack_icon_carrier) + return // Xenos will only have a vis_obj if they've been equipped with a pack before + + var/obj/item/storage/backpack/backpack = back + if(!backpack?.xeno_icon_state) + backpack_icon_carrier.icon_state = "none" + return + + var/state_modifier = "" + if(stat == DEAD) + state_modifier = " Dead" + else if(lying) + if((resting || sleeping) && (!knocked_down && !knocked_out && health > 0)) + state_modifier = " Sleeping" + else + state_modifier = " Knocked Down" + else if(handle_special_state()) + state_modifier = handle_special_backpack_states() + + backpack_icon_carrier.icon_state = backpack.xeno_icon_state + state_modifier + + backpack_icon_carrier.layer = -X_BACK_LAYER + if(dir == NORTH && (back.flags_item & ITEM_OVERRIDE_NORTHFACE)) + backpack_icon_carrier.layer = -X_BACK_FRONT_LAYER + /mob/living/carbon/Xenomorph/proc/update_inv_resource() remove_overlay(X_RESOURCE_LAYER) if(crystal_stored) @@ -220,6 +250,9 @@ /mob/living/carbon/Xenomorph/proc/handle_special_wound_states() return FALSE +/mob/living/carbon/Xenomorph/proc/handle_special_backpack_states() + return "" + // Shamelessly inspired from the equivalent proc on TGCM /mob/living/carbon/Xenomorph/proc/update_wounds() if(!wound_icon_carrier) @@ -242,30 +275,22 @@ wound_icon_carrier.icon_state = handle_special_wound_states(health_threshold) -///Used to display the xeno wounds without rapidly switching overlays +///Used to display the xeno wounds/backpacks without rapidly switching overlays +/atom/movable/vis_obj + vis_flags = VIS_INHERIT_ID|VIS_INHERIT_DIR + appearance_flags = RESET_COLOR + /atom/movable/vis_obj/xeno_wounds icon = 'icons/mob/xenos/wounds.dmi' - var/mob/living/carbon/Xenomorph/wound_owner - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -/atom/movable/vis_obj/xeno_wounds/Initialize(mapload, mob/living/carbon/Xenomorph/owner) +/atom/movable/vis_obj/xeno_pack/Initialize(mapload, mob/living/carbon/source) . = ..() - if(owner) - wound_owner = owner - RegisterSignal(owner, COMSIG_ATOM_DIR_CHANGE, .proc/on_dir_change) - -/atom/movable/vis_obj/xeno_wounds/Destroy() - if(wound_owner) - UnregisterSignal(wound_owner, COMSIG_ATOM_DIR_CHANGE) - wound_owner = null - return ..() - -/atom/movable/vis_obj/xeno_wounds/proc/on_dir_change(mob/living/carbon/Xenomorph/source, olddir, newdir) - SIGNAL_HANDLER - dir = newdir + if(source) + icon = default_xeno_onmob_icons[source.type] //Xeno Overlays Indexes////////// +#undef X_BACK_LAYER +#undef X_BACK_FRONT_LAYER #undef X_HEAD_LAYER #undef X_SUIT_LAYER #undef X_L_HAND_LAYER diff --git a/icons/mob/xenos/onmob/defender.dmi b/icons/mob/xenos/onmob/defender.dmi new file mode 100644 index 000000000000..07098360c47e Binary files /dev/null and b/icons/mob/xenos/onmob/defender.dmi differ diff --git a/icons/mob/xenos/onmob/drone.dmi b/icons/mob/xenos/onmob/drone.dmi new file mode 100644 index 000000000000..8118dd4ac3b7 Binary files /dev/null and b/icons/mob/xenos/onmob/drone.dmi differ diff --git a/icons/mob/xenos/onmob/praetorian.dmi b/icons/mob/xenos/onmob/praetorian.dmi new file mode 100644 index 000000000000..1109020c0099 Binary files /dev/null and b/icons/mob/xenos/onmob/praetorian.dmi differ diff --git a/icons/mob/xenos/onmob/runner.dmi b/icons/mob/xenos/onmob/runner.dmi new file mode 100644 index 000000000000..7ec0a18bad93 Binary files /dev/null and b/icons/mob/xenos/onmob/runner.dmi differ diff --git a/icons/mob/xenos/onmob/sentinel.dmi b/icons/mob/xenos/onmob/sentinel.dmi new file mode 100644 index 000000000000..41ce51f19fd6 Binary files /dev/null and b/icons/mob/xenos/onmob/sentinel.dmi differ diff --git a/icons/mob/xenos/onmob/spitter.dmi b/icons/mob/xenos/onmob/spitter.dmi new file mode 100644 index 000000000000..6e96385d5d60 Binary files /dev/null and b/icons/mob/xenos/onmob/spitter.dmi differ diff --git a/icons/mob/xenos/onmob/warrior.dmi b/icons/mob/xenos/onmob/warrior.dmi new file mode 100644 index 000000000000..4351ad78339e Binary files /dev/null and b/icons/mob/xenos/onmob/warrior.dmi differ