mirror of
https://github.com/KabKebab/GS13.git
synced 2026-07-16 18:36:54 +01:00
Uploading all files.
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
//Originally coded by ISaidNo, later modified by Kelenius. Ported from Baystation12.
|
||||
|
||||
/obj/structure/closet/crate/secure/loot
|
||||
name = "abandoned crate"
|
||||
desc = "What could be inside?"
|
||||
icon_state = "securecrate"
|
||||
integrity_failure = 0 //no breaking open the crate
|
||||
var/code = null
|
||||
var/lastattempt = null
|
||||
var/attempts = 10
|
||||
var/codelen = 4
|
||||
tamperproof = 90
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/Initialize()
|
||||
. = ..()
|
||||
var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
|
||||
code = ""
|
||||
for(var/i = 0, i < codelen, i++)
|
||||
var/dig = pick(digits)
|
||||
code += dig
|
||||
digits -= dig //there are never matching digits in the answer
|
||||
|
||||
var/loot = rand(1,100) //100 different crates with varying chances of spawning
|
||||
switch(loot)
|
||||
if(1 to 5) //5% chance
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/rum(src)
|
||||
new /obj/item/reagent_containers/food/snacks/grown/ambrosia/deus(src)
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/whiskey(src)
|
||||
new /obj/item/lighter(src)
|
||||
if(6 to 10)
|
||||
new /obj/item/bedsheet(src)
|
||||
new /obj/item/kitchen/knife(src)
|
||||
new /obj/item/wirecutters(src)
|
||||
new /obj/item/screwdriver(src)
|
||||
new /obj/item/weldingtool(src)
|
||||
new /obj/item/hatchet(src)
|
||||
new /obj/item/crowbar(src)
|
||||
if(11 to 15)
|
||||
new /obj/item/reagent_containers/glass/beaker/bluespace(src)
|
||||
if(16 to 20)
|
||||
new /obj/item/stack/ore/diamond(src, 10)
|
||||
if(21 to 25)
|
||||
for(var/i in 1 to 5)
|
||||
new /obj/item/poster/random_contraband(src)
|
||||
if(26 to 30)
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/reagent_containers/glass/beaker/noreact(src)
|
||||
if(31 to 35)
|
||||
new /obj/item/seeds/firelemon(src)
|
||||
if(36 to 40)
|
||||
new /obj/item/melee/baton(src)
|
||||
if(41 to 45)
|
||||
new /obj/item/clothing/under/shorts/red(src)
|
||||
new /obj/item/clothing/under/shorts/blue(src)
|
||||
if(46 to 50)
|
||||
new /obj/item/clothing/under/chameleon(src)
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/clothing/neck/tie/horrible(src)
|
||||
if(51 to 52) // 2% chance
|
||||
new /obj/item/melee/classic_baton(src)
|
||||
if(53 to 54)
|
||||
new /obj/item/toy/balloon(src)
|
||||
if(55 to 56)
|
||||
var/newitem = pick(subtypesof(/obj/item/toy/prize))
|
||||
new newitem(src)
|
||||
if(57 to 58)
|
||||
new /obj/item/toy/syndicateballoon(src)
|
||||
if(59 to 60)
|
||||
new /obj/item/borg/upgrade/modkit/aoe/mobs(src)
|
||||
new /obj/item/clothing/suit/space(src)
|
||||
new /obj/item/clothing/head/helmet/space(src)
|
||||
if(61 to 62)
|
||||
for(var/i in 1 to 5)
|
||||
new /obj/item/clothing/head/kitty(src)
|
||||
new /obj/item/clothing/neck/petcollar(src)
|
||||
if(63 to 64)
|
||||
for(var/i in 1 to rand(4, 7))
|
||||
var/newcoin = pick(/obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/gold, /obj/item/coin/diamond, /obj/item/coin/plasma, /obj/item/coin/uranium)
|
||||
new newcoin(src)
|
||||
if(65 to 66)
|
||||
new /obj/item/clothing/suit/ianshirt(src)
|
||||
new /obj/item/clothing/suit/hooded/ian_costume(src)
|
||||
if(67 to 68)
|
||||
for(var/i in 1 to rand(4, 7))
|
||||
var/newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace)
|
||||
new newitem(src)
|
||||
if(69 to 70)
|
||||
new /obj/item/stack/ore/bluespace_crystal(src, 5)
|
||||
if(71 to 72)
|
||||
new /obj/item/pickaxe/drill(src)
|
||||
if(73 to 74)
|
||||
new /obj/item/pickaxe/drill/jackhammer(src)
|
||||
if(75 to 76)
|
||||
new /obj/item/pickaxe/diamond(src)
|
||||
if(77 to 78)
|
||||
new /obj/item/pickaxe/drill/diamonddrill(src)
|
||||
if(79 to 80)
|
||||
new /obj/item/cane(src)
|
||||
new /obj/item/clothing/head/collectable/tophat(src)
|
||||
if(81 to 82)
|
||||
new /obj/item/gun/energy/plasmacutter(src)
|
||||
if(83 to 84)
|
||||
new /obj/item/toy/katana(src)
|
||||
if(85 to 86)
|
||||
new /obj/item/defibrillator/compact(src)
|
||||
if(87) //1% chance
|
||||
new /obj/item/weed_extract(src)
|
||||
if(88)
|
||||
new /obj/item/organ/brain(src)
|
||||
if(89)
|
||||
new /obj/item/organ/brain/alien(src)
|
||||
if(90)
|
||||
new /obj/item/organ/heart(src)
|
||||
if(91)
|
||||
new /obj/item/soulstone/anybody(src)
|
||||
if(92)
|
||||
new /obj/item/katana(src)
|
||||
if(93)
|
||||
new /obj/item/dnainjector/xraymut(src)
|
||||
if(94)
|
||||
new /obj/item/storage/backpack/clown(src)
|
||||
new /obj/item/clothing/under/rank/clown(src)
|
||||
new /obj/item/clothing/shoes/clown_shoes(src)
|
||||
new /obj/item/pda/clown(src)
|
||||
new /obj/item/clothing/mask/gas/clown_hat(src)
|
||||
new /obj/item/bikehorn(src)
|
||||
new /obj/item/toy/crayon/rainbow(src)
|
||||
new /obj/item/reagent_containers/spray/waterflower(src)
|
||||
if(95)
|
||||
new /obj/item/clothing/under/rank/mime(src)
|
||||
new /obj/item/clothing/shoes/sneakers/black(src)
|
||||
new /obj/item/pda/mime(src)
|
||||
new /obj/item/clothing/gloves/color/white(src)
|
||||
new /obj/item/clothing/mask/gas/mime(src)
|
||||
new /obj/item/clothing/head/beret(src)
|
||||
new /obj/item/clothing/suit/suspenders(src)
|
||||
new /obj/item/toy/crayon/mime(src)
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing(src)
|
||||
if(96)
|
||||
new /obj/item/hand_tele(src)
|
||||
if(97)
|
||||
new /obj/item/clothing/mask/balaclava
|
||||
new /obj/item/gun/ballistic/automatic/pistol(src)
|
||||
new /obj/item/ammo_box/magazine/m10mm(src)
|
||||
if(98)
|
||||
new /obj/item/katana/cursed(src)
|
||||
if(99)
|
||||
new /obj/item/storage/belt/champion(src)
|
||||
new /obj/item/clothing/mask/luchador(src)
|
||||
if(100)
|
||||
new /obj/item/clothing/head/bearpelt(src)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user)
|
||||
if(locked)
|
||||
to_chat(user, "<span class='notice'>The crate is locked with a Deca-code lock.</span>")
|
||||
var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text
|
||||
if(user.canUseTopic(src, BE_CLOSE))
|
||||
var/list/sanitised = list()
|
||||
var/sanitycheck = 1
|
||||
for(var/i=1,i<=length(input),i++) //put the guess into a list
|
||||
sanitised += text2num(copytext(input,i,i+1))
|
||||
for(var/i=1,i<=(length(input)-1),i++) //compare each digit in the guess to all those following it
|
||||
for(var/j=(i+1),j<=length(input),j++)
|
||||
if(sanitised[i] == sanitised[j])
|
||||
sanitycheck = null //if a digit is repeated, reject the input
|
||||
if (input == code)
|
||||
to_chat(user, "<span class='notice'>The crate unlocks!</span>")
|
||||
locked = FALSE
|
||||
cut_overlays()
|
||||
add_overlay("securecrateg")
|
||||
else if (input == null || sanitycheck == null || length(input) != codelen)
|
||||
to_chat(user, "<span class='notice'>You leave the crate alone.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>A red light flashes.</span>")
|
||||
lastattempt = input
|
||||
attempts--
|
||||
if(attempts == 0)
|
||||
boom(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/AltClick(mob/living/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
return attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom.
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/attackby(obj/item/W, mob/user)
|
||||
if(locked)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
to_chat(user, "<span class='notice'>DECA-CODE LOCK REPORT:</span>")
|
||||
if(attempts == 1)
|
||||
to_chat(user, "<span class='warning'>* Anti-Tamper Bomb will activate on next failed access attempt.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>* Anti-Tamper Bomb will activate after [attempts] failed access attempts.</span>")
|
||||
if(lastattempt != null)
|
||||
var/list/guess = list()
|
||||
var/list/answer = list()
|
||||
var/bulls = 0
|
||||
var/cows = 0
|
||||
for(var/i=1,i<=length(lastattempt),i++)
|
||||
guess += text2num(copytext(lastattempt,i,i+1))
|
||||
for(var/i=1,i<=length(lastattempt),i++)
|
||||
answer += text2num(copytext(code,i,i+1))
|
||||
for(var/i = 1, i < codelen + 1, i++) // Go through list and count matches
|
||||
if( answer.Find(guess[i],1,codelen+1))
|
||||
++cows
|
||||
if( answer[i] == guess[i])
|
||||
++bulls
|
||||
--cows
|
||||
|
||||
to_chat(user, "<span class='notice'>Last code attempt, [lastattempt], had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/emag_act(mob/user)
|
||||
if(locked)
|
||||
boom(user)
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/togglelock(mob/user)
|
||||
if(locked)
|
||||
boom(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/deconstruct(disassembled = TRUE)
|
||||
boom()
|
||||
@@ -0,0 +1,378 @@
|
||||
///Mining Base////
|
||||
|
||||
#define ZONE_SET 0
|
||||
#define BAD_ZLEVEL 1
|
||||
#define BAD_AREA 2
|
||||
#define BAD_COORDS 3
|
||||
#define BAD_TURF 4
|
||||
|
||||
/area/shuttle/auxillary_base
|
||||
name = "Auxillary Base"
|
||||
luminosity = 0 //Lighting gets lost when it lands anyway
|
||||
|
||||
|
||||
/obj/machinery/computer/auxillary_base
|
||||
name = "auxillary base management console"
|
||||
icon = 'icons/obj/terminals.dmi'
|
||||
icon_state = "dorm_available"
|
||||
var/shuttleId = "colony_drop"
|
||||
desc = "Allows a deployable expedition base to be dropped from the station to a designated mining location. It can also \
|
||||
interface with the mining shuttle at the landing site if a mobile beacon is also deployed."
|
||||
var/launch_warning = TRUE
|
||||
var/list/turrets = list() //List of connected turrets
|
||||
|
||||
req_one_access = list(ACCESS_CARGO, ACCESS_CONSTRUCTION, ACCESS_HEADS, ACCESS_RESEARCH)
|
||||
var/possible_destinations
|
||||
clockwork = TRUE
|
||||
var/obj/item/gps/internal/base/locator
|
||||
circuit = /obj/item/circuitboard/computer/auxillary_base
|
||||
|
||||
/obj/machinery/computer/auxillary_base/Initialize()
|
||||
. = ..()
|
||||
locator = new(src)
|
||||
|
||||
/obj/machinery/computer/auxillary_base/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/list/options = params2list(possible_destinations)
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
var/dat = "[is_station_level(z) ? "Docking clamps engaged. Standing by." : "Mining Shuttle Uplink: [M ? M.getStatusText() : "*OFFLINE*"]"]<br>"
|
||||
if(M)
|
||||
var/destination_found
|
||||
for(var/obj/docking_port/stationary/S in SSshuttle.stationary)
|
||||
if(!options.Find(S.id))
|
||||
continue
|
||||
if(!M.check_dock(S, silent=TRUE))
|
||||
continue
|
||||
destination_found = 1
|
||||
dat += "<A href='?src=[REF(src)];move=[S.id]'>Send to [S.name]</A><br>"
|
||||
if(!destination_found && is_station_level(z)) //Only available if miners are lazy and did not set an LZ using the remote.
|
||||
dat += "<A href='?src=[REF(src)];random=1'>Prepare for blind drop? (Dangerous)</A><br>"
|
||||
if(LAZYLEN(turrets))
|
||||
dat += "<br><b>Perimeter Defense System:</b> <A href='?src=[REF(src)];turrets_power=on'>Enable All</A> / <A href='?src=[REF(src)];turrets_power=off'>Disable All</A><br> \
|
||||
Units connected: [LAZYLEN(turrets)]<br>\
|
||||
Unit | Condition | Status | Direction | Distance<br>"
|
||||
for(var/PDT in turrets)
|
||||
var/obj/machinery/porta_turret/aux_base/T = PDT
|
||||
var/integrity = max((T.obj_integrity-T.integrity_failure)/(T.max_integrity-T.integrity_failure)*100, 0)
|
||||
var/status
|
||||
if(T.stat & BROKEN)
|
||||
status = "<span class='bad'>ERROR</span>"
|
||||
else if(!T.on)
|
||||
status = "Disabled"
|
||||
else if(T.raised)
|
||||
status = "<span class='average'><b>Firing</b></span>"
|
||||
else
|
||||
status = "<span class='good'>All Clear</span>"
|
||||
dat += "[T.name] | [integrity]% | [status] | [dir2text(get_dir(src, T))] | [get_dist(src, T)]m <A href='?src=[REF(src)];single_turret_power=[REF(T)]'>Toggle Power</A><br>"
|
||||
|
||||
|
||||
dat += "<a href='?src=[REF(user)];mach_close=computer'>Close</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "base management", 550, 300) //width, height
|
||||
popup.set_content("<center>[dat]</center>")
|
||||
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/computer/auxillary_base/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
|
||||
if(href_list["move"])
|
||||
if(!is_station_level(z) && shuttleId == "colony_drop")
|
||||
to_chat(usr, "<span class='warning'>You can't move the base again!</span>")
|
||||
return
|
||||
var/shuttle_error = SSshuttle.moveShuttle(shuttleId, href_list["move"], 1)
|
||||
if(launch_warning)
|
||||
say("<span class='danger'>Launch sequence activated! Prepare for drop!!</span>")
|
||||
playsound(loc, 'sound/machines/warning-buzzer.ogg', 70, 0)
|
||||
launch_warning = FALSE
|
||||
else if(!shuttle_error)
|
||||
say("Shuttle request uploaded. Please stand away from the doors.")
|
||||
else
|
||||
say("Shuttle interface failed.")
|
||||
|
||||
if(href_list["random"] && !possible_destinations)
|
||||
usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam
|
||||
var/list/all_mining_turfs = list()
|
||||
for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING))
|
||||
all_mining_turfs += Z_TURFS(z_level)
|
||||
var/turf/LZ = safepick(all_mining_turfs) //Pick a random mining Z-level turf
|
||||
if(!ismineralturf(LZ) && !istype(LZ, /turf/open/floor/plating/asteroid))
|
||||
//Find a suitable mining turf. Reduces chance of landing in a bad area
|
||||
to_chat(usr, "<span class='warning'>Landing zone scan failed. Please try again.</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(set_landing_zone(LZ, usr) != ZONE_SET)
|
||||
to_chat(usr, "<span class='warning'>Landing zone unsuitable. Please recalculate.</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
if(LAZYLEN(turrets))
|
||||
if(href_list["turrets_power"])
|
||||
for(var/obj/machinery/porta_turret/aux_base/T in turrets)
|
||||
if(href_list["turrets_power"] == "on")
|
||||
T.on = TRUE
|
||||
else
|
||||
T.on = FALSE
|
||||
if(href_list["single_turret_power"])
|
||||
var/obj/machinery/porta_turret/aux_base/T = locate(href_list["single_turret_power"]) in turrets
|
||||
if(istype(T))
|
||||
T.on = !T.on
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/auxillary_base/proc/set_mining_mode()
|
||||
if(is_mining_level(z)) //The console switches to controlling the mining shuttle once landed.
|
||||
req_one_access = list()
|
||||
shuttleId = "mining" //The base can only be dropped once, so this gives the console a new purpose.
|
||||
possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public"
|
||||
|
||||
/obj/machinery/computer/auxillary_base/proc/set_landing_zone(turf/T, mob/user, no_restrictions)
|
||||
var/obj/docking_port/mobile/auxillary_base/base_dock = locate(/obj/docking_port/mobile/auxillary_base) in SSshuttle.mobile
|
||||
if(!base_dock) //Not all maps have an Aux base. This object is useless in that case.
|
||||
to_chat(user, "<span class='warning'>This station is not equipped with an auxillary base. Please contact your Nanotrasen contractor.</span>")
|
||||
return
|
||||
if(!no_restrictions)
|
||||
var/static/list/disallowed_turf_types = typecacheof(list(
|
||||
/turf/closed,
|
||||
/turf/open/lava,
|
||||
/turf/open/indestructible,
|
||||
)) - typecacheof(list(
|
||||
/turf/closed/mineral,
|
||||
))
|
||||
|
||||
if(!is_mining_level(T.z))
|
||||
return BAD_ZLEVEL
|
||||
|
||||
|
||||
var/list/colony_turfs = base_dock.return_ordered_turfs(T.x,T.y,T.z,base_dock.dir)
|
||||
for(var/i in 1 to colony_turfs.len)
|
||||
CHECK_TICK
|
||||
var/turf/place = colony_turfs[i]
|
||||
if(!place)
|
||||
return BAD_COORDS
|
||||
if(!istype(place.loc, /area/lavaland/surface))
|
||||
return BAD_AREA
|
||||
if(disallowed_turf_types[place.type])
|
||||
return BAD_TURF
|
||||
|
||||
|
||||
var/area/A = get_area(T)
|
||||
|
||||
var/obj/docking_port/stationary/landing_zone = new /obj/docking_port/stationary(T)
|
||||
landing_zone.id = "colony_drop([REF(src)])"
|
||||
landing_zone.name = "Landing Zone ([T.x], [T.y])"
|
||||
landing_zone.dwidth = base_dock.dwidth
|
||||
landing_zone.dheight = base_dock.dheight
|
||||
landing_zone.width = base_dock.width
|
||||
landing_zone.height = base_dock.height
|
||||
landing_zone.setDir(base_dock.dir)
|
||||
landing_zone.area_type = A.type
|
||||
|
||||
possible_destinations += "[landing_zone.id];"
|
||||
|
||||
//Serves as a nice mechanic to people get ready for the launch.
|
||||
minor_announce("Auxiliary base landing zone coordinates locked in for [A]. Launch command now available!")
|
||||
to_chat(user, "<span class='notice'>Landing zone set.</span>")
|
||||
return ZONE_SET
|
||||
|
||||
|
||||
/obj/item/assault_pod/mining
|
||||
name = "Landing Field Designator"
|
||||
icon_state = "gangtool-purple"
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
desc = "Deploy to designate the landing zone of the auxillary base."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
shuttle_id = "colony_drop"
|
||||
var/setting = FALSE
|
||||
var/no_restrictions = FALSE //Badmin variable to let you drop the colony ANYWHERE.
|
||||
|
||||
/obj/item/assault_pod/mining/attack_self(mob/living/user)
|
||||
if(setting)
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin setting the landing zone parameters...</span>")
|
||||
setting = TRUE
|
||||
if(!do_after(user, 50, target = user)) //You get a few seconds to cancel if you do not want to drop there.
|
||||
setting = FALSE
|
||||
return
|
||||
setting = FALSE
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/machinery/computer/auxillary_base/AB
|
||||
|
||||
for (var/obj/machinery/computer/auxillary_base/A in GLOB.machines)
|
||||
if(is_station_level(A.z))
|
||||
AB = A
|
||||
break
|
||||
if(!AB)
|
||||
to_chat(user, "<span class='warning'>No auxillary base console detected.</span>")
|
||||
return
|
||||
|
||||
switch(AB.set_landing_zone(T, user, no_restrictions))
|
||||
if(ZONE_SET)
|
||||
qdel(src)
|
||||
if(BAD_ZLEVEL)
|
||||
to_chat(user, "<span class='warning'>This uplink can only be used in a designed mining zone.</span>")
|
||||
if(BAD_AREA)
|
||||
to_chat(user, "<span class='warning'>Unable to acquire a targeting lock. Find an area clear of structures or entirely within one.</span>")
|
||||
if(BAD_COORDS)
|
||||
to_chat(user, "<span class='warning'>Location is too close to the edge of the station's scanning range. Move several paces away and try again.</span>")
|
||||
if(BAD_TURF)
|
||||
to_chat(user, "<span class='warning'>The landing zone contains turfs unsuitable for a base. Make sure you've removed all walls and dangerous terrain from the landing zone.</span>")
|
||||
|
||||
/obj/item/assault_pod/mining/unrestricted
|
||||
name = "omni-locational landing field designator"
|
||||
desc = "Allows the deployment of the mining base ANYWHERE. Use with caution."
|
||||
no_restrictions = TRUE
|
||||
|
||||
|
||||
/obj/docking_port/mobile/auxillary_base
|
||||
name = "auxillary base"
|
||||
id = "colony_drop"
|
||||
//Reminder to map-makers to set these values equal to the size of your base.
|
||||
dheight = 4
|
||||
dwidth = 4
|
||||
width = 9
|
||||
height = 9
|
||||
|
||||
/obj/docking_port/mobile/auxillary_base/takeoff(list/old_turfs, list/new_turfs, list/moved_atoms, rotation, movement_direction, old_dock, area/underlying_old_area)
|
||||
for(var/i in new_turfs)
|
||||
var/turf/place = i
|
||||
if(istype(place, /turf/closed/mineral))
|
||||
place.ScrapeAway()
|
||||
return ..()
|
||||
|
||||
/obj/docking_port/stationary/public_mining_dock
|
||||
name = "public mining base dock"
|
||||
id = "disabled" //The Aux Base has to leave before this can be used as a dock.
|
||||
//Should be checked on the map to ensure it matchs the mining shuttle dimensions.
|
||||
dwidth = 3
|
||||
width = 7
|
||||
height = 5
|
||||
area_type = /area/construction/mining/aux_base
|
||||
|
||||
/obj/structure/mining_shuttle_beacon
|
||||
name = "mining shuttle beacon"
|
||||
desc = "A bluespace beacon calibrated to mark a landing spot for the mining shuttle when deployed near the auxillary mining base."
|
||||
anchored = FALSE
|
||||
density = FALSE
|
||||
var/shuttle_ID = "landing_zone_dock"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "miningbeacon"
|
||||
var/obj/docking_port/stationary/Mport //Linked docking port for the mining shuttle
|
||||
pressure_resistance = 200 //So it does not get blown into lava.
|
||||
var/anti_spam_cd = 0 //The linking process might be a bit intensive, so this here to prevent over use.
|
||||
var/console_range = 15 //Wifi range of the beacon to find the aux base console
|
||||
|
||||
/obj/structure/mining_shuttle_beacon/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(anchored)
|
||||
to_chat(user, "<span class='warning'>Landing zone already set.</span>")
|
||||
return
|
||||
|
||||
if(anti_spam_cd)
|
||||
to_chat(user, "<span class='warning'>[src] is currently recalibrating. Please wait.</span>")
|
||||
return
|
||||
|
||||
anti_spam_cd = 1
|
||||
addtimer(CALLBACK(src, .proc/clear_cooldown), 50)
|
||||
|
||||
var/turf/landing_spot = get_turf(src)
|
||||
|
||||
if(!is_mining_level(landing_spot.z))
|
||||
to_chat(user, "<span class='warning'>This device is only to be used in a mining zone.</span>")
|
||||
return
|
||||
var/obj/machinery/computer/auxillary_base/aux_base_console
|
||||
for(var/obj/machinery/computer/auxillary_base/ABC in GLOB.machines)
|
||||
if(get_dist(landing_spot, ABC) <= console_range)
|
||||
aux_base_console = ABC
|
||||
break
|
||||
if(!aux_base_console) //Needs to be near the base to serve as its dock and configure it to control the mining shuttle.
|
||||
to_chat(user, "<span class='warning'>The auxillary base's console must be within [console_range] meters in order to interface.</span>")
|
||||
return
|
||||
|
||||
//Mining shuttles may not be created equal, so we find the map's shuttle dock and size accordingly.
|
||||
for(var/S in SSshuttle.stationary)
|
||||
var/obj/docking_port/stationary/SM = S //SM is declared outside so it can be checked for null
|
||||
if(SM.id == "mining_home" || SM.id == "mining_away")
|
||||
|
||||
var/area/A = get_area(landing_spot)
|
||||
|
||||
Mport = new(landing_spot)
|
||||
Mport.id = "landing_zone_dock"
|
||||
Mport.name = "auxillary base landing site"
|
||||
Mport.dwidth = SM.dwidth
|
||||
Mport.dheight = SM.dheight
|
||||
Mport.width = SM.width
|
||||
Mport.height = SM.height
|
||||
Mport.setDir(dir)
|
||||
Mport.area_type = A.type
|
||||
|
||||
break
|
||||
if(!Mport)
|
||||
to_chat(user, "<span class='warning'>This station is not equipped with an appropriate mining shuttle. Please contact Nanotrasen Support.</span>")
|
||||
return
|
||||
|
||||
var/obj/docking_port/mobile/mining_shuttle
|
||||
var/list/landing_turfs = list() //List of turfs where the mining shuttle may land.
|
||||
for(var/S in SSshuttle.mobile)
|
||||
var/obj/docking_port/mobile/MS = S
|
||||
if(MS.id != "mining")
|
||||
continue
|
||||
mining_shuttle = MS
|
||||
landing_turfs = mining_shuttle.return_ordered_turfs(x,y,z,dir)
|
||||
break
|
||||
|
||||
if(!mining_shuttle) //Not having a mining shuttle is a map issue
|
||||
to_chat(user, "<span class='warning'>No mining shuttle signal detected. Please contact Nanotrasen Support.</span>")
|
||||
SSshuttle.stationary.Remove(Mport)
|
||||
qdel(Mport)
|
||||
return
|
||||
|
||||
for(var/i in 1 to landing_turfs.len) //You land NEAR the base, not IN it.
|
||||
var/turf/L = landing_turfs[i]
|
||||
if(!L) //This happens at map edges
|
||||
to_chat(user, "<span class='warning'>Unable to secure a valid docking zone. Please try again in an open area near, but not within the aux. mining base.</span>")
|
||||
SSshuttle.stationary.Remove(Mport)
|
||||
qdel(Mport)
|
||||
return
|
||||
if(istype(get_area(L), /area/shuttle/auxillary_base))
|
||||
to_chat(user, "<span class='warning'>The mining shuttle must not land within the mining base itself.</span>")
|
||||
SSshuttle.stationary.Remove(Mport)
|
||||
qdel(Mport)
|
||||
return
|
||||
|
||||
if(mining_shuttle.canDock(Mport) != SHUTTLE_CAN_DOCK)
|
||||
to_chat(user, "<span class='warning'>Unable to secure a valid docking zone. Please try again in an open area near, but not within the aux. mining base.</span>")
|
||||
SSshuttle.stationary.Remove(Mport)
|
||||
qdel(Mport)
|
||||
return
|
||||
|
||||
aux_base_console.set_mining_mode() //Lets the colony park the shuttle there, now that it has a dock.
|
||||
to_chat(user, "<span class='notice'>Mining shuttle calibration successful! Shuttle interface available at base console.</span>")
|
||||
anchored = TRUE //Locks in place to mark the landing zone.
|
||||
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
|
||||
|
||||
/obj/structure/mining_shuttle_beacon/proc/clear_cooldown()
|
||||
anti_spam_cd = 0
|
||||
|
||||
/obj/structure/mining_shuttle_beacon/attack_robot(mob/user)
|
||||
return attack_hand(user) //So borgies can help
|
||||
|
||||
#undef ZONE_SET
|
||||
#undef BAD_ZLEVEL
|
||||
#undef BAD_AREA
|
||||
#undef BAD_COORDS
|
||||
#undef BAD_TURF
|
||||
@@ -0,0 +1,274 @@
|
||||
//Aux base construction console
|
||||
/mob/camera/aiEye/remote/base_construction
|
||||
name = "construction holo-drone"
|
||||
move_on_shuttle = 1 //Allows any curious crew to watch the base after it leaves. (This is safe as the base cannot be modified once it leaves)
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "construction_drone"
|
||||
var/area/starting_area
|
||||
|
||||
/mob/camera/aiEye/remote/base_construction/Initialize()
|
||||
. = ..()
|
||||
starting_area = get_area(loc)
|
||||
|
||||
/mob/camera/aiEye/remote/base_construction/setLoc(var/t)
|
||||
var/area/curr_area = get_area(t)
|
||||
if(curr_area == starting_area || istype(curr_area, /area/shuttle/auxillary_base))
|
||||
return ..()
|
||||
//While players are only allowed to build in the base area, but consoles starting outside the base can move into the base area to begin work.
|
||||
|
||||
/mob/camera/aiEye/remote/base_construction/relaymove(mob/user, direct)
|
||||
dir = direct //This camera eye is visible as a drone, and needs to keep the dir updated
|
||||
..()
|
||||
|
||||
/obj/item/construction/rcd/internal //Base console's internal RCD. Roundstart consoles are filled, rebuilt cosoles start empty.
|
||||
name = "internal RCD"
|
||||
max_matter = 600 //Bigger container and faster speeds due to being specialized and stationary.
|
||||
no_ammo_message = "<span class='warning'>Internal matter exhausted. Please add additional materials.</span>"
|
||||
delay_mod = 0.5
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction
|
||||
name = "base construction console"
|
||||
desc = "An industrial computer integrated with a camera-assisted rapid construction drone."
|
||||
networks = list("ss13")
|
||||
var/obj/item/construction/rcd/internal/RCD //Internal RCD. The computer passes user commands to this in order to avoid massive copypaste.
|
||||
circuit = /obj/item/circuitboard/computer/base_construction
|
||||
off_action = new/datum/action/innate/camera_off/base_construction
|
||||
jump_action = null
|
||||
var/datum/action/innate/aux_base/switch_mode/switch_mode_action = new //Action for switching the RCD's build modes
|
||||
var/datum/action/innate/aux_base/build/build_action = new //Action for using the RCD
|
||||
var/datum/action/innate/aux_base/airlock_type/airlock_mode_action = new //Action for setting the airlock type
|
||||
var/datum/action/innate/aux_base/window_type/window_action = new //Action for setting the window type
|
||||
var/datum/action/innate/aux_base/place_fan/fan_action = new //Action for spawning fans
|
||||
var/fans_remaining = 0 //Number of fans in stock.
|
||||
var/datum/action/innate/aux_base/install_turret/turret_action = new //Action for spawning turrets
|
||||
var/turret_stock = 0 //Turrets in stock
|
||||
var/obj/machinery/computer/auxillary_base/found_aux_console //Tracker for the Aux base console, so the eye can always find it.
|
||||
|
||||
icon_screen = "mining"
|
||||
icon_keyboard = "rd_key"
|
||||
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/Initialize()
|
||||
. = ..()
|
||||
RCD = new(src)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload) //Map spawned consoles have a filled RCD and stocked special structures
|
||||
RCD.matter = RCD.max_matter
|
||||
fans_remaining = 4
|
||||
turret_stock = 4
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/CreateEye()
|
||||
|
||||
var/spawn_spot
|
||||
for(var/obj/machinery/computer/auxillary_base/ABC in GLOB.machines)
|
||||
if(istype(get_area(ABC), /area/shuttle/auxillary_base))
|
||||
found_aux_console = ABC
|
||||
break
|
||||
|
||||
if(found_aux_console)
|
||||
spawn_spot = found_aux_console
|
||||
else
|
||||
spawn_spot = src
|
||||
|
||||
|
||||
eyeobj = new /mob/camera/aiEye/remote/base_construction(get_turf(spawn_spot))
|
||||
eyeobj.origin = src
|
||||
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/rcd_ammo) || istype(W, /obj/item/stack/sheet))
|
||||
RCD.attackby(W, user, params) //If trying to feed the console more materials, pass it along to the RCD.
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/Destroy()
|
||||
qdel(RCD)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/GrantActions(mob/living/user)
|
||||
..()
|
||||
|
||||
if(switch_mode_action)
|
||||
switch_mode_action.target = src
|
||||
switch_mode_action.Grant(user)
|
||||
actions += switch_mode_action
|
||||
|
||||
if(build_action)
|
||||
build_action.target = src
|
||||
build_action.Grant(user)
|
||||
actions += build_action
|
||||
|
||||
if(airlock_mode_action)
|
||||
airlock_mode_action.target = src
|
||||
airlock_mode_action.Grant(user)
|
||||
actions += airlock_mode_action
|
||||
|
||||
if(window_action)
|
||||
window_action.target = src
|
||||
window_action.Grant(user)
|
||||
actions += window_action
|
||||
|
||||
if(fan_action)
|
||||
fan_action.target = src
|
||||
fan_action.Grant(user)
|
||||
actions += fan_action
|
||||
|
||||
if(turret_action)
|
||||
turret_action.target = src
|
||||
turret_action.Grant(user)
|
||||
actions += turret_action
|
||||
|
||||
eyeobj.invisibility = 0 //When the eye is in use, make it visible to players so they know when someone is building.
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/remove_eye_control(mob/living/user)
|
||||
..()
|
||||
eyeobj.invisibility = INVISIBILITY_MAXIMUM //Hide the eye when not in use.
|
||||
|
||||
/datum/action/innate/aux_base //Parent aux base action
|
||||
icon_icon = 'icons/mob/actions/actions_construction.dmi'
|
||||
var/mob/living/C //Mob using the action
|
||||
var/mob/camera/aiEye/remote/base_construction/remote_eye //Console's eye mob
|
||||
var/obj/machinery/computer/camera_advanced/base_construction/B //Console itself
|
||||
|
||||
/datum/action/innate/aux_base/Activate()
|
||||
if(!target)
|
||||
return TRUE
|
||||
C = owner
|
||||
remote_eye = C.remote_control
|
||||
B = target
|
||||
if(!B.RCD) //The console must always have an RCD.
|
||||
B.RCD = new /obj/item/construction/rcd/internal(src) //If the RCD is lost somehow, make a new (empty) one!
|
||||
|
||||
/datum/action/innate/aux_base/proc/check_spot()
|
||||
//Check a loction to see if it is inside the aux base at the station. Camera visbility checks omitted so as to not hinder construction.
|
||||
var/turf/build_target = get_turf(remote_eye)
|
||||
var/area/build_area = get_area(build_target)
|
||||
|
||||
if(!istype(build_area, /area/shuttle/auxillary_base))
|
||||
to_chat(owner, "<span class='warning'>You can only build within the mining base!</span>")
|
||||
return FALSE
|
||||
|
||||
if(!is_station_level(build_target.z))
|
||||
to_chat(owner, "<span class='warning'>The mining base has launched and can no longer be modified.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/action/innate/camera_off/base_construction
|
||||
name = "Log out"
|
||||
|
||||
//*******************FUNCTIONS*******************
|
||||
|
||||
/datum/action/innate/aux_base/build
|
||||
name = "Build"
|
||||
button_icon_state = "build"
|
||||
|
||||
/datum/action/innate/aux_base/build/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!check_spot())
|
||||
return
|
||||
|
||||
var/turf/target_turf = get_turf(remote_eye)
|
||||
var/atom/rcd_target = target_turf
|
||||
|
||||
//Find airlocks and other shite
|
||||
for(var/obj/S in target_turf)
|
||||
if(LAZYLEN(S.rcd_vals(owner,B.RCD)))
|
||||
rcd_target = S //If we don't break out of this loop we'll get the last placed thing
|
||||
|
||||
owner.changeNext_move(CLICK_CD_RANGE)
|
||||
B.RCD.afterattack(rcd_target, owner, TRUE) //Activate the RCD and force it to work remotely!
|
||||
playsound(target_turf, 'sound/items/deconstruct.ogg', 60, 1)
|
||||
|
||||
/datum/action/innate/aux_base/switch_mode
|
||||
name = "Switch Mode"
|
||||
button_icon_state = "builder_mode"
|
||||
|
||||
/datum/action/innate/aux_base/switch_mode/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/buildlist = list("Walls and Floors" = 1,"Airlocks" = 2,"Deconstruction" = 3,"Windows and Grilles" = 4)
|
||||
var/buildmode = input("Set construction mode.", "Base Console", null) in buildlist
|
||||
B.RCD.mode = buildlist[buildmode]
|
||||
to_chat(owner, "Build mode is now [buildmode].")
|
||||
|
||||
/datum/action/innate/aux_base/airlock_type
|
||||
name = "Select Airlock Type"
|
||||
button_icon_state = "airlock_select"
|
||||
|
||||
datum/action/innate/aux_base/airlock_type/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
B.RCD.change_airlock_setting()
|
||||
|
||||
|
||||
datum/action/innate/aux_base/window_type
|
||||
name = "Select Window Type"
|
||||
button_icon_state = "window_select"
|
||||
|
||||
datum/action/innate/aux_base/window_type/Activate()
|
||||
if(..())
|
||||
return
|
||||
B.RCD.toggle_window_type()
|
||||
|
||||
datum/action/innate/aux_base/place_fan
|
||||
name = "Place Tiny Fan"
|
||||
button_icon_state = "build_fan"
|
||||
|
||||
datum/action/innate/aux_base/place_fan/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/turf/fan_turf = get_turf(remote_eye)
|
||||
|
||||
if(!B.fans_remaining)
|
||||
to_chat(owner, "<span class='warning'>[B] is out of fans!</span>")
|
||||
return
|
||||
|
||||
if(!check_spot())
|
||||
return
|
||||
|
||||
if(fan_turf.density)
|
||||
to_chat(owner, "<span class='warning'>Fans may only be placed on a floor.</span>")
|
||||
return
|
||||
|
||||
new /obj/structure/fans/tiny(fan_turf)
|
||||
B.fans_remaining--
|
||||
to_chat(owner, "<span class='notice'>Tiny fan placed. [B.fans_remaining] remaining.</span>")
|
||||
playsound(fan_turf, 'sound/machines/click.ogg', 50, 1)
|
||||
|
||||
datum/action/innate/aux_base/install_turret
|
||||
name = "Install Plasma Anti-Wildlife Turret"
|
||||
button_icon_state = "build_turret"
|
||||
|
||||
datum/action/innate/aux_base/install_turret/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!check_spot())
|
||||
return
|
||||
|
||||
if(!B.turret_stock)
|
||||
to_chat(owner, "<span class='warning'>Unable to construct additional turrets.</span>")
|
||||
return
|
||||
|
||||
var/turf/turret_turf = get_turf(remote_eye)
|
||||
|
||||
if(is_blocked_turf(turret_turf))
|
||||
to_chat(owner, "<span class='warning'>Location is obstructed by something. Please clear the location and try again.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/porta_turret/aux_base/T = new /obj/machinery/porta_turret/aux_base(turret_turf)
|
||||
if(B.found_aux_console)
|
||||
B.found_aux_console.turrets += T //Add new turret to the console's control
|
||||
|
||||
B.turret_stock--
|
||||
to_chat(owner, "<span class='notice'>Turret installation complete!</span>")
|
||||
playsound(turret_turf, 'sound/items/drill_use.ogg', 65, 1)
|
||||
@@ -0,0 +1,184 @@
|
||||
/****************Explorer's Suit and Mask****************/
|
||||
/obj/item/clothing/suit/hooded/explorer
|
||||
name = "explorer suit"
|
||||
desc = "An armoured suit for exploring harsh environments."
|
||||
icon_state = "explorer"
|
||||
item_state = "explorer"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
cold_protection = CHEST|GROIN|LEGS|ARMS
|
||||
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
|
||||
heat_protection = CHEST|GROIN|LEGS|ARMS
|
||||
hoodtype = /obj/item/clothing/head/hooded/explorer
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
resistance_flags = FIRE_PROOF
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer
|
||||
name = "explorer hood"
|
||||
desc = "An armoured hood for exploring harsh environments."
|
||||
icon_state = "explorer"
|
||||
body_parts_covered = HEAD
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
|
||||
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
|
||||
max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/suit/hooded/explorer/standard
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer/standard
|
||||
|
||||
/obj/item/clothing/suit/hooded/explorer/standard/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer/standard/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
/obj/item/clothing/mask/gas/explorer
|
||||
name = "explorer gas mask"
|
||||
desc = "A military-grade gas mask that can be connected to an air supply."
|
||||
icon_state = "gas_mining"
|
||||
visor_flags = BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
|
||||
visor_flags_inv = HIDEFACIALHAIR
|
||||
visor_flags_cover = MASKCOVERSMOUTH
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 20, "acid" = 40)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/mask/gas/explorer/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
/obj/item/clothing/mask/gas/explorer/adjustmask(user)
|
||||
..()
|
||||
w_class = mask_adjusted ? WEIGHT_CLASS_NORMAL : WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/clothing/mask/gas/explorer/folded/Initialize()
|
||||
. = ..()
|
||||
adjustmask()
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment
|
||||
name = "H.E.C.K. suit"
|
||||
desc = "Hostile Environment Cross-Kinetic Suit: A suit designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
|
||||
icon_state = "hostile_env"
|
||||
item_state = "hostile_env"
|
||||
clothing_flags = THICKMATERIAL //not spaceproof
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
slowdown = 0
|
||||
armor = list("melee" = 70, "bullet" = 40, "laser" = 10, "energy" = 10, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/spraycan_paintable)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment/process()
|
||||
var/mob/living/carbon/C = loc
|
||||
if(istype(C) && prob(2)) //cursed by bubblegum
|
||||
if(prob(15))
|
||||
new /datum/hallucination/oh_yeah(C)
|
||||
to_chat(C, "<span class='colossus'><b>[pick("I AM IMMORTAL.","I SHALL TAKE BACK WHAT'S MINE.","I SEE YOU.","YOU CANNOT ESCAPE ME FOREVER.","DEATH CANNOT HOLD ME.")]</b></span>")
|
||||
else
|
||||
to_chat(C, "<span class='warning'>[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]</span>")
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hostile_environment
|
||||
name = "H.E.C.K. helmet"
|
||||
desc = "Hostile Environiment Cross-Kinetic Helmet: A helmet designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
|
||||
icon_state = "hostile_env"
|
||||
item_state = "hostile_env"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
clothing_flags = THICKMATERIAL // no space protection
|
||||
armor = list("melee" = 70, "bullet" = 40, "laser" = 10, "energy" = 10, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hostile_environment/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/spraycan_paintable)
|
||||
update_icon()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hostile_environment/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
var/mutable_appearance/glass_overlay = mutable_appearance(icon, "hostile_env_glass")
|
||||
glass_overlay.appearance_flags = RESET_COLOR
|
||||
add_overlay(glass_overlay)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands)
|
||||
. = ..()
|
||||
if(!isinhands)
|
||||
var/mutable_appearance/M = mutable_appearance('icons/mob/head.dmi', "hostile_env_glass")
|
||||
M.appearance_flags = RESET_COLOR
|
||||
. += M
|
||||
|
||||
|
||||
// CITADEL ADDITIONS BELOW
|
||||
|
||||
/****************SEVA Suit and Mask****************/
|
||||
|
||||
/obj/item/clothing/suit/hooded/explorer/seva
|
||||
name = "SEVA Suit"
|
||||
desc = "A fire-proof suit for exploring hot environments."
|
||||
icon_state = "seva"
|
||||
item_state = "seva"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
|
||||
hoodtype = /obj/item/clothing/head/hooded/explorer/seva
|
||||
armor = list("melee" = 15, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25)
|
||||
resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer/seva
|
||||
name = "SEVA Hood"
|
||||
desc = "A fire-proof hood for exploring hot environments."
|
||||
icon_state = "seva"
|
||||
item_state = "seva"
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25)
|
||||
resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS
|
||||
|
||||
/obj/item/clothing/mask/gas/seva
|
||||
name = "SEVA Mask"
|
||||
desc = "A face-covering plate that can be connected to an air supply. Intended for use with the SEVA Suit."
|
||||
icon_state = "seva"
|
||||
item_state = "seva"
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/****************Exo-Suit and Mask****************/
|
||||
|
||||
/obj/item/clothing/suit/hooded/explorer/exo
|
||||
name = "Exo-suit"
|
||||
desc = "A robust suit for exploring dangerous environments."
|
||||
icon_state = "exo"
|
||||
item_state = "exo"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
|
||||
hoodtype = /obj/item/clothing/head/hooded/explorer/exo
|
||||
armor = list("melee" = 65, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
|
||||
resistance_flags = FIRE_PROOF | GOLIATH_RESISTANCE
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer/exo
|
||||
name = "Exo-hood"
|
||||
desc = "A robust helmet for exploring dangerous environments."
|
||||
icon_state = "exo"
|
||||
item_state = "exo"
|
||||
armor = list("melee" = 65, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
|
||||
resistance_flags = FIRE_PROOF | GOLIATH_RESISTANCE
|
||||
|
||||
/obj/item/clothing/mask/gas/exo
|
||||
name = "Exosuit Mask"
|
||||
desc = "A face-covering mask that can be connected to an air supply. Intended for use with the Exosuit."
|
||||
icon_state = "exo"
|
||||
item_state = "exo"
|
||||
resistance_flags = FIRE_PROOF
|
||||
@@ -0,0 +1,12 @@
|
||||
/**********************Goliath Hide**********************/
|
||||
/obj/item/stack/sheet/animalhide/goliath_hide
|
||||
name = "goliath hide plates"
|
||||
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "goliath_hide"
|
||||
singular_name = "hide plate"
|
||||
max_amount = 6
|
||||
novariants = FALSE
|
||||
item_flags = NOBLUDGEON
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
layer = MOB_LAYER
|
||||
@@ -0,0 +1,414 @@
|
||||
/*********************Mining Hammer****************/
|
||||
/obj/item/twohanded/required/kinetic_crusher
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "mining_hammer1"
|
||||
item_state = "mining_hammer1"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
|
||||
name = "proto-kinetic crusher"
|
||||
desc = "An early design of the proto-kinetic accelerator, it is little more than an combination of various mining tools cobbled together, forming a high-tech club. \
|
||||
While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna."
|
||||
force = 20 //As much as a bone spear, but this is significantly more annoying to carry around due to requiring the use of both hands at all times
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
force_unwielded = 20 //It's never not wielded so these are the same
|
||||
force_wielded = 20
|
||||
throwforce = 5
|
||||
throw_speed = 4
|
||||
light_range = 7
|
||||
light_power = 2
|
||||
armour_penetration = 10
|
||||
materials = list(MAT_METAL=1150, MAT_GLASS=2075)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
|
||||
sharpness = IS_SHARP
|
||||
var/list/trophies = list()
|
||||
var/charged = TRUE
|
||||
var/charge_time = 15
|
||||
var/detonation_damage = 50
|
||||
var/backstab_bonus = 30
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/Destroy()
|
||||
QDEL_LIST(trophies)
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/examine(mob/living/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Mark a large creature with the destabilizing force, then hit them in melee to do <b>[force + detonation_damage]</b> damage.</span>")
|
||||
to_chat(user, "<span class='notice'>Does <b>[force + detonation_damage + backstab_bonus]</b> damage if the target is backstabbed, instead of <b>[force + detonation_damage]</b>.</span>")
|
||||
for(var/t in trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
to_chat(user, "<span class='notice'>It has \a [T] attached, which causes [T.effect_desc()].</span>")
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/attackby(obj/item/I, mob/living/user)
|
||||
if(istype(I, /obj/item/crowbar))
|
||||
if(LAZYLEN(trophies))
|
||||
to_chat(user, "<span class='notice'>You remove [src]'s trophies.</span>")
|
||||
I.play_tool_sound(src)
|
||||
for(var/t in trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
T.remove_from(src, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There are no trophies on [src].</span>")
|
||||
else if(istype(I, /obj/item/crusher_trophy))
|
||||
var/obj/item/crusher_trophy/T = I
|
||||
T.add_to(src, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
|
||||
var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
var/target_health = target.health
|
||||
..()
|
||||
for(var/t in trophies)
|
||||
if(!QDELETED(target))
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
T.on_melee_hit(target, user)
|
||||
if(!QDELETED(C) && !QDELETED(target))
|
||||
C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
|
||||
. = ..()
|
||||
if(istype(target, /obj/item/crusher_trophy))
|
||||
var/obj/item/crusher_trophy/T = target
|
||||
T.add_to(src, user)
|
||||
if(!proximity_flag && charged)//Mark a target, or mine a tile.
|
||||
var/turf/proj_turf = user.loc
|
||||
if(!isturf(proj_turf))
|
||||
return
|
||||
var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(proj_turf)
|
||||
for(var/t in trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
T.on_projectile_fire(D, user)
|
||||
D.preparePixelProjectile(target, user, clickparams)
|
||||
D.firer = user
|
||||
D.hammer_synced = src
|
||||
playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
|
||||
D.fire()
|
||||
charged = FALSE
|
||||
icon_state = "mining_hammer1_uncharged"
|
||||
addtimer(CALLBACK(src, .proc/Recharge), charge_time)
|
||||
return
|
||||
if(proximity_flag && isliving(target))
|
||||
var/mob/living/L = target
|
||||
var/datum/status_effect/crusher_mark/CM = L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)
|
||||
if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK))
|
||||
return
|
||||
var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
var/target_health = L.health
|
||||
for(var/t in trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
T.on_mark_detonation(target, user)
|
||||
if(!QDELETED(L))
|
||||
if(!QDELETED(C))
|
||||
C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did
|
||||
new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
|
||||
var/backstab_dir = get_dir(user, L)
|
||||
var/def_check = L.getarmor(type = "bomb")
|
||||
if((user.dir & backstab_dir) && (L.dir & backstab_dir))
|
||||
if(!QDELETED(C))
|
||||
C.total_damage += detonation_damage + backstab_bonus //cheat a little and add the total before killing it, so certain mobs don't have much lower chances of giving an item
|
||||
L.apply_damage(detonation_damage + backstab_bonus, BRUTE, blocked = def_check)
|
||||
playsound(user, 'sound/weapons/kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
|
||||
else
|
||||
if(!QDELETED(C))
|
||||
C.total_damage += detonation_damage
|
||||
L.apply_damage(detonation_damage, BRUTE, blocked = def_check)
|
||||
|
||||
if(user && lavaland_equipment_pressure_check(get_turf(user))) //CIT CHANGE - makes sure below only happens in low pressure environments
|
||||
user.adjustStaminaLoss(-30)//CIT CHANGE - makes crushers heal stamina
|
||||
|
||||
/obj/item/twohanded/required/kinetic_crusher/proc/Recharge()
|
||||
if(!charged)
|
||||
charged = TRUE
|
||||
icon_state = "mining_hammer1"
|
||||
playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
|
||||
|
||||
//destablizing force
|
||||
/obj/item/projectile/destabilizer
|
||||
name = "destabilizing force"
|
||||
icon_state = "pulse1"
|
||||
nodamage = TRUE
|
||||
damage = 0 //We're just here to mark people. This is still a melee weapon.
|
||||
damage_type = BRUTE
|
||||
flag = "bomb"
|
||||
range = 6
|
||||
log_override = TRUE
|
||||
var/obj/item/twohanded/required/kinetic_crusher/hammer_synced
|
||||
|
||||
/obj/item/projectile/destabilizer/Destroy()
|
||||
hammer_synced = null
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = FALSE)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
var/had_effect = (L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)) //used as a boolean
|
||||
var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(STATUS_EFFECT_CRUSHERMARK, hammer_synced)
|
||||
if(hammer_synced)
|
||||
for(var/t in hammer_synced.trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
T.on_mark_application(target, CM, had_effect)
|
||||
var/target_turf = get_turf(target)
|
||||
if(ismineralturf(target_turf))
|
||||
var/turf/closed/mineral/M = target_turf
|
||||
new /obj/effect/temp_visual/kinetic_blast(M)
|
||||
M.gets_drilled(firer)
|
||||
..()
|
||||
|
||||
//trophies
|
||||
/obj/item/crusher_trophy
|
||||
name = "tail spike"
|
||||
desc = "A strange spike with no usage."
|
||||
icon = 'icons/obj/lavaland/artefacts.dmi'
|
||||
icon_state = "tail_spike"
|
||||
var/bonus_value = 10 //if it has a bonus effect, this is how much that effect is
|
||||
var/denied_type = /obj/item/crusher_trophy
|
||||
|
||||
/obj/item/crusher_trophy/examine(mob/living/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Causes [effect_desc()] when attached to a kinetic crusher.</span>")
|
||||
|
||||
/obj/item/crusher_trophy/proc/effect_desc()
|
||||
return "errors"
|
||||
|
||||
/obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user)
|
||||
if(istype(A, /obj/item/twohanded/required/kinetic_crusher))
|
||||
add_to(A, user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
for(var/t in H.trophies)
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
if(istype(T, denied_type) || istype(src, T.denied_type))
|
||||
to_chat(user, "<span class='warning'>You can't seem to attach [src] to [H]. Maybe remove a few trophies?</span>")
|
||||
return FALSE
|
||||
if(!user.transferItemToLoc(src, H))
|
||||
return
|
||||
H.trophies += src
|
||||
to_chat(user, "<span class='notice'>You attach [src] to [H].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
forceMove(get_turf(H))
|
||||
H.trophies -= src
|
||||
return TRUE
|
||||
|
||||
/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user
|
||||
/obj/item/crusher_trophy/proc/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user
|
||||
/obj/item/crusher_trophy/proc/on_mark_application(mob/living/target, datum/status_effect/crusher_mark/mark, had_mark) //the target, the mark applied, and if the target had a mark before
|
||||
/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user
|
||||
|
||||
//goliath
|
||||
/obj/item/crusher_trophy/goliath_tentacle
|
||||
name = "goliath tentacle"
|
||||
desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "goliath_tentacle"
|
||||
denied_type = /obj/item/crusher_trophy/goliath_tentacle
|
||||
bonus_value = 2
|
||||
var/missing_health_ratio = 0.1
|
||||
var/missing_health_desc = 10
|
||||
|
||||
/obj/item/crusher_trophy/goliath_tentacle/effect_desc()
|
||||
return "mark detonation to do <b>[bonus_value]</b> more damage for every <b>[missing_health_desc]</b> health you are missing"
|
||||
|
||||
/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
var/missing_health = user.health - user.maxHealth
|
||||
missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health
|
||||
missing_health *= bonus_value //multiply the remaining amount by bonus_value
|
||||
if(missing_health > 0)
|
||||
target.adjustBruteLoss(missing_health) //and do that much damage
|
||||
|
||||
//watcher
|
||||
/obj/item/crusher_trophy/watcher_wing
|
||||
name = "watcher wing"
|
||||
desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "watcher_wing"
|
||||
denied_type = /obj/item/crusher_trophy/watcher_wing
|
||||
bonus_value = 10
|
||||
|
||||
/obj/item/crusher_trophy/watcher_wing/effect_desc()
|
||||
return "mark detonation to prevent certain creatures from using certain attacks for <b>[bonus_value*0.1]</b> second\s"
|
||||
|
||||
/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
if(ishostile(target))
|
||||
var/mob/living/simple_animal/hostile/H = target
|
||||
if(H.ranged) //briefly delay ranged attacks
|
||||
if(H.ranged_cooldown >= world.time)
|
||||
H.ranged_cooldown += bonus_value
|
||||
else
|
||||
H.ranged_cooldown = bonus_value + world.time
|
||||
|
||||
//magmawing watcher
|
||||
/obj/item/crusher_trophy/blaster_tubes/magma_wing
|
||||
name = "magmawing watcher wing"
|
||||
desc = "A still-searing wing from a magmawing watcher. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "magma_wing"
|
||||
gender = NEUTER
|
||||
bonus_value = 5
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/magma_wing/effect_desc()
|
||||
return "mark detonation to make the next destabilizer shot deal <b>[bonus_value]</b> damage"
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/magma_wing/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
|
||||
if(deadly_shot)
|
||||
marker.name = "heated [marker.name]"
|
||||
marker.icon_state = "lava"
|
||||
marker.damage = bonus_value
|
||||
marker.nodamage = FALSE
|
||||
deadly_shot = FALSE
|
||||
|
||||
//icewing watcher
|
||||
/obj/item/crusher_trophy/watcher_wing/ice_wing
|
||||
name = "icewing watcher wing"
|
||||
desc = "A carefully preserved frozen wing from an icewing watcher. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "ice_wing"
|
||||
bonus_value = 8
|
||||
|
||||
//legion
|
||||
/obj/item/crusher_trophy/legion_skull
|
||||
name = "legion skull"
|
||||
desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "legion_skull"
|
||||
denied_type = /obj/item/crusher_trophy/legion_skull
|
||||
bonus_value = 3
|
||||
|
||||
/obj/item/crusher_trophy/legion_skull/effect_desc()
|
||||
return "a kinetic crusher to recharge <b>[bonus_value*0.1]</b> second\s faster"
|
||||
|
||||
/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.charge_time -= bonus_value
|
||||
|
||||
/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.charge_time += bonus_value
|
||||
|
||||
//blood-drunk hunter
|
||||
/obj/item/crusher_trophy/miner_eye
|
||||
name = "eye of a blood-drunk hunter"
|
||||
desc = "Its pupil is collapsed and turned to mush. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "hunter_eye"
|
||||
denied_type = /obj/item/crusher_trophy/miner_eye
|
||||
|
||||
/obj/item/crusher_trophy/miner_eye/effect_desc()
|
||||
return "mark detonation to grant stun immunity and <b>90%</b> damage reduction for <b>1</b> second"
|
||||
|
||||
/obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
user.apply_status_effect(STATUS_EFFECT_BLOODDRUNK)
|
||||
|
||||
//ash drake
|
||||
/obj/item/crusher_trophy/tail_spike
|
||||
desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher."
|
||||
denied_type = /obj/item/crusher_trophy/tail_spike
|
||||
bonus_value = 5
|
||||
|
||||
/obj/item/crusher_trophy/tail_spike/effect_desc()
|
||||
return "mark detonation to do <b>[bonus_value]</b> damage to nearby creatures and push them back"
|
||||
|
||||
/obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
for(var/mob/living/L in oview(2, user))
|
||||
if(L.stat == DEAD)
|
||||
continue
|
||||
playsound(L, 'sound/magic/fireball.ogg', 20, 1)
|
||||
new /obj/effect/temp_visual/fire(L.loc)
|
||||
addtimer(CALLBACK(src, .proc/pushback, L, user), 1) //no free backstabs, we push AFTER module stuff is done
|
||||
L.adjustFireLoss(bonus_value, forced = TRUE)
|
||||
|
||||
/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user)
|
||||
if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed
|
||||
step(target, get_dir(user, target))
|
||||
|
||||
//bubblegum
|
||||
/obj/item/crusher_trophy/demon_claws
|
||||
name = "demon claws"
|
||||
desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "demon_claws"
|
||||
gender = PLURAL
|
||||
denied_type = /obj/item/crusher_trophy/demon_claws
|
||||
bonus_value = 10
|
||||
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
|
||||
|
||||
/obj/item/crusher_trophy/demon_claws/effect_desc()
|
||||
return "melee hits to do <b>[bonus_value * 0.2]</b> more damage and heal you for <b>[bonus_value * 0.1]</b>, with <b>5X</b> effect on mark detonation"
|
||||
|
||||
/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.force += bonus_value * 0.2
|
||||
H.force_unwielded += bonus_value * 0.2
|
||||
H.force_wielded += bonus_value * 0.2
|
||||
H.detonation_damage += bonus_value * 0.8
|
||||
|
||||
/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.force -= bonus_value * 0.2
|
||||
H.force_unwielded -= bonus_value * 0.2
|
||||
H.force_wielded -= bonus_value * 0.2
|
||||
H.detonation_damage -= bonus_value * 0.8
|
||||
|
||||
/obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user)
|
||||
user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order)
|
||||
|
||||
/obj/item/crusher_trophy/demon_claws/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
user.heal_ordered_damage(bonus_value * 0.4, damage_heal_order)
|
||||
|
||||
//colossus
|
||||
/obj/item/crusher_trophy/blaster_tubes
|
||||
name = "blaster tubes"
|
||||
desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "blaster_tubes"
|
||||
gender = PLURAL
|
||||
denied_type = /obj/item/crusher_trophy/blaster_tubes
|
||||
bonus_value = 15
|
||||
var/deadly_shot = FALSE
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/effect_desc()
|
||||
return "mark detonation to make the next destabilizer shot deal <b>[bonus_value]</b> damage but move slower"
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
|
||||
if(deadly_shot)
|
||||
marker.name = "deadly [marker.name]"
|
||||
marker.icon_state = "chronobolt"
|
||||
marker.damage = bonus_value
|
||||
marker.nodamage = FALSE
|
||||
marker.speed = 2
|
||||
deadly_shot = FALSE
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
deadly_shot = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_deadly_shot), 300, TIMER_UNIQUE|TIMER_OVERRIDE)
|
||||
|
||||
/obj/item/crusher_trophy/blaster_tubes/proc/reset_deadly_shot()
|
||||
deadly_shot = FALSE
|
||||
|
||||
//hierophant
|
||||
/obj/item/crusher_trophy/vortex_talisman
|
||||
name = "vortex talisman"
|
||||
desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "vortex_talisman"
|
||||
denied_type = /obj/item/crusher_trophy/vortex_talisman
|
||||
|
||||
/obj/item/crusher_trophy/vortex_talisman/effect_desc()
|
||||
return "mark detonation to create a barrier you can pass"
|
||||
|
||||
/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user)
|
||||
var/turf/T = get_turf(user)
|
||||
new /obj/effect/temp_visual/hierophant/wall/crusher(T, user) //a wall only you can pass!
|
||||
var/turf/otherT = get_step(T, turn(user.dir, 90))
|
||||
if(otherT)
|
||||
new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
|
||||
otherT = get_step(T, turn(user.dir, -90))
|
||||
if(otherT)
|
||||
new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
|
||||
|
||||
/obj/effect/temp_visual/hierophant/wall/crusher
|
||||
duration = 75
|
||||
@@ -0,0 +1,66 @@
|
||||
/**********************Lazarus Injector**********************/
|
||||
/obj/item/lazarus_injector
|
||||
name = "lazarus injector"
|
||||
desc = "An injector with a cocktail of nanomachines and chemicals, this device can seemingly raise animals from the dead, making them become friendly to the user. Unfortunately, the process is useless on higher forms of life and incredibly costly, so these were hidden in storage until an executive thought they'd be great motivation for some of their employees."
|
||||
icon = 'icons/obj/syringe.dmi'
|
||||
icon_state = "lazarus_hypo"
|
||||
item_state = "hypo"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
throwforce = 0
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
var/loaded = 1
|
||||
var/malfunctioning = 0
|
||||
var/revive_type = SENTIENCE_ORGANIC //So you can't revive boss monsters or robots with it
|
||||
|
||||
/obj/item/lazarus_injector/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(!loaded)
|
||||
return
|
||||
if(isliving(target) && proximity_flag)
|
||||
if(isanimal(target))
|
||||
var/mob/living/simple_animal/M = target
|
||||
if(M.sentience_type != revive_type)
|
||||
to_chat(user, "<span class='info'>[src] does not work on this sort of creature.</span>")
|
||||
return
|
||||
if(M.stat == DEAD)
|
||||
M.faction = list("neutral")
|
||||
M.revive(full_heal = 1, admin_revive = 1)
|
||||
if(ishostile(target))
|
||||
var/mob/living/simple_animal/hostile/H = M
|
||||
if(malfunctioning)
|
||||
H.faction |= list("lazarus", "[REF(user)]")
|
||||
H.robust_searching = 1
|
||||
H.friends += user
|
||||
H.attack_same = 1
|
||||
log_game("[key_name(user)] has revived hostile mob [key_name(target)] with a malfunctioning lazarus injector")
|
||||
else
|
||||
H.attack_same = 0
|
||||
loaded = 0
|
||||
user.visible_message("<span class='notice'>[user] injects [M] with [src], reviving it.</span>")
|
||||
SSblackbox.record_feedback("tally", "lazarus_injector", 1, M.type)
|
||||
playsound(src,'sound/effects/refill.ogg',50,1)
|
||||
icon_state = "lazarus_empty"
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='info'>[src] is only effective on the dead.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='info'>[src] is only effective on lesser beings.</span>")
|
||||
return
|
||||
|
||||
/obj/item/lazarus_injector/emp_act()
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(!malfunctioning)
|
||||
malfunctioning = 1
|
||||
|
||||
/obj/item/lazarus_injector/examine(mob/user)
|
||||
..()
|
||||
if(!loaded)
|
||||
to_chat(user, "<span class='info'>[src] is empty.</span>")
|
||||
if(malfunctioning)
|
||||
to_chat(user, "<span class='info'>The display on [src] seems to be flickering.</span>")
|
||||
@@ -0,0 +1,139 @@
|
||||
/*****************Marker Beacons**************************/
|
||||
GLOBAL_LIST_INIT(marker_beacon_colors, list(
|
||||
"Random" = FALSE, //not a true color, will pick a random color
|
||||
"Burgundy" = LIGHT_COLOR_FLARE,
|
||||
"Bronze" = LIGHT_COLOR_ORANGE,
|
||||
"Yellow" = LIGHT_COLOR_YELLOW,
|
||||
"Lime" = LIGHT_COLOR_SLIME_LAMP,
|
||||
"Olive" = LIGHT_COLOR_GREEN,
|
||||
"Jade" = LIGHT_COLOR_BLUEGREEN,
|
||||
"Teal" = LIGHT_COLOR_LIGHT_CYAN,
|
||||
"Cerulean" = LIGHT_COLOR_BLUE,
|
||||
"Indigo" = LIGHT_COLOR_DARK_BLUE,
|
||||
"Purple" = LIGHT_COLOR_PURPLE,
|
||||
"Violet" = LIGHT_COLOR_LAVENDER,
|
||||
"Fuchsia" = LIGHT_COLOR_PINK))
|
||||
|
||||
/obj/item/stack/marker_beacon
|
||||
name = "marker beacon"
|
||||
singular_name = "marker beacon"
|
||||
desc = "Prism-brand path illumination devices. Used by miners to mark paths and warn of danger."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "marker"
|
||||
merge_type = /obj/item/stack/marker_beacon
|
||||
max_amount = 100
|
||||
novariants = TRUE
|
||||
var/picked_color = "random"
|
||||
|
||||
/obj/item/stack/marker_beacon/ten //miners start with 10 of these
|
||||
amount = 10
|
||||
|
||||
/obj/item/stack/marker_beacon/thirty //and they're bought in stacks of 1, 10, or 30
|
||||
amount = 30
|
||||
|
||||
/obj/item/stack/marker_beacon/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/stack/marker_beacon/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Use in-hand to place a [singular_name].</span>")
|
||||
to_chat(user, "<span class='notice'>Alt-click to select a color. Current color is [picked_color].</span>")
|
||||
|
||||
/obj/item/stack/marker_beacon/update_icon()
|
||||
icon_state = "[initial(icon_state)][lowertext(picked_color)]"
|
||||
|
||||
/obj/item/stack/marker_beacon/attack_self(mob/user)
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "<span class='warning'>You need more space to place a [singular_name] here.</span>")
|
||||
return
|
||||
if(locate(/obj/structure/marker_beacon) in user.loc)
|
||||
to_chat(user, "<span class='warning'>There is already a [singular_name] here.</span>")
|
||||
return
|
||||
if(use(1))
|
||||
to_chat(user, "<span class='notice'>You activate and anchor [amount ? "a":"the"] [singular_name] in place.</span>")
|
||||
playsound(user, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/structure/marker_beacon/M = new(user.loc, picked_color)
|
||||
transfer_fingerprints_to(M)
|
||||
|
||||
/obj/item/stack/marker_beacon/AltClick(mob/living/user)
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
if(input_color)
|
||||
picked_color = input_color
|
||||
update_icon()
|
||||
|
||||
/obj/structure/marker_beacon
|
||||
name = "marker beacon"
|
||||
desc = "A Prism-brand path illumination device. It is anchored in place and glowing steadily."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "marker"
|
||||
layer = BELOW_OPEN_DOOR_LAYER
|
||||
armor = list("melee" = 50, "bullet" = 75, "laser" = 75, "energy" = 75, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 25, "acid" = 0)
|
||||
max_integrity = 50
|
||||
anchored = TRUE
|
||||
light_range = 2
|
||||
light_power = 3
|
||||
var/remove_speed = 15
|
||||
var/picked_color
|
||||
|
||||
/obj/structure/marker_beacon/Initialize(mapload, set_color)
|
||||
. = ..()
|
||||
picked_color = set_color
|
||||
update_icon()
|
||||
|
||||
/obj/structure/marker_beacon/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
var/obj/item/stack/marker_beacon/M = new(loc)
|
||||
M.picked_color = picked_color
|
||||
M.update_icon()
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/marker_beacon/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to select a color. Current color is [picked_color].</span>")
|
||||
|
||||
/obj/structure/marker_beacon/update_icon()
|
||||
while(!picked_color || !GLOB.marker_beacon_colors[picked_color])
|
||||
picked_color = pick(GLOB.marker_beacon_colors)
|
||||
icon_state = "[initial(icon_state)][lowertext(picked_color)]-on"
|
||||
set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color])
|
||||
|
||||
/obj/structure/marker_beacon/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start picking [src] up...</span>")
|
||||
if(do_after(user, remove_speed, target = src))
|
||||
var/obj/item/stack/marker_beacon/M = new(loc)
|
||||
M.picked_color = picked_color
|
||||
M.update_icon()
|
||||
transfer_fingerprints_to(M)
|
||||
if(user.put_in_hands(M, TRUE)) //delete the beacon if it fails
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
qdel(src) //otherwise delete us
|
||||
|
||||
/obj/structure/marker_beacon/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/stack/marker_beacon))
|
||||
var/obj/item/stack/marker_beacon/M = I
|
||||
to_chat(user, "<span class='notice'>You start picking [src] up...</span>")
|
||||
if(do_after(user, remove_speed, target = src) && M.amount + 1 <= M.max_amount)
|
||||
M.add(1)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
qdel(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/marker_beacon/AltClick(mob/living/user)
|
||||
..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
if(input_color)
|
||||
picked_color = input_color
|
||||
update_icon()
|
||||
@@ -0,0 +1,82 @@
|
||||
/**********************Mining Scanners**********************/
|
||||
/obj/item/mining_scanner
|
||||
desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations."
|
||||
name = "manual mining scanner"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "mining1"
|
||||
item_state = "analyzer"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
var/cooldown = 35
|
||||
var/current_cooldown = 0
|
||||
|
||||
/obj/item/mining_scanner/attack_self(mob/user)
|
||||
if(!user.client)
|
||||
return
|
||||
if(current_cooldown <= world.time)
|
||||
current_cooldown = world.time + cooldown
|
||||
mineral_scan_pulse(get_turf(user))
|
||||
|
||||
//Debug item to identify all ore spread quickly
|
||||
/obj/item/mining_scanner/admin
|
||||
|
||||
/obj/item/mining_scanner/admin/attack_self(mob/user)
|
||||
for(var/turf/closed/mineral/M in world)
|
||||
if(M.scan_state)
|
||||
M.icon_state = M.scan_state
|
||||
qdel(src)
|
||||
|
||||
/obj/item/t_scanner/adv_mining_scanner
|
||||
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. This one has an extended range."
|
||||
name = "advanced automatic mining scanner"
|
||||
icon_state = "mining0"
|
||||
item_state = "analyzer"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
var/cooldown = 35
|
||||
var/current_cooldown = 0
|
||||
var/range = 7
|
||||
|
||||
/obj/item/t_scanner/adv_mining_scanner/lesser
|
||||
name = "automatic mining scanner"
|
||||
desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations."
|
||||
range = 4
|
||||
cooldown = 50
|
||||
|
||||
/obj/item/t_scanner/adv_mining_scanner/scan()
|
||||
if(current_cooldown <= world.time)
|
||||
current_cooldown = world.time + cooldown
|
||||
var/turf/t = get_turf(src)
|
||||
mineral_scan_pulse(t, range)
|
||||
|
||||
/proc/mineral_scan_pulse(turf/T, range = world.view)
|
||||
var/list/minerals = list()
|
||||
for(var/turf/closed/mineral/M in range(range, T))
|
||||
if(M.scan_state)
|
||||
minerals += M
|
||||
if(LAZYLEN(minerals))
|
||||
for(var/turf/closed/mineral/M in minerals)
|
||||
var/obj/effect/temp_visual/mining_overlay/oldC = locate(/obj/effect/temp_visual/mining_overlay) in M
|
||||
if(oldC)
|
||||
qdel(oldC)
|
||||
var/obj/effect/temp_visual/mining_overlay/C = new /obj/effect/temp_visual/mining_overlay(M)
|
||||
C.icon_state = M.scan_state
|
||||
|
||||
/obj/effect/temp_visual/mining_overlay
|
||||
plane = FULLSCREEN_PLANE
|
||||
layer = FLASH_LAYER
|
||||
icon = 'icons/effects/ore_visuals.dmi'
|
||||
appearance_flags = 0 //to avoid having TILE_BOUND in the flags, so that the 480x480 icon states let you see it no matter where you are
|
||||
duration = 35
|
||||
pixel_x = -224
|
||||
pixel_y = -224
|
||||
|
||||
/obj/effect/temp_visual/mining_overlay/Initialize()
|
||||
. = ..()
|
||||
animate(src, alpha = 0, time = duration, easing = EASE_IN)
|
||||
@@ -0,0 +1,137 @@
|
||||
/*****************Pickaxes & Drills & Shovels****************/
|
||||
/obj/item/pickaxe
|
||||
name = "pickaxe"
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "pickaxe"
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
||||
force = 15
|
||||
throwforce = 10
|
||||
item_state = "pickaxe"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
materials = list(MAT_METAL=2000) //one sheet, but where can you make them?
|
||||
tool_behaviour = TOOL_MINING
|
||||
toolspeed = 1
|
||||
usesound = list('sound/effects/picaxe1.ogg', 'sound/effects/picaxe2.ogg', 'sound/effects/picaxe3.ogg')
|
||||
attack_verb = list("hit", "pierced", "sliced", "attacked")
|
||||
|
||||
/obj/item/pickaxe/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] begins digging into [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(use_tool(user, user, 30, volume=50))
|
||||
return BRUTELOSS
|
||||
user.visible_message("<span class='suicide'>[user] couldn't do it!</span>")
|
||||
return SHAME
|
||||
|
||||
/obj/item/pickaxe/mini
|
||||
name = "compact pickaxe"
|
||||
desc = "A smaller, compact version of the standard pickaxe."
|
||||
icon_state = "minipick"
|
||||
force = 10
|
||||
throwforce = 7
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=1000)
|
||||
|
||||
/obj/item/pickaxe/silver
|
||||
name = "silver-plated pickaxe"
|
||||
icon_state = "spickaxe"
|
||||
item_state = "spickaxe"
|
||||
toolspeed = 0.5 //mines faster than a normal pickaxe, bought from mining vendor
|
||||
desc = "A silver-plated pickaxe that mines slightly faster than standard-issue."
|
||||
force = 17
|
||||
materials = list(MAT_SILVER=4000)
|
||||
|
||||
/obj/item/pickaxe/diamond
|
||||
name = "diamond-tipped pickaxe"
|
||||
icon_state = "dpickaxe"
|
||||
item_state = "dpickaxe"
|
||||
toolspeed = 0.3
|
||||
desc = "A pickaxe with a diamond pick head. Extremely robust at cracking rock walls and digging up dirt."
|
||||
force = 19
|
||||
materials = list(MAT_DIAMOND=4000)
|
||||
|
||||
/obj/item/pickaxe/drill
|
||||
name = "mining drill"
|
||||
icon_state = "handdrill"
|
||||
item_state = "jackhammer"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
toolspeed = 0.6 //available from roundstart, faster than a pickaxe.
|
||||
usesound = 'sound/weapons/drill.ogg'
|
||||
hitsound = 'sound/weapons/drill.ogg'
|
||||
desc = "An electric mining drill for the especially scrawny."
|
||||
|
||||
/obj/item/pickaxe/drill/cyborg
|
||||
name = "cyborg mining drill"
|
||||
desc = "An integrated electric mining drill."
|
||||
flags_1 = NONE
|
||||
|
||||
/obj/item/pickaxe/drill/cyborg/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
|
||||
|
||||
/obj/item/pickaxe/drill/diamonddrill
|
||||
name = "diamond-tipped mining drill"
|
||||
icon_state = "diamonddrill"
|
||||
toolspeed = 0.2
|
||||
desc = "Yours is the drill that will pierce the heavens!"
|
||||
|
||||
/obj/item/pickaxe/drill/cyborg/diamond //This is the BORG version!
|
||||
name = "diamond-tipped cyborg mining drill" //To inherit the NODROP_1 flag, and easier to change borg specific drill mechanics.
|
||||
icon_state = "diamonddrill"
|
||||
toolspeed = 0.1
|
||||
|
||||
/obj/item/pickaxe/drill/jackhammer
|
||||
name = "sonic jackhammer"
|
||||
icon_state = "jackhammer"
|
||||
item_state = "jackhammer"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
toolspeed = 0.1 //the epitome of powertools. extremely fast mining, laughs at puny walls
|
||||
usesound = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
hitsound = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
desc = "Cracks rocks with sonic blasts, and doubles as a demolition power tool for smashing walls."
|
||||
|
||||
/obj/item/shovel
|
||||
name = "shovel"
|
||||
desc = "A large tool for digging and moving dirt."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "shovel"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
force = 8
|
||||
tool_behaviour = TOOL_SHOVEL
|
||||
toolspeed = 0.1 //Can only dig ash and thats about it, out classed by the picks and drills no more!
|
||||
usesound = 'sound/effects/shovel_dig.ogg'
|
||||
throwforce = 4
|
||||
item_state = "shovel"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
materials = list(MAT_METAL=350)
|
||||
attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked")
|
||||
sharpness = IS_SHARP
|
||||
|
||||
/obj/item/shovel/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 150, 40) //it's sharp, so it works, but barely.
|
||||
|
||||
/obj/item/shovel/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] begins digging their own grave! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(use_tool(user, user, 30, volume=50))
|
||||
return BRUTELOSS
|
||||
user.visible_message("<span class='suicide'>[user] couldn't do it!</span>")
|
||||
return SHAME
|
||||
|
||||
/obj/item/shovel/spade
|
||||
name = "spade"
|
||||
desc = "A small tool for digging and moving dirt."
|
||||
icon_state = "spade"
|
||||
item_state = "spade"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
|
||||
toolspeed = 0.5
|
||||
force = 5
|
||||
throwforce = 7
|
||||
materials = list(MAT_METAL=50)
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -0,0 +1,128 @@
|
||||
/*********************Hivelord stabilizer****************/
|
||||
/obj/item/hivelordstabilizer
|
||||
name = "stabilizing serum"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle19"
|
||||
desc = "Inject certain types of monster organs with this stabilizer to preserve their healing powers indefinitely."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/obj/item/hivelordstabilizer/afterattack(obj/item/organ/M, mob/user)
|
||||
. = ..()
|
||||
var/obj/item/organ/regenerative_core/C = M
|
||||
if(!istype(C, /obj/item/organ/regenerative_core))
|
||||
to_chat(user, "<span class='warning'>The stabilizer only works on certain types of monster organs, generally regenerative in nature.</span>")
|
||||
return ..()
|
||||
|
||||
C.preserved()
|
||||
to_chat(user, "<span class='notice'>You inject the [M] with the stabilizer. It will no longer go inert.</span>")
|
||||
qdel(src)
|
||||
|
||||
/************************Hivelord core*******************/
|
||||
/obj/item/organ/regenerative_core
|
||||
name = "regenerative core"
|
||||
desc = "All that remains of a hivelord. It can be used to heal completely, but it will rapidly decay into uselessness."
|
||||
icon_state = "roro core 2"
|
||||
item_flags = NOBLUDGEON
|
||||
slot = "hivecore"
|
||||
force = 0
|
||||
actions_types = list(/datum/action/item_action/organ_action/use)
|
||||
var/inert = 0
|
||||
var/preserved = 0
|
||||
|
||||
/obj/item/organ/regenerative_core/Initialize()
|
||||
. = ..()
|
||||
addtimer(CALLBACK(src, .proc/inert_check), 2400)
|
||||
|
||||
/obj/item/organ/regenerative_core/proc/inert_check()
|
||||
if(!preserved)
|
||||
go_inert()
|
||||
|
||||
/obj/item/organ/regenerative_core/proc/preserved(implanted = 0)
|
||||
inert = FALSE
|
||||
preserved = TRUE
|
||||
update_icon()
|
||||
desc = "All that remains of a hivelord. It is preserved, allowing you to use it to heal completely without danger of decay."
|
||||
if(implanted)
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "implanted"))
|
||||
else
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "stabilizer"))
|
||||
|
||||
/obj/item/organ/regenerative_core/proc/go_inert()
|
||||
inert = TRUE
|
||||
name = "decayed regenerative core"
|
||||
desc = "All that remains of a hivelord. It has decayed, and is completely useless."
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "inert"))
|
||||
update_icon()
|
||||
|
||||
/obj/item/organ/regenerative_core/ui_action_click()
|
||||
if(inert)
|
||||
to_chat(owner, "<span class='notice'>[src] breaks down as it tries to activate.</span>")
|
||||
else
|
||||
owner.revive(full_heal = 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/regenerative_core/on_life()
|
||||
..()
|
||||
if(owner.health < owner.crit_threshold)
|
||||
ui_action_click()
|
||||
|
||||
/obj/item/organ/regenerative_core/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag && ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(inert)
|
||||
to_chat(user, "<span class='notice'>[src] has decayed and can no longer be used to heal.</span>")
|
||||
return
|
||||
else
|
||||
if(H.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>[src] are useless on the dead.</span>")
|
||||
return
|
||||
if(H != user)
|
||||
H.visible_message("[user] forces [H] to apply [src]... [H.p_they()] quickly regenerate all injuries!")
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "other"))
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.</span>")
|
||||
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self"))
|
||||
H.revive(full_heal = 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/regenerative_core/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
. = ..()
|
||||
if(!preserved && !inert)
|
||||
preserved(TRUE)
|
||||
owner.visible_message("<span class='notice'>[src] stabilizes as it's inserted.</span>")
|
||||
|
||||
/obj/item/organ/regenerative_core/Remove(mob/living/carbon/M, special = 0)
|
||||
if(!inert && !special)
|
||||
owner.visible_message("<span class='notice'>[src] rapidly decays as it's removed.</span>")
|
||||
go_inert()
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/regenerative_core/prepare_eat()
|
||||
return null
|
||||
|
||||
/*************************Legion core********************/
|
||||
/obj/item/organ/regenerative_core/legion
|
||||
desc = "A strange rock that crackles with power. It can be used to heal completely, but it will rapidly decay into uselessness."
|
||||
icon_state = "legion_soul"
|
||||
|
||||
/obj/item/organ/regenerative_core/legion/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/organ/regenerative_core/update_icon()
|
||||
icon_state = inert ? "legion_soul_inert" : "legion_soul"
|
||||
cut_overlays()
|
||||
if(!inert && !preserved)
|
||||
add_overlay("legion_soul_crackle")
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
/obj/item/organ/regenerative_core/legion/go_inert()
|
||||
..()
|
||||
desc = "[src] has become inert. It has decayed, and is completely useless."
|
||||
|
||||
/obj/item/organ/regenerative_core/legion/preserved(implanted = 0)
|
||||
..()
|
||||
desc = "[src] has been stabilized. It is preserved, allowing you to use it to heal completely without danger of decay."
|
||||
@@ -0,0 +1,117 @@
|
||||
/**********************Resonator**********************/
|
||||
/obj/item/resonator
|
||||
name = "resonator"
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "resonator"
|
||||
item_state = "resonator"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
|
||||
desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It does increased damage in low pressure."
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 18
|
||||
throwforce = 10
|
||||
var/burst_time = 30
|
||||
var/fieldlimit = 6
|
||||
var/list/fields = list()
|
||||
var/quick_burst_mod = 0.8
|
||||
|
||||
/obj/item/resonator/upgraded
|
||||
name = "upgraded resonator"
|
||||
desc = "An upgraded version of the resonator that can produce more fields at once, as well as having no damage penalty for bursting a resonance field early."
|
||||
icon_state = "resonator_u"
|
||||
item_state = "resonator_u"
|
||||
force = 20
|
||||
fieldlimit = 8
|
||||
quick_burst_mod = 1
|
||||
|
||||
/obj/item/resonator/attack_self(mob/user)
|
||||
if(burst_time == 50)
|
||||
burst_time = 30
|
||||
to_chat(user, "<span class='info'>You set the resonator's fields to detonate after 3 seconds.</span>")
|
||||
else
|
||||
burst_time = 50
|
||||
to_chat(user, "<span class='info'>You set the resonator's fields to detonate after 5 seconds.</span>")
|
||||
|
||||
/obj/item/resonator/proc/CreateResonance(target, mob/user)
|
||||
var/turf/T = get_turf(target)
|
||||
var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in T
|
||||
if(R)
|
||||
R.damage_multiplier = quick_burst_mod
|
||||
R.burst()
|
||||
return
|
||||
if(LAZYLEN(fields) < fieldlimit)
|
||||
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
|
||||
if(check_allowed_items(target, 1))
|
||||
CreateResonance(target, user)
|
||||
return TRUE
|
||||
|
||||
//resonance field, crushes rock, damages mobs
|
||||
/obj/effect/temp_visual/resonance
|
||||
name = "resonance field"
|
||||
desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures. More damaging in low pressure environments."
|
||||
icon_state = "shield1"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
duration = 50
|
||||
var/resonance_damage = 20
|
||||
var/damage_multiplier = 1
|
||||
var/creator
|
||||
var/obj/item/resonator/res
|
||||
|
||||
/obj/effect/temp_visual/resonance/Initialize(mapload, set_creator, set_resonator, set_duration)
|
||||
duration = set_duration
|
||||
. = ..()
|
||||
creator = set_creator
|
||||
res = set_resonator
|
||||
if(res)
|
||||
res.fields += src
|
||||
playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
|
||||
transform = matrix()*0.75
|
||||
animate(src, transform = matrix()*1.5, time = duration)
|
||||
deltimer(timerid)
|
||||
timerid = addtimer(CALLBACK(src, .proc/burst), duration, TIMER_STOPPABLE)
|
||||
|
||||
/obj/effect/temp_visual/resonance/Destroy()
|
||||
if(res)
|
||||
res.fields -= src
|
||||
res = null
|
||||
creator = null
|
||||
. = ..()
|
||||
|
||||
/obj/effect/temp_visual/resonance/proc/check_pressure(turf/proj_turf)
|
||||
if(!proj_turf)
|
||||
proj_turf = get_turf(src)
|
||||
resonance_damage = initial(resonance_damage)
|
||||
if(lavaland_equipment_pressure_check(proj_turf))
|
||||
name = "strong [initial(name)]"
|
||||
resonance_damage *= 3
|
||||
else
|
||||
name = initial(name)
|
||||
resonance_damage *= damage_multiplier
|
||||
|
||||
/obj/effect/temp_visual/resonance/proc/burst()
|
||||
var/turf/T = get_turf(src)
|
||||
new /obj/effect/temp_visual/resonance_crush(T)
|
||||
if(ismineralturf(T))
|
||||
var/turf/closed/mineral/M = T
|
||||
M.gets_drilled(creator)
|
||||
check_pressure(T)
|
||||
playsound(T,'sound/weapons/resonator_blast.ogg',50,1)
|
||||
for(var/mob/living/L in T)
|
||||
if(creator)
|
||||
log_combat(creator, L, "used a resonator field on", "resonator")
|
||||
to_chat(L, "<span class='userdanger'>[src] ruptured with you in it!</span>")
|
||||
L.apply_damage(resonance_damage, BRUTE)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/temp_visual/resonance_crush
|
||||
icon_state = "shield1"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
duration = 4
|
||||
|
||||
/obj/effect/temp_visual/resonance_crush/Initialize()
|
||||
. = ..()
|
||||
transform = matrix()*1.5
|
||||
animate(src, transform = matrix()*0.1, alpha = 50, time = 4)
|
||||
@@ -0,0 +1,310 @@
|
||||
/*****************************Survival Pod********************************/
|
||||
/area/survivalpod
|
||||
name = "\improper Emergency Shelter"
|
||||
icon_state = "away"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
|
||||
requires_power = FALSE
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
valid_territory = FALSE
|
||||
|
||||
//Survival Capsule
|
||||
/obj/item/survivalcapsule
|
||||
name = "bluespace shelter capsule"
|
||||
desc = "An emergency shelter stored within a pocket of bluespace."
|
||||
icon_state = "capsule"
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/template_id = "shelter_alpha"
|
||||
var/datum/map_template/shelter/template
|
||||
var/used = FALSE
|
||||
|
||||
/obj/item/survivalcapsule/proc/get_template()
|
||||
if(template)
|
||||
return
|
||||
template = SSmapping.shelter_templates[template_id]
|
||||
if(!template)
|
||||
throw EXCEPTION("Shelter template ([template_id]) not found!")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/survivalcapsule/Destroy()
|
||||
template = null // without this, capsules would be one use. per round.
|
||||
. = ..()
|
||||
|
||||
/obj/item/survivalcapsule/examine(mob/user)
|
||||
. = ..()
|
||||
get_template()
|
||||
to_chat(user, "This capsule has the [template.name] stored.")
|
||||
to_chat(user, template.description)
|
||||
|
||||
/obj/item/survivalcapsule/attack_self()
|
||||
//Can't grab when capsule is New() because templates aren't loaded then
|
||||
get_template()
|
||||
if(!used)
|
||||
loc.visible_message("<span class='warning'>\The [src] begins to shake. Stand back!</span>")
|
||||
used = TRUE
|
||||
sleep(50)
|
||||
var/turf/deploy_location = get_turf(src)
|
||||
var/status = template.check_deploy(deploy_location)
|
||||
switch(status)
|
||||
if(SHELTER_DEPLOY_BAD_AREA)
|
||||
src.loc.visible_message("<span class='warning'>\The [src] will not function in this area.</span>")
|
||||
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS)
|
||||
var/width = template.width
|
||||
var/height = template.height
|
||||
src.loc.visible_message("<span class='warning'>\The [src] doesn't have room to deploy! You need to clear a [width]x[height] area!</span>")
|
||||
|
||||
if(status != SHELTER_DEPLOY_ALLOWED)
|
||||
used = FALSE
|
||||
return
|
||||
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
|
||||
var/turf/T = deploy_location
|
||||
if(!is_mining_level(T.z)) //only report capsules away from the mining/lavaland level
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] activated a bluespace capsule away from the mining level! [ADMIN_VERBOSEJMP(T)]")
|
||||
log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [AREACOORD(T)]")
|
||||
template.load(deploy_location, centered = TRUE)
|
||||
new /obj/effect/particle_effect/smoke(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/survivalcapsule/luxury
|
||||
name = "luxury bluespace shelter capsule"
|
||||
desc = "An exorbitantly expensive luxury suite stored within a pocket of bluespace."
|
||||
template_id = "shelter_beta"
|
||||
|
||||
//Pod objects
|
||||
|
||||
//Window
|
||||
/obj/structure/window/shuttle/survival_pod
|
||||
name = "pod window"
|
||||
icon = 'icons/obj/smooth_structures/pod_window.dmi'
|
||||
icon_state = "smooth"
|
||||
smooth = SMOOTH_MORE
|
||||
canSmoothWith = list(/turf/closed/wall/mineral/titanium/survival, /obj/machinery/door/airlock/survival_pod, /obj/structure/window/shuttle/survival_pod)
|
||||
|
||||
/obj/structure/window/shuttle/survival_pod/spawner/north
|
||||
dir = NORTH
|
||||
|
||||
/obj/structure/window/shuttle/survival_pod/spawner/east
|
||||
dir = EAST
|
||||
|
||||
/obj/structure/window/shuttle/survival_pod/spawner/west
|
||||
dir = WEST
|
||||
|
||||
/obj/structure/window/reinforced/survival_pod
|
||||
name = "pod window"
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "pwindow"
|
||||
|
||||
//Door
|
||||
/obj/machinery/door/airlock/survival_pod
|
||||
name = "airlock"
|
||||
icon = 'icons/obj/doors/airlocks/survival/survival.dmi'
|
||||
overlays_file = 'icons/obj/doors/airlocks/survival/survival_overlays.dmi'
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_pod
|
||||
|
||||
/obj/machinery/door/airlock/survival_pod/glass
|
||||
opacity = FALSE
|
||||
glass = TRUE
|
||||
|
||||
/obj/structure/door_assembly/door_assembly_pod
|
||||
name = "pod airlock assembly"
|
||||
icon = 'icons/obj/doors/airlocks/survival/survival.dmi'
|
||||
base_name = "pod airlock"
|
||||
overlays_file = 'icons/obj/doors/airlocks/survival/survival_overlays.dmi'
|
||||
airlock_type = /obj/machinery/door/airlock/survival_pod
|
||||
glass_type = /obj/machinery/door/airlock/survival_pod/glass
|
||||
|
||||
//Windoor
|
||||
/obj/machinery/door/window/survival_pod
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "windoor"
|
||||
base_state = "windoor"
|
||||
|
||||
//Table
|
||||
/obj/structure/table/survival_pod
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "table"
|
||||
smooth = SMOOTH_FALSE
|
||||
|
||||
//Sleeper
|
||||
/obj/machinery/sleeper/survival_pod
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "sleeper"
|
||||
|
||||
/obj/machinery/sleeper/survival_pod/update_icon()
|
||||
if(state_open)
|
||||
cut_overlays()
|
||||
else
|
||||
add_overlay("sleeper_cover")
|
||||
|
||||
//Computer
|
||||
/obj/item/gps/computer
|
||||
name = "pod computer"
|
||||
icon_state = "pod_computer"
|
||||
icon = 'icons/obj/lavaland/pod_computer.dmi'
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
pixel_y = -32
|
||||
|
||||
/obj/item/gps/computer/wrench_act(mob/living/user, obj/item/I)
|
||||
if(flags_1 & NODECONSTRUCT_1)
|
||||
return TRUE
|
||||
|
||||
user.visible_message("<span class='warning'>[user] disassembles [src].</span>",
|
||||
"<span class='notice'>You start to disassemble [src]...</span>", "You hear clanking and banging noises.")
|
||||
if(I.use_tool(src, user, 20, volume=50))
|
||||
new /obj/item/gps(loc)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/gps/computer/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
attack_self(user)
|
||||
|
||||
//Bed
|
||||
/obj/structure/bed/pod
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "bed"
|
||||
|
||||
//Survival Storage Unit
|
||||
/obj/machinery/smartfridge/survival_pod
|
||||
name = "survival pod storage"
|
||||
desc = "A heated storage unit."
|
||||
icon_state = "donkvendor"
|
||||
icon = 'icons/obj/lavaland/donkvendor.dmi'
|
||||
light_range = 5
|
||||
light_power = 1.2
|
||||
light_color = "#DDFFD3"
|
||||
max_n_of_items = 10
|
||||
pixel_y = -4
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
var/empty = FALSE
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/Initialize(mapload)
|
||||
. = ..()
|
||||
if(empty)
|
||||
return
|
||||
for(var/i in 1 to 5)
|
||||
var/obj/item/reagent_containers/food/snacks/donkpocket/warm/W = new(src)
|
||||
load(W)
|
||||
if(prob(50))
|
||||
var/obj/item/storage/pill_bottle/dice/D = new(src)
|
||||
load(D)
|
||||
else
|
||||
var/obj/item/instrument/guitar/G = new(src)
|
||||
load(G)
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/accept_check(obj/item/O)
|
||||
return isitem(O)
|
||||
|
||||
/obj/machinery/smartfridge/survival_pod/empty
|
||||
name = "dusty survival pod storage"
|
||||
desc = "A heated storage unit. This one's seen better days."
|
||||
empty = TRUE
|
||||
|
||||
//Fans
|
||||
/obj/structure/fans
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "fans"
|
||||
name = "environmental regulation system"
|
||||
desc = "A large machine releasing a constant gust of air."
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
var/buildstacktype = /obj/item/stack/sheet/metal
|
||||
var/buildstackamount = 5
|
||||
CanAtmosPass = ATMOS_PASS_NO
|
||||
|
||||
/obj/structure/fans/deconstruct()
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(buildstacktype)
|
||||
new buildstacktype(loc,buildstackamount)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/fans/wrench_act(mob/living/user, obj/item/I)
|
||||
if(flags_1 & NODECONSTRUCT_1)
|
||||
return TRUE
|
||||
|
||||
user.visible_message("<span class='warning'>[user] disassembles [src].</span>",
|
||||
"<span class='notice'>You start to disassemble [src]...</span>", "You hear clanking and banging noises.")
|
||||
if(I.use_tool(src, user, 20, volume=50))
|
||||
deconstruct()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/fans/tiny
|
||||
name = "tiny fan"
|
||||
desc = "A tiny fan, releasing a thin gust of air."
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
density = FALSE
|
||||
icon_state = "fan_tiny"
|
||||
buildstackamount = 2
|
||||
|
||||
/obj/structure/fans/Initialize(mapload)
|
||||
. = ..()
|
||||
air_update_turf(1)
|
||||
|
||||
//Inivisible, indestructible fans
|
||||
/obj/structure/fans/tiny/invisible
|
||||
name = "air flow blocker"
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
//Signs
|
||||
/obj/structure/sign/mining
|
||||
name = "nanotrasen mining corps sign"
|
||||
desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims."
|
||||
icon = 'icons/turf/walls/survival_pod_walls.dmi'
|
||||
icon_state = "ntpod"
|
||||
|
||||
/obj/structure/sign/mining/survival
|
||||
name = "shelter sign"
|
||||
desc = "A high visibility sign designating a safe shelter."
|
||||
icon = 'icons/turf/walls/survival_pod_walls.dmi'
|
||||
icon_state = "survival"
|
||||
|
||||
//Fluff
|
||||
/obj/structure/tubes
|
||||
icon_state = "tubes"
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
name = "tubes"
|
||||
anchored = TRUE
|
||||
layer = BELOW_MOB_LAYER
|
||||
density = FALSE
|
||||
|
||||
/obj/item/fakeartefact
|
||||
name = "expensive forgery"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
var/possible = list(/obj/item/ship_in_a_bottle,
|
||||
/obj/item/gun/energy/pulse,
|
||||
/obj/item/book/granter/martial/carp,
|
||||
/obj/item/melee/supermatter_sword,
|
||||
/obj/item/shield/changeling,
|
||||
/obj/item/lava_staff,
|
||||
/obj/item/energy_katana,
|
||||
/obj/item/hierophant_club,
|
||||
/obj/item/his_grace,
|
||||
/obj/item/gun/ballistic/minigun,
|
||||
/obj/item/gun/ballistic/automatic/l6_saw,
|
||||
/obj/item/gun/magic/staff/chaos,
|
||||
/obj/item/gun/magic/staff/spellblade,
|
||||
/obj/item/gun/magic/wand/death,
|
||||
/obj/item/gun/magic/wand/fireball,
|
||||
/obj/item/stack/telecrystal/twenty,
|
||||
/obj/item/nuke_core,
|
||||
/obj/item/phylactery,
|
||||
/obj/item/banhammer)
|
||||
|
||||
/obj/item/fakeartefact/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/I = pick(possible)
|
||||
name = initial(I.name)
|
||||
icon = initial(I.icon)
|
||||
desc = initial(I.desc)
|
||||
icon_state = initial(I.icon_state)
|
||||
item_state = initial(I.item_state)
|
||||
@@ -0,0 +1,14 @@
|
||||
/**********************Mining Equipment Vendor Items**************************/
|
||||
//misc stuff you can buy from the vendor that has special code but doesn't really need its own file
|
||||
|
||||
/**********************Facehugger toy**********************/
|
||||
/obj/item/clothing/mask/facehugger/toy
|
||||
item_state = "facehugger_inactive"
|
||||
desc = "A toy often used to play pranks on other miners by putting it in their beds. It takes a bit to recharge after latching onto something."
|
||||
throwforce = 0
|
||||
real = 0
|
||||
sterile = 1
|
||||
tint = 3 //Makes it feel more authentic when it latches on
|
||||
|
||||
/obj/item/clothing/mask/facehugger/toy/Die()
|
||||
return
|
||||
@@ -0,0 +1,99 @@
|
||||
/**********************Jaunter**********************/
|
||||
/obj/item/wormhole_jaunter
|
||||
name = "wormhole jaunter"
|
||||
desc = "A single use device harnessing outdated wormhole technology, Nanotrasen has since turned its eyes to blue space for more accurate teleportation. The wormholes it creates are unpleasant to travel through, to say the least.\nThanks to modifications provided by the Free Golems, this jaunter can be worn on the belt to provide protection from chasms."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "Jaunter"
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
throwforce = 0
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
|
||||
/obj/item/wormhole_jaunter/attack_self(mob/user)
|
||||
user.visible_message("<span class='notice'>[user.name] activates the [src.name]!</span>")
|
||||
SSblackbox.record_feedback("tally", "jaunter", 1, "User") // user activated
|
||||
activate(user, TRUE)
|
||||
|
||||
/obj/item/wormhole_jaunter/proc/turf_check(mob/user)
|
||||
var/turf/device_turf = get_turf(user)
|
||||
if(!device_turf || is_centcom_level(device_turf.z) || is_reserved_level(device_turf.z))
|
||||
to_chat(user, "<span class='notice'>You're having difficulties getting the [src.name] to work.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/wormhole_jaunter/proc/get_destinations(mob/user)
|
||||
var/list/destinations = list()
|
||||
|
||||
for(var/obj/item/beacon/B in GLOB.teleportbeacons)
|
||||
var/turf/T = get_turf(B)
|
||||
if(is_station_level(T.z))
|
||||
destinations += B
|
||||
|
||||
return destinations
|
||||
|
||||
/obj/item/wormhole_jaunter/proc/activate(mob/user, adjacent)
|
||||
if(!turf_check(user))
|
||||
return
|
||||
|
||||
var/list/L = get_destinations(user)
|
||||
if(!L.len)
|
||||
to_chat(user, "<span class='notice'>The [src.name] found no beacons in the world to anchor a wormhole to.</span>")
|
||||
return
|
||||
var/chosen_beacon = pick(L)
|
||||
var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon))
|
||||
if(adjacent)
|
||||
try_move_adjacent(J)
|
||||
playsound(src,'sound/effects/sparks4.ogg',50,1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/wormhole_jaunter/emp_act(power)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
|
||||
var/mob/M = loc
|
||||
if(istype(M))
|
||||
var/triggered = FALSE
|
||||
if(M.get_item_by_slot(SLOT_BELT) == src)
|
||||
if(power == 1)
|
||||
triggered = TRUE
|
||||
else if(power == 2 && prob(50))
|
||||
triggered = TRUE
|
||||
|
||||
if(triggered)
|
||||
M.visible_message("<span class='warning'>[src] overloads and activates!</span>")
|
||||
SSblackbox.record_feedback("tally", "jaunter", 1, "EMP") // EMP accidental activation
|
||||
activate(M)
|
||||
|
||||
/obj/item/wormhole_jaunter/proc/chasm_react(mob/user)
|
||||
if(user.get_item_by_slot(SLOT_BELT) == src)
|
||||
to_chat(user, "Your [name] activates, saving you from the chasm!</span>")
|
||||
SSblackbox.record_feedback("tally", "jaunter", 1, "Chasm") // chasm automatic activation
|
||||
activate(user, FALSE)
|
||||
else
|
||||
to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.</span>")
|
||||
|
||||
//jaunter tunnel
|
||||
/obj/effect/portal/jaunt_tunnel
|
||||
name = "jaunt tunnel"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "bhole3"
|
||||
desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon."
|
||||
mech_sized = TRUE //save your ripley
|
||||
innate_accuracy_penalty = 6
|
||||
|
||||
/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
// KERPLUNK
|
||||
playsound(M,'sound/weapons/resonator_blast.ogg',50,1)
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/L = M
|
||||
L.Knockdown(60)
|
||||
if(ishuman(L))
|
||||
shake_camera(L, 20, 1)
|
||||
addtimer(CALLBACK(L, /mob/living/carbon.proc/vomit), 20)
|
||||
@@ -0,0 +1,190 @@
|
||||
GLOBAL_LIST_EMPTY(total_extraction_beacons)
|
||||
|
||||
/obj/item/extraction_pack
|
||||
name = "fulton extraction pack"
|
||||
desc = "A balloon that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
|
||||
icon = 'icons/obj/fulton.dmi'
|
||||
icon_state = "extraction_pack"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/obj/structure/extraction_point/beacon
|
||||
var/list/beacon_networks = list("station")
|
||||
var/uses_left = 3
|
||||
var/can_use_indoors
|
||||
var/safe_for_living_creatures = 1
|
||||
|
||||
/obj/item/extraction_pack/examine()
|
||||
. = ..()
|
||||
usr.show_message("It has [uses_left] use\s remaining.", 1)
|
||||
|
||||
/obj/item/extraction_pack/attack_self(mob/user)
|
||||
var/list/possible_beacons = list()
|
||||
for(var/B in GLOB.total_extraction_beacons)
|
||||
var/obj/structure/extraction_point/EP = B
|
||||
if(EP.beacon_network in beacon_networks)
|
||||
possible_beacons += EP
|
||||
|
||||
if(!possible_beacons.len)
|
||||
to_chat(user, "There are no extraction beacons in existence!")
|
||||
return
|
||||
|
||||
else
|
||||
var/A
|
||||
|
||||
A = input("Select a beacon to connect to", "Balloon Extraction Pack", A) as null|anything in possible_beacons
|
||||
|
||||
if(!A)
|
||||
return
|
||||
beacon = A
|
||||
to_chat(user, "You link the extraction pack to the beacon system.")
|
||||
|
||||
/obj/item/extraction_pack/afterattack(atom/movable/A, mob/living/carbon/human/user, flag, params)
|
||||
. = ..()
|
||||
if(!beacon)
|
||||
to_chat(user, "[src] is not linked to a beacon, and cannot be used.")
|
||||
return
|
||||
if(!can_use_indoors)
|
||||
var/area/area = get_area(A)
|
||||
if(!area.outdoors)
|
||||
to_chat(user, "[src] can only be used on things that are outdoors!")
|
||||
return
|
||||
if(!flag)
|
||||
return
|
||||
if(!istype(A))
|
||||
return
|
||||
else
|
||||
if(!safe_for_living_creatures && check_for_living_mobs(A))
|
||||
to_chat(user, "[src] is not safe for use with living creatures, they wouldn't survive the trip back!")
|
||||
return
|
||||
if(!isturf(A.loc)) // no extracting stuff inside other stuff
|
||||
return
|
||||
if(A.anchored)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start attaching the pack to [A]...</span>")
|
||||
if(do_after(user,50,target=A))
|
||||
to_chat(user, "<span class='notice'>You attach the pack to [A] and activate it.</span>")
|
||||
if(loc == user && istype(user.back, /obj/item/storage/backpack))
|
||||
var/obj/item/storage/backpack/B = user.back
|
||||
SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
|
||||
uses_left--
|
||||
if(uses_left <= 0)
|
||||
user.transferItemToLoc(src, A, TRUE)
|
||||
var/mutable_appearance/balloon
|
||||
var/mutable_appearance/balloon2
|
||||
var/mutable_appearance/balloon3
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
M.Knockdown(320) // Keep them from moving during the duration of the extraction
|
||||
M.buckled = 0 // Unbuckle them to prevent anchoring problems
|
||||
else
|
||||
A.anchored = TRUE
|
||||
A.density = FALSE
|
||||
var/obj/effect/extraction_holder/holder_obj = new(A.loc)
|
||||
holder_obj.appearance = A.appearance
|
||||
A.forceMove(holder_obj)
|
||||
balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
|
||||
balloon2.pixel_y = 10
|
||||
balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.add_overlay(balloon2)
|
||||
sleep(4)
|
||||
balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
|
||||
balloon.pixel_y = 10
|
||||
balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon2)
|
||||
holder_obj.add_overlay(balloon)
|
||||
playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 10, time = 20)
|
||||
sleep(20)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 1000, time = 30)
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/L = A
|
||||
L.SetUnconscious(0)
|
||||
L.drowsyness = 0
|
||||
L.SetSleeping(0)
|
||||
sleep(30)
|
||||
var/list/flooring_near_beacon = list()
|
||||
for(var/turf/open/floor in orange(1, beacon))
|
||||
flooring_near_beacon += floor
|
||||
holder_obj.forceMove(pick(flooring_near_beacon))
|
||||
animate(holder_obj, pixel_z = 10, time = 50)
|
||||
sleep(50)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
|
||||
balloon3.pixel_y = 10
|
||||
balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon)
|
||||
holder_obj.add_overlay(balloon3)
|
||||
sleep(4)
|
||||
holder_obj.cut_overlay(balloon3)
|
||||
A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
|
||||
A.density = initial(A.density)
|
||||
animate(holder_obj, pixel_z = 0, time = 5)
|
||||
sleep(5)
|
||||
A.forceMove(holder_obj.loc)
|
||||
qdel(holder_obj)
|
||||
if(uses_left <= 0)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/fulton_core
|
||||
name = "extraction beacon signaller"
|
||||
desc = "Emits a signal which fulton recovery devices can lock onto. Activate in hand to create a beacon."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "subspace_amplifier"
|
||||
|
||||
/obj/item/fulton_core/attack_self(mob/user)
|
||||
if(do_after(user,15,target = user) && !QDELETED(src))
|
||||
new /obj/structure/extraction_point(get_turf(user))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/extraction_point
|
||||
name = "fulton recovery beacon"
|
||||
desc = "A beacon for the fulton recovery system. Activate a pack in your hand to link it to a beacon."
|
||||
icon = 'icons/obj/fulton.dmi'
|
||||
icon_state = "extraction_point"
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
var/beacon_network = "station"
|
||||
|
||||
/obj/structure/extraction_point/Initialize()
|
||||
. = ..()
|
||||
name += " ([rand(100,999)]) ([get_area_name(src, TRUE)])"
|
||||
GLOB.total_extraction_beacons += src
|
||||
|
||||
/obj/structure/extraction_point/Destroy()
|
||||
GLOB.total_extraction_beacons -= src
|
||||
..()
|
||||
|
||||
/obj/effect/extraction_holder
|
||||
name = "extraction holder"
|
||||
desc = "you shouldnt see this"
|
||||
var/atom/movable/stored_obj
|
||||
|
||||
/obj/item/extraction_pack/proc/check_for_living_mobs(atom/A)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(L.stat != DEAD)
|
||||
return 1
|
||||
for(var/thing in A.GetAllContents())
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(L.stat != DEAD)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/effect/extraction_holder/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/extraction_holder/singularity_pull()
|
||||
return
|
||||
@@ -0,0 +1,27 @@
|
||||
/obj/machinery/computer/shuttle/labor
|
||||
name = "labor shuttle console"
|
||||
desc = "Used to call and send the labor camp shuttle."
|
||||
circuit = /obj/item/circuitboard/computer/labor_shuttle
|
||||
shuttleId = "laborcamp"
|
||||
possible_destinations = "laborcamp_home;laborcamp_away"
|
||||
req_access = list(ACCESS_BRIG)
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle/labor/one_way
|
||||
name = "prisoner shuttle console"
|
||||
desc = "A one-way shuttle console, used to summon the shuttle to the labor camp."
|
||||
possible_destinations = "laborcamp_away"
|
||||
circuit = /obj/item/circuitboard/computer/labor_shuttle/one_way
|
||||
req_access = list( )
|
||||
|
||||
/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list)
|
||||
if(href_list["move"])
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp")
|
||||
if(!M)
|
||||
to_chat(usr, "<span class='warning'>Cannot locate shuttle!</span>")
|
||||
return 0
|
||||
var/obj/docking_port/stationary/S = M.get_docked()
|
||||
if(S && S.name == "laborcamp_away")
|
||||
to_chat(usr, "<span class='warning'>Shuttle is already at the outpost!</span>")
|
||||
return 0
|
||||
..()
|
||||
@@ -0,0 +1,178 @@
|
||||
GLOBAL_LIST(labor_sheet_values)
|
||||
|
||||
/**********************Prisoners' Console**************************/
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console
|
||||
name = "point claim console"
|
||||
desc = "A stacking console with an electromagnetic writer, used to track ore mined by prisoners."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = FALSE
|
||||
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null
|
||||
var/machinedir = SOUTH
|
||||
var/obj/item/card/id/prisoner/inserted_id
|
||||
var/obj/machinery/door/airlock/release_door
|
||||
var/door_tag = "prisonshuttle"
|
||||
var/obj/item/radio/Radio //needed to send messages to sec radio
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/Initialize()
|
||||
. = ..()
|
||||
Radio = new/obj/item/radio(src)
|
||||
Radio.listening = FALSE
|
||||
locate_stacking_machine()
|
||||
|
||||
if(!GLOB.labor_sheet_values)
|
||||
var/sheet_list = list()
|
||||
for(var/sheet_type in subtypesof(/obj/item/stack/sheet))
|
||||
var/obj/item/stack/sheet/sheet = sheet_type
|
||||
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
|
||||
continue
|
||||
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
|
||||
GLOB.labor_sheet_values = sortList(sheet_list, /proc/cmp_sheet_list)
|
||||
|
||||
/proc/cmp_sheet_list(list/a, list/b)
|
||||
return a["value"] - b["value"]
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
if(!inserted_id)
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
inserted_id = I
|
||||
to_chat(user, "<span class='notice'>You insert [I].</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There's an ID inserted already.</span>")
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "labor_claim_console", name, 450, 475, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/can_go_home = FALSE
|
||||
|
||||
data["emagged"] = (obj_flags & EMAGGED) ? 1 : 0
|
||||
if(inserted_id)
|
||||
data["id"] = inserted_id
|
||||
data["id_name"] = inserted_id.registered_name
|
||||
data["points"] = inserted_id.points
|
||||
data["goal"] = inserted_id.goal
|
||||
if(check_auth())
|
||||
can_go_home = TRUE
|
||||
|
||||
if(stacking_machine)
|
||||
data["unclaimed_points"] = stacking_machine.points
|
||||
|
||||
data["ores"] = GLOB.labor_sheet_values
|
||||
data["can_go_home"] = can_go_home
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("handle_id")
|
||||
if(inserted_id)
|
||||
if(!usr.get_active_held_item())
|
||||
usr.put_in_hands(inserted_id)
|
||||
inserted_id = null
|
||||
else
|
||||
inserted_id.forceMove(get_turf(src))
|
||||
inserted_id = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
if(!usr.transferItemToLoc(I, src))
|
||||
return
|
||||
inserted_id = I
|
||||
if("claim_points")
|
||||
inserted_id.points += stacking_machine.points
|
||||
stacking_machine.points = 0
|
||||
to_chat(usr, "Points transferred.")
|
||||
if("move_shuttle")
|
||||
if(!alone_in_area(get_area(src), usr))
|
||||
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
|
||||
else if(!check_auth())
|
||||
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released when they reach their point goal.</span>")
|
||||
else
|
||||
switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE))
|
||||
if(1)
|
||||
to_chat(usr, "<span class='notice'>Shuttle not found.</span>")
|
||||
if(2)
|
||||
to_chat(usr, "<span class='notice'>Shuttle already at station.</span>")
|
||||
if(3)
|
||||
to_chat(usr, "<span class='notice'>No permission to dock could be granted.</span>")
|
||||
else
|
||||
if(!(obj_flags & EMAGGED))
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY)
|
||||
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/check_auth()
|
||||
if(obj_flags & EMAGGED)
|
||||
return 1 //Shuttle is emagged, let any ol' person through
|
||||
return (istype(inserted_id) && inserted_id.points >= inserted_id.goal) //Otherwise, only let them out if the prisoner's reached his quota.
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
|
||||
stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
if(stacking_machine)
|
||||
stacking_machine.CONSOLE = src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
|
||||
if(!(obj_flags & EMAGGED))
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
|
||||
|
||||
/**********************Prisoner Collection Unit**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker
|
||||
force_connect = TRUE
|
||||
var/points = 0 //The unclaimed value of ore stacked.
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
|
||||
points += inp.point_value * inp.amount
|
||||
..()
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/attackby(obj/item/I, mob/living/user)
|
||||
if(istype(I, /obj/item/stack/sheet) && user.canUnEquip(I))
|
||||
var/obj/item/stack/sheet/inp = I
|
||||
points += inp.point_value * inp.amount
|
||||
return ..()
|
||||
|
||||
/**********************Point Lookup Console**************************/
|
||||
/obj/machinery/mineral/labor_points_checker
|
||||
name = "points checking console"
|
||||
desc = "A console used by prisoners to check the progress on their quotas. Simply swipe a prisoner ID."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.examinate(src)
|
||||
|
||||
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if(istype(I, /obj/item/card/id/prisoner))
|
||||
var/obj/item/card/id/prisoner/prisoner_id = I
|
||||
to_chat(user, "<span class='notice'><B>ID: [prisoner_id.registered_name]</B></span>")
|
||||
to_chat(user, "<span class='notice'>Points Collected:[prisoner_id.points]</span>")
|
||||
to_chat(user, "<span class='notice'>Point Quota: [prisoner_id.goal]</span>")
|
||||
to_chat(user, "<span class='notice'>Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Error: Invalid ID</span>")
|
||||
else
|
||||
return ..()
|
||||
@@ -0,0 +1,248 @@
|
||||
/obj/structure/flora/ash
|
||||
gender = PLURAL
|
||||
layer = PROJECTILE_HIT_THRESHHOLD_LAYER //sporangiums up don't shoot
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "l_mushroom"
|
||||
name = "large mushrooms"
|
||||
desc = "A number of large mushrooms, covered in a faint layer of ash and what can only be spores."
|
||||
var/harvested_name = "shortened mushrooms"
|
||||
var/harvested_desc = "Some quickly regrowing mushrooms, formerly known to be quite large."
|
||||
var/needs_sharp_harvest = TRUE
|
||||
var/harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/shavings
|
||||
var/harvest_amount_low = 1
|
||||
var/harvest_amount_high = 3
|
||||
var/harvest_time = 60
|
||||
var/harvest_message_low = "You pick a mushroom, but fail to collect many shavings from its cap."
|
||||
var/harvest_message_med = "You pick a mushroom, carefully collecting the shavings from its cap."
|
||||
var/harvest_message_high = "You harvest and collect shavings from several mushroom caps."
|
||||
var/harvested = FALSE
|
||||
var/base_icon
|
||||
var/regrowth_time_low = 8 MINUTES
|
||||
var/regrowth_time_high = 16 MINUTES
|
||||
|
||||
/obj/structure/flora/ash/Initialize()
|
||||
. = ..()
|
||||
base_icon = "[icon_state][rand(1, 4)]"
|
||||
icon_state = base_icon
|
||||
|
||||
/obj/structure/flora/ash/proc/harvest(user)
|
||||
if(harvested)
|
||||
return 0
|
||||
|
||||
var/rand_harvested = rand(harvest_amount_low, harvest_amount_high)
|
||||
if(rand_harvested)
|
||||
if(user)
|
||||
var/msg = harvest_message_med
|
||||
if(rand_harvested == harvest_amount_low)
|
||||
msg = harvest_message_low
|
||||
else if(rand_harvested == harvest_amount_high)
|
||||
msg = harvest_message_high
|
||||
to_chat(user, "<span class='notice'>[msg]</span>")
|
||||
for(var/i in 1 to rand_harvested)
|
||||
new harvest(get_turf(src))
|
||||
|
||||
icon_state = "[base_icon]p"
|
||||
name = harvested_name
|
||||
desc = harvested_desc
|
||||
harvested = TRUE
|
||||
addtimer(CALLBACK(src, .proc/regrow), rand(regrowth_time_low, regrowth_time_high))
|
||||
return 1
|
||||
|
||||
/obj/structure/flora/ash/proc/regrow()
|
||||
icon_state = base_icon
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
harvested = FALSE
|
||||
|
||||
/obj/structure/flora/ash/attackby(obj/item/W, mob/user, params)
|
||||
if(!harvested && needs_sharp_harvest && W.sharpness)
|
||||
user.visible_message("<span class='notice'>[user] starts to harvest from [src] with [W].</span>","<span class='notice'>You begin to harvest from [src] with [W].</span>")
|
||||
if(do_after(user, harvest_time, target = src))
|
||||
harvest(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/flora/ash/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!harvested && !needs_sharp_harvest)
|
||||
user.visible_message("<span class='notice'>[user] starts to harvest from [src].</span>","<span class='notice'>You begin to harvest from [src].</span>")
|
||||
if(do_after(user, harvest_time, target = src))
|
||||
harvest(user)
|
||||
|
||||
/obj/structure/flora/ash/tall_shroom //exists only so that the spawning check doesn't allow these spawning near other things
|
||||
regrowth_time_low = 4200
|
||||
|
||||
/obj/structure/flora/ash/leaf_shroom
|
||||
icon_state = "s_mushroom"
|
||||
name = "leafy mushrooms"
|
||||
desc = "A number of mushrooms, each of which surrounds a greenish sporangium with a number of leaf-like structures."
|
||||
harvested_name = "leafless mushrooms"
|
||||
harvested_desc = "A bunch of formerly-leafed mushrooms, with their sporangiums exposed. Scandalous?"
|
||||
harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_leaf
|
||||
needs_sharp_harvest = FALSE
|
||||
harvest_amount_high = 4
|
||||
harvest_time = 20
|
||||
harvest_message_low = "You pluck a single, suitable leaf."
|
||||
harvest_message_med = "You pluck a number of leaves, leaving a few unsuitable ones."
|
||||
harvest_message_high = "You pluck quite a lot of suitable leaves."
|
||||
regrowth_time_low = 2400
|
||||
regrowth_time_high = 6000
|
||||
|
||||
/obj/structure/flora/ash/cap_shroom
|
||||
icon_state = "r_mushroom"
|
||||
name = "tall mushrooms"
|
||||
desc = "Several mushrooms, the larger of which have a ring of conks at the midpoint of their stems."
|
||||
harvested_name = "small mushrooms"
|
||||
harvested_desc = "Several small mushrooms near the stumps of what likely were larger mushrooms."
|
||||
harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_cap
|
||||
harvest_amount_high = 4
|
||||
harvest_time = 50
|
||||
harvest_message_low = "You slice the cap off a mushroom."
|
||||
harvest_message_med = "You slice off a few conks from the larger mushrooms."
|
||||
harvest_message_high = "You slice off a number of caps and conks from these mushrooms."
|
||||
regrowth_time_low = 3000
|
||||
regrowth_time_high = 5400
|
||||
|
||||
/obj/structure/flora/ash/stem_shroom
|
||||
icon_state = "t_mushroom"
|
||||
name = "numerous mushrooms"
|
||||
desc = "A large number of mushrooms, some of which have long, fleshy stems. They're radiating light!"
|
||||
light_range = 1.5
|
||||
light_power = 2.1
|
||||
harvested_name = "tiny mushrooms"
|
||||
harvested_desc = "A few tiny mushrooms around larger stumps. You can already see them growing back."
|
||||
harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
|
||||
harvest_amount_high = 4
|
||||
harvest_time = 40
|
||||
harvest_message_low = "You pick and slice the cap off a mushroom, leaving the stem."
|
||||
harvest_message_med = "You pick and decapitate several mushrooms for their stems."
|
||||
harvest_message_high = "You acquire a number of stems from these mushrooms."
|
||||
regrowth_time_low = 3000
|
||||
regrowth_time_high = 6000
|
||||
|
||||
/obj/structure/flora/ash/cacti
|
||||
icon_state = "cactus"
|
||||
name = "fruiting cacti"
|
||||
desc = "Several prickly cacti, brimming with ripe fruit and covered in a thin layer of ash."
|
||||
harvested_name = "cacti"
|
||||
harvested_desc = "A bunch of prickly cacti. You can see fruits slowly growing beneath the covering of ash."
|
||||
harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
|
||||
needs_sharp_harvest = FALSE
|
||||
harvest_amount_high = 2
|
||||
harvest_time = 10
|
||||
harvest_message_low = "You pick a cactus fruit."
|
||||
harvest_message_med = "You pick several cactus fruit." //shouldn't show up, because you can't get more than two
|
||||
harvest_message_high = "You pick a pair of cactus fruit."
|
||||
regrowth_time_low = 4800
|
||||
regrowth_time_high = 7200
|
||||
|
||||
/obj/structure/flora/ash/cacti/Initialize(mapload)
|
||||
. = ..()
|
||||
// min dmg 3, max dmg 6, prob(70)
|
||||
AddComponent(/datum/component/caltrop, 3, 6, 70)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora
|
||||
name = "mushroom shavings"
|
||||
desc = "Some shavings from a tall mushroom. With enough, might serve as a bowl."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_shavings"
|
||||
list_reagents = list("sugar" = 3, "ethanol" = 2, "stabilizing_agent" = 3, "minttoxin" = 2)
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 100
|
||||
seed = /obj/item/seeds/lavaland/polypore
|
||||
wine_power = 20
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-4, 4)
|
||||
pixel_y = rand(-4, 4)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/shavings //for actual crafting
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_leaf
|
||||
name = "mushroom leaf"
|
||||
desc = "A leaf, from a mushroom."
|
||||
list_reagents = list("nutriment" = 3, "vitfro" = 2, "nicotine" = 2)
|
||||
icon_state = "mushroom_leaf"
|
||||
seed = /obj/item/seeds/lavaland/porcini
|
||||
wine_power = 40
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_cap
|
||||
name = "mushroom cap"
|
||||
desc = "The cap of a large mushroom."
|
||||
list_reagents = list("mindbreaker" = 2, "entpoly" = 4, "mushroomhallucinogen" = 2)
|
||||
icon_state = "mushroom_cap"
|
||||
seed = /obj/item/seeds/lavaland/inocybe
|
||||
wine_power = 70
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
|
||||
name = "mushroom stem"
|
||||
desc = "A long mushroom stem. It's slightly glowing."
|
||||
list_reagents = list("tinlux" = 2, "vitamin" = 1, "space_drugs" = 1)
|
||||
icon_state = "mushroom_stem"
|
||||
seed = /obj/item/seeds/lavaland/ember
|
||||
wine_power = 60
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
|
||||
name = "cactus fruit"
|
||||
list_reagents = list("vitamin" = 2, "nutriment" = 2, "vitfro" = 6)
|
||||
desc = "A cactus fruit covered in a thick, reddish skin. And some ash."
|
||||
icon_state = "cactus_fruit"
|
||||
seed = /obj/item/seeds/lavaland/cactus
|
||||
wine_power = 50
|
||||
|
||||
/obj/item/reagent_containers/glass/bowl/mushroom_bowl
|
||||
name = "mushroom bowl"
|
||||
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_bowl"
|
||||
|
||||
/obj/item/reagent_containers/glass/bowl/mushroom_bowl/update_icon()
|
||||
cut_overlays()
|
||||
if(reagents && reagents.total_volume)
|
||||
var/mutable_appearance/filling = mutable_appearance('icons/obj/lavaland/ash_flora.dmi', "fullbowl")
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
add_overlay(filling)
|
||||
else
|
||||
icon_state = "mushroom_bowl"
|
||||
|
||||
/obj/item/reagent_containers/glass/bowl/mushroom_bowl/attackby(obj/item/I,mob/user, params)
|
||||
if(istype(I, /obj/item/reagent_containers/food/snacks))
|
||||
var/obj/item/reagent_containers/food/snacks/S = I
|
||||
if(I.w_class > WEIGHT_CLASS_SMALL)
|
||||
to_chat(user, "<span class='warning'>The ingredient is too big for [src]!</span>")
|
||||
else if(contents.len >= 20)
|
||||
to_chat(user, "<span class='warning'>You can't add more ingredients to [src]!</span>")
|
||||
else
|
||||
if(reagents.has_reagent("water", 10)) //are we starting a soup or a salad?
|
||||
var/obj/item/reagent_containers/food/snacks/customizable/A = new/obj/item/reagent_containers/food/snacks/customizable/soup/ashsoup(get_turf(src))
|
||||
A.initialize_custom_food(src, S, user)
|
||||
else
|
||||
var/obj/item/reagent_containers/food/snacks/customizable/A = new/obj/item/reagent_containers/food/snacks/customizable/salad/ashsalad(get_turf(src))
|
||||
A.initialize_custom_food(src, S, user)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
//what you can craft with these things
|
||||
/datum/crafting_recipe/mushroom_bowl
|
||||
name = "Mushroom Bowl"
|
||||
result = /obj/item/reagent_containers/glass/bowl/mushroom_bowl
|
||||
reqs = list(/obj/item/reagent_containers/food/snacks/grown/ash_flora/shavings = 5)
|
||||
time = 30
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/salad/ashsalad
|
||||
desc = "Very ashy."
|
||||
trash = /obj/item/reagent_containers/glass/bowl/mushroom_bowl
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_bowl"
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/customizable/soup/ashsoup
|
||||
desc = "A bowl with ash and... stuff in it."
|
||||
trash = /obj/item/reagent_containers/glass/bowl/mushroom_bowl
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_soup"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
/obj/structure/punching_bag
|
||||
name = "punching bag"
|
||||
desc = "A punching bag. Can you get to speed level 4???"
|
||||
icon = 'goon/icons/obj/fitness.dmi'
|
||||
icon_state = "punchingbag"
|
||||
anchored = TRUE
|
||||
layer = WALL_OBJ_LAYER
|
||||
var/list/hit_sounds = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg',\
|
||||
'sound/weapons/punch1.ogg', 'sound/weapons/punch2.ogg', 'sound/weapons/punch3.ogg', 'sound/weapons/punch4.ogg')
|
||||
|
||||
/obj/structure/punching_bag/attack_hand(mob/user as mob)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
flick("[icon_state]2", src)
|
||||
playsound(loc, pick(hit_sounds), 25, 1, -1)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "exercise", /datum/mood_event/exercise)
|
||||
L.apply_status_effect(STATUS_EFFECT_EXERCISED)
|
||||
|
||||
/obj/structure/weightmachine
|
||||
name = "Weight Machine"
|
||||
desc = "Just looking at this thing makes you feel tired."
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/icon_state_inuse
|
||||
|
||||
/obj/structure/weightmachine/proc/AnimateMachine(mob/living/user)
|
||||
return
|
||||
|
||||
/obj/structure/weightmachine/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(obj_flags & IN_USE)
|
||||
to_chat(user, "It's already in use - wait a bit.")
|
||||
return
|
||||
else
|
||||
obj_flags |= IN_USE
|
||||
icon_state = icon_state_inuse
|
||||
user.setDir(SOUTH)
|
||||
user.Stun(80)
|
||||
user.forceMove(src.loc)
|
||||
var/bragmessage = pick("pushing it to the limit","going into overdrive","burning with determination","rising up to the challenge", "getting strong now","getting ripped")
|
||||
user.visible_message("<B>[user] is [bragmessage]!</B>")
|
||||
AnimateMachine(user)
|
||||
|
||||
playsound(user, 'sound/machines/click.ogg', 60, 1)
|
||||
obj_flags &= ~IN_USE
|
||||
user.pixel_y = 0
|
||||
var/finishmessage = pick("You feel stronger!","You feel like you can take on the world!","You feel robust!","You feel indestructible!")
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "exercise", /datum/mood_event/exercise)
|
||||
icon_state = initial(icon_state)
|
||||
to_chat(user, finishmessage)
|
||||
user.apply_status_effect(STATUS_EFFECT_EXERCISED)
|
||||
|
||||
/obj/structure/weightmachine/stacklifter
|
||||
icon = 'goon/icons/obj/fitness.dmi'
|
||||
icon_state = "fitnesslifter"
|
||||
icon_state_inuse = "fitnesslifter2"
|
||||
|
||||
/obj/structure/weightmachine/stacklifter/AnimateMachine(mob/living/user)
|
||||
var/lifts = 0
|
||||
while (lifts++ < 6)
|
||||
if (user.loc != src.loc)
|
||||
break
|
||||
sleep(3)
|
||||
animate(user, pixel_y = -2, time = 3)
|
||||
sleep(3)
|
||||
animate(user, pixel_y = -4, time = 3)
|
||||
sleep(3)
|
||||
playsound(user, 'goon/sound/effects/spring.ogg', 60, 1)
|
||||
|
||||
/obj/structure/weightmachine/weightlifter
|
||||
icon = 'goon/icons/obj/fitness.dmi'
|
||||
icon_state = "fitnessweight"
|
||||
icon_state_inuse = "fitnessweight-c"
|
||||
|
||||
/obj/structure/weightmachine/weightlifter/AnimateMachine(mob/living/user)
|
||||
var/mutable_appearance/swole_overlay = mutable_appearance(icon, "fitnessweight-w", WALL_OBJ_LAYER)
|
||||
add_overlay(swole_overlay)
|
||||
var/reps = 0
|
||||
user.pixel_y = 5
|
||||
while (reps++ < 6)
|
||||
if (user.loc != src.loc)
|
||||
break
|
||||
for (var/innerReps = max(reps, 1), innerReps > 0, innerReps--)
|
||||
sleep(3)
|
||||
animate(user, pixel_y = (user.pixel_y == 3) ? 5 : 3, time = 3)
|
||||
playsound(user, 'goon/sound/effects/spring.ogg', 60, 1)
|
||||
sleep(3)
|
||||
animate(user, pixel_y = 2, time = 3)
|
||||
sleep(3)
|
||||
cut_overlay(swole_overlay)
|
||||
@@ -0,0 +1,211 @@
|
||||
#define SMELT_AMOUNT 10
|
||||
|
||||
/**********************Mineral processing unit console**************************/
|
||||
|
||||
/obj/machinery/mineral
|
||||
var/input_dir = NORTH
|
||||
var/output_dir = SOUTH
|
||||
|
||||
/obj/machinery/mineral/proc/unload_mineral(atom/movable/S)
|
||||
S.forceMove(drop_location())
|
||||
var/turf/T = get_step(src,output_dir)
|
||||
if(T)
|
||||
S.forceMove(T)
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console
|
||||
name = "production machine console"
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
density = TRUE
|
||||
var/obj/machinery/mineral/processing_unit/machine = null
|
||||
var/machinedir = EAST
|
||||
speed_process = TRUE
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/Initialize()
|
||||
. = ..()
|
||||
machine = locate(/obj/machinery/mineral/processing_unit, get_step(src, machinedir))
|
||||
if (machine)
|
||||
machine.CONSOLE = src
|
||||
else
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!machine)
|
||||
return
|
||||
|
||||
var/dat = machine.get_machine_data()
|
||||
|
||||
var/datum/browser/popup = new(user, "processing", "Smelting Console", 300, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["material"])
|
||||
machine.selected_material = href_list["material"]
|
||||
machine.selected_alloy = null
|
||||
|
||||
if(href_list["alloy"])
|
||||
machine.selected_material = null
|
||||
machine.selected_alloy = href_list["alloy"]
|
||||
|
||||
if(href_list["set_on"])
|
||||
machine.on = (href_list["set_on"] == "on")
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/Destroy()
|
||||
machine = null
|
||||
return ..()
|
||||
|
||||
|
||||
/**********************Mineral processing unit**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/processing_unit
|
||||
name = "furnace"
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "furnace"
|
||||
density = TRUE
|
||||
var/obj/machinery/mineral/CONSOLE = null
|
||||
var/on = FALSE
|
||||
var/selected_material = MAT_METAL
|
||||
var/selected_alloy = null
|
||||
var/datum/techweb/stored_research
|
||||
|
||||
/obj/machinery/mineral/processing_unit/Initialize()
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 1)
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), INFINITY, TRUE, /obj/item/stack)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/smelter
|
||||
|
||||
/obj/machinery/mineral/processing_unit/Destroy()
|
||||
CONSOLE = null
|
||||
QDEL_NULL(stored_research)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/processing_unit/HasProximity(atom/movable/AM)
|
||||
if(istype(AM, /obj/item/stack/ore) && AM.loc == get_step(src, input_dir))
|
||||
process_ore(AM)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
var/material_amount = materials.get_item_material_amount(O)
|
||||
if(!materials.has_space(material_amount))
|
||||
unload_mineral(O)
|
||||
else
|
||||
materials.insert_item(O)
|
||||
qdel(O)
|
||||
if(CONSOLE)
|
||||
CONSOLE.updateUsrDialog()
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/get_machine_data()
|
||||
var/dat = "<b>Smelter control console</b><br><br>"
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
dat += "<span class=\"res_name\">[M.name]: </span>[M.amount] cm³"
|
||||
if (selected_material == mat_id)
|
||||
dat += " <i>Smelting</i>"
|
||||
else
|
||||
dat += " <A href='?src=[REF(CONSOLE)];material=[mat_id]'><b>Not Smelting</b></A> "
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<br><br>"
|
||||
dat += "<b>Smelt Alloys</b><br>"
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = stored_research.researched_designs[v]
|
||||
dat += "<span class=\"res_name\">[D.name] "
|
||||
if (selected_alloy == D.id)
|
||||
dat += " <i>Smelting</i>"
|
||||
else
|
||||
dat += " <A href='?src=[REF(CONSOLE)];alloy=[D.id]'><b>Not Smelting</b></A> "
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<br><br>"
|
||||
//On or off
|
||||
dat += "Machine is currently "
|
||||
if (on)
|
||||
dat += "<A href='?src=[REF(CONSOLE)];set_on=off'>On</A> "
|
||||
else
|
||||
dat += "<A href='?src=[REF(CONSOLE)];set_on=on'>Off</A> "
|
||||
|
||||
return dat
|
||||
|
||||
/obj/machinery/mineral/processing_unit/process()
|
||||
if (on)
|
||||
if(selected_material)
|
||||
smelt_ore()
|
||||
|
||||
else if(selected_alloy)
|
||||
smelt_alloy()
|
||||
|
||||
|
||||
if(CONSOLE)
|
||||
CONSOLE.updateUsrDialog()
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/smelt_ore()
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
var/datum/material/mat = materials.materials[selected_material]
|
||||
if(mat)
|
||||
var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
if(!sheets_to_remove)
|
||||
on = FALSE
|
||||
else
|
||||
var/out = get_step(src, output_dir)
|
||||
materials.retrieve_sheets(sheets_to_remove, selected_material, out)
|
||||
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/smelt_alloy()
|
||||
var/datum/design/alloy = stored_research.isDesignResearchedID(selected_alloy) //check if it's a valid design
|
||||
if(!alloy)
|
||||
on = FALSE
|
||||
return
|
||||
|
||||
var/amount = can_smelt(alloy)
|
||||
|
||||
if(!amount)
|
||||
on = FALSE
|
||||
return
|
||||
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
materials.use_amount(alloy.materials, amount)
|
||||
|
||||
generate_mineral(alloy.build_path)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/can_smelt(datum/design/D)
|
||||
if(D.make_reagents.len)
|
||||
return FALSE
|
||||
|
||||
var/build_amount = SMELT_AMOUNT
|
||||
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
|
||||
for(var/mat_id in D.materials)
|
||||
var/M = D.materials[mat_id]
|
||||
var/datum/material/smelter_mat = materials.materials[mat_id]
|
||||
|
||||
if(!M || !smelter_mat)
|
||||
return FALSE
|
||||
|
||||
build_amount = min(build_amount, round(smelter_mat.amount / M))
|
||||
|
||||
return build_amount
|
||||
|
||||
/obj/machinery/mineral/processing_unit/proc/generate_mineral(P)
|
||||
var/O = new P(src)
|
||||
unload_mineral(O)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/on_deconstruction()
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
..()
|
||||
|
||||
#undef SMELT_AMOUNT
|
||||
@@ -0,0 +1,357 @@
|
||||
/**********************Ore Redemption Unit**************************/
|
||||
//Turns all the various mining machines into a single unit to speed up mining and establish a point system
|
||||
|
||||
/obj/machinery/mineral/ore_redemption
|
||||
name = "ore redemption machine"
|
||||
desc = "A machine that accepts ore and instantly transforms it into workable material sheets. Points for ore are generated based on type and can be redeemed at a mining equipment vendor."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "ore_redemption"
|
||||
density = TRUE
|
||||
input_dir = NORTH
|
||||
output_dir = SOUTH
|
||||
req_access = list(ACCESS_MINERAL_STOREROOM)
|
||||
speed_process = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/ore_redemption
|
||||
layer = BELOW_OBJ_LAYER
|
||||
var/obj/item/card/id/inserted_id
|
||||
var/points = 0
|
||||
var/ore_pickup_rate = 15
|
||||
var/sheet_per_ore = 1
|
||||
var/point_upgrade = 1
|
||||
var/list/ore_values = list(MAT_GLASS = 1, MAT_METAL = 1, MAT_PLASMA = 15, MAT_SILVER = 16, MAT_GOLD = 18, MAT_TITANIUM = 30, MAT_URANIUM = 30, MAT_DIAMOND = 50, MAT_BLUESPACE = 50, MAT_BANANIUM = 60)
|
||||
var/message_sent = FALSE
|
||||
var/list/ore_buffer = list()
|
||||
var/datum/techweb/stored_research
|
||||
var/obj/item/disk/design_disk/inserted_disk
|
||||
var/datum/component/remote_materials/materials
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/Initialize(mapload)
|
||||
. = ..()
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/smelter
|
||||
materials = AddComponent(/datum/component/remote_materials, "orm", mapload)
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/Destroy()
|
||||
QDEL_NULL(stored_research)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/RefreshParts()
|
||||
var/ore_pickup_rate_temp = 15
|
||||
var/point_upgrade_temp = 1
|
||||
var/sheet_per_ore_temp = 1
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
sheet_per_ore_temp = 0.65 + (0.35 * B.rating)
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
ore_pickup_rate_temp = 15 * M.rating
|
||||
for(var/obj/item/stock_parts/micro_laser/L in component_parts)
|
||||
point_upgrade_temp = 0.65 + (0.35 * L.rating)
|
||||
ore_pickup_rate = ore_pickup_rate_temp
|
||||
point_upgrade = point_upgrade_temp
|
||||
sheet_per_ore = sheet_per_ore_temp
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/smelt_ore(obj/item/stack/ore/O)
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
if (!mat_container)
|
||||
return
|
||||
|
||||
if(istype(O, /obj/item/stack/ore/bluespace_crystal/refined))
|
||||
return
|
||||
|
||||
ore_buffer -= O
|
||||
|
||||
if(O && O.refined_type)
|
||||
points += O.points * point_upgrade * O.amount
|
||||
|
||||
var/material_amount = mat_container.get_item_material_amount(O)
|
||||
|
||||
if(!material_amount)
|
||||
qdel(O) //no materials, incinerate it
|
||||
|
||||
else if(!mat_container.has_space(material_amount * sheet_per_ore * O.amount)) //if there is no space, eject it
|
||||
unload_mineral(O)
|
||||
|
||||
else
|
||||
var/mats = O.materials & mat_container.materials
|
||||
var/amount = O.amount
|
||||
var/id = inserted_id && inserted_id.registered_name
|
||||
if (id)
|
||||
id = " (ID: [id])"
|
||||
mat_container.insert_item(O, sheet_per_ore) //insert it
|
||||
materials.silo_log(src, "smelted", amount, "ores[id]", mats)
|
||||
qdel(O)
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/can_smelt_alloy(datum/design/D)
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
if(!mat_container || D.make_reagents.len)
|
||||
return FALSE
|
||||
|
||||
var/build_amount = 0
|
||||
|
||||
for(var/mat_id in D.materials)
|
||||
var/M = D.materials[mat_id]
|
||||
var/datum/material/redemption_mat = mat_container.materials[mat_id]
|
||||
|
||||
if(!M || !redemption_mat)
|
||||
return FALSE
|
||||
|
||||
var/smeltable_sheets = FLOOR(redemption_mat.amount / M, 1)
|
||||
|
||||
if(!smeltable_sheets)
|
||||
return FALSE
|
||||
|
||||
if(!build_amount)
|
||||
build_amount = smeltable_sheets
|
||||
|
||||
build_amount = min(build_amount, smeltable_sheets)
|
||||
|
||||
return build_amount
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/process_ores(list/ores_to_process)
|
||||
var/current_amount = 0
|
||||
for(var/ore in ores_to_process)
|
||||
if(current_amount >= ore_pickup_rate)
|
||||
break
|
||||
smelt_ore(ore)
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/send_console_message()
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
if(!mat_container || !is_station_level(z))
|
||||
return
|
||||
message_sent = TRUE
|
||||
|
||||
var/area/A = get_area(src)
|
||||
var/msg = "Now available in [A]:<br>"
|
||||
|
||||
var/has_minerals = FALSE
|
||||
|
||||
for(var/mat_id in mat_container.materials)
|
||||
var/datum/material/M = mat_container.materials[mat_id]
|
||||
var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
|
||||
if(mineral_amount)
|
||||
has_minerals = TRUE
|
||||
msg += "[capitalize(M.name)]: [mineral_amount] sheets<br>"
|
||||
|
||||
if(!has_minerals)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/requests_console/D in GLOB.allConsoles)
|
||||
if(D.receive_ore_updates)
|
||||
D.createmessage("Ore Redemption Machine", "New minerals available!", msg, 1, 0)
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/process()
|
||||
if(!materials.mat_container || panel_open || !powered())
|
||||
return
|
||||
var/atom/input = get_step(src, input_dir)
|
||||
var/obj/structure/ore_box/OB = locate() in input
|
||||
if(OB)
|
||||
input = OB
|
||||
|
||||
for(var/obj/item/stack/ore/O in input)
|
||||
if(QDELETED(O))
|
||||
continue
|
||||
ore_buffer |= O
|
||||
O.forceMove(src)
|
||||
CHECK_TICK
|
||||
|
||||
if(LAZYLEN(ore_buffer))
|
||||
message_sent = FALSE
|
||||
process_ores(ore_buffer)
|
||||
else if(!message_sent)
|
||||
send_console_message()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params)
|
||||
if(default_unfasten_wrench(user, W))
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "ore_redemption-open", "ore_redemption", W))
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(default_deconstruction_crowbar(W))
|
||||
return
|
||||
|
||||
if(!powered())
|
||||
return
|
||||
if(istype(W, /obj/item/card/id))
|
||||
var/obj/item/card/id/I = user.get_active_held_item()
|
||||
if(istype(I) && !istype(inserted_id))
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
inserted_id = I
|
||||
interact(user)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/disk/design_disk))
|
||||
if(user.transferItemToLoc(W, src))
|
||||
inserted_disk = W
|
||||
return TRUE
|
||||
|
||||
if(istype(W, /obj/item/stack/ore/bluespace_crystal/refined))
|
||||
to_chat(user, "<span class='notice'>[W] has already been refined!</span>")
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/multitool_act(mob/living/user, obj/item/multitool/I)
|
||||
if (panel_open)
|
||||
input_dir = turn(input_dir, -90)
|
||||
output_dir = turn(output_dir, -90)
|
||||
to_chat(user, "<span class='notice'>You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ore_redemption_machine", "Ore Redemption Machine", 440, 550, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["unclaimedPoints"] = points
|
||||
if(inserted_id)
|
||||
data["hasID"] = TRUE
|
||||
data["claimedPoints"] = inserted_id.mining_points
|
||||
|
||||
data["materials"] = list()
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
if (mat_container)
|
||||
for(var/mat_id in mat_container.materials)
|
||||
var/datum/material/M = mat_container.materials[mat_id]
|
||||
var/sheet_amount = M.amount ? M.amount / MINERAL_MATERIAL_AMOUNT : "0"
|
||||
data["materials"] += list(list("name" = M.name, "id" = M.id, "amount" = sheet_amount, "value" = ore_values[M.id] * point_upgrade))
|
||||
|
||||
data["alloys"] = list()
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = stored_research.researched_designs[v]
|
||||
data["alloys"] += list(list("name" = D.name, "id" = D.id, "amount" = can_smelt_alloy(D)))
|
||||
|
||||
if (!mat_container)
|
||||
data["disconnected"] = "local mineral storage is unavailable"
|
||||
else if (!materials.silo)
|
||||
data["disconnected"] = "no ore silo connection is available; storing locally"
|
||||
else if (materials.on_hold())
|
||||
data["disconnected"] = "mineral withdrawal is on hold"
|
||||
|
||||
data["diskDesigns"] = list()
|
||||
if(inserted_disk)
|
||||
data["hasDisk"] = TRUE
|
||||
if(inserted_disk.blueprints.len)
|
||||
var/index = 1
|
||||
for (var/datum/design/thisdesign in inserted_disk.blueprints)
|
||||
if(thisdesign)
|
||||
data["diskDesigns"] += list(list("name" = thisdesign.name, "index" = index, "canupload" = thisdesign.build_type&SMELTER))
|
||||
index++
|
||||
return data
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
switch(action)
|
||||
if("Eject")
|
||||
if(!inserted_id)
|
||||
return
|
||||
usr.put_in_hands(inserted_id)
|
||||
inserted_id = null
|
||||
return TRUE
|
||||
if("Insert")
|
||||
var/obj/item/card/id/I = usr.get_active_held_item()
|
||||
if(istype(I))
|
||||
if(!usr.transferItemToLoc(I,src))
|
||||
return
|
||||
inserted_id = I
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Not a valid ID!</span>")
|
||||
return TRUE
|
||||
if("Claim")
|
||||
if(inserted_id)
|
||||
inserted_id.mining_points += points
|
||||
points = 0
|
||||
return TRUE
|
||||
if("Release")
|
||||
if(!mat_container)
|
||||
return
|
||||
if(materials.on_hold())
|
||||
to_chat(usr, "<span class='warning'>Mineral access is on hold, please contact the quartermaster.</span>")
|
||||
else if(!check_access(inserted_id) && !allowed(usr)) //Check the ID inside, otherwise check the user
|
||||
to_chat(usr, "<span class='warning'>Required access not found.</span>")
|
||||
else
|
||||
var/mat_id = params["id"]
|
||||
if(!mat_container.materials[mat_id])
|
||||
return
|
||||
var/datum/material/mat = mat_container.materials[mat_id]
|
||||
var/stored_amount = mat.amount / MINERAL_MATERIAL_AMOUNT
|
||||
|
||||
if(!stored_amount)
|
||||
return
|
||||
|
||||
var/desired = 0
|
||||
if (params["sheets"])
|
||||
desired = text2num(params["sheets"])
|
||||
else
|
||||
desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num
|
||||
|
||||
var/sheets_to_remove = round(min(desired,50,stored_amount))
|
||||
var/count = mat_container.retrieve_sheets(sheets_to_remove, mat_id, get_step(src, output_dir))
|
||||
var/list/mats = list()
|
||||
mats[mat_id] = MINERAL_MATERIAL_AMOUNT
|
||||
materials.silo_log(src, "released", -count, "sheets", mats)
|
||||
return TRUE
|
||||
if("diskInsert")
|
||||
var/obj/item/disk/design_disk/disk = usr.get_active_held_item()
|
||||
if(istype(disk))
|
||||
if(!usr.transferItemToLoc(disk,src))
|
||||
return
|
||||
inserted_disk = disk
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Not a valid Design Disk!</span>")
|
||||
return TRUE
|
||||
if("diskEject")
|
||||
if(inserted_disk)
|
||||
usr.put_in_hands(inserted_disk)
|
||||
inserted_disk = null
|
||||
return TRUE
|
||||
if("diskUpload")
|
||||
var/n = text2num(params["design"])
|
||||
if(inserted_disk && inserted_disk.blueprints && inserted_disk.blueprints[n])
|
||||
stored_research.add_design(inserted_disk.blueprints[n])
|
||||
return TRUE
|
||||
if("Smelt")
|
||||
if(!mat_container)
|
||||
return
|
||||
if(materials.on_hold())
|
||||
to_chat(usr, "<span class='warning'>Mineral access is on hold, please contact the quartermaster.</span>")
|
||||
return
|
||||
var/alloy_id = params["id"]
|
||||
var/datum/design/alloy = stored_research.isDesignResearchedID(alloy_id)
|
||||
if((check_access(inserted_id) || allowed(usr)) && alloy)
|
||||
var/smelt_amount = can_smelt_alloy(alloy)
|
||||
var/desired = 0
|
||||
if (params["sheets"])
|
||||
desired = text2num(params["sheets"])
|
||||
else
|
||||
desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num
|
||||
var/amount = round(min(desired,50,smelt_amount))
|
||||
mat_container.use_amount(alloy.materials, amount)
|
||||
materials.silo_log(src, "released", -amount, "sheets", alloy.materials)
|
||||
var/output
|
||||
if(ispath(alloy.build_path, /obj/item/stack/sheet))
|
||||
output = new alloy.build_path(src, amount)
|
||||
else
|
||||
output = new alloy.build_path(src)
|
||||
unload_mineral(output)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Required access not found.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ex_act(severity, target)
|
||||
do_sparks(5, TRUE, src)
|
||||
..()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/update_icon()
|
||||
if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
return
|
||||
@@ -0,0 +1,234 @@
|
||||
GLOBAL_DATUM(ore_silo_default, /obj/machinery/ore_silo)
|
||||
GLOBAL_LIST_EMPTY(silo_access_logs)
|
||||
|
||||
/obj/machinery/ore_silo
|
||||
name = "ore silo"
|
||||
desc = "An all-in-one bluespace storage and transmission system for the station's mineral distribution needs."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "silo"
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/ore_silo
|
||||
|
||||
var/list/holds = list()
|
||||
var/list/datum/component/remote_materials/connected = list()
|
||||
var/log_page = 1
|
||||
|
||||
/obj/machinery/ore_silo/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/material_container,
|
||||
list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC),
|
||||
INFINITY,
|
||||
FALSE,
|
||||
/obj/item/stack,
|
||||
null,
|
||||
null,
|
||||
TRUE)
|
||||
if (!GLOB.ore_silo_default && mapload && is_station_level(z))
|
||||
GLOB.ore_silo_default = src
|
||||
|
||||
/obj/machinery/ore_silo/Destroy()
|
||||
if (GLOB.ore_silo_default == src)
|
||||
GLOB.ore_silo_default = null
|
||||
|
||||
for(var/C in connected)
|
||||
var/datum/component/remote_materials/mats = C
|
||||
mats.disconnect_from(src)
|
||||
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/ore_silo/proc/remote_attackby(obj/machinery/M, mob/user, obj/item/stack/I)
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
// stolen from /datum/component/material_container/proc/OnAttackBy
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if(I.item_flags & ABSTRACT)
|
||||
return
|
||||
if(!istype(I) || (I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION))
|
||||
to_chat(user, "<span class='warning'>[M] won't accept [I]!</span>")
|
||||
return
|
||||
var/item_mats = I.materials & materials.materials
|
||||
if(!length(item_mats))
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [M].</span>")
|
||||
return
|
||||
// assumes unlimited space...
|
||||
var/amount = I.amount
|
||||
materials.user_insert(I, user)
|
||||
silo_log(M, "deposited", amount, "sheets", item_mats)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/ore_silo/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/stack))
|
||||
return remote_attackby(src, user, W)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/ore_silo/ui_interact(mob/user)
|
||||
user.set_machine(src)
|
||||
var/datum/browser/popup = new(user, "ore_silo", null, 600, 550)
|
||||
popup.set_content(generate_ui())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/ore_silo/proc/generate_ui()
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
var/list/ui = list("<head><title>Ore Silo</title></head><body><div class='statusDisplay'><h2>Stored Material:</h2>")
|
||||
var/any = FALSE
|
||||
for(var/M in materials.materials)
|
||||
var/datum/material/mat = materials.materials[M]
|
||||
var/sheets = round(mat.amount) / MINERAL_MATERIAL_AMOUNT
|
||||
if (sheets)
|
||||
if (sheets >= 1)
|
||||
ui += "<a href='?src=[REF(src)];ejectsheet=[mat.id];eject_amt=1'>Eject</a>"
|
||||
else
|
||||
ui += "<span class='linkOff'>Eject</span>"
|
||||
if (sheets >= 20)
|
||||
ui += "<a href='?src=[REF(src)];ejectsheet=[mat.id];eject_amt=20'>20x</a>"
|
||||
else
|
||||
ui += "<span class='linkOff'>20x</span>"
|
||||
ui += "<b>[mat.name]</b>: [sheets] sheets<br>"
|
||||
any = TRUE
|
||||
if(!any)
|
||||
ui += "Nothing!"
|
||||
|
||||
ui += "</div><div class='statusDisplay'><h2>Connected Machines:</h2>"
|
||||
for(var/C in connected)
|
||||
var/datum/component/remote_materials/mats = C
|
||||
var/atom/parent = mats.parent
|
||||
var/hold_key = "[get_area(parent)]/[mats.category]"
|
||||
ui += "<a href='?src=[REF(src)];remove=[REF(mats)]'>Remove</a>"
|
||||
ui += "<a href='?src=[REF(src)];hold[!holds[hold_key]]=[url_encode(hold_key)]'>[holds[hold_key] ? "Allow" : "Hold"]</a>"
|
||||
ui += " <b>[parent.name]</b> in [get_area_name(parent, TRUE)]<br>"
|
||||
if(!connected.len)
|
||||
ui += "Nothing!"
|
||||
|
||||
ui += "</div><div class='statusDisplay'><h2>Access Logs:</h2>"
|
||||
var/list/logs = GLOB.silo_access_logs[REF(src)]
|
||||
var/len = LAZYLEN(logs)
|
||||
var/num_pages = 1 + round((len - 1) / 30)
|
||||
var/page = CLAMP(log_page, 1, num_pages)
|
||||
if(num_pages > 1)
|
||||
for(var/i in 1 to num_pages)
|
||||
if(i == page)
|
||||
ui += "<span class='linkOff'>[i]</span>"
|
||||
else
|
||||
ui += "<a href='?src=[REF(src)];page=[i]'>[i]</a>"
|
||||
|
||||
ui += "<ol>"
|
||||
any = FALSE
|
||||
for(var/i in (page - 1) * 30 + 1 to min(page * 30, len))
|
||||
var/datum/ore_silo_log/entry = logs[i]
|
||||
ui += "<li value=[len + 1 - i]>[entry.formatted]</li>"
|
||||
any = TRUE
|
||||
if (!any)
|
||||
ui += "<li>Nothing!</li>"
|
||||
|
||||
ui += "</ol></div>"
|
||||
return ui.Join()
|
||||
|
||||
/obj/machinery/ore_silo/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["remove"])
|
||||
var/datum/component/remote_materials/mats = locate(href_list["remove"]) in connected
|
||||
if (mats)
|
||||
mats.disconnect_from(src)
|
||||
connected -= mats
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
else if(href_list["hold1"])
|
||||
holds[href_list["hold1"]] = TRUE
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
else if(href_list["hold0"])
|
||||
holds -= href_list["hold0"]
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
else if(href_list["ejectsheet"])
|
||||
var/eject_sheet = href_list["ejectsheet"]
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
var/count = materials.retrieve_sheets(text2num(href_list["eject_amt"]), eject_sheet, drop_location())
|
||||
var/list/matlist = list()
|
||||
matlist[eject_sheet] = MINERAL_MATERIAL_AMOUNT
|
||||
silo_log(src, "ejected", -count, "sheets", matlist)
|
||||
return TRUE
|
||||
else if(href_list["page"])
|
||||
log_page = text2num(href_list["page"]) || 1
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/ore_silo/multitool_act(mob/living/user, obj/item/multitool/I)
|
||||
if (istype(I))
|
||||
to_chat(user, "<span class='notice'>You log [src] in the multitool's buffer.</span>")
|
||||
I.buffer = src
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/ore_silo/proc/silo_log(obj/machinery/M, action, amount, noun, list/mats)
|
||||
if (!length(mats))
|
||||
return
|
||||
var/datum/ore_silo_log/entry = new(M, action, amount, noun, mats)
|
||||
|
||||
var/list/logs = GLOB.silo_access_logs[REF(src)]
|
||||
if(!LAZYLEN(logs))
|
||||
GLOB.silo_access_logs[REF(src)] = logs = list(entry)
|
||||
else if(!logs[1].merge(entry))
|
||||
logs.Insert(1, entry)
|
||||
|
||||
updateUsrDialog()
|
||||
flick("silo_active", src)
|
||||
|
||||
/obj/machinery/ore_silo/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>[src] can be linked to techfabs, circuit printers and protolathes with a multitool.</span>")
|
||||
|
||||
/datum/ore_silo_log
|
||||
var/name // for VV
|
||||
var/formatted // for display
|
||||
|
||||
var/timestamp
|
||||
var/machine_name
|
||||
var/area_name
|
||||
var/action
|
||||
var/noun
|
||||
var/amount
|
||||
var/list/materials
|
||||
|
||||
/datum/ore_silo_log/New(obj/machinery/M, _action, _amount, _noun, list/mats=list())
|
||||
timestamp = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
machine_name = M.name
|
||||
area_name = get_area_name(M, TRUE)
|
||||
action = _action
|
||||
amount = _amount
|
||||
noun = _noun
|
||||
materials = mats.Copy()
|
||||
for(var/each in materials)
|
||||
materials[each] *= abs(_amount)
|
||||
format()
|
||||
|
||||
/datum/ore_silo_log/proc/merge(datum/ore_silo_log/other)
|
||||
if (other == src || action != other.action || noun != other.noun)
|
||||
return FALSE
|
||||
if (machine_name != other.machine_name || area_name != other.area_name)
|
||||
return FALSE
|
||||
|
||||
timestamp = other.timestamp
|
||||
amount += other.amount
|
||||
for(var/each in other.materials)
|
||||
materials[each] += other.materials[each]
|
||||
format()
|
||||
return TRUE
|
||||
|
||||
/datum/ore_silo_log/proc/format()
|
||||
name = "[machine_name]: [action] [amount]x [noun]"
|
||||
|
||||
var/list/msg = list("([timestamp]) <b>[machine_name]</b> in [area_name]<br>[action] [abs(amount)]x [noun]<br>")
|
||||
var/sep = ""
|
||||
for(var/key in materials)
|
||||
var/val = round(materials[key]) / MINERAL_MATERIAL_AMOUNT
|
||||
msg += sep
|
||||
sep = ", "
|
||||
msg += "[amount < 0 ? "-" : "+"][val] [copytext(key, 2)]"
|
||||
formatted = msg.Join()
|
||||
@@ -0,0 +1,121 @@
|
||||
/**********************Mineral stacking unit console**************************/
|
||||
|
||||
/obj/machinery/mineral/stacking_unit_console
|
||||
name = "stacking machine console"
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "console"
|
||||
desc = "Controls a stacking machine... in theory."
|
||||
density = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/stacking_unit_console
|
||||
var/obj/machinery/mineral/stacking_machine/machine
|
||||
var/machinedir = SOUTHEAST
|
||||
|
||||
/obj/machinery/mineral/stacking_unit_console/Initialize()
|
||||
. = ..()
|
||||
machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
if (machine)
|
||||
machine.CONSOLE = src
|
||||
|
||||
/obj/machinery/mineral/stacking_unit_console/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(!machine)
|
||||
to_chat(user, "<span class='notice'>[src] is not linked to a machine!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/stack/sheet/s
|
||||
var/dat
|
||||
|
||||
dat += text("<b>Stacking unit console</b><br><br>")
|
||||
|
||||
for(var/O in machine.stack_list)
|
||||
s = machine.stack_list[O]
|
||||
if(s.amount > 0)
|
||||
dat += text("[capitalize(s.name)]: [s.amount] <A href='?src=[REF(src)];release=[s.type]'>Release</A><br>")
|
||||
|
||||
dat += text("<br>Stacking: [machine.stack_amt]<br><br>")
|
||||
|
||||
user << browse(dat, "window=console_stacking_machine")
|
||||
|
||||
/obj/machinery/mineral/stacking_unit_console/multitool_act(mob/living/user, obj/item/I)
|
||||
if(istype(I, /obj/item/multitool))
|
||||
var/obj/item/multitool/M = I
|
||||
M.buffer = src
|
||||
to_chat(user, "<span class='notice'>You store linkage information in [I]'s buffer.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/stacking_unit_console/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(href_list["release"])
|
||||
if(!(text2path(href_list["release"]) in machine.stack_list))
|
||||
return //someone tried to spawn materials by spoofing hrefs
|
||||
var/obj/item/stack/sheet/inp = machine.stack_list[text2path(href_list["release"])]
|
||||
var/obj/item/stack/sheet/out = new inp.type(null, inp.amount)
|
||||
inp.amount = 0
|
||||
machine.unload_mineral(out)
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/**********************Mineral stacking unit**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/stacking_machine
|
||||
name = "stacking machine"
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "stacker"
|
||||
desc = "A machine that automatically stacks acquired materials. Controlled by a nearby console."
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/stacking_machine
|
||||
input_dir = EAST
|
||||
output_dir = WEST
|
||||
var/obj/machinery/mineral/stacking_unit_console/CONSOLE
|
||||
var/stk_types = list()
|
||||
var/stk_amt = list()
|
||||
var/stack_list[0] //Key: Type. Value: Instance of type.
|
||||
var/stack_amt = 50 //amount to stack before releassing
|
||||
var/datum/component/remote_materials/materials
|
||||
var/force_connect = FALSE
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/Initialize(mapload)
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 1)
|
||||
materials = AddComponent(/datum/component/remote_materials, "stacking", mapload, FALSE, mapload && force_connect)
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/HasProximity(atom/movable/AM)
|
||||
if(istype(AM, /obj/item/stack/sheet) && AM.loc == get_step(src, input_dir))
|
||||
process_sheet(AM)
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/multitool_act(mob/living/user, obj/item/multitool/M)
|
||||
if(istype(M))
|
||||
if(istype(M.buffer, /obj/machinery/mineral/stacking_unit_console))
|
||||
CONSOLE = M.buffer
|
||||
CONSOLE.machine = src
|
||||
to_chat(user, "<span class='notice'>You link [src] to the console in [M]'s buffer.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp)
|
||||
var/key = inp.merge_type
|
||||
var/obj/item/stack/sheet/storage = stack_list[key]
|
||||
if(!storage) //It's the first of this sheet added
|
||||
stack_list[key] = storage = new inp.type(src, 0)
|
||||
storage.amount += inp.amount //Stack the sheets
|
||||
qdel(inp)
|
||||
|
||||
if(materials.silo && !materials.on_hold()) //Dump the sheets to the silo
|
||||
var/matlist = storage.materials & materials.mat_container.materials
|
||||
if (length(matlist))
|
||||
var/inserted = materials.mat_container.insert_stack(storage)
|
||||
materials.silo_log(src, "collected", inserted, "sheets", matlist)
|
||||
if (QDELETED(storage))
|
||||
stack_list -= key
|
||||
return
|
||||
|
||||
while(storage.amount >= stack_amt) //Get rid of excessive stackage
|
||||
var/obj/item/stack/sheet/out = new inp.type(null, stack_amt)
|
||||
unload_mineral(out)
|
||||
storage.amount -= stack_amt
|
||||
@@ -0,0 +1,31 @@
|
||||
/**********************Unloading unit**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/unloading_machine
|
||||
name = "unloading machine"
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "unloader"
|
||||
density = TRUE
|
||||
input_dir = WEST
|
||||
output_dir = EAST
|
||||
speed_process = TRUE
|
||||
|
||||
/obj/machinery/mineral/unloading_machine/process()
|
||||
var/turf/T = get_step(src,input_dir)
|
||||
if(T)
|
||||
var/limit
|
||||
for(var/obj/structure/ore_box/B in T)
|
||||
for (var/obj/item/stack/ore/O in B)
|
||||
B.contents -= O
|
||||
unload_mineral(O)
|
||||
limit++
|
||||
if (limit>=10)
|
||||
return
|
||||
CHECK_TICK
|
||||
CHECK_TICK
|
||||
for(var/obj/item/I in T)
|
||||
unload_mineral(I)
|
||||
limit++
|
||||
if (limit>=10)
|
||||
return
|
||||
CHECK_TICK
|
||||
@@ -0,0 +1,366 @@
|
||||
/**********************Mining Equipment Vendor**************************/
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor
|
||||
name = "mining equipment vendor"
|
||||
desc = "An equipment vendor for miners, points collected at an ore redemption machine can be spent here."
|
||||
icon = 'icons/obj/machines/mining_machines.dmi'
|
||||
icon_state = "mining"
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/mining_equipment_vendor
|
||||
var/icon_deny = "mining-deny"
|
||||
var/obj/item/card/id/inserted_id
|
||||
var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces.
|
||||
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
|
||||
new /datum/data/mining_equipment("50 Point Transfer Card", /obj/item/card/mining_point_card, 50),
|
||||
new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
|
||||
new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
|
||||
new /datum/data/mining_equipment("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100),
|
||||
new /datum/data/mining_equipment("Absinthe", /obj/item/reagent_containers/food/drinks/bottle/absinthe/premium, 100),
|
||||
new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/cigarette/cigar/havana, 150),
|
||||
new /datum/data/mining_equipment("Soap", /obj/item/soap/nanotrasen, 200),
|
||||
new /datum/data/mining_equipment("Laser Pointer", /obj/item/laser_pointer, 300),
|
||||
new /datum/data/mining_equipment("Alien Toy", /obj/item/clothing/mask/facehugger/toy, 300),
|
||||
new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 400),
|
||||
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/survivalcapsule, 400),
|
||||
new /datum/data/mining_equipment("Survival Knife", /obj/item/kitchen/knife/combat/survival, 450),
|
||||
new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500),
|
||||
new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
|
||||
new /datum/data/mining_equipment("Larger Ore Bag", /obj/item/storage/bag/ore/large, 500),
|
||||
new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500),
|
||||
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
|
||||
new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/medipen/survival, 750),
|
||||
new /datum/data/mining_equipment("Stabilizing Serum", /obj/item/hivelordstabilizer, 750),
|
||||
new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
|
||||
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
|
||||
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
|
||||
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 800),
|
||||
new /datum/data/mining_equipment("Burn First-Aid Kit", /obj/item/storage/firstaid/fire, 800),
|
||||
new /datum/data/mining_equipment("First-Aid Kit", /obj/item/storage/firstaid/regular, 800),
|
||||
new /datum/data/mining_equipment("Advanced Scanner", /obj/item/t_scanner/adv_mining_scanner, 800),
|
||||
new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800),
|
||||
new /datum/data/mining_equipment("Mini Extinguisher", /obj/item/extinguisher/mini, 1000),
|
||||
new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1000),
|
||||
new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000),
|
||||
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000),
|
||||
new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000),
|
||||
new /datum/data/mining_equipment("1000 Point Transfer Card", /obj/item/card/mining_point_card/mp1000, 1000),
|
||||
new /datum/data/mining_equipment("1500 Point Transfer Card", /obj/item/card/mining_point_card/mp1500, 1500),
|
||||
new /datum/data/mining_equipment("2000 Point Transfer Card", /obj/item/card/mining_point_card/mp2000, 2000),
|
||||
new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/tank/jetpack/suit, 2000),
|
||||
new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000),
|
||||
new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
|
||||
new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000),
|
||||
new /datum/data/mining_equipment("Spare Suit Voucher", /obj/item/suit_voucher, 2000),
|
||||
new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500),
|
||||
new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
|
||||
new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000),
|
||||
new /datum/data/mining_equipment("Miner Full Replacement", /obj/item/storage/backpack/duffelbag/mining_cloned, 3000),
|
||||
new /datum/data/mining_equipment("Nanotrasen Minebot", /mob/living/simple_animal/hostile/mining_drone, 800),
|
||||
new /datum/data/mining_equipment("Minebot Melee Upgrade", /obj/item/mine_bot_upgrade, 400),
|
||||
new /datum/data/mining_equipment("Minebot Armor Upgrade", /obj/item/mine_bot_upgrade/health, 400),
|
||||
new /datum/data/mining_equipment("Minebot Cooldown Upgrade", /obj/item/borg/upgrade/modkit/cooldown/minebot, 600),
|
||||
new /datum/data/mining_equipment("Minebot AI Upgrade", /obj/item/slimepotion/slime/sentience/mining, 1000),
|
||||
new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100),
|
||||
new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100),
|
||||
new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150),
|
||||
new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
|
||||
new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
|
||||
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
|
||||
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
|
||||
new /datum/data/mining_equipment("KA Cooldown Decrease", /obj/item/borg/upgrade/modkit/cooldown, 1000),
|
||||
new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
|
||||
new /datum/data/mining_equipment("Premium Accelerator", /obj/item/gun/energy/kinetic_accelerator/premiumka, 8000)
|
||||
|
||||
)
|
||||
|
||||
/datum/data/mining_equipment
|
||||
var/equipment_name = "generic"
|
||||
var/equipment_path = null
|
||||
var/cost = 0
|
||||
|
||||
/datum/data/mining_equipment/New(name, path, cost)
|
||||
src.equipment_name = name
|
||||
src.equipment_path = path
|
||||
src.cost = cost
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/update_icon()
|
||||
if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat
|
||||
dat +="<div class='statusDisplay'>"
|
||||
if(istype(inserted_id))
|
||||
dat += "You have [inserted_id.mining_points] mining points collected. <A href='?src=[REF(src)];choice=eject'>Eject ID.</A><br>"
|
||||
else
|
||||
dat += "No ID inserted. <A href='?src=[REF(src)];choice=insert'>Insert ID.</A><br>"
|
||||
dat += "</div>"
|
||||
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='300'>"
|
||||
for(var/datum/data/mining_equipment/prize in prize_list)
|
||||
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=[REF(src)];purchase=[REF(prize)]'>Purchase</A></td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 350)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["choice"])
|
||||
if(istype(inserted_id))
|
||||
if(href_list["choice"] == "eject")
|
||||
to_chat(usr, "<span class='notice'>You eject the ID from [src]'s card slot.</span>")
|
||||
inserted_id.forceMove(loc)
|
||||
inserted_id.verb_pickup()
|
||||
inserted_id = null
|
||||
else if(href_list["choice"] == "insert")
|
||||
var/obj/item/card/id/I = usr.get_active_held_item()
|
||||
if(istype(I))
|
||||
if(!usr.transferItemToLoc(I, src))
|
||||
return
|
||||
inserted_id = I
|
||||
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error: No valid ID!</span>")
|
||||
flick(icon_deny, src)
|
||||
if(href_list["purchase"])
|
||||
if(istype(inserted_id))
|
||||
var/datum/data/mining_equipment/prize = locate(href_list["purchase"])
|
||||
if (!prize || !(prize in prize_list))
|
||||
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
|
||||
flick(icon_deny, src)
|
||||
return
|
||||
if(prize.cost > inserted_id.mining_points)
|
||||
to_chat(usr, "<span class='warning'>Error: Insufficient points for [prize.equipment_name]!</span>")
|
||||
flick(icon_deny, src)
|
||||
else
|
||||
inserted_id.mining_points -= prize.cost
|
||||
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
|
||||
new prize.equipment_path(src.loc)
|
||||
SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]"))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error: Please insert a valid ID!</span>")
|
||||
flick(icon_deny, src)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/mining_voucher))
|
||||
RedeemVoucher(I, user)
|
||||
return
|
||||
if(istype(I, /obj/item/suit_voucher))
|
||||
RedeemSVoucher(I, user)
|
||||
return
|
||||
if(istype(I, /obj/item/card/id))
|
||||
var/obj/item/card/id/C = usr.get_active_held_item()
|
||||
if(istype(C) && !istype(inserted_id))
|
||||
if(!usr.transferItemToLoc(C, src))
|
||||
return
|
||||
inserted_id = C
|
||||
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
|
||||
interact(user)
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "mining-open", "mining", I))
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/mining_voucher/voucher, mob/redeemer)
|
||||
var/items = list("Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Extraction and Rescue Kit", "Crusher Kit", "Mining Conscription Kit")
|
||||
|
||||
var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in items
|
||||
if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer)
|
||||
return
|
||||
var/drop_location = drop_location()
|
||||
switch(selection)
|
||||
if("Survival Capsule and Explorer's Webbing")
|
||||
new /obj/item/storage/belt/mining/vendor(drop_location)
|
||||
if("Resonator Kit")
|
||||
new /obj/item/extinguisher/mini(drop_location)
|
||||
new /obj/item/resonator(drop_location)
|
||||
if("Minebot Kit")
|
||||
new /mob/living/simple_animal/hostile/mining_drone(drop_location)
|
||||
new /obj/item/weldingtool/hugetank(drop_location)
|
||||
new /obj/item/clothing/head/welding(drop_location)
|
||||
new /obj/item/borg/upgrade/modkit/minebot_passthrough(drop_location)
|
||||
if("Extraction and Rescue Kit")
|
||||
new /obj/item/extraction_pack(drop_location)
|
||||
new /obj/item/fulton_core(drop_location)
|
||||
new /obj/item/stack/marker_beacon/thirty(drop_location)
|
||||
if("Crusher Kit")
|
||||
new /obj/item/extinguisher/mini(drop_location)
|
||||
new /obj/item/twohanded/required/kinetic_crusher(drop_location)
|
||||
if("Mining Conscription Kit")
|
||||
new /obj/item/storage/backpack/duffelbag/mining_conscript(drop_location)
|
||||
|
||||
SSblackbox.record_feedback("tally", "mining_voucher_redeemed", 1, selection)
|
||||
qdel(voucher)
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/ex_act(severity, target)
|
||||
do_sparks(5, TRUE, src)
|
||||
if(prob(50 / severity) && severity < 3)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/****************Golem Point Vendor**************************/
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/golem
|
||||
name = "golem ship equipment vendor"
|
||||
circuit = /obj/item/circuitboard/machine/mining_equipment_vendor/golem
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/golem/Initialize()
|
||||
. = ..()
|
||||
desc += "\nIt seems a few selections have been added."
|
||||
prize_list += list(
|
||||
new /datum/data/mining_equipment("Extra Id", /obj/item/card/id/mining, 250),
|
||||
new /datum/data/mining_equipment("Science Goggles", /obj/item/clothing/glasses/science, 250),
|
||||
new /datum/data/mining_equipment("Monkey Cube", /obj/item/reagent_containers/food/snacks/monkeycube, 300),
|
||||
new /datum/data/mining_equipment("Toolbelt", /obj/item/storage/belt/utility, 350),
|
||||
new /datum/data/mining_equipment("Royal Cape of the Liberator", /obj/item/bedsheet/rd/royal_cape, 500),
|
||||
new /datum/data/mining_equipment("Sulphuric Acid", /obj/item/reagent_containers/glass/beaker/sulphuric, 500),
|
||||
new /datum/data/mining_equipment("Grey Slime Extract", /obj/item/slime_extract/grey, 1000),
|
||||
new /datum/data/mining_equipment("Modification Kit", /obj/item/borg/upgrade/modkit/trigger_guard, 1700),
|
||||
new /datum/data/mining_equipment("The Liberator's Legacy", /obj/item/storage/box/rndboards, 2000)
|
||||
)
|
||||
|
||||
/**********************Mining Equipment Vendor Items**************************/
|
||||
|
||||
/**********************Mining Equipment Voucher**********************/
|
||||
|
||||
/obj/item/mining_voucher
|
||||
name = "mining voucher"
|
||||
desc = "A token to redeem a piece of equipment. Use it on a mining equipment vendor."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "mining_voucher"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/obj/item/suit_voucher
|
||||
name = "suit voucher"
|
||||
desc = "A token to redeem a new suit. Use it on a mining equipment vendor."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "mining_voucher"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
/**********************Mining Point Card**********************/
|
||||
//mp = Miner Pointers
|
||||
//c = Cash
|
||||
//TODO add in cr = Credits for cargo
|
||||
/obj/item/card/mining_point_card
|
||||
name = "mining points card"
|
||||
desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard. This one only holds a small 50 points on it."
|
||||
icon_state = "data_1"
|
||||
var/points = 50
|
||||
|
||||
/obj/item/card/mining_point_card/mp500
|
||||
desc = "A small card preloaded with 500 mining points. Swipe your ID card over it to transfer the points, then discard."
|
||||
points = 500
|
||||
|
||||
/obj/item/card/mining_point_card/mp1000
|
||||
desc = "A small card preloaded with 1000 mining points. Swipe your ID card over it to transfer the points, then discard."
|
||||
points = 1000
|
||||
|
||||
/obj/item/card/mining_point_card/mp1500
|
||||
desc = "A small card preloaded with 1500 mining points. Swipe your ID card over it to transfer the points, then discard."
|
||||
points = 1500
|
||||
|
||||
/obj/item/card/mining_point_card/mp2000
|
||||
desc = "A small card preloaded with 2000 mining points. Swipe your ID card over it to transfer the points, then discard."
|
||||
points = 2000
|
||||
|
||||
/obj/item/card/mining_point_card/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if(points)
|
||||
var/obj/item/card/id/C = I
|
||||
C.mining_points += points
|
||||
to_chat(user, "<span class='info'>You transfer [points] points to [C].</span>")
|
||||
points = 0
|
||||
else
|
||||
to_chat(user, "<span class='info'>There's no points left on [src].</span>")
|
||||
..()
|
||||
|
||||
/obj/item/card/mining_point_card/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "There's [points] point\s on the card.")
|
||||
|
||||
///Conscript kit
|
||||
/obj/item/card/mining_access_card
|
||||
name = "mining access card"
|
||||
desc = "A small card, that when used on any ID, will add mining access."
|
||||
icon_state = "data_1"
|
||||
|
||||
/obj/item/card/mining_access_card/afterattack(atom/movable/AM, mob/user, proximity)
|
||||
. = ..()
|
||||
if(istype(AM, /obj/item/card/id) && proximity)
|
||||
var/obj/item/card/id/I = AM
|
||||
I.access |= ACCESS_MINING
|
||||
I.access |= ACCESS_MINING_STATION
|
||||
I.access |= ACCESS_MINERAL_STOREROOM
|
||||
I.access |= ACCESS_CARGO
|
||||
to_chat(user, "You upgrade [I] with mining access.")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_conscript
|
||||
name = "mining conscription kit"
|
||||
desc = "A kit containing everything a crewmember needs to support a shaft miner in the field."
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_conscript/PopulateContents()
|
||||
new /obj/item/pickaxe/mini(src)
|
||||
new /obj/item/clothing/glasses/meson(src)
|
||||
new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
|
||||
new /obj/item/storage/bag/ore(src)
|
||||
new /obj/item/clothing/suit/hooded/explorer/standard(src)
|
||||
new /obj/item/encryptionkey/headset_cargo(src)
|
||||
new /obj/item/clothing/mask/gas/explorer(src)
|
||||
new /obj/item/card/mining_access_card(src)
|
||||
|
||||
//CITADEL ADDITIONS BELOW
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_cloned
|
||||
name = "mining replacement kit"
|
||||
desc = "A large bag that has advance tools and a spare jumpsuit, boots, and gloves for a newly cloned miner to get back in the field. Even as a new Id!"
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_cloned/PopulateContents()
|
||||
new /obj/item/pickaxe/mini(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/clothing/shoes/workboots/mining(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/implanter/tracking/gps(src)
|
||||
new /obj/item/kitchen/knife/combat/survival(src)
|
||||
new /obj/item/storage/firstaid/regular(src)
|
||||
new /obj/item/reagent_containers/hypospray/medipen/survival(src)
|
||||
new /obj/item/t_scanner/adv_mining_scanner(src)
|
||||
new /obj/item/clothing/suit/hooded/explorer/standard(src)
|
||||
new /obj/item/encryptionkey/headset_cargo(src)
|
||||
new /obj/item/clothing/mask/gas/explorer(src)
|
||||
new /obj/item/card/id/mining(src)
|
||||
new /obj/item/storage/bag/ore(src)
|
||||
new /obj/item/clothing/glasses/meson/prescription(src)
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/proc/RedeemSVoucher(obj/item/suit_voucher/voucher, mob/redeemer)
|
||||
var/items = list("Exo-suit", "SEVA suit")
|
||||
|
||||
var/selection = input(redeemer, "Pick your suit.", "Suit Voucher Redemption") as null|anything in items
|
||||
if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer)
|
||||
return
|
||||
var/drop_location = drop_location()
|
||||
switch(selection)
|
||||
if("Exo-suit")
|
||||
new /obj/item/clothing/suit/hooded/explorer/exo(drop_location)
|
||||
new /obj/item/clothing/mask/gas/exo(drop_location)
|
||||
if("SEVA suit")
|
||||
new /obj/item/clothing/suit/hooded/explorer/seva(drop_location)
|
||||
new /obj/item/clothing/mask/gas/seva(drop_location)
|
||||
|
||||
SSblackbox.record_feedback("tally", "suit_voucher_redeemed", 1, selection)
|
||||
qdel(voucher)
|
||||
@@ -0,0 +1,91 @@
|
||||
/**********************Light************************/
|
||||
|
||||
//this item is intended to give the effect of entering the mine, so that light gradually fades
|
||||
/obj/effect/light_emitter
|
||||
name = "Light emitter"
|
||||
anchored = TRUE
|
||||
invisibility = 101
|
||||
var/set_luminosity = 8
|
||||
var/set_cap = 0
|
||||
|
||||
/obj/effect/light_emitter/Initialize()
|
||||
. = ..()
|
||||
set_light(set_luminosity, set_cap)
|
||||
|
||||
/obj/effect/light_emitter/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/light_emitter/singularity_act()
|
||||
return
|
||||
|
||||
/**********************Miner Lockers**************************/
|
||||
|
||||
/obj/structure/closet/wardrobe/miner
|
||||
name = "mining wardrobe"
|
||||
icon_door = "mixed"
|
||||
|
||||
/obj/structure/closet/wardrobe/miner/PopulateContents()
|
||||
new /obj/item/storage/backpack/duffelbag(src)
|
||||
new /obj/item/storage/backpack/explorer(src)
|
||||
new /obj/item/storage/backpack/satchel/explorer(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/clothing/shoes/workboots/mining(src)
|
||||
new /obj/item/clothing/shoes/workboots/mining(src)
|
||||
new /obj/item/clothing/shoes/workboots/mining(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
|
||||
/obj/structure/closet/secure_closet/miner
|
||||
name = "miner's equipment"
|
||||
icon_state = "mining"
|
||||
req_access = list(ACCESS_MINING)
|
||||
|
||||
/obj/structure/closet/secure_closet/miner/unlocked
|
||||
locked = FALSE
|
||||
|
||||
/obj/structure/closet/secure_closet/miner/PopulateContents()
|
||||
..()
|
||||
new /obj/item/stack/sheet/mineral/sandbags(src, 5)
|
||||
new /obj/item/storage/box/emptysandbags(src)
|
||||
new /obj/item/shovel(src)
|
||||
new /obj/item/pickaxe/mini(src)
|
||||
new /obj/item/radio/headset/headset_cargo/mining(src)
|
||||
new /obj/item/flashlight/seclite(src)
|
||||
new /obj/item/storage/bag/plants(src)
|
||||
new /obj/item/storage/bag/ore(src)
|
||||
new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
|
||||
new /obj/item/gun/energy/kinetic_accelerator(src)
|
||||
new /obj/item/clothing/glasses/meson(src)
|
||||
new /obj/item/survivalcapsule(src)
|
||||
new /obj/item/assault_pod/mining(src)
|
||||
|
||||
|
||||
/**********************Shuttle Computer**************************/
|
||||
|
||||
/obj/machinery/computer/shuttle/mining
|
||||
name = "mining shuttle console"
|
||||
desc = "Used to call and send the mining shuttle."
|
||||
req_access = list(ACCESS_MINING)
|
||||
circuit = /obj/item/circuitboard/computer/mining_shuttle
|
||||
shuttleId = "mining"
|
||||
possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public"
|
||||
no_destination_swap = 1
|
||||
var/global/list/dumb_rev_heads = list()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/machinery/computer/shuttle/mining/attack_hand(mob/user)
|
||||
if(is_station_level(user.z) && user.mind && is_head_revolutionary(user) && !(user.mind in dumb_rev_heads))
|
||||
to_chat(user, "<span class='warning'>You get a feeling that leaving the station might be a REALLY dumb idea...</span>")
|
||||
dumb_rev_heads += user.mind
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/**********************Mining car (Crate like thing, not the rail car)**************************/
|
||||
|
||||
/obj/structure/closet/crate/miningcar
|
||||
desc = "A mining car. This one doesn't work on rails, but has to be dragged."
|
||||
name = "Mining car (not for rails)"
|
||||
icon_state = "miningcar"
|
||||
@@ -0,0 +1,323 @@
|
||||
/**********************Mining drone**********************/
|
||||
#define MINEDRONE_COLLECT 1
|
||||
#define MINEDRONE_ATTACK 2
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone
|
||||
name = "nanotrasen minebot"
|
||||
desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife."
|
||||
gender = NEUTER
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "mining_drone"
|
||||
icon_living = "mining_drone"
|
||||
status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
faction = list("neutral")
|
||||
a_intent = INTENT_HARM
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
move_to_delay = 10
|
||||
health = 125
|
||||
maxHealth = 125
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
obj_damage = 10
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
check_friendly_fire = TRUE
|
||||
stop_automated_movement_when_pulled = TRUE
|
||||
attacktext = "drills"
|
||||
attack_sound = 'sound/weapons/circsawhit.ogg'
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
speak_emote = list("states")
|
||||
wanted_objects = list(/obj/item/stack/ore/diamond, /obj/item/stack/ore/gold, /obj/item/stack/ore/silver,
|
||||
/obj/item/stack/ore/plasma, /obj/item/stack/ore/uranium, /obj/item/stack/ore/iron,
|
||||
/obj/item/stack/ore/bananium, /obj/item/stack/ore/titanium)
|
||||
healable = 0
|
||||
loot = list(/obj/effect/decal/cleanable/robot_debris)
|
||||
del_on_death = TRUE
|
||||
var/mode = MINEDRONE_COLLECT
|
||||
var/light_on = 0
|
||||
var/obj/item/gun/energy/kinetic_accelerator/minebot/stored_gun
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/Initialize()
|
||||
. = ..()
|
||||
stored_gun = new(src)
|
||||
var/datum/action/innate/minedrone/toggle_light/toggle_light_action = new()
|
||||
toggle_light_action.Grant(src)
|
||||
var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action = new()
|
||||
toggle_meson_vision_action.Grant(src)
|
||||
var/datum/action/innate/minedrone/toggle_mode/toggle_mode_action = new()
|
||||
toggle_mode_action.Grant(src)
|
||||
var/datum/action/innate/minedrone/dump_ore/dump_ore_action = new()
|
||||
dump_ore_action.Grant(src)
|
||||
var/obj/item/implant/radio/mining/imp = new(src)
|
||||
imp.implant(src)
|
||||
|
||||
access_card = new /obj/item/card/id(src)
|
||||
var/datum/job/mining/M = new
|
||||
access_card.access = M.get_access()
|
||||
|
||||
SetCollectBehavior()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/Destroy()
|
||||
for (var/datum/action/innate/minedrone/action in actions)
|
||||
qdel(action)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/sentience_act()
|
||||
..()
|
||||
check_friendly_fire = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/examine(mob/user)
|
||||
..()
|
||||
var/t_He = p_they(TRUE)
|
||||
var/t_him = p_them()
|
||||
var/t_s = p_s()
|
||||
if(health < maxHealth)
|
||||
if(health >= maxHealth * 0.5)
|
||||
to_chat(user, "<span class='warning'>[t_He] look[t_s] slightly dented.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='boldwarning'>[t_He] look[t_s] severely dented!</span>")
|
||||
to_chat(user, "<span class='notice'>Using a mining scanner on [t_him] will instruct [t_him] to drop stored ore. <b>[max(0, LAZYLEN(contents) - 1)] Stored Ore</b>\n\
|
||||
Field repairs can be done with a welder.")
|
||||
if(stored_gun && stored_gun.max_mod_capacity)
|
||||
to_chat(user, "<b>[stored_gun.get_remaining_mod_capacity()]%</b> mod capacity remaining.")
|
||||
for(var/A in stored_gun.get_modkits())
|
||||
var/obj/item/borg/upgrade/modkit/M = A
|
||||
to_chat(user, "<span class='notice'>There is \a [M] installed, using <b>[M.cost]%</b> capacity.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/welder_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(mode == MINEDRONE_ATTACK)
|
||||
to_chat(user, "<span class='info'>[src] can't be repaired while in attack mode!</span>")
|
||||
return
|
||||
|
||||
if(maxHealth == health)
|
||||
to_chat(user, "<span class='info'>[src] is at full integrity.</span>")
|
||||
return
|
||||
|
||||
if(I.use_tool(src, user, 0, volume=40))
|
||||
adjustBruteLoss(-15)
|
||||
to_chat(user, "<span class='info'>You repair some of the armor on [src].</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner))
|
||||
to_chat(user, "<span class='info'>You instruct [src] to drop any collected ore.</span>")
|
||||
DropOre()
|
||||
return
|
||||
if(istype(I, /obj/item/crowbar) || istype(I, /obj/item/borg/upgrade/modkit))
|
||||
I.melee_attack_chain(user, stored_gun, params)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/death()
|
||||
DropOre(0)
|
||||
if(stored_gun)
|
||||
for(var/obj/item/borg/upgrade/modkit/M in stored_gun.modkits)
|
||||
M.uninstall(stored_gun)
|
||||
deathmessage = "blows apart!"
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(M.a_intent == INTENT_HELP)
|
||||
toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_COLLECT)
|
||||
to_chat(M, "<span class='info'>[src] has been set to search and store loose ore.</span>")
|
||||
if(MINEDRONE_ATTACK)
|
||||
to_chat(M, "<span class='info'>[src] has been set to attack hostile wildlife.</span>")
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/CanPass(atom/movable/O)
|
||||
if(istype(O, /obj/item/projectile/kinetic))
|
||||
var/obj/item/projectile/kinetic/K = O
|
||||
if(K.kinetic_gun)
|
||||
for(var/A in K.kinetic_gun.get_modkits())
|
||||
var/obj/item/borg/upgrade/modkit/M = A
|
||||
if(istype(M, /obj/item/borg/upgrade/modkit/minebot_passthrough))
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/projectile/destabilizer))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
|
||||
mode = MINEDRONE_COLLECT
|
||||
vision_range = 9
|
||||
search_objects = 2
|
||||
wander = TRUE
|
||||
ranged = FALSE
|
||||
minimum_distance = 1
|
||||
retreat_distance = null
|
||||
icon_state = "mining_drone"
|
||||
to_chat(src, "<span class='info'>You are set to collect mode. You can now collect loose ore.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior()
|
||||
mode = MINEDRONE_ATTACK
|
||||
vision_range = 7
|
||||
search_objects = 0
|
||||
wander = FALSE
|
||||
ranged = TRUE
|
||||
retreat_distance = 2
|
||||
minimum_distance = 1
|
||||
icon_state = "mining_drone_offense"
|
||||
to_chat(src, "<span class='info'>You are set to attack mode. You can now attack from range.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/AttackingTarget()
|
||||
if(istype(target, /obj/item/stack/ore) && mode == MINEDRONE_COLLECT)
|
||||
CollectOre()
|
||||
return
|
||||
if(isliving(target))
|
||||
SetOffenseBehavior()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/OpenFire(atom/A)
|
||||
if(CheckFriendlyFire(A))
|
||||
return
|
||||
stored_gun.afterattack(A, src) //of the possible options to allow minebots to have KA mods, would you believe this is the best?
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
|
||||
for(var/obj/item/stack/ore/O in range(1, src))
|
||||
O.forceMove(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre(message = 1)
|
||||
if(!contents.len)
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You attempt to dump your stored ore, but you have none.</span>")
|
||||
return
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You dump your stored ore.</span>")
|
||||
for(var/obj/item/stack/ore/O in contents)
|
||||
O.forceMove(drop_location())
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount)
|
||||
if(mode != MINEDRONE_ATTACK && amount > 0)
|
||||
SetOffenseBehavior()
|
||||
. = ..()
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision
|
||||
name = "Toggle Meson Vision"
|
||||
button_icon_state = "meson"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
if(user.sight & SEE_TURFS)
|
||||
user.sight &= ~SEE_TURFS
|
||||
user.lighting_alpha = initial(user.lighting_alpha)
|
||||
else
|
||||
user.sight |= SEE_TURFS
|
||||
user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
|
||||
user.sync_lighting_plane_alpha()
|
||||
|
||||
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].</span>")
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_ATTACK)
|
||||
SetCollectBehavior()
|
||||
else
|
||||
SetOffenseBehavior()
|
||||
|
||||
//Actions for sentient minebots
|
||||
|
||||
/datum/action/innate/minedrone
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
|
||||
background_icon_state = "bg_default"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light
|
||||
name = "Toggle Light"
|
||||
button_icon_state = "mech_lights_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
|
||||
if(user.light_on)
|
||||
user.set_light(0)
|
||||
else
|
||||
user.set_light(6)
|
||||
user.light_on = !user.light_on
|
||||
to_chat(user, "<span class='notice'>You toggle your light [user.light_on ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode
|
||||
name = "Toggle Mode"
|
||||
button_icon_state = "mech_cycle_equip_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.toggle_mode()
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore
|
||||
name = "Dump Ore"
|
||||
button_icon_state = "mech_eject"
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.DropOre()
|
||||
|
||||
|
||||
/**********************Minebot Upgrades**********************/
|
||||
|
||||
//Melee
|
||||
|
||||
/obj/item/mine_bot_upgrade
|
||||
name = "minebot melee upgrade"
|
||||
desc = "A minebot upgrade."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
|
||||
/obj/item/mine_bot_upgrade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!istype(M) || !proximity)
|
||||
return
|
||||
upgrade_bot(M, user)
|
||||
|
||||
/obj/item/mine_bot_upgrade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.melee_damage_upper != initial(M.melee_damage_upper))
|
||||
to_chat(user, "[src] already has a combat upgrade installed!")
|
||||
return
|
||||
M.melee_damage_lower += 7
|
||||
M.melee_damage_upper += 7
|
||||
qdel(src)
|
||||
|
||||
//Health
|
||||
|
||||
/obj/item/mine_bot_upgrade/health
|
||||
name = "minebot armor upgrade"
|
||||
|
||||
/obj/item/mine_bot_upgrade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.maxHealth != initial(M.maxHealth))
|
||||
to_chat(user, "[src] already has reinforced armor!")
|
||||
return
|
||||
M.maxHealth += 45
|
||||
M.updatehealth()
|
||||
qdel(src)
|
||||
|
||||
//AI
|
||||
|
||||
/obj/item/slimepotion/slime/sentience/mining
|
||||
name = "minebot AI upgrade"
|
||||
desc = "Can be used to grant sentience to minebots. It's incompatible with minebot armor and melee upgrades, and will override them."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
var/base_health_add = 5 //sentient minebots are penalized for beign sentient; they have their stats reset to normal plus these values
|
||||
var/base_damage_add = 1 //this thus disables other minebot upgrades
|
||||
var/base_speed_add = 1
|
||||
var/base_cooldown_add = 10 //base cooldown isn't reset to normal, it's just added on, since it's not practical to disable the cooldown module
|
||||
|
||||
/obj/item/slimepotion/slime/sentience/mining/after_success(mob/living/user, mob/living/simple_animal/SM)
|
||||
if(istype(SM, /mob/living/simple_animal/hostile/mining_drone))
|
||||
var/mob/living/simple_animal/hostile/mining_drone/M = SM
|
||||
M.maxHealth = initial(M.maxHealth) + base_health_add
|
||||
M.melee_damage_lower = initial(M.melee_damage_lower) + base_damage_add
|
||||
M.melee_damage_upper = initial(M.melee_damage_upper) + base_damage_add
|
||||
M.move_to_delay = initial(M.move_to_delay) + base_speed_add
|
||||
if(M.stored_gun)
|
||||
M.stored_gun.overheat_time += base_cooldown_add
|
||||
|
||||
#undef MINEDRONE_COLLECT
|
||||
#undef MINEDRONE_ATTACK
|
||||
@@ -0,0 +1,105 @@
|
||||
/**********************Mint**************************/
|
||||
|
||||
|
||||
/obj/machinery/mineral/mint
|
||||
name = "coin press"
|
||||
icon = 'icons/obj/economy.dmi'
|
||||
icon_state = "coinpress0"
|
||||
density = TRUE
|
||||
var/newCoins = 0 //how many coins the machine made in it's last load
|
||||
var/processing = FALSE
|
||||
var/chosen = MAT_METAL //which material will be used to make coins
|
||||
var/coinsToProduce = 10
|
||||
speed_process = TRUE
|
||||
|
||||
|
||||
/obj/machinery/mineral/mint/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack)
|
||||
|
||||
/obj/machinery/mineral/mint/process()
|
||||
var/turf/T = get_step(src, input_dir)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
for(var/obj/item/stack/sheet/O in T)
|
||||
materials.insert_stack(O, O.amount)
|
||||
|
||||
/obj/machinery/mineral/mint/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/dat = "<b>Coin Press</b><br>"
|
||||
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
if(!M.amount && chosen != mat_id)
|
||||
continue
|
||||
dat += "<br><b>[M.name] amount:</b> [M.amount] cm<sup>3</sup> "
|
||||
if (chosen == mat_id)
|
||||
dat += "<b>Chosen</b>"
|
||||
else
|
||||
dat += "<A href='?src=[REF(src)];choose=[mat_id]'>Choose</A>"
|
||||
|
||||
var/datum/material/M = materials.materials[chosen]
|
||||
|
||||
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-10'>-10</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-5'>-5</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=-1'>-1</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=1'>+1</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=5'>+5</A> "
|
||||
dat += "<A href='?src=[REF(src)];chooseAmt=10'>+10</A> "
|
||||
|
||||
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
|
||||
dat += "<br><A href='?src=[REF(src)];makeCoins=[1]'>Make coins</A>"
|
||||
user << browse(dat, "window=mint")
|
||||
|
||||
/obj/machinery/mineral/mint/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(processing==1)
|
||||
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
|
||||
return
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
if(href_list["choose"])
|
||||
if(materials.materials[href_list["choose"]])
|
||||
chosen = href_list["choose"]
|
||||
if(href_list["chooseAmt"])
|
||||
coinsToProduce = CLAMP(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
|
||||
if(href_list["makeCoins"])
|
||||
var/temp_coins = coinsToProduce
|
||||
processing = TRUE
|
||||
icon_state = "coinpress1"
|
||||
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
|
||||
var/datum/material/M = materials.materials[chosen]
|
||||
if(!M || !M.coin_type)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen))
|
||||
create_coins(M.coin_type)
|
||||
coinsToProduce--
|
||||
newCoins++
|
||||
src.updateUsrDialog()
|
||||
sleep(5)
|
||||
|
||||
icon_state = "coinpress0"
|
||||
processing = FALSE
|
||||
coinsToProduce = temp_coins
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/mineral/mint/proc/create_coins(P)
|
||||
var/turf/T = get_step(src,output_dir)
|
||||
if(T)
|
||||
var/obj/item/O = new P(src)
|
||||
var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T)
|
||||
if(!M)
|
||||
M = new /obj/item/storage/bag/money(src)
|
||||
unload_mineral(M)
|
||||
O.forceMove(M)
|
||||
@@ -0,0 +1,27 @@
|
||||
/*****************************Money bag********************************/
|
||||
|
||||
/obj/item/storage/bag/money
|
||||
name = "money bag"
|
||||
icon_state = "moneybag"
|
||||
force = 10
|
||||
throwforce = 0
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 100
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/storage/bag/money/Initialize()
|
||||
. = ..()
|
||||
GET_COMPONENT(STR, /datum/component/storage)
|
||||
STR.max_w_class = WEIGHT_CLASS_NORMAL
|
||||
STR.max_items = 40
|
||||
STR.max_combined_w_class = 40
|
||||
STR.can_hold = typecacheof(list(/obj/item/coin, /obj/item/stack/spacecash))
|
||||
|
||||
/obj/item/storage/bag/money/vault/PopulateContents()
|
||||
new /obj/item/coin/silver(src)
|
||||
new /obj/item/coin/silver(src)
|
||||
new /obj/item/coin/silver(src)
|
||||
new /obj/item/coin/silver(src)
|
||||
new /obj/item/coin/gold(src)
|
||||
new /obj/item/coin/gold(src)
|
||||
new /obj/item/coin/adamantine(src)
|
||||
@@ -0,0 +1,487 @@
|
||||
|
||||
#define GIBTONITE_QUALITY_HIGH 3
|
||||
#define GIBTONITE_QUALITY_MEDIUM 2
|
||||
#define GIBTONITE_QUALITY_LOW 1
|
||||
|
||||
#define ORESTACK_OVERLAYS_MAX 10
|
||||
|
||||
/**********************Mineral ores**************************/
|
||||
|
||||
/obj/item/stack/ore
|
||||
name = "rock"
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "ore"
|
||||
item_state = "ore"
|
||||
full_w_class = WEIGHT_CLASS_BULKY
|
||||
singular_name = "ore chunk"
|
||||
var/points = 0 //How many points this ore gets you from the ore redemption machine
|
||||
var/refined_type = null //What this ore defaults to being refined into
|
||||
novariants = TRUE // Ore stacks handle their icon updates themselves to keep the illusion that there's more going
|
||||
var/list/stack_overlays
|
||||
|
||||
/obj/item/stack/ore/update_icon()
|
||||
var/difference = min(ORESTACK_OVERLAYS_MAX, amount) - (LAZYLEN(stack_overlays)+1)
|
||||
if(difference == 0)
|
||||
return
|
||||
else if(difference < 0 && LAZYLEN(stack_overlays)) //amount < stack_overlays, remove excess.
|
||||
cut_overlays()
|
||||
if (LAZYLEN(stack_overlays)-difference <= 0)
|
||||
stack_overlays = null;
|
||||
else
|
||||
stack_overlays.len += difference
|
||||
else if(difference > 0) //amount > stack_overlays, add some.
|
||||
cut_overlays()
|
||||
for(var/i in 1 to difference)
|
||||
var/mutable_appearance/newore = mutable_appearance(icon, icon_state)
|
||||
newore.pixel_x = rand(-8,8)
|
||||
newore.pixel_y = rand(-8,8)
|
||||
LAZYADD(stack_overlays, newore)
|
||||
if (stack_overlays)
|
||||
add_overlay(stack_overlays)
|
||||
|
||||
/obj/item/stack/ore/welder_act(mob/living/user, obj/item/I)
|
||||
if(!refined_type)
|
||||
return TRUE
|
||||
|
||||
if(I.use_tool(src, user, 0, volume=50, amount=15))
|
||||
new refined_type(drop_location())
|
||||
use(1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/ore/fire_act(exposed_temperature, exposed_volume)
|
||||
. = ..()
|
||||
if(isnull(refined_type))
|
||||
return
|
||||
else
|
||||
var/probability = (rand(0,100))/100
|
||||
var/burn_value = probability*amount
|
||||
var/amountrefined = round(burn_value, 1)
|
||||
if(amountrefined < 1)
|
||||
qdel(src)
|
||||
else
|
||||
new refined_type(drop_location(),amountrefined)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/stack/ore/uranium
|
||||
name = "uranium ore"
|
||||
icon_state = "Uranium ore"
|
||||
item_state = "Uranium ore"
|
||||
singular_name = "uranium ore chunk"
|
||||
points = 30
|
||||
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/uranium
|
||||
|
||||
/obj/item/stack/ore/iron
|
||||
name = "iron ore"
|
||||
icon_state = "Iron ore"
|
||||
item_state = "Iron ore"
|
||||
singular_name = "iron ore chunk"
|
||||
points = 1
|
||||
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/metal
|
||||
|
||||
/obj/item/stack/ore/glass
|
||||
name = "sand pile"
|
||||
icon_state = "Glass ore"
|
||||
item_state = "Glass ore"
|
||||
singular_name = "sand pile"
|
||||
points = 1
|
||||
materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/glass
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50)\
|
||||
))
|
||||
|
||||
/obj/item/stack/ore/glass/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.sand_recipes
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/ore/glass/throw_impact(atom/hit_atom)
|
||||
if(..() || !ishuman(hit_atom))
|
||||
return
|
||||
var/mob/living/carbon/human/C = hit_atom
|
||||
if(C.head && C.head.flags_cover & HEADCOVERSEYES)
|
||||
visible_message("<span class='danger'>[C]'s headgear blocks the sand!</span>")
|
||||
return
|
||||
if(C.wear_mask && C.wear_mask.flags_cover & MASKCOVERSEYES)
|
||||
visible_message("<span class='danger'>[C]'s mask blocks the sand!</span>")
|
||||
return
|
||||
if(C.glasses && C.glasses.flags_cover & GLASSESCOVERSEYES)
|
||||
visible_message("<span class='danger'>[C]'s glasses block the sand!</span>")
|
||||
return
|
||||
C.adjust_blurriness(6)
|
||||
C.adjustStaminaLoss(15)//the pain from your eyes burning does stamina damage
|
||||
C.confused += 5
|
||||
to_chat(C, "<span class='userdanger'>\The [src] gets into your eyes! The pain, it burns!</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/stack/ore/glass/ex_act(severity, target)
|
||||
if (severity == EXPLODE_NONE)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/obj/item/stack/ore/glass/basalt
|
||||
name = "volcanic ash"
|
||||
icon_state = "volcanic_sand"
|
||||
icon_state = "volcanic_sand"
|
||||
singular_name = "volcanic ash pile"
|
||||
|
||||
/obj/item/stack/ore/plasma
|
||||
name = "plasma ore"
|
||||
icon_state = "Plasma ore"
|
||||
item_state = "Plasma ore"
|
||||
singular_name = "plasma ore chunk"
|
||||
points = 15
|
||||
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/plasma
|
||||
|
||||
/obj/item/stack/ore/plasma/welder_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='warning'>You can't hit a high enough temperature to smelt [src] properly!</span>")
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/stack/ore/silver
|
||||
name = "silver ore"
|
||||
icon_state = "Silver ore"
|
||||
item_state = "Silver ore"
|
||||
singular_name = "silver ore chunk"
|
||||
points = 16
|
||||
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/silver
|
||||
|
||||
/obj/item/stack/ore/gold
|
||||
name = "gold ore"
|
||||
icon_state = "Gold ore"
|
||||
icon_state = "Gold ore"
|
||||
singular_name = "gold ore chunk"
|
||||
points = 18
|
||||
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/gold
|
||||
|
||||
/obj/item/stack/ore/diamond
|
||||
name = "diamond ore"
|
||||
icon_state = "Diamond ore"
|
||||
item_state = "Diamond ore"
|
||||
singular_name = "diamond ore chunk"
|
||||
points = 50
|
||||
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/diamond
|
||||
|
||||
/obj/item/stack/ore/bananium
|
||||
name = "bananium ore"
|
||||
icon_state = "Bananium ore"
|
||||
item_state = "Bananium ore"
|
||||
singular_name = "bananium ore chunk"
|
||||
points = 60
|
||||
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/bananium
|
||||
|
||||
/obj/item/stack/ore/titanium
|
||||
name = "titanium ore"
|
||||
icon_state = "Titanium ore"
|
||||
item_state = "Titanium ore"
|
||||
singular_name = "titanium ore chunk"
|
||||
points = 50
|
||||
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
|
||||
refined_type = /obj/item/stack/sheet/mineral/titanium
|
||||
|
||||
/obj/item/stack/ore/slag
|
||||
name = "slag"
|
||||
desc = "Completely useless."
|
||||
icon_state = "slag"
|
||||
item_state = "slag"
|
||||
singular_name = "slag chunk"
|
||||
|
||||
/obj/item/twohanded/required/gibtonite
|
||||
name = "gibtonite ore"
|
||||
desc = "Extremely explosive if struck with mining equipment, Gibtonite is often used by miners to speed up their work by using it as a mining charge. This material is illegal to possess by unauthorized personnel under space law."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "Gibtonite ore"
|
||||
item_state = "Gibtonite ore"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
throw_range = 0
|
||||
var/primed = FALSE
|
||||
var/det_time = 100
|
||||
var/quality = GIBTONITE_QUALITY_LOW //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher value = better
|
||||
var/attacher = "UNKNOWN"
|
||||
var/det_timer
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/Destroy()
|
||||
qdel(wires)
|
||||
wires = null
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/attackby(obj/item/I, mob/user, params)
|
||||
if(!wires && istype(I, /obj/item/assembly/igniter))
|
||||
user.visible_message("[user] attaches [I] to [src].", "<span class='notice'>You attach [I] to [src].</span>")
|
||||
wires = new /datum/wires/explosive/gibtonite(src)
|
||||
attacher = key_name(user)
|
||||
qdel(I)
|
||||
add_overlay("Gibtonite_igniter")
|
||||
return
|
||||
|
||||
if(wires && !primed)
|
||||
if(is_wire_tool(I))
|
||||
wires.interact(user)
|
||||
return
|
||||
|
||||
if(I.tool_behaviour == TOOL_MINING || istype(I, /obj/item/resonator) || I.force >= 10)
|
||||
GibtoniteReaction(user)
|
||||
return
|
||||
if(primed)
|
||||
if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || istype(I, /obj/item/multitool))
|
||||
primed = FALSE
|
||||
if(det_timer)
|
||||
deltimer(det_timer)
|
||||
user.visible_message("The chain reaction was stopped! ...The ore's quality looks diminished.", "<span class='notice'>You stopped the chain reaction. ...The ore's quality looks diminished.</span>")
|
||||
icon_state = "Gibtonite ore"
|
||||
quality = GIBTONITE_QUALITY_LOW
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/attack_self(user)
|
||||
if(wires)
|
||||
wires.interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/bullet_act(obj/item/projectile/P)
|
||||
GibtoniteReaction(P.firer)
|
||||
..()
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/ex_act()
|
||||
GibtoniteReaction(null, 1)
|
||||
|
||||
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0)
|
||||
if(!primed)
|
||||
primed = TRUE
|
||||
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1)
|
||||
icon_state = "Gibtonite active"
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/notify_admins = 0
|
||||
if(z != 5)//Only annoy the admins ingame if we're triggered off the mining zlevel
|
||||
notify_admins = 1
|
||||
|
||||
if(notify_admins)
|
||||
if(triggered_by == 1)
|
||||
message_admins("An explosion has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)].")
|
||||
else if(triggered_by == 2)
|
||||
message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]")
|
||||
else
|
||||
message_admins("[ADMIN_LOOKUPFLW(attacher)] has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)].")
|
||||
if(triggered_by == 1)
|
||||
log_game("An explosion has primed a [name] for detonation at [AREACOORD(bombturf)]")
|
||||
else if(triggered_by == 2)
|
||||
log_game("A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)].")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] strikes \the [src], causing a chain reaction!</span>", "<span class='danger'>You strike \the [src], causing a chain reaction.</span>")
|
||||
log_game("[key_name(user)] has primed a [name] for detonation at [AREACOORD(bombturf)]")
|
||||
det_timer = addtimer(CALLBACK(src, .proc/detonate, notify_admins), det_time, TIMER_STOPPABLE)
|
||||
|
||||
/obj/item/twohanded/required/gibtonite/proc/detonate(notify_admins)
|
||||
if(primed)
|
||||
switch(quality)
|
||||
if(GIBTONITE_QUALITY_HIGH)
|
||||
explosion(src,2,4,9,adminlog = notify_admins)
|
||||
if(GIBTONITE_QUALITY_MEDIUM)
|
||||
explosion(src,1,2,5,adminlog = notify_admins)
|
||||
if(GIBTONITE_QUALITY_LOW)
|
||||
explosion(src,0,1,3,adminlog = notify_admins)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/stack/ore/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(0,16)-8
|
||||
pixel_y = rand(0,8)-8
|
||||
|
||||
/obj/item/stack/ore/ex_act(severity, target)
|
||||
if (!severity || severity >= 2)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
|
||||
/*****************************Coin********************************/
|
||||
|
||||
// The coin's value is a value of it's materials.
|
||||
// Yes, the gold standard makes a come-back!
|
||||
// This is the only way to make coins that are possible to produce on station actually worth anything.
|
||||
/obj/item/coin
|
||||
icon = 'icons/obj/economy.dmi'
|
||||
name = "coin"
|
||||
icon_state = "coin__heads"
|
||||
flags_1 = CONDUCT_1
|
||||
force = 1
|
||||
throwforce = 2
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/string_attached
|
||||
var/list/sideslist = list("heads","tails")
|
||||
var/cmineral = null
|
||||
var/cooldown = 0
|
||||
var/value = 1
|
||||
var/coinflip
|
||||
|
||||
/obj/item/coin/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] contemplates suicide with \the [src]!</span>")
|
||||
if (!attack_self(user))
|
||||
user.visible_message("<span class='suicide'>[user] couldn't flip \the [src]!</span>")
|
||||
return SHAME
|
||||
addtimer(CALLBACK(src, .proc/manual_suicide, user), 10)//10 = time takes for flip animation
|
||||
return MANUAL_SUICIDE
|
||||
|
||||
/obj/item/coin/proc/manual_suicide(mob/living/user)
|
||||
var/index = sideslist.Find(coinflip)
|
||||
if (index==2)//tails
|
||||
user.visible_message("<span class='suicide'>\the [src] lands on [coinflip]! [user] promptly falls over, dead!</span>")
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
else
|
||||
user.visible_message("<span class='suicide'>\the [src] lands on [coinflip]! [user] keeps on living!</span>")
|
||||
|
||||
/obj/item/coin/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(0,16)-8
|
||||
pixel_y = rand(0,8)-8
|
||||
|
||||
/obj/item/coin/examine(mob/user)
|
||||
..()
|
||||
if(value)
|
||||
to_chat(user, "<span class='info'>It's worth [value] credit\s.</span>")
|
||||
|
||||
/obj/item/coin/gold
|
||||
name = "gold coin"
|
||||
cmineral = "gold"
|
||||
icon_state = "coin_gold_heads"
|
||||
value = 50
|
||||
materials = list(MAT_GOLD = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("gold" = 4)
|
||||
|
||||
/obj/item/coin/silver
|
||||
name = "silver coin"
|
||||
cmineral = "silver"
|
||||
icon_state = "coin_silver_heads"
|
||||
value = 20
|
||||
materials = list(MAT_SILVER = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("silver" = 4)
|
||||
|
||||
/obj/item/coin/diamond
|
||||
name = "diamond coin"
|
||||
cmineral = "diamond"
|
||||
icon_state = "coin_diamond_heads"
|
||||
value = 500
|
||||
materials = list(MAT_DIAMOND = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("carbon" = 4)
|
||||
|
||||
/obj/item/coin/iron
|
||||
name = "iron coin"
|
||||
cmineral = "iron"
|
||||
icon_state = "coin_iron_heads"
|
||||
value = 1
|
||||
materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("iron" = 4)
|
||||
|
||||
/obj/item/coin/plasma
|
||||
name = "plasma coin"
|
||||
cmineral = "plasma"
|
||||
icon_state = "coin_plasma_heads"
|
||||
value = 100
|
||||
materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("plasma" = 4)
|
||||
|
||||
/obj/item/coin/uranium
|
||||
name = "uranium coin"
|
||||
cmineral = "uranium"
|
||||
icon_state = "coin_uranium_heads"
|
||||
value = 80
|
||||
materials = list(MAT_URANIUM = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("uranium" = 4)
|
||||
|
||||
/obj/item/coin/bananium
|
||||
name = "bananium coin"
|
||||
cmineral = "bananium"
|
||||
icon_state = "coin_bananium_heads"
|
||||
value = 1000 //makes the clown cry
|
||||
materials = list(MAT_BANANIUM = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
grind_results = list("banana" = 4)
|
||||
|
||||
/obj/item/coin/adamantine
|
||||
name = "adamantine coin"
|
||||
cmineral = "adamantine"
|
||||
icon_state = "coin_adamantine_heads"
|
||||
value = 1500
|
||||
|
||||
/obj/item/coin/mythril
|
||||
name = "mythril coin"
|
||||
cmineral = "mythril"
|
||||
icon_state = "coin_mythril_heads"
|
||||
value = 3000
|
||||
|
||||
/obj/item/coin/twoheaded
|
||||
cmineral = "iron"
|
||||
icon_state = "coin_iron_heads"
|
||||
desc = "Hey, this coin's the same on both sides!"
|
||||
sideslist = list("heads")
|
||||
materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT*0.2)
|
||||
value = 1
|
||||
grind_results = list("iron" = 4)
|
||||
|
||||
/obj/item/coin/antagtoken
|
||||
name = "antag token"
|
||||
icon_state = "coin_valid_valid"
|
||||
cmineral = "valid"
|
||||
desc = "A novelty coin that helps the heart know what hard evidence cannot prove."
|
||||
sideslist = list("valid", "salad")
|
||||
value = 0
|
||||
grind_results = list("sodiumchloride" = 4)
|
||||
|
||||
/obj/item/coin/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(string_attached)
|
||||
to_chat(user, "<span class='warning'>There already is a string attached to this coin!</span>")
|
||||
return
|
||||
|
||||
if (CC.use(1))
|
||||
add_overlay("coin_string_overlay")
|
||||
string_attached = 1
|
||||
to_chat(user, "<span class='notice'>You attach a string to the coin.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one length of cable to attach a string to the coin!</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/coin/wirecutter_act(mob/living/user, obj/item/I)
|
||||
if(!string_attached)
|
||||
return TRUE
|
||||
|
||||
new /obj/item/stack/cable_coil(drop_location(), 1)
|
||||
overlays = list()
|
||||
string_attached = null
|
||||
to_chat(user, "<span class='notice'>You detach the string from the coin.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/coin/attack_self(mob/user)
|
||||
if(cooldown < world.time)
|
||||
if(string_attached) //does the coin have a wire attached
|
||||
to_chat(user, "<span class='warning'>The coin won't flip very well with something attached!</span>" )
|
||||
return FALSE//do not flip the coin
|
||||
coinflip = pick(sideslist)
|
||||
cooldown = world.time + 15
|
||||
flick("coin_[cmineral]_flip", src)
|
||||
icon_state = "coin_[cmineral]_[coinflip]"
|
||||
playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1)
|
||||
var/oldloc = loc
|
||||
sleep(15)
|
||||
if(loc == oldloc && user && !user.incapacitated())
|
||||
user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \
|
||||
"<span class='notice'>You flip [src]. It lands on [coinflip].</span>", \
|
||||
"<span class='italics'>You hear the clattering of loose change.</span>")
|
||||
return TRUE//did the coin flip? useful for suicide_act
|
||||
|
||||
|
||||
#undef ORESTACK_OVERLAYS_MAX
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
/**********************Ore box**************************/
|
||||
|
||||
/obj/structure/ore_box
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "orebox"
|
||||
name = "ore box"
|
||||
desc = "A heavy wooden box, which can be filled with a lot of ores."
|
||||
density = TRUE
|
||||
pressure_resistance = 5*ONE_ATMOSPHERE
|
||||
|
||||
/obj/structure/ore_box/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/stack/ore))
|
||||
user.transferItemToLoc(W, src)
|
||||
else if(SEND_SIGNAL(W, COMSIG_CONTAINS_STORAGE))
|
||||
SEND_SIGNAL(W, COMSIG_TRY_STORAGE_TAKE_TYPE, /obj/item/stack/ore, src)
|
||||
to_chat(user, "<span class='notice'>You empty the ore in [W] into \the [src].</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I)
|
||||
if(I.use_tool(src, user, 50, volume=50))
|
||||
user.visible_message("[user] pries \the [src] apart.",
|
||||
"<span class='notice'>You pry apart \the [src].</span>",
|
||||
"<span class='italics'>You hear splitting wood.</span>")
|
||||
deconstruct(TRUE, user)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/ore_box/examine(mob/living/user)
|
||||
if(Adjacent(user) && istype(user))
|
||||
show_contents(user)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/ore_box/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(Adjacent(user))
|
||||
show_contents(user)
|
||||
|
||||
/obj/structure/ore_box/attack_robot(mob/user)
|
||||
if(Adjacent(user))
|
||||
show_contents(user)
|
||||
|
||||
/obj/structure/ore_box/proc/show_contents(mob/user)
|
||||
var/dat = text("<b>The contents of the ore box reveal...</b><br>")
|
||||
var/list/assembled = list()
|
||||
for(var/obj/item/stack/ore/O in src)
|
||||
assembled[O.type] += O.amount
|
||||
for(var/type in assembled)
|
||||
var/obj/item/stack/ore/O = type
|
||||
dat += "[initial(O.name)] - [assembled[type]]<br>"
|
||||
dat += text("<br><br><A href='?src=[REF(src)];removeall=1'>Empty box</A>")
|
||||
user << browse(dat, "window=orebox")
|
||||
|
||||
/obj/structure/ore_box/proc/dump_box_contents()
|
||||
var/drop = drop_location()
|
||||
for(var/obj/item/stack/ore/O in src)
|
||||
if(QDELETED(O))
|
||||
continue
|
||||
if(QDELETED(src))
|
||||
break
|
||||
O.forceMove(drop)
|
||||
if(TICK_CHECK)
|
||||
stoplag()
|
||||
drop = drop_location()
|
||||
|
||||
/obj/structure/ore_box/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!Adjacent(usr))
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["removeall"])
|
||||
dump_box_contents()
|
||||
to_chat(usr, "<span class='notice'>You open the release hatch on the box..</span>")
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/structure/ore_box/deconstruct(disassembled = TRUE, mob/user)
|
||||
var/obj/item/stack/sheet/mineral/wood/WD = new (loc, 4)
|
||||
if(user)
|
||||
WD.add_fingerprint(user)
|
||||
dump_box_contents()
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/ore_box/onTransitZ()
|
||||
return
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/map_template/shelter
|
||||
var/shelter_id
|
||||
var/description
|
||||
var/blacklisted_turfs
|
||||
var/whitelisted_turfs
|
||||
var/banned_areas
|
||||
var/banned_objects
|
||||
|
||||
/datum/map_template/shelter/New()
|
||||
. = ..()
|
||||
blacklisted_turfs = typecacheof(/turf/closed)
|
||||
whitelisted_turfs = list()
|
||||
banned_areas = typecacheof(/area/shuttle)
|
||||
banned_objects = list()
|
||||
|
||||
/datum/map_template/shelter/proc/check_deploy(turf/deploy_location)
|
||||
var/affected = get_affected_turfs(deploy_location, centered=TRUE)
|
||||
for(var/turf/T in affected)
|
||||
var/area/A = get_area(T)
|
||||
if(is_type_in_typecache(A, banned_areas))
|
||||
return SHELTER_DEPLOY_BAD_AREA
|
||||
|
||||
var/banned = is_type_in_typecache(T, blacklisted_turfs)
|
||||
var/permitted = is_type_in_typecache(T, whitelisted_turfs)
|
||||
if(banned && !permitted)
|
||||
return SHELTER_DEPLOY_BAD_TURFS
|
||||
|
||||
for(var/obj/O in T)
|
||||
if((O.density && O.anchored) || is_type_in_typecache(O, banned_objects))
|
||||
return SHELTER_DEPLOY_ANCHORED_OBJECTS
|
||||
return SHELTER_DEPLOY_ALLOWED
|
||||
|
||||
/datum/map_template/shelter/alpha
|
||||
name = "Shelter Alpha"
|
||||
shelter_id = "shelter_alpha"
|
||||
description = "A cosy self-contained pressurized shelter, with \
|
||||
built-in navigation, entertainment, medical facilities and a \
|
||||
sleeping area! Order now, and we'll throw in a TINY FAN, \
|
||||
absolutely free!"
|
||||
mappath = "_maps/templates/shelter_1.dmm"
|
||||
|
||||
/datum/map_template/shelter/alpha/New()
|
||||
. = ..()
|
||||
whitelisted_turfs = typecacheof(/turf/closed/mineral)
|
||||
banned_objects = typecacheof(/obj/structure/stone_tile)
|
||||
|
||||
/datum/map_template/shelter/beta
|
||||
name = "Shelter Beta"
|
||||
shelter_id = "shelter_beta"
|
||||
description = "An extremely luxurious shelter, containing all \
|
||||
the amenities of home, including carpeted floors, hot and cold \
|
||||
running water, a gourmet three course meal, cooking facilities, \
|
||||
and a deluxe companion to keep you from getting lonely during \
|
||||
an ash storm."
|
||||
mappath = "_maps/templates/shelter_2.dmm"
|
||||
|
||||
/datum/map_template/shelter/beta/New()
|
||||
. = ..()
|
||||
whitelisted_turfs = typecacheof(/turf/closed/mineral)
|
||||
banned_objects = typecacheof(/obj/structure/stone_tile)
|
||||
Reference in New Issue
Block a user