Files

468 lines
16 KiB
Plaintext

//As part of the Phase 3 expansions, Ashlanders are receiving some dedicated structures.
//One of these is a functional forge where they can produce metal rods and lead sheets.
//Another is a bricklayer that will compress sandstone blocks for construction.
/obj/structure/ashlander
name = "ashlander structure"
desc = "Woah! You shouldn't be seeing me, outlander! Report me to the Buried Ones at once!"
icon = 'icons/obj/lavaland.dmi'
density = TRUE
anchored = TRUE
/obj/structure/ashlander/production
name = "abstract machine"
desc = "You shouldn't be able to see this. Contact an admin."
icon = 'icons/obj/lavaland.dmi'
icon_state = "forge"
var/list/ore_mapping = list()
var/default_message = "..."
var/list/insert_msg_override = list()
/obj/structure/ashlander/production/attackby(var/obj/item/I, mob/user)
. = ..()
var/msg = insert_msg_override[I.type] || default_message
if(istype(I, /obj/item/stack/ore))
var/obj/item/stack/ore/O = I
if(O.amount > 1)
to_chat(user, "<span class='danger'>You pour all [O.amount] of [O] into [src]! [msg]</span>")
else
to_chat(user, "<span class='danger'>You pour [O] into [src]! [msg]</span>")
attempt_consume(O, user, O.amount)
if(istype(I, /obj/item/storage/bag))
var/obj/item/storage/bag/B = I
var/inserted = 0
for(I in B)
if(istype(I, /obj/item/stack/ore))
var/obj/item/stack/ore/O = I
if(attempt_consume(O, user, O.amount))
inserted += O.amount
if(inserted)
user.action_feedback(SPAN_NOTICE("You insert [inserted] units of material from [B] into [src]. [msg]"), src)
else
user.action_feedback(SPAN_WARNING("You fail to insert anything from [B] into [src]."), src)
else if(attempt_consume(I, user)) //is this really needed when attempt_consume only asks for ores???
return CLICKCHAIN_DO_NOT_PROPAGATE | CLICKCHAIN_DID_SOMETHING
return ..()
/**
* Attempts to consume a piece of ore
*
* @params
* * inserting - what they're trying to put into us
* * user - optional: the user doing it
*
* @return TRUE / FALSE based on success / failure.
*/
/obj/structure/ashlander/production/proc/attempt_consume(obj/item/stack/ore/O, mob/user, amount = 1)
if (!istype(O))
return FALSE
/// Ensure the ore is able to be put in if it's being held / in inventory
if(!isnull(user) && user.is_holding(O) && !O.use(amount))
user.action_feedback(SPAN_WARNING("[O] doesn't exist! Likely some stack bug. Yell at coderbus."), src)
return FALSE
for (var/ty in ore_mapping)
if (istype(O, ty))
var/target_type = ore_mapping[ty]
if(istype(target_type, /obj/item/stack))
var/obj/item/stack/ttstack = target_type
new ttstack(get_turf(src), amount)
else //I sure hope nobody DOES make production machines that results in non-stackable objects.
var/i = 0
for(i = 0; i < amount; ++i)
new target_type(get_turf(src))
return TRUE
return FALSE
/obj/structure/ashlander/production/forge
name = "magma forge"
desc = "A primitive forge of Scorian design. It is used primarily to convert iron and lead into more workable shapes."
default_message = "It begins to melt in the crucible."
ore_mapping = list(
/obj/item/stack/ore/lead = /obj/item/stack/material/lead,
/obj/item/stack/ore/copper = /obj/item/stack/material/copper,
/obj/item/stack/ore/glass = /obj/item/stack/ore/slag
)
insert_msg_override = list(
/obj/item/stack/ore/iron = "It slowly feeds through the extruder."
)
/obj/structure/ashlander/production/brickmaker
name = "brick press"
desc = "Scori have been observed using this device to compress sand and clay into hardened bricks."
icon_state = "brickmaker"
default_message = "It is slowly compacted by the press."
ore_mapping = list(
/obj/item/stack/ore/glass = /obj/item/stack/material/sandstone
)
//This is a child of the Hydroponics seed extractor, and was originally in that file. But I've moved it here since it's an Ashlander "machine".
/obj/machinery/seed_extractor/press
name = "primitive press"
desc = "A hand crafted press and sieve designed to extract seeds from fruit."
icon = 'icons/obj/lavaland.dmi'
icon_state = "press"
use_power = USE_POWER_OFF
//This is a child of the juicer/all-in-one grinder/reagent grinder. Just for some fun alchemy.
/obj/machinery/reagentgrinder/ashlander
name = "basic alchemical station"
desc = "A primitive assembly designed to hold a mortar and pestle."
icon = 'icons/obj/lavaland.dmi'
icon_state = "alchemy1"
density = FALSE
anchored = FALSE
use_power = USE_POWER_OFF
circuit = null
no_panel = TRUE
/obj/machinery/reagentgrinder/ashlander/Initialize(mapload, newdir)
. = ..()
beaker = new /obj/item/reagent_containers/glass/stone(src)
/obj/machinery/reagentgrinder/ashlander/update_icon()
icon_state = "alchemy"+num2text(!isnull(beaker))
return
/obj/machinery/reagentgrinder/ashlander/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(beaker)
if(default_deconstruction_screwdriver(user, O))
return
if(default_deconstruction_crowbar(user, O))
return
if (istype(O,/obj/item/reagent_containers/glass) || \
istype(O,/obj/item/reagent_containers/food/drinks/glass2) || \
istype(O,/obj/item/reagent_containers/food/drinks/shaker))
if (beaker)
return 1
else
if(!user.attempt_insert_item_for_installation(O, src))
return
beaker = O
update_icon()
updateUsrDialog()
return 0
if(holdingitems && holdingitems.len >= limit)
to_chat(user, "The assembly cannot hold anymore items.")
return 1
if(!istype(O))
return
if(istype(O,/obj/item/storage/bag/plants))
var/obj/item/storage/bag/plants/bag = O
var/failed = 1
for(var/obj/item/G in O.contents)
if(!G.reagents || !G.reagents.total_volume)
continue
failed = 0
bag.obj_storage.remove(G, src)
holdingitems += G
if(holdingitems && holdingitems.len >= limit)
break
if(failed)
to_chat(user, "Nothing in the plant bag is usable.")
return 1
if(!O.contents.len)
to_chat(user, "You empty \the [O] into \the [src].")
else
to_chat(user, "You fill \the [src] from \the [O].")
src.updateUsrDialog()
return 0
if(!sheet_reagents[O.type] && (!O.reagents || !O.reagents.total_volume))
to_chat(user, "\The [O] is not suitable for reduction.")
return 1
if(!user.attempt_insert_item_for_installation(O, src))
return
holdingitems += O
src.updateUsrDialog()
return 0
/obj/machinery/reagentgrinder/ashlander/grind()
// Sanity check.
if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume))
return
playsound(src, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
inuse = 1
// Reset the machine.
spawn(60)
inuse = 0
// Process.
for (var/obj/item/O in holdingitems)
var/remaining_volume = beaker.reagents.maximum_volume - beaker.reagents.total_volume
if(remaining_volume <= 0)
break
if(sheet_reagents[O.type])
var/obj/item/stack/stack = O
if(istype(stack))
var/list/sheet_components = sheet_reagents[stack.type]
var/amount_to_take = max(0,min(stack.amount,round(remaining_volume/REAGENTS_PER_SHEET)))
if(amount_to_take)
stack.use(amount_to_take)
if(QDELETED(stack))
holdingitems -= stack
if(islist(sheet_components))
amount_to_take = (amount_to_take/(sheet_components.len))
for(var/i in sheet_components)
beaker.reagents.add_reagent(i, (amount_to_take*REAGENTS_PER_SHEET))
else
beaker.reagents.add_reagent(sheet_components, (amount_to_take*REAGENTS_PER_SHEET))
continue
if(O.reagents)
O.reagents.trans_to_obj(beaker, min(O.reagents.total_volume, remaining_volume))
if(O.reagents.total_volume == 0)
holdingitems -= O
qdel(O)
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
//Calcinator
//"A very basic implement that burns things down into ash. Pretty simple. Almost a waste to create it."
//The above is the note I wrote for this when I started. Obviously now it's gigantic.
/obj/structure/ashlander/calcinator
name = "calcinator"
desc = "This carved basin is used in alchemy to reduce an item down to ashes, thereby releasing its inner properties."
icon_state = "calcinator1"
var/obj/item/reagent_containers/beaker
/obj/structure/ashlander/calcinator/Initialize(mapload, newdir)
. = ..()
beaker = new /obj/item/reagent_containers/glass/stone(src)
/obj/structure/ashlander/calcinator/update_icon()
icon_state = "calcinator"+num2text(!isnull(beaker))
return
/obj/structure/ashlander/calcinator/attackby(obj/item/I as obj, mob/user as mob)
if(!istype(I))
return
if (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
return
if(istype(I,/obj/item/reagent_containers/glass/stone))
if(beaker)
return
if(!user.attempt_insert_item_for_installation(I, src))
return
else
beaker = I
update_icon()
updateUsrDialog()
return 0
if(istype(I,/obj/item/stack/material/wood))
if(!beaker)
return
else
var/obj/item/stack/material/wood/W = I
if(W.get_amount() < 1)
return
else if(do_after(user, 10))
W.use(1)
user.visible_message("<span class='notice'>[user] feeds \the [W] into \the [src].</span>","<span class='notice'>You reduce \the [W] using \the [src].</span>")
playsound(loc, 'sound/weapons/gun_flamethrower3.ogg', 50, 1)
beaker.reagents.add_reagent("ash", 10)
if(istype(I,/obj/item/stack/material/bone))
if(!beaker)
return
else
var/obj/item/stack/material/bone/W = I
if(W.get_amount() < 1)
return
else if(do_after(user, 10))
W.use(1)
user.visible_message("<span class='notice'>[user] feeds \the [W] into \the [src].</span>","<span class='notice'>You reduce \the [W] using \the [src].</span>")
playsound(loc, 'sound/weapons/gun_flamethrower3.ogg', 50, 1)
beaker.reagents.add_reagent("ash", 10)
if(istype(I,/obj/item/stack/material/shell))
if(!beaker)
return
else
var/obj/item/stack/material/shell/W = I
if(W.get_amount() < 1)
return
else if(do_after(user, 10))
W.use(1)
user.visible_message("<span class='notice'>[user] feeds \the [W] into \the [src].</span>","<span class='notice'>You reduce \the [W] using \the [src].</span>")
playsound(loc, 'sound/weapons/gun_flamethrower3.ogg', 50, 1)
beaker.reagents.add_reagent("calcium", 10)
if(istype(I,/obj/item/elderstone))
if(!beaker)
return
else if(do_after(user, 10))
qdel(I)
user.visible_message("<span class='notice'>[user] feeds \the [I] into \the [src].</span>","<span class='notice'>You reduce \the [I] using \the [src].</span>")
playsound(loc, 'sound/weapons/gun_flamethrower3.ogg', 50, 1)
beaker.reagents.add_reagent("catalyst", 10)
src.updateUsrDialog()
return 0
/obj/structure/ashlander/calcinator/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
interact(user)
/obj/structure/ashlander/calcinator/AltClick(mob/user)
. = ..()
if(user.incapacitated() || !Adjacent(user))
return
replace_beaker(user)
/obj/structure/ashlander/calcinator/interact(mob/user)
if(user.incapacitated())
return
if(beaker)
replace_beaker(user)
/obj/structure/ashlander/calcinator/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(!user)
return FALSE
if(beaker)
if(!user.incapacitated() && Adjacent(user) && !isrobot(user))
user.put_in_hands(beaker)
else
beaker.forceMove(drop_location())
beaker = null
if(new_beaker)
beaker = new_beaker
update_icon()
return TRUE
//Ashies gotta eat.
/obj/machinery/appliance/cooker/grill/spit
name = "cooking spit"
desc = "Primitive structures such as these have been used to cook raw meat for as long as the benefits of such a practice have been known."
icon = 'icons/obj/lavaland.dmi'
icon_state = "spitgrill_off"
food_color = "#630905"
on_icon = "spitgrill_on"
off_icon = "spitgrill_off"
max_contents = 1
container_type = /obj/item/reagent_containers/cooking_container/grill/spit
use_power = USE_POWER_OFF
var/lit = 0
/obj/machinery/appliance/cooker/grill/spit/attempt_toggle_power(mob/user)
if (!isliving(user))
return
if (!user.IsAdvancedToolUser())
to_chat(user, "You lack the dexterity to do that!")
return
if (user.stat || user.restrained() || user.incapacitated())
return
if (!Adjacent(user) && !issilicon(user))
to_chat(user, "You can't reach [src] from here.")
return
if (!lit) //It's not lit.
machine_stat &= ~POWEROFF
lit = 1
user.visible_message("[user] ignites the flame beneath the [src].", "You ignite the flame under the [src].")
else //Its on, turn it off.
lit = 0
user.visible_message("[user] douses the flame of the [src].", "You douse the flame.")
playsound(src, 'sound/weapons/gun_flamethrower2.ogg', 40, 1)
update_icon()
/obj/machinery/appliance/cooker/grill/spit/update_icon()
. = ..()
if(lit)
set_light(3, 2, "#FF9933")
icon_state = "[on_icon]"
else
set_light(0)
icon_state = "[off_icon]"
/obj/structure/ashlander/statue
name = "religious statue"
desc = "This statue depicts the Mother, one of the Buried Ones. It has been carved from one giant piece of elderstone. It seems to glow faintly, and the distant ring of the chiming stone fills the air around it. The Mother can be seen standing proudly, one arm outstretched. Floating above her open hand somehow is a small, polished sphere of pure elderstone."
icon_state = "mother_statue"
/obj/structure/ashlander/statue/Initialize(mapload)
. = ..()
set_light(3, 2, "#9463bb")
/obj/structure/ashlander/statue/attack_hand(mob/user, datum/event_args/actor/clickchain/e_args)
var/choice = tgui_alert(user, "Do you wish to pray to the statue?", "Interact With the Statue", list("Yes", "No"))
if(choice != "Yes")
return
else
user.visible_message("[user] prays before the [src].", "You pray before the [src].")
Bless()
/obj/structure/ashlander/statue/proc/Bless(mob/user)
var/mob/living/carbon/human/H = usr
// if(!H.faction == "lavaland")
// to_chat(user, "<span class='danger'>You feel as if an eye briefly regards you, and then turns away.</span>")
// else
H.add_modifier(/datum/modifier/ashlander_blessing, 15 MINUTES)
/datum/modifier/ashlander_blessing
name = "The Mother's Blessing"
desc = "You feel as if a higher power is protecting you."
stacks = MODIFIER_STACK_FORBID
pain_immunity = TRUE
incoming_tox_damage_percent = 0.25
incoming_fire_damage_percent = 0.75
evasion = 5
on_created_text = "<span class='notice'>You feel safe and content. There is a sense that someone is watching over you.</span>"
on_expired_text = "<span class='notice'>The feeling that you are being protected fades, but the sense of contentment lingers.</span>"
//Ashlander Cryo
/obj/machinery/cryopod/robot/door/travel/ashlander
name = "Warrens Passage"
desc = "A mildly obscured passage down into the deep warrens of Surt-nar-Cthardamz."
icon = 'icons/obj/lavaland.dmi'
icon_state = "golicryo_0"
base_icon_state = "golicryo_0"
occupied_icon_state = "golicryo_1"
announce_channel = "Mercenary"
on_store_message = "has descended into the Dark Below."
on_store_name = "The Mother"
on_enter_visible_message = "begins descending into the"
on_enter_occupant_message = "The goliath hide cloak flutters behind you as you begin to walk down the hand-carved stairs."
on_store_visible_message_1 = "echoes with fading footsteps"
on_store_visible_message_2 = "to the dark below."
//Ashlander Chem Master
/obj/machinery/chem_master/ashlander
name = "advanced alchemical station"
desc = "A finely carved bone cabinet designed to hold stone mortars for precise mixing and alchemical work."
icon = 'icons/obj/lavaland.dmi'
icon_state = "ashchem0"
base_icon_state = "ashchem"
use_power = USE_POWER_OFF
//primi = TRUE
/obj/machinery/chem_master/ashlander/ui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ChemPrimi", name)
ui.open()