Merge pull request #12648 from timothyteakettle/tray-and-jar
bluespace tray + bluespace jar
This commit is contained in:
@@ -22,6 +22,11 @@
|
|||||||
var/occupant_weight = 0
|
var/occupant_weight = 0
|
||||||
var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
|
var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
|
||||||
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
|
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
|
||||||
|
var/entrance_name = "door" //name of the entrance to the item
|
||||||
|
var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
|
||||||
|
var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
|
||||||
|
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
|
||||||
|
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
|
||||||
|
|
||||||
/obj/item/pet_carrier/Destroy()
|
/obj/item/pet_carrier/Destroy()
|
||||||
if(occupants.len)
|
if(occupants.len)
|
||||||
@@ -51,20 +56,20 @@
|
|||||||
else
|
else
|
||||||
. += "<span class='notice'>It has nothing inside.</span>"
|
. += "<span class='notice'>It has nothing inside.</span>"
|
||||||
if(user.canUseTopic(src))
|
if(user.canUseTopic(src))
|
||||||
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its door.</span>"
|
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its [entrance_name].</span>"
|
||||||
if(!open)
|
if(!open)
|
||||||
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its door.</span>"
|
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its [entrance_name].</span>"
|
||||||
|
|
||||||
/obj/item/pet_carrier/attack_self(mob/living/user)
|
/obj/item/pet_carrier/attack_self(mob/living/user)
|
||||||
if(open)
|
if(open)
|
||||||
to_chat(user, "<span class='notice'>You close [src]'s door.</span>")
|
to_chat(user, "<span class='notice'>You close [src]'s [entrance_name].</span>")
|
||||||
playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
|
playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
|
||||||
open = FALSE
|
open = FALSE
|
||||||
else
|
else
|
||||||
if(locked)
|
if(locked)
|
||||||
to_chat(user, "<span class='warning'>[src] is locked!</span>")
|
to_chat(user, "<span class='warning'>[src] is locked!</span>")
|
||||||
return
|
return
|
||||||
to_chat(user, "<span class='notice'>You open [src]'s door.</span>")
|
to_chat(user, "<span class='notice'>You open [src]'s [entrance_name].</span>")
|
||||||
playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
|
playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
|
||||||
open = TRUE
|
open = TRUE
|
||||||
update_icon()
|
update_icon()
|
||||||
@@ -86,7 +91,7 @@
|
|||||||
if(user.a_intent == INTENT_HARM)
|
if(user.a_intent == INTENT_HARM)
|
||||||
return ..()
|
return ..()
|
||||||
if(!open)
|
if(!open)
|
||||||
to_chat(user, "<span class='warning'>You need to open [src]'s door!</span>")
|
to_chat(user, "<span class='warning'>You need to open [src]'s [entrance_name]!</span>")
|
||||||
return
|
return
|
||||||
if(target.mob_size > max_occupant_weight)
|
if(target.mob_size > max_occupant_weight)
|
||||||
if(ishuman(target))
|
if(ishuman(target))
|
||||||
@@ -94,13 +99,15 @@
|
|||||||
if(iscatperson(H))
|
if(iscatperson(H))
|
||||||
to_chat(user, "<span class='warning'>You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.</span>")
|
to_chat(user, "<span class='warning'>You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.</span>")
|
||||||
else
|
else
|
||||||
to_chat(user, "<span class='warning'>Humans, generally, do not fit into pet carriers.</span>")
|
to_chat(user, "<span class='warning'>Humans, generally, do not fit into [name]s.</span>")
|
||||||
else
|
else
|
||||||
to_chat(user, "<span class='warning'>You get the feeling [target] isn't meant for a [name].</span>")
|
to_chat(user, "<span class='warning'>You get the feeling [target] isn't meant for a [name].</span>")
|
||||||
return
|
return
|
||||||
if(user == target)
|
if(user == target)
|
||||||
to_chat(user, "<span class='warning'>Why would you ever do that?</span>")
|
to_chat(user, "<span class='warning'>Why would you ever do that?</span>")
|
||||||
return
|
return
|
||||||
|
if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers
|
||||||
|
to_chat(user, "<span class='warning'>You have a feeling you shouldn't keep this as a pet.</span>")
|
||||||
load_occupant(user, target)
|
load_occupant(user, target)
|
||||||
|
|
||||||
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
|
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
|
||||||
@@ -110,8 +117,8 @@
|
|||||||
remove_occupant(user)
|
remove_occupant(user)
|
||||||
return
|
return
|
||||||
else if(!locked)
|
else if(!locked)
|
||||||
loc.visible_message("<span class='notice'>[user] pushes open the door to [src]!</span>", \
|
loc.visible_message("<span class='notice'>[user] pushes open the [entrance_name] to [src]!</span>", \
|
||||||
"<span class='warning'>[user] pushes open the door of [src]!</span>")
|
"<span class='warning'>[user] pushes open the [entrance_name] of [src]!</span>")
|
||||||
open = TRUE
|
open = TRUE
|
||||||
update_icon()
|
update_icon()
|
||||||
return
|
return
|
||||||
@@ -119,12 +126,19 @@
|
|||||||
container_resist(user)
|
container_resist(user)
|
||||||
|
|
||||||
/obj/item/pet_carrier/container_resist(mob/living/user)
|
/obj/item/pet_carrier/container_resist(mob/living/user)
|
||||||
|
//don't do the whole resist timer thing if it's open!
|
||||||
|
if(open)
|
||||||
|
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
|
||||||
|
"<span class='warning'>[user] jumps out of [src]!</span>")
|
||||||
|
remove_occupant(user)
|
||||||
|
return
|
||||||
|
|
||||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||||
if(user.mob_size <= MOB_SIZE_SMALL)
|
if(user.mob_size <= MOB_SIZE_SMALL)
|
||||||
to_chat(user, "<span class='notice'>You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)</span>")
|
to_chat(user, "<span class='notice'>You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)</span>")
|
||||||
to_chat(loc, "<span class='warning'>You see [user] reach through the bars and fumble for the lock switch!</span>")
|
to_chat(loc, "<span class='warning'>You see [user] attempting to unlock the [src]!</span>")
|
||||||
if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants))
|
if(!do_after(user, rand(escape_time * 1.5, escape_time * 2), target = user) || open || !locked || !(user in occupants))
|
||||||
return
|
return
|
||||||
loc.visible_message("<span class='warning'>[user] flips the lock switch on [src] by reaching through!</span>", null, null, null, user)
|
loc.visible_message("<span class='warning'>[user] flips the lock switch on [src] by reaching through!</span>", null, null, null, user)
|
||||||
to_chat(user, "<span class='boldannounce'>Bingo! The lock pops open!</span>")
|
to_chat(user, "<span class='boldannounce'>Bingo! The lock pops open!</span>")
|
||||||
@@ -132,12 +146,12 @@
|
|||||||
playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
|
playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
|
||||||
update_icon()
|
update_icon()
|
||||||
else
|
else
|
||||||
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the door!</span>", null, null, null, user)
|
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the [entrance_name]!</span>", null, null, null, user)
|
||||||
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
|
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
|
||||||
if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants))
|
if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
|
||||||
return
|
return
|
||||||
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
|
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
|
||||||
to_chat(user, "<span class='notice'>You shove open [src]'s door against the lock's resistance and fall out!</span>")
|
to_chat(user, "<span class='notice'>You shove open [src]'s [entrance_name] against the lock's resistance and fall out!</span>")
|
||||||
locked = FALSE
|
locked = FALSE
|
||||||
open = TRUE
|
open = TRUE
|
||||||
update_icon()
|
update_icon()
|
||||||
@@ -151,7 +165,7 @@
|
|||||||
|
|
||||||
/obj/item/pet_carrier/update_overlays()
|
/obj/item/pet_carrier/update_overlays()
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!open)
|
if(!open && has_lock_sprites)
|
||||||
. += "[locked ? "" : "un"]locked"
|
. += "[locked ? "" : "un"]locked"
|
||||||
|
|
||||||
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
|
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
|
||||||
@@ -170,7 +184,7 @@
|
|||||||
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
|
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
|
||||||
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
|
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
|
||||||
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
|
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
|
||||||
if(!do_mob(user, target, 30))
|
if(!do_mob(user, target, load_time))
|
||||||
return
|
return
|
||||||
if(target in occupants)
|
if(target in occupants)
|
||||||
return
|
return
|
||||||
@@ -192,9 +206,74 @@
|
|||||||
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
|
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
|
||||||
if(!(occupant in occupants) || !istype(occupant))
|
if(!(occupant in occupants) || !istype(occupant))
|
||||||
return
|
return
|
||||||
occupant.forceMove(new_turf ? new_turf : drop_location())
|
occupant.forceMove(new_turf ? new_turf : get_turf(src))
|
||||||
occupants -= occupant
|
occupants -= occupant
|
||||||
occupant_weight -= occupant.mob_size
|
occupant_weight -= occupant.mob_size
|
||||||
occupant.setDir(SOUTH)
|
occupant.setDir(SOUTH)
|
||||||
|
|
||||||
|
//bluespace jar, a reskin of the pet carrier that can fit people and smashes when thrown
|
||||||
|
/obj/item/pet_carrier/bluespace
|
||||||
|
name = "bluespace jar"
|
||||||
|
desc = "A jar, that seems to be bigger on the inside, somehow allowing lifeforms to fit through its narrow entrance."
|
||||||
|
open = FALSE //starts closed so it looks better on menus
|
||||||
|
icon_state = "bluespace_jar"
|
||||||
|
item_state = "bluespace_jar"
|
||||||
|
lefthand_file = ""
|
||||||
|
righthand_file = ""
|
||||||
|
max_occupant_weight = MOB_SIZE_HUMAN //can fit people, like a bluespace bodybag!
|
||||||
|
load_time = 40 //loading things into a jar takes longer than a regular pet carrier
|
||||||
|
entrance_name = "lid"
|
||||||
|
w_class = WEIGHT_CLASS_SMALL //it's a jar
|
||||||
|
throw_speed = 3
|
||||||
|
throw_range = 7
|
||||||
|
max_occupants = 1 //far less than a regular carrier or bluespace bodybag, because it can be thrown to release the contents
|
||||||
|
allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
|
||||||
|
has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
|
||||||
|
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
|
||||||
|
escape_time = 10 //half the time of a bluespace bodybag
|
||||||
|
var/datum/gas_mixture/occupant_gas_supply
|
||||||
|
|
||||||
|
/obj/item/pet_carrier/bluespace/update_icon_state()
|
||||||
|
if(open)
|
||||||
|
icon_state = "bluespace_jar_open"
|
||||||
|
else
|
||||||
|
icon_state = "bluespace_jar"
|
||||||
|
|
||||||
|
/obj/item/pet_carrier/bluespace/throw_impact()
|
||||||
|
. = ..()
|
||||||
|
//delete the item upon impact, releasing the creature inside (this is handled by its deletion)
|
||||||
|
if(occupants.len)
|
||||||
|
loc.visible_message("<span class='warning'>The bluespace jar smashes, releasing [occupants[1]]!</span>")
|
||||||
|
playsound(src, "shatter", 70, 1)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/obj/item/pet_carrier/bluespace/add_occupant(mob/living/occupant) //update the gas supply as required, this acts like magical internals
|
||||||
|
. = ..()
|
||||||
|
if(!occupant_gas_supply)
|
||||||
|
occupant_gas_supply = new
|
||||||
|
if(isanimal(occupant))
|
||||||
|
var/mob/living/simple_animal/animal = occupant
|
||||||
|
occupant_gas_supply.temperature = animal.minbodytemp //simple animals only care about temperature when their turf isnt a location
|
||||||
|
else
|
||||||
|
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
|
||||||
|
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
|
||||||
|
ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
|
||||||
|
ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
|
||||||
|
ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
|
||||||
|
ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
|
||||||
|
|
||||||
|
/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
|
||||||
|
. = ..()
|
||||||
|
if(ishuman(occupant))
|
||||||
|
REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
|
||||||
|
REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
|
||||||
|
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
|
||||||
|
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
|
||||||
|
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
|
||||||
|
|
||||||
|
/obj/item/pet_carrier/bluespace/return_air()
|
||||||
|
if(!occupant_gas_supply)
|
||||||
|
occupant_gas_supply = new
|
||||||
|
return occupant_gas_supply
|
||||||
|
|
||||||
#undef pet_carrier_full
|
#undef pet_carrier_full
|
||||||
|
|||||||
@@ -326,6 +326,7 @@
|
|||||||
w_class = WEIGHT_CLASS_BULKY
|
w_class = WEIGHT_CLASS_BULKY
|
||||||
flags_1 = CONDUCT_1
|
flags_1 = CONDUCT_1
|
||||||
custom_materials = list(/datum/material/iron=3000)
|
custom_materials = list(/datum/material/iron=3000)
|
||||||
|
var/max_items = 7
|
||||||
|
|
||||||
/obj/item/storage/bag/tray/ComponentInitialize()
|
/obj/item/storage/bag/tray/ComponentInitialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -333,6 +334,7 @@
|
|||||||
STR.max_w_class = WEIGHT_CLASS_NORMAL
|
STR.max_w_class = WEIGHT_CLASS_NORMAL
|
||||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes.
|
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes.
|
||||||
STR.insert_preposition = "on"
|
STR.insert_preposition = "on"
|
||||||
|
STR.max_items = max_items
|
||||||
|
|
||||||
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
|
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -373,6 +375,14 @@
|
|||||||
. = ..()
|
. = ..()
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
//bluespace tray, holds more items
|
||||||
|
/obj/item/storage/bag/tray/bluespace
|
||||||
|
name = "bluespace tray"
|
||||||
|
icon_state = "bluespace_tray"
|
||||||
|
desc = "A tray created using bluespace technology to fit more food on it."
|
||||||
|
max_items = 30 // far more items
|
||||||
|
custom_materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Chemistry bag
|
* Chemistry bag
|
||||||
*/
|
*/
|
||||||
@@ -462,4 +472,4 @@
|
|||||||
STR.max_combined_w_class = INFINITY
|
STR.max_combined_w_class = INFINITY
|
||||||
STR.max_items = 2
|
STR.max_items = 2
|
||||||
STR.display_numerical_stacking = TRUE
|
STR.display_numerical_stacking = TRUE
|
||||||
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
|
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
|
||||||
|
|||||||
@@ -95,3 +95,23 @@
|
|||||||
build_path = /obj/item/storage/bag/ore/holding
|
build_path = /obj/item/storage/bag/ore/holding
|
||||||
category = list("Bluespace Designs")
|
category = list("Bluespace Designs")
|
||||||
departmental_flags = DEPARTMENTAL_FLAG_CARGO
|
departmental_flags = DEPARTMENTAL_FLAG_CARGO
|
||||||
|
|
||||||
|
/datum/design/bluespace_tray
|
||||||
|
name = "Bluespace Tray"
|
||||||
|
desc = "A tray created using bluespace technology to fit more food on it."
|
||||||
|
id = "bluespace_tray"
|
||||||
|
build_type = PROTOLATHE
|
||||||
|
build_path = /obj/item/storage/bag/tray/bluespace
|
||||||
|
materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
|
||||||
|
category = list("Bluespace Designs")
|
||||||
|
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
|
||||||
|
|
||||||
|
/datum/design/bluespace_carrier
|
||||||
|
name = "Bluespace Jar"
|
||||||
|
desc = "A jar used to contain creatures, using the power of bluespace."
|
||||||
|
id = "bluespace_carrier"
|
||||||
|
build_type = PROTOLATHE
|
||||||
|
build_path = /obj/item/pet_carrier/bluespace
|
||||||
|
materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
|
||||||
|
category = list("Bluespace Designs")
|
||||||
|
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
display_name = "Applied Bluespace Research"
|
display_name = "Applied Bluespace Research"
|
||||||
description = "Using bluespace to make things faster and better."
|
description = "Using bluespace to make things faster and better."
|
||||||
prereq_ids = list("bluespace_basic", "engineering")
|
prereq_ids = list("bluespace_basic", "engineering")
|
||||||
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic")
|
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "bluespace_carrier")
|
||||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||||
|
|
||||||
/datum/techweb_node/adv_bluespace
|
/datum/techweb_node/adv_bluespace
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.3 KiB |
Reference in New Issue
Block a user