Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xeno Backpacks #1274

Merged
merged 20 commits into from
Dec 17, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7ae1fe6
Initial support adding runner and praetorian backpack support
Drulikar Oct 16, 2022
90246f1
Added shake verb for xenos and humans
Drulikar Oct 16, 2022
3d23a77
Fix no sfx for unequipping a backpack
Drulikar Oct 16, 2022
3164cf6
Update prae sprites and add regular pack support for praes
Drulikar Oct 16, 2022
7537a5e
Added the ability to bag fruit
Drulikar Oct 16, 2022
de038dc
Set engie packs to use marinepack sprite for now
Drulikar Oct 16, 2022
6694908
Refactoring
Drulikar Oct 16, 2022
d252954
Added tailswipes to the head when not allied
Drulikar Oct 16, 2022
21626c8
Added sprites for runner regular, warrior regular/medical (needs twea…
Drulikar Oct 31, 2022
7b7b73a
Remove unintended backpack types from being allowed as xeno packs.
Drulikar Oct 31, 2022
d1de3fd
Refactor xeno packs to use atom/moveable/vis_obj instead (only creati…
Drulikar Oct 31, 2022
22761eb
More vis_obj refactoring: No need to create a dir change signal if th…
Drulikar Oct 31, 2022
b6e2e01
Update resting sprites for defender and warrior
Drulikar Nov 2, 2022
966030d
Blocked strapping backpacks onto xenoids via trait (since they don't …
Drulikar Nov 16, 2022
2701127
Fix xeno packs inheriting hive color
Drulikar Nov 20, 2022
d1f2334
More comments for gitactions breaking.
Drulikar Nov 20, 2022
c884cfd
Merge branch 'master' into Drathek_XenoBackpacks
Drulikar Nov 22, 2022
319f428
Move onmob files to new xeno icon directory.
Drulikar Nov 27, 2022
c51d826
Sprite update for east facing defender, prae, and warrior medical packs
Drulikar Dec 9, 2022
428e47c
More tweaks to warrior, sentinel, runner, prae, and defender sprites.
Drulikar Dec 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,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/hostiles/onmob/runner.dmi',
/mob/living/carbon/Xenomorph/Praetorian = 'icons/mob/hostiles/onmob/praetorian.dmi',
/mob/living/carbon/Xenomorph/Drone = 'icons/mob/hostiles/onmob/drone.dmi',
/mob/living/carbon/Xenomorph/Warrior = 'icons/mob/hostiles/onmob/warrior.dmi',
/mob/living/carbon/Xenomorph/Defender = 'icons/mob/hostiles/onmob/defender.dmi',
/mob/living/carbon/Xenomorph/Sentinel = 'icons/mob/hostiles/onmob/sentinel.dmi',
/mob/living/carbon/Xenomorph/Spitter = 'icons/mob/hostiles/onmob/spitter.dmi'
)

// species names
#define SPECIES_HUMAN "Human"
#define SPECIES_YAUTJA "Yautja"
Expand Down
3 changes: 3 additions & 0 deletions code/_onclick/adjacent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions code/_onclick/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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 . = ..()

Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,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.
Expand Down
68 changes: 66 additions & 2 deletions code/game/objects/items/storage/backpack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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

Drulikar marked this conversation as resolved.
Show resolved Hide resolved
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]!"))
Expand All @@ -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)
..()
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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."
Expand Down Expand Up @@ -490,20 +549,23 @@ 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 MARSOC IMP tactical rucksack"
icon_state = "tacrucksack"
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"
desc = "A specially-designed backpack that fits to the IMP mounting frame on standard USCM pattern M3 armors. It's made of two waterproofed reinforced tubes and one smaller satchel slung at the bottom. The two silos are for rockets, but no one is stopping you from cramming other things in there."
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"
Expand All @@ -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))
Expand All @@ -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
Expand Down Expand Up @@ -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()
. = ..()
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/items/storage/smartpack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
66 changes: 66 additions & 0 deletions code/game/objects/items/storage/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion code/modules/cm_aliens/structures/fruit.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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/hostiles/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
Expand Down
2 changes: 2 additions & 0 deletions code/modules/cm_marines/Donor_Items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
23 changes: 21 additions & 2 deletions code/modules/mob/inventory.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))
Expand Down Expand Up @@ -366,3 +383,5 @@
return WEAR_L_HAND
if(I == r_hand)
return WEAR_R_HAND
if(I == back)
return WEAR_BACK
Loading