diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index 1e8f99814df..c1f14fc625d 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -49,8 +49,8 @@ /obj/screen/blob/Blobbernaut icon_state = "ui_blobbernaut" - name = "Produce Blobbernaut (20)" - desc = "Produces a strong, but dumb blobbernaut from a factory blob for 20 resources.
The factory blob will be destroyed in the process." + name = "Produce Blobbernaut (60)" + desc = "Produces a strong, intelligent blobbernaut from a factory blob for 60 resources.
The factory blob will be destroyed in the process." /obj/screen/blob/Blobbernaut/Click() if(isovermind(usr)) diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index bf2143b9784..f15f1dc742c 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -163,10 +163,10 @@ icon_state = "blobbernaut" icon_living = "blobbernaut" icon_dead = "blobbernaut_dead" - health = 240 - maxHealth = 240 - melee_damage_lower = 20 - melee_damage_upper = 20 + health = 200 + maxHealth = 200 + melee_damage_lower = 10 + melee_damage_upper = 15 obj_damage = 60 attacktext = "hits" attack_sound = 'sound/effects/blobattack.ogg' @@ -175,18 +175,48 @@ maxbodytemp = 360 force_threshold = 10 mob_size = MOB_SIZE_LARGE - environment_smash = ENVIRONMENT_SMASH_RWALLS + environment_smash = ENVIRONMENT_SMASH_STRUCTURES pressure_resistance = 100 //100 kPa difference required to push throw_pressure_limit = 120 //120 kPa difference required to throw see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE +/mob/living/simple_animal/hostile/blob/blobbernaut/Life(seconds, times_fired) + if(stat != DEAD && (getBruteLoss() || getFireLoss())) // Heal on blob structures + if(locate(/obj/structure/blob) in get_turf(src)) + adjustBruteLoss(-0.25) + adjustFireLoss(-0.25) + else + adjustBruteLoss(0.2) // If you are at full health, you won't lose health. You'll need it. However the moment anybody sneezes on you, the decaying will begin. + adjustFireLoss(0.2) + /mob/living/simple_animal/hostile/blob/blobbernaut/blob_act() return +/mob/living/simple_animal/hostile/blob/blobbernaut/New() + ..() + if(name == "blobbernaut") + name = text("blobbernaut ([rand(1, 1000)])") + /mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed) // Only execute the below if we successfully died . = ..() if(!.) return FALSE flick("blobbernaut_death", src) + +/mob/living/simple_animal/hostile/blob/blobbernaut/verb/communicate_overmind() + set category = "Blobbernaut" + set name = "Blob Telepathy" + set desc = "Send a message to the Overmind" + + if(stat != DEAD) + blob_talk() + +/mob/living/simple_animal/hostile/blob/blobbernaut/proc/blob_talk() + var/message = input(src, "Announce to the overmind", "Blob Telepathy") + var/rendered = "Blob Telepathy, [name]([overmind]) states, \"[message]\"" + if(message) + for(var/mob/M in GLOB.mob_list) + if(isovermind(M) || isobserver(M) || istype((M), /mob/living/simple_animal/hostile/blob/blobbernaut)) + M.show_message(rendered, 2) \ No newline at end of file diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 4489aaf707b..d4d9dc15c58 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -84,7 +84,7 @@ var/rendered = "Blob Telepathy, [name]([blob_reagent_datum.name]) [verb] \"[message]\"" for(var/mob/M in GLOB.mob_list) - if(isovermind(M) || isobserver(M)) + if(isovermind(M) || isobserver(M) || istype((M), /mob/living/simple_animal/hostile/blob/blobbernaut)) M.show_message(rendered, 2) /mob/camera/blob/emote(act, m_type = 1, message = null, force) diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index d6d4a91cf19..f90cfc94480 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -208,7 +208,7 @@ /mob/camera/blob/verb/create_blobbernaut() set category = "Blob" - set name = "Create Blobbernaut (20)" + set name = "Create Blobbernaut (60)" set desc = "Create a powerful blob-being, a Blobbernaut" var/turf/T = get_turf(src) @@ -225,7 +225,7 @@ to_chat(src, "Unable to use this blob, find a factory blob.") return - if(!can_buy(20)) + if(!can_buy(60)) return var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B)) @@ -234,6 +234,14 @@ blobber.color = blob_reagent_datum.complementary_color blobber.overmind = src blob_mobs.Add(blobber) + spawn() + var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 150) + if(candidates.len) + var/mob/C = pick(candidates) + if(C) + blobber.key = C.key + to_chat(blobber, "You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!") + to_chat(blobber, "You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.") return diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 09de3f917bd..b11c43299ad 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -76,14 +76,19 @@ var/bomb_set if(panel_open && (istype(O, /obj/item/multitool) || istype(O, /obj/item/wirecutters))) return attack_hand(user) - - if(extended) - if(istype(O, /obj/item/disk/nuclear)) - usr.drop_item() - O.loc = src + + if(istype(O, /obj/item/disk/nuclear)) + if(extended) + if(!user.drop_item()) + to_chat(user, "\The [O] is stuck to your hand!") + return + O.forceMove(src) auth = O add_fingerprint(user) return attack_hand(user) + else + to_chat(user, "You need to deploy \the [src] first. Right click on the sprite, select 'Make Deployable' then click on \the [src] with an empty hand.") + return if(anchored) switch(removal_stage) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b8c0f3d02f4..1284a9a485c 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -510,6 +510,7 @@ About the new airlock wires panel: else to_chat(user, "There's a [note.name] pinned to the front...") note.examine(user) + to_chat(user, "Use an empty hand on the airlock on grab mode to remove [note.name].") if(panel_open) switch(security_level) diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index fbdc403d758..45309b381c0 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -45,7 +45,7 @@ /obj/item/defibrillator/examine(mob/user) ..(user) - to_chat(user,"Ctrl-click to remove the paddles from the defibrillator.") + to_chat(user, "Ctrl-click to remove the paddles from the defibrillator.") /obj/item/defibrillator/proc/update_power() if(bcell) diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index c047fc82abd..72394db2733 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -163,6 +163,15 @@ to_chat(user, "The meter on [src] indicates you are almost out of air!") playsound(user, 'sound/effects/alert.ogg', 50, 1) +/obj/item/tank/jetpack/carbondioxide/mining + name = "mining jetpack" + icon_state = "jetpack-mining" + item_state = "jetpack-mining" + origin_tech = "materials=4;magnets=4;engineering=5" + desc = "A tank of compressed carbon dioxide for miners to use as propulsion in local space. The compact size allows for easy storage at the cost of capacity." + volume = 40 + throw_range = 7 + w_class = WEIGHT_CLASS_NORMAL //same as syndie harness /obj/item/tank/jetpack/rig name = "jetpack" diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index acedb317bb3..d22f0a59a61 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -6,203 +6,194 @@ icon_state = "fireaxe1000" icon_closed = "fireaxe1000" icon_opened = "fireaxe1100" - anchored = 1 - density = 0 + anchored = TRUE + density = FALSE armor = list(melee = 50, bullet = 50, laser = 50, energy = 100, bomb = 10, bio = 100, rad = 100) - var/localopened = 0 //Setting this to keep it from behaviouring like a normal closet and obstructing movement in the map. -Agouri - opened = 1 - var/hitstaken = 0 - locked = 1 - var/smashed = 0 + var/localopened = FALSE //Setting this to keep it from behaviouring like a normal closet and obstructing movement in the map. -Agouri + opened = TRUE + var/hitstaken = FALSE + locked = TRUE + var/smashed = FALSE - attackby(var/obj/item/O as obj, var/mob/living/user as mob) //Marker -Agouri - //..() //That's very useful, Erro +/obj/structure/closet/fireaxecabinet/examine(mob/user) + . = ..() + to_chat(user, "Use a multitool to lock/unlock it.") - var/hasaxe = 0 //gonna come in handy later~ - if(fireaxe) - hasaxe = 1 - - if(isrobot(user) || src.locked) - if(istype(O, /obj/item/multitool)) - to_chat(user, "Resetting circuitry...") - playsound(user, 'sound/machines/lockreset.ogg', 50, 1) - if(do_after(user, 20 * O.toolspeed, target = src)) - src.locked = 0 - to_chat(user, " You disable the locking modules.") - update_icon() - return - else if(istype(O, /obj/item)) - user.changeNext_move(CLICK_CD_MELEE) - var/obj/item/W = O - if(src.smashed || src.localopened) - if(localopened) - localopened = 0 - icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - return - else - user.do_attack_animation(src) - playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time - if(W.force < 15) - to_chat(user, "The cabinet's protective glass glances off the hit.") - else - src.hitstaken++ - if(src.hitstaken == 4) - playsound(user, 'sound/effects/glassbr3.ogg', 100, 1) //Break cabinet, receive goodies. Cabinet's fucked for life after that. - src.smashed = 1 - src.locked = 0 - src.localopened = 1 +/obj/structure/closet/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/living/user as mob) //Marker -Agouri + if(isrobot(user) || locked) + if(istype(O, /obj/item/multitool)) + to_chat(user, "Resetting circuitry...") + playsound(user, 'sound/machines/lockreset.ogg', 50, 1) + if(do_after(user, 20 * O.toolspeed, target = src)) + locked = FALSE + to_chat(user, " You disable the locking modules.") update_icon() return - if(istype(O, /obj/item/twohanded/fireaxe) && src.localopened) - if(!fireaxe) - if(O:wielded) - to_chat(user, "Unwield the axe first.") - return - fireaxe = O - user.drop_item(O) - src.contents += O - to_chat(user, "You place the fire axe back in the [src.name].") - update_icon() - else - if(src.smashed) - return - else - localopened = !localopened - if(localopened) - icon_state = text("fireaxe[][][][]opening",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - else - icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - else - if(src.smashed) - return - if(istype(O, /obj/item/multitool)) + else if(istype(O, /obj/item)) + user.changeNext_move(CLICK_CD_MELEE) + var/obj/item/W = O + if(smashed || localopened) if(localopened) - localopened = 0 - icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - return - else - to_chat(user, "Resetting circuitry...") - sleep(50) - src.locked = 1 - to_chat(user, "You re-enable the locking modules.") - playsound(user, 'sound/machines/lockenable.ogg', 50, 1) - if(do_after(user, 20 * O.toolspeed, target = src)) - src.locked = 1 - to_chat(user, " You re-enable the locking modules.") - return + localopened = FALSE + update_icon_closing() + return + else + user.do_attack_animation(src) + playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time + if(W.force < 15) + to_chat(user, "The cabinet's protective glass glances off the hit.") + else + hitstaken++ + if(hitstaken == 4) + playsound(user, 'sound/effects/glassbr3.ogg', 100, 1) //Break cabinet, receive goodies. Cabinet's fucked for life after that. + smashed = TRUE + locked = FALSE + localopened = TRUE + update_icon() + return + if(istype(O, /obj/item/twohanded/fireaxe) && localopened) + if(!fireaxe) + var/obj/item/twohanded/fireaxe/F = O + if(F.wielded) + to_chat(user, "Unwield \the [F] first.") + return + if(!user.unEquip(F, FALSE)) + to_chat(user, "\The [F] stays stuck to your hands!") + return + fireaxe = F + contents += F + to_chat(user, "You place \the [F] back in the [name].") + update_icon() + else + if(smashed) + return else localopened = !localopened if(localopened) - icon_state = text("fireaxe[][][][]opening",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() + update_icon_opening() else - icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - - - - - attack_hand(mob/user as mob) - - var/hasaxe = 0 - if(fireaxe) - hasaxe = 1 - - if(src.locked) - to_chat(user, "The cabinet won't budge!") + update_icon_closing() + else + if(smashed) return - if(localopened) - if(fireaxe) - user.put_in_hands(fireaxe) - fireaxe = null - to_chat(user, "You take the fire axe from the [name].") - src.add_fingerprint(user) - update_icon() - else - if(src.smashed) - return - else - localopened = !localopened - if(localopened) - src.icon_state = text("fireaxe[][][][]opening",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - else - src.icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - - else - localopened = !localopened //I'm pretty sure we don't need an if(src.smashed) in here. In case I'm wrong and it fucks up teh cabinet, **MARKER**. -Agouri + if(istype(O, /obj/item/multitool)) if(localopened) - src.icon_state = text("fireaxe[][][][]opening",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() + localopened = FALSE + update_icon_closing() + return else - src.icon_state = text("fireaxe[][][][]closing",hasaxe,src.localopened,src.hitstaken,src.smashed) - spawn(10) update_icon() - - attack_tk(mob/user as mob) - if(localopened && fireaxe) - fireaxe.forceMove(loc) - to_chat(user, "You telekinetically remove the fire axe.") - fireaxe = null - update_icon() - return - attack_hand(user) - - verb/toggle_openness() //nice name, huh? HUH?! -Erro //YEAH -Agouri - set name = "Open/Close" - set category = "Object" - - if(isrobot(usr) || src.locked || src.smashed) - if(src.locked) - to_chat(usr, "The cabinet won't budge!") - else if(src.smashed) - to_chat(usr, "The protective glass is broken!") - return - - localopened = !localopened - update_icon() - - verb/remove_fire_axe() - set name = "Remove Fire Axe" - set category = "Object" - - if(isrobot(usr)) - return - - if(localopened) - if(fireaxe) - usr.put_in_hands(fireaxe) - fireaxe = null - to_chat(usr, "You take the Fire axe from the [name].") - else - to_chat(usr, "The [src.name] is empty.") + to_chat(user, "Resetting circuitry...") + playsound(user, 'sound/machines/lockenable.ogg', 50, 1) + if(do_after(user, 20 * O.toolspeed, target = src)) + locked = TRUE + to_chat(user, " You re-enable the locking modules.") + return else - to_chat(usr, "The [src.name] is closed.") - update_icon() - - attack_ai(mob/user as mob) - if(src.smashed) - to_chat(user, "The security of the cabinet is compromised.") - return - else - locked = !locked - if(locked) - to_chat(user, "Cabinet locked.") + localopened = !localopened + if(localopened) + update_icon_opening() else - to_chat(user, "Cabinet unlocked.") + update_icon_closing() - update_icon() //Template: fireaxe[has fireaxe][is opened][hits taken][is smashed]. If you want the opening or closing animations, add "opening" or "closing" right after the numbers - var/hasaxe = 0 +/obj/structure/closet/fireaxecabinet/attack_hand(mob/user as mob) + if(locked) + to_chat(user, "The cabinet won't budge!") + return + if(localopened) if(fireaxe) - hasaxe = 1 - icon_state = text("fireaxe[][][][]",hasaxe,src.localopened,src.hitstaken,src.smashed) + user.put_in_hands(fireaxe) + to_chat(user, "You take \the [fireaxe] from the [src].") + fireaxe = null + + add_fingerprint(user) + update_icon() + else + if(smashed) + return + else + localopened = !localopened + if(localopened) + update_icon_opening() + else + update_icon_closing() - open() + else + localopened = !localopened //I'm pretty sure we don't need an if(smashed) in here. In case I'm wrong and it fucks up teh cabinet, **MARKER**. -Agouri + if(localopened) + update_icon_opening() + else + update_icon_closing() + +/obj/structure/closet/fireaxecabinet/attack_tk(mob/user as mob) + if(localopened && fireaxe) + fireaxe.forceMove(loc) + to_chat(user, "You telekinetically remove \the [fireaxe].") + fireaxe = null + update_icon() + return + attack_hand(user) + +/obj/structure/closet/fireaxecabinet/verb/toggle_openness() //nice name, huh? HUH?! -Erro //YEAH -Agouri + set name = "Open/Close" + set category = "Object" + + if(isrobot(usr) || locked || smashed) + if(locked) + to_chat(usr, "The cabinet won't budge!") + else if(smashed) + to_chat(usr, "The protective glass is broken!") return - close() - return \ No newline at end of file + localopened = !localopened + update_icon() + +/obj/structure/closet/fireaxecabinet/verb/remove_fire_axe() + set name = "Remove Fire Axe" + set category = "Object" + + if(isrobot(usr)) + return + + if(localopened) + if(fireaxe) + usr.put_in_hands(fireaxe) + to_chat(usr, "You take \the [fireaxe] from the [src].") + fireaxe = null + else + to_chat(usr, "The [src] is empty.") + else + to_chat(usr, "The [src] is closed.") + update_icon() + +/obj/structure/closet/fireaxecabinet/attack_ai(mob/user as mob) + if(smashed) + to_chat(user, "The security of the cabinet is compromised.") + return + else + locked = !locked + if(locked) + to_chat(user, "Cabinet locked.") + else + to_chat(user, "Cabinet unlocked.") + +/obj/structure/closet/fireaxecabinet/proc/update_icon_opening() + var/hasaxe = fireaxe != null + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" + spawn(10) + update_icon() + +/obj/structure/closet/fireaxecabinet/proc/update_icon_closing() + var/hasaxe = fireaxe != null + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" + spawn(10) + update_icon() + +/obj/structure/closet/fireaxecabinet/update_icon() //Template: fireaxe[has fireaxe][is opened][hits taken][is smashed]. If you want the opening or closing animations, add "opening" or "closing" right after the numbers + var/hasaxe = fireaxe != null + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]" + +/obj/structure/closet/fireaxecabinet/open() + return + +/obj/structure/closet/fireaxecabinet/close() + return \ No newline at end of file diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 345d35cb4aa..6d41209aa94 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -145,6 +145,12 @@ name = "\improper RADIOACTIVE AREA" desc = "A warning sign which reads 'RADIOACTIVE AREA'." +/obj/structure/sign/xeno_warning_mining + name = "DANGEROUS ALIEN LIFE" + desc = "A sign that warns would be travellers of hostile alien life in the vicinity." + icon = 'icons/obj/mining.dmi' + icon_state = "xeno_warning" + /obj/structure/sign/redcross name = "medbay" desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'" @@ -210,7 +216,7 @@ desc = "A glowing dragon invites you in." icon_state = "chinese" -/obj/structure/sign/science +/obj/structure/sign/science name = "\improper SCIENCE!" desc = "A warning sign which reads 'SCIENCE!'" icon_state = "science1" diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm index bfb326eae1d..e87e35a0dea 100644 --- a/code/modules/clothing/spacesuits/rig/modules/utility.dm +++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm @@ -56,7 +56,7 @@ interface_desc = "A diamond-tipped industrial drill." suit_overlay_active = "mounted-drill" suit_overlay_inactive = "mounted-drill" - device_type = /obj/item/pickaxe/diamonddrill + device_type = /obj/item/pickaxe/drill/diamonddrill /obj/item/rig_module/device/orescanner name = "ore scanner module" diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index e96fd0e867b..3e4d4d143ec 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -40,9 +40,11 @@ if(21 to 25) for(var/i in 1 to 5) new /obj/item/poster/random_contraband(src) - if(26 to 35) + 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) @@ -109,7 +111,7 @@ if(90) new /obj/item/organ/internal/heart(src) if(91) - new /obj/item/soulstone(src) + new /obj/item/soulstone/anybody(src) if(92) new /obj/item/katana(src) if(93) diff --git a/code/modules/mining/coins.dm b/code/modules/mining/coins.dm deleted file mode 100644 index 70d920cd38f..00000000000 --- a/code/modules/mining/coins.dm +++ /dev/null @@ -1,153 +0,0 @@ -/*****************************Coin********************************/ - -/obj/item/coin - icon = 'icons/obj/economy.dmi' - name = "coin" - icon_state = "coin__heads" - flags = CONDUCT - 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/credits = 10 - -/obj/item/coin/New() - pixel_x = rand(0,16)-8 - pixel_y = rand(0,8)-8 - - icon_state = "coin_[cmineral]_[sideslist[1]]" - if(cmineral) - name = "[cmineral] coin" - -/obj/item/coin/gold - cmineral = "gold" - icon_state = "coin_gold_heads" - materials = list(MAT_GOLD = 400) - credits = 160 - -/obj/item/coin/silver - cmineral = "silver" - icon_state = "coin_silver_heads" - materials = list(MAT_SILVER = 400) - credits = 40 - -/obj/item/coin/diamond - cmineral = "diamond" - icon_state = "coin_diamond_heads" - materials = list(MAT_DIAMOND = 400) - credits = 120 - -/obj/item/coin/iron - cmineral = "iron" - icon_state = "coin_iron_heads" - materials = list(MAT_METAL = 400) - credits = 20 - -/obj/item/coin/plasma - cmineral = "plasma" - icon_state = "coin_plasma_heads" - materials = list(MAT_PLASMA = 400) - credits = 80 - -/obj/item/coin/uranium - cmineral = "uranium" - icon_state = "coin_uranium_heads" - materials = list(MAT_URANIUM = 400) - credits = 160 - -/obj/item/coin/clown - cmineral = "bananium" - icon_state = "coin_bananium_heads" - materials = list(MAT_BANANIUM = 400) - credits = 600 //makes the clown cri - -/obj/item/coin/mime - cmineral = "tranquillite" - icon_state = "coin_tranquillite_heads" - materials = list(MAT_TRANQUILLITE = 400) - credits = 600 //makes the mime cri - -/obj/item/coin/adamantine - cmineral = "adamantine" - icon_state = "coin_adamantine_heads" - credits = 400 - -/obj/item/coin/mythril - cmineral = "mythril" - icon_state = "coin_mythril_heads" - credits = 400 - -/obj/item/coin/twoheaded - cmineral = "iron" - icon_state = "coin_iron_heads" - desc = "Hey, this coin's the same on both sides!" - sideslist = list("heads") - credits = 20 - -/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") - credits = 20 - -/obj/item/coin/antagtoken/syndicate - name = "syndicate coin" - credits = 160 - -/obj/item/coin/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CC = W - if(string_attached) - to_chat(user, "There already is a string attached to this coin.") - return - - if(CC.use(1)) - overlays += image('icons/obj/economy.dmi',"coin_string_overlay") - string_attached = 1 - to_chat(user, "You attach a string to the coin.") - else - to_chat(user, "You need one length of cable to attach a string to the coin.") - return - - else if(istype(W,/obj/item/wirecutters)) - if(!string_attached) - ..() - return - - var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) - CC.amount = 1 - CC.update_icon() - overlays = list() - string_attached = null - to_chat(user, "You detach the string from the coin.") - else if(istype(W,/obj/item/weldingtool)) - var/obj/item/weldingtool/WT = W - if(WT.welding && WT.remove_fuel(0, user)) - var/typelist = list("iron" = /obj/item/clothing/gloves/ring, - "silver" = /obj/item/clothing/gloves/ring/silver, - "gold" = /obj/item/clothing/gloves/ring/gold, - "plasma" = /obj/item/clothing/gloves/ring/plasma, - "uranium" = /obj/item/clothing/gloves/ring/uranium) - var/typekey = typelist[cmineral] - if(ispath(typekey)) - to_chat(user, "You make [src] into a ring.") - new typekey(get_turf(loc)) - qdel(src) - else ..() - -/obj/item/coin/attack_self(mob/user as mob) - if(cooldown < world.time - 15) - var/coinflip = pick(sideslist) - cooldown = world.time - flick("coin_[cmineral]_flip", src) - icon_state = "coin_[cmineral]_[coinflip]" - playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1) - if(do_after(user, 15, target = src)) - user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \ - "You flip [src]. It lands on [coinflip].", \ - "You hear the clattering of loose change.") diff --git a/code/modules/mining/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm similarity index 100% rename from code/modules/mining/explorer_gear.dm rename to code/modules/mining/equipment/explorer_gear.dm diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm new file mode 100644 index 00000000000..dcd0916d876 --- /dev/null +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -0,0 +1,122 @@ +/**********************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/hypo.dmi' + icon_state = "lazarus_hypo" + item_state = "hypo" + origin_tech = "biotech=4;magnets=6" + 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(istype(target, /mob/living) && proximity_flag) + if(istype(target, /mob/living/simple_animal)) + var/mob/living/simple_animal/M = target + if(M.sentience_type != revive_type) + to_chat(user, "[src] does not work on this sort of creature.") + return + if(M.stat == DEAD) + M.faction = list("neutral") + M.revive() + M.can_collar = 1 + if(istype(target, /mob/living/simple_animal/hostile)) + 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("[user] has revived hostile mob [target] with a malfunctioning lazarus injector") + else + H.attack_same = 0 + loaded = 0 + user.visible_message("[user] injects [M] with [src], reviving it.") + playsound(src,'sound/effects/refill.ogg',50,1) + icon_state = "lazarus_empty" + return + else + to_chat(user, "[src] is only effective on the dead.") + return + else + to_chat(user, "[src] is only effective on lesser beings.") + return + +/obj/item/lazarus_injector/emag_act(mob/user) + if(!malfunctioning) + malfunctioning = 1 + to_chat(user, "You override [src]'s safety protocols.") + +/obj/item/lazarus_injector/emp_act() + if(!malfunctioning) + malfunctioning = 1 + +/obj/item/lazarus_injector/examine(mob/user) + ..(user) + if(!loaded) + to_chat(user, "[src] is empty.") + if(malfunctioning) + to_chat(user, "The display on [src] seems to be flickering.") + +/*********************Mob Capsule*************************/ + +/obj/item/mobcapsule + name = "lazarus capsule" + desc = "It allows you to store and deploy lazarus-injected creatures easier." + icon = 'icons/obj/mobcap.dmi' + icon_state = "mobcap0" + w_class = WEIGHT_CLASS_TINY + throw_range = 20 + var/mob/living/simple_animal/captured = null + var/colorindex = 0 + +/obj/item/mobcapsule/Destroy() + if(captured) + captured.ghostize() + QDEL_NULL(captured) + return ..() + +/obj/item/mobcapsule/attack(var/atom/A, mob/user, prox_flag) + if(!istype(A, /mob/living/simple_animal) || isbot(A)) + return ..() + capture(A, user) + return 1 + +/obj/item/mobcapsule/proc/capture(var/mob/target, var/mob/U as mob) + var/mob/living/simple_animal/T = target + if(captured) + to_chat(U, "Capture failed!: The capsule already has a mob registered to it!") + else + if(istype(T) && "neutral" in T.faction) + T.forceMove(src) + T.name = "[U.name]'s [initial(T.name)]" + T.cancel_camera() + name = "Lazarus Capsule: [initial(T.name)]" + to_chat(U, "You placed a [T.name] inside the Lazarus Capsule!") + captured = T + else + to_chat(U, "You can't capture that mob!") + +/obj/item/mobcapsule/throw_impact(atom/A, mob/user) + ..() + if(captured) + dump_contents(user) + +/obj/item/mobcapsule/proc/dump_contents(mob/user) + if(captured) + captured.forceMove(get_turf(src)) + captured = null + +/obj/item/mobcapsule/attack_self(mob/user) + colorindex += 1 + if(colorindex >= 6) + colorindex = 0 + icon_state = "mobcap[colorindex]" + update_icon() \ No newline at end of file diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm new file mode 100644 index 00000000000..6a706ca523f --- /dev/null +++ b/code/modules/mining/equipment/mineral_scanner.dm @@ -0,0 +1,116 @@ +/**********************Mining Scanner**********************/ +/obj/item/mining_scanner + desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." + name = "manual mining scanner" + icon = 'icons/obj/device.dmi' + icon_state = "mining1" + item_state = "analyzer" + w_class = WEIGHT_CLASS_SMALL + flags = CONDUCT + slot_flags = SLOT_BELT + var/cooldown = 0 + origin_tech = "engineering=1;magnets=1" + +/obj/item/mining_scanner/attack_self(mob/user) + if(!user.client) + return + if(!cooldown) + cooldown = 1 + spawn(40) + cooldown = 0 + var/list/mobs = list() + mobs |= user + mineral_scan_pulse(mobs, 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/simulated/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. Wear meson scanners for optimal results. This one has an extended range." + name = "advanced automatic mining scanner" + icon_state = "mining0" + item_state = "analyzer" + w_class = WEIGHT_CLASS_SMALL + flags = CONDUCT + slot_flags = SLOT_BELT + var/cooldown = 35 + var/on_cooldown = 0 + var/range = 7 + var/meson = TRUE + origin_tech = "engineering=3;magnets=3" + +/obj/item/t_scanner/adv_mining_scanner/cyborg + flags = CONDUCT | NODROP + +/obj/item/t_scanner/adv_mining_scanner/material + meson = FALSE + desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results. This one has an extended range." + +/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. Wear meson scanners for optimal results." + range = 4 + cooldown = 50 + +/obj/item/t_scanner/adv_mining_scanner/lesser/material + desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." + meson = FALSE + +/obj/item/t_scanner/adv_mining_scanner/scan() + if(!on_cooldown) + on_cooldown = 1 + spawn(cooldown) + on_cooldown = 0 + var/turf/t = get_turf(src) + var/list/mobs = recursive_mob_check(t, client_check = 1, sight_check = 0, include_radio = 0) + if(!mobs.len) + return + if(meson) + mineral_scan_pulse(mobs, t, range) + else + mineral_scan_pulse_material(mobs, t, range) + +//For use with mesons +/proc/mineral_scan_pulse(list/mobs, turf/T, range = world.view) + var/list/minerals = list() + for(var/turf/simulated/mineral/M in range(range, T)) + if(M.scan_state) + minerals += M + if(minerals.len) + for(var/mob/user in mobs) + if(user.client) + var/client/C = user.client + for(var/turf/simulated/mineral/M in minerals) + var/turf/F = get_turf(M) + var/image/I = image('icons/turf/mining.dmi', loc = F, icon_state = M.scan_state, layer = 18) + C.images += I + spawn(30) + if(C) + C.images -= I + +//For use with material scanners +/proc/mineral_scan_pulse_material(list/mobs, turf/T, range = world.view) + var/list/minerals = list() + for(var/turf/simulated/mineral/M in range(range, T)) + if(M.scan_state) + minerals += M + if(minerals.len) + for(var/turf/simulated/mineral/M in minerals) + 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 + layer = 18 + icon = 'icons/turf/mining.dmi' + anchored = 1 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + duration = 30 + pixel_x = -4 + pixel_y = -4 \ No newline at end of file diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm new file mode 100644 index 00000000000..4d47f88e065 --- /dev/null +++ b/code/modules/mining/equipment/mining_tools.dm @@ -0,0 +1,142 @@ +/*****************Pickaxes & Drills & Shovels****************/ +/obj/item/pickaxe + name = "pickaxe" + icon = 'icons/obj/items.dmi' + icon_state = "pickaxe" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 15 + throwforce = 10 + item_state = "pickaxe" + w_class = WEIGHT_CLASS_BULKY + materials = list(MAT_METAL=2000) //one sheet, but where can you make them? + origin_tech = "materials=2;engineering=3" + attack_verb = list("hit", "pierced", "sliced", "attacked") + var/list/digsound = list('sound/effects/picaxe1.ogg','sound/effects/picaxe2.ogg','sound/effects/picaxe3.ogg') + var/drill_verb = "picking" + sharp = 1 + var/excavation_amount = 100 + usesound = 'sound/effects/picaxe1.ogg' + toolspeed = 1 + +/obj/item/pickaxe/proc/playDigSound() + playsound(src, pick(digsound),20,1) + +/obj/item/pickaxe/emergency + name = "emergency disembarkation tool" + desc = "For extracting yourself from rough landings." + +/obj/item/pickaxe/safety + name = "safety pickaxe" + desc = "A pickaxe designed to be only effective at digging rock and ore, very ineffective as a weapon." + force = 1 + throwforce = 1 + attack_verb = list("ineffectively hit") + +/obj/item/pickaxe/mini + name = "compact pickaxe" + desc = "A smaller, compact version of the standard pickaxe." + icon_state = "minipick" + force = 10 + throwforce = 7 + w_class = WEIGHT_CLASS_NORMAL + materials = list(MAT_METAL = 1000) + +/obj/item/pickaxe/silver + name = "silver-plated pickaxe" + icon_state = "spickaxe" + item_state = "spickaxe" + origin_tech = "materials=3;engineering=4" + 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 + +/obj/item/pickaxe/gold + name = "golden pickaxe" + icon_state = "gpickaxe" + item_state = "gpickaxe" + origin_tech = "materials=4;engineering=4" + toolspeed = 0.4 + desc = "A gold-plated pickaxe that mines faster than standard-issue." + force = 18 + +/obj/item/pickaxe/diamond + name = "diamond-tipped pickaxe" + icon_state = "dpickaxe" + item_state = "dpickaxe" + origin_tech = "materials=5;engineering=4" + toolspeed = 0.3 + desc = "A pickaxe with a diamond pick head. Extremely robust at cracking rock walls and digging up dirt." + force = 19 + +/obj/item/pickaxe/drill + name = "mining drill" + icon_state = "handdrill" + item_state = "jackhammer" + digsound = list('sound/weapons/drill.ogg') + toolspeed = 0.6 //available from roundstart, faster than a pickaxe. + hitsound = 'sound/weapons/drill.ogg' + usesound = 'sound/weapons/drill.ogg' + origin_tech = "materials=2;powerstorage=2;engineering=3" + 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 = NODROP + +/obj/item/pickaxe/drill/diamonddrill + name = "diamond-tipped mining drill" + icon_state = "diamonddrill" + origin_tech = "materials=6;powerstorage=4;engineering=4" + desc = "Yours is the drill that will pierce the heavens!" + toolspeed = 0.2 + +/obj/item/pickaxe/drill/cyborg/diamond //This is the BORG version! + name = "diamond-tipped cyborg mining drill" //To inherit the NODROP flag, and easier to change borg specific drill mechanics. + icon_state = "diamonddrill" + toolspeed = 0.2 + +/obj/item/pickaxe/drill/jackhammer + name = "sonic jackhammer" + icon_state = "jackhammer" + item_state = "jackhammer" + origin_tech = "materials=6;powerstorage=4;engineering=5;magnets=4" + digsound = list('sound/weapons/sonic_jackhammer.ogg') + hitsound = 'sound/weapons/sonic_jackhammer.ogg' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + desc = "Cracks rocks with sonic blasts, and doubles as a demolition power tool for smashing walls." + toolspeed = 0.1 //the epitome of powertools. extremely fast mining, laughs at puny walls + +/obj/item/shovel + name = "shovel" + desc = "A large tool for digging and moving dirt." + icon = 'icons/obj/items.dmi' + icon_state = "shovel" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 8 + throwforce = 4 + item_state = "shovel" + w_class = WEIGHT_CLASS_NORMAL + materials = list(MAT_METAL=50) + origin_tech = "materials=2;engineering=2" + attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked") + usesound = 'sound/effects/shovel_dig.ogg' + toolspeed = 1 + +/obj/item/shovel/spade + name = "spade" + desc = "A small tool for digging and moving dirt." + icon_state = "spade" + item_state = "spade" + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/shovel/safety + name = "safety shovel" + desc = "A large tool for digging and moving dirt. Was modified with extra safety, making it ineffective as a weapon." + force = 1 + throwforce = 1 + attack_verb = list("ineffectively hit") \ No newline at end of file diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm new file mode 100644 index 00000000000..2d96c46d161 --- /dev/null +++ b/code/modules/mining/equipment/regenerative_core.dm @@ -0,0 +1,139 @@ +/*********************Hivelord stabilizer****************/ +/obj/item/hivelordstabilizer + name = "hivelord stabilizer" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle19" + desc = "Inject a hivelord core with this stabilizer to preserve its healing powers indefinitely." + w_class = WEIGHT_CLASS_TINY + origin_tech = "biotech=3" + +/obj/item/hivelordstabilizer/afterattack(obj/item/organ/internal/M, mob/user) + . = ..() + var/obj/item/organ/internal/hivelord_core/C = M + if(!istype(C, /obj/item/organ/internal/hivelord_core)) + to_chat(user, "The stabilizer only works on certain types of monster organs, generally regenerative in nature.") + return ..() + + C.preserved() + to_chat(user, "You inject the [M] with the stabilizer. It will no longer go inert.") + qdel(src) + +/************************Hivelord core*******************/ +/obj/item/organ/internal/hivelord_core + name = "hivelord remains" + desc = "All that remains of a hivelord. It can be used to help keep your body going, but it will rapidly decay into uselessness." + icon_state = "roro core 2" + 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/internal/hivelord_core/New() + ..() + addtimer(CALLBACK(src, .proc/inert_check), 2400) + +/obj/item/organ/internal/hivelord_core/proc/inert_check() + if(!preserved) + go_inert() + +/obj/item/organ/internal/hivelord_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) + feedback_add_details("hivelord_core", "[type]|implanted") + else + feedback_add_details("hivelord_core", "[type]|stabilizer") + +/obj/item/organ/internal/hivelord_core/proc/go_inert() + inert = TRUE + name = "decayed regenerative core" + desc = "All that remains of a hivelord. It has decayed, and is completely useless." + feedback_add_details("hivelord_core", "[src.type]|inert") + update_icon() + +/obj/item/organ/internal/hivelord_core/ui_action_click() + if(inert) + to_chat(owner, "[src] breaks down as it tries to activate.") + else + owner.revive() + qdel(src) + +/obj/item/organ/internal/hivelord_core/on_life() + ..() + if(owner.health < HEALTH_THRESHOLD_CRIT) + ui_action_click() + +///Handles applying the core, logging and status/mood events. +/obj/item/organ/internal/hivelord_core/proc/applyto(atom/target, mob/user) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(inert) + to_chat(user, "[src] has decayed and can no longer be used to heal.") + return + else + if(H.stat == DEAD) + to_chat(user, "[src] is useless on the dead.") + return + if(H != user) + H.visible_message("[user] forces [H] to apply [src]... Black tendrils entangle and reinforce [H.p_them()]!") + feedback_add_details("hivelord_core","[src.type]|used|other") + else + to_chat(user, "You start to smear [src] on yourself. Disgusting tendrils hold you together and allow you to keep moving, but for how long?") + feedback_add_details("hivelord_core","[src.type]|used|self") + H.revive() + user.drop_item() + qdel(src) + +/obj/item/organ/internal/hivelord_core/afterattack(atom/target, mob/user, proximity_flag) + . = ..() + if(proximity_flag) + applyto(target, user) + +/obj/item/organ/internal/hivelord_core/attack_self(mob/user) + applyto(user, user) + +/obj/item/organ/internal/hivelord_core/insert(mob/living/carbon/M, special = 0) + ..() + if(!preserved && !inert) + preserved(TRUE) + owner.visible_message("[src] stabilizes as it's inserted.") + +/obj/item/organ/internal/hivelord_core/remove(mob/living/carbon/M, special = 0) + if(!inert && !special) + owner.visible_message("[src] rapidly decays as it's removed.") + go_inert() + return ..() + +/obj/item/organ/internal/hivelord_core/prepare_eat() + return null + +/*************************Legion core********************/ +/obj/item/organ/internal/hivelord_core/legion + name = "legion's soul" + 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/internal/hivelord_core/legion/New() + ..() + update_icon() + +/obj/item/organ/internal/hivelord_core/legion/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/internal/hivelord_core/legion/go_inert() + ..() + desc = "[src] has become inert. It has decayed, and is completely useless." + +/obj/item/organ/internal/hivelord_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." \ No newline at end of file diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm new file mode 100644 index 00000000000..4c7c4e599ef --- /dev/null +++ b/code/modules/mining/equipment/resonator.dm @@ -0,0 +1,116 @@ +/**********************Resonator**********************/ +/obj/item/resonator + name = "resonator" + icon = 'icons/obj/items.dmi' + icon_state = "resonator" + item_state = "resonator" + origin_tech = "magnets=3;engineering=3" + desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in a vaccuum." + w_class = WEIGHT_CLASS_NORMAL + force = 15 + throwforce = 10 + var/burst_time = 30 + var/fieldlimit = 4 + 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." + icon_state = "resonator_u" + origin_tech = "materials=4;powerstorage=3;engineering=3;magnets=3" + fieldlimit = 6 + quick_burst_mod = 1 + +/obj/item/resonator/attack_self(mob/user) + if(burst_time == 50) + burst_time = 30 + to_chat(user, "You set the resonator's fields to detonate after 3 seconds.") + else + burst_time = 50 + to_chat(user, "You set the resonator's fields to detonate after 5 seconds.") + +/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_attackby(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 = 'icons/effects/effects.dmi' + 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/New(loc, 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 + return ..() + +/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/simulated/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) + add_attack_logs(creator, L, "Resonance field'ed") + to_chat(L, "[src] ruptured with you in it!") + 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/New() + ..() + transform = matrix()*1.5 + animate(src, transform = matrix() * 0.1, alpha = 50, time = 4) \ No newline at end of file diff --git a/code/modules/mining/equipment/vendor_items.dm b/code/modules/mining/equipment/vendor_items.dm new file mode 100644 index 00000000000..8868d4655b5 --- /dev/null +++ b/code/modules/mining/equipment/vendor_items.dm @@ -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 diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm new file mode 100644 index 00000000000..7ab7276bb9e --- /dev/null +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -0,0 +1,77 @@ +/**********************Jaunter**********************/ +/obj/item/wormhole_jaunter + name = "wormhole jaunter" + desc = "A single use device harnessing outdated wormhole technology, Nanotrasen has since turned its eyes to bluespace 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/items.dmi' + icon_state = "Jaunter" + item_state = "electronic" + throwforce = 0 + w_class = WEIGHT_CLASS_SMALL + throw_speed = 3 + throw_range = 5 + origin_tech = "bluespace=2" + slot_flags = SLOT_BELT + +/obj/item/wormhole_jaunter/attack_self(mob/user) + user.visible_message("[user.name] activates the [name]!") + activate(user, TRUE) + +/obj/item/wormhole_jaunter/proc/turf_check(mob/user) + var/turf/device_turf = get_turf(user) + if(!device_turf || !is_teleport_allowed(device_turf.z)) + to_chat(user, "You're having difficulties getting the [name] to work.") + return FALSE + return TRUE + +/obj/item/wormhole_jaunter/proc/get_destinations(mob/user) + var/list/destinations = list() + + for(var/obj/item/radio/beacon/B in world) + 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, "The [name] found no beacons in the world to anchor a wormhole to.") + return + var/chosen_beacon = pick(L) + var/obj/effect/portal/jaunt_tunnel/J = new(get_turf(src), get_turf(chosen_beacon), src, 100) + if(adjacent) + try_move_adjacent(J) + else + J.teleport(user) + playsound(src,'sound/effects/sparks4.ogg',50,1) + qdel(src) + +/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!") + activate(user, FALSE) + else + to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.") + +/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." + failchance = 0 + +/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.Weaken(6) + if(ishuman(L)) + shake_camera(L, 20, 1) + addtimer(CALLBACK(L, /mob/living/carbon.proc/vomit), 20) \ No newline at end of file diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm deleted file mode 100644 index ef7a74f5d60..00000000000 --- a/code/modules/mining/equipment_locker.dm +++ /dev/null @@ -1,1151 +0,0 @@ -/**********************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 - anchored = TRUE - input_dir = NORTH - output_dir = SOUTH - req_access = list(access_mineral_storeroom) - speed_process = TRUE - layer = BELOW_OBJ_LAYER - var/req_access_reclaim = access_mining_station - 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("sand" = 1, "iron" = 1, "plasma" = 15, "silver" = 16, "gold" = 18, "titanium" = 30, "uranium" = 30, "diamond" = 50, "bluespace crystal" = 50, "bananium" = 60, "tranquillite" = 60) - var/message_sent = FALSE - var/list/ore_buffer = list() - var/datum/research/files - var/obj/item/disk/design_disk/inserted_disk - var/list/supply_consoles = list("Science", "Robotics", "Research Director's Desk", "Mechanic", "Engineering" = list("metal", "glass", "plasma"), "Chief Engineer's Desk" = list("metal", "glass", "plasma"), "Atmospherics" = list("metal", "glass", "plasma"), "Bar" = list("uranium", "plasma"), "Virology" = list("plasma", "uranium", "gold")) - -/obj/machinery/mineral/ore_redemption/New() - ..() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), INFINITY, FALSE, /obj/item/stack) - files = new /datum/research/smelter(src) - component_parts = list() - component_parts += new /obj/item/circuitboard/ore_redemption(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/manipulator(null) - component_parts += new /obj/item/stock_parts/micro_laser(null) - component_parts += new /obj/item/assembly/igniter(null) - component_parts += new /obj/item/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/mineral/ore_redemption/upgraded/New() - ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/ore_redemption(null) - component_parts += new /obj/item/stock_parts/matter_bin/super(null) - component_parts += new /obj/item/stock_parts/manipulator/pico(null) - component_parts += new /obj/item/stock_parts/micro_laser/ultra(null) - component_parts += new /obj/item/assembly/igniter(null) - component_parts += new /obj/item/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/mineral/ore_redemption/golem - req_access = list(access_free_golems) - req_access_reclaim = access_free_golems - -/obj/machinery/mineral/ore_redemption/golem/New() - ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/ore_redemption/golem(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/manipulator(null) - component_parts += new /obj/item/stock_parts/micro_laser(null) - component_parts += new /obj/item/assembly/igniter(null) - component_parts += new /obj/item/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/mineral/ore_redemption/Destroy() - QDEL_NULL(files) - GET_COMPONENT(materials, /datum/component/material_container) - materials.retrieve_all() - 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) - - ore_buffer -= O - - if(O && O.refined_type) - points += O.points * point_upgrade * O.amount - - GET_COMPONENT(materials, /datum/component/material_container) - var/material_amount = materials.get_item_material_amount(O) - - if(!material_amount) - qdel(O) //no materials, incinerate it - - else if(!materials.has_space(material_amount * sheet_per_ore * O.amount)) //if there is no space, eject it - unload_mineral(O) - - else - materials.insert_item(O, sheet_per_ore) //insert it - qdel(O) - -/obj/machinery/mineral/ore_redemption/proc/can_smelt_alloy(datum/design/D) - if(D.make_reagents.len) - return FALSE - - var/build_amount = 0 - - GET_COMPONENT(materials, /datum/component/material_container) - for(var/mat_id in D.materials) - var/M = D.materials[mat_id] - var/datum/material/redemption_mat = materials.materials[mat_id] - - if(!M || !redemption_mat) - return FALSE - - var/smeltable_sheets = round(redemption_mat.amount / M) - - 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() - if(!is_station_level(z)) - return - message_sent = TRUE - var/area/A = get_area(src) - var/msg = "Now available in [A]:
" - - var/has_minerals = FALSE - var/mineral_name = null - GET_COMPONENT(materials, /datum/component/material_container) - for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT - mineral_name = capitalize(M.name) - if(mineral_amount) - has_minerals = TRUE - msg += "[mineral_name]: [mineral_amount] sheets
" - - if(!has_minerals) - return - - for(var/obj/machinery/requests_console/D in allConsoles) - if(D.department in src.supply_consoles) - if(supply_consoles[D.department] == null || (mineral_name in supply_consoles[D.department])) - D.createMessage("Ore Redemption Machine", "New Minerals Available!", msg, 1) - -/obj/machinery/mineral/ore_redemption/process() - if(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(exchange_parts(user, W)) - return - 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_hand() - if(istype(I) && !istype(inserted_id)) - if(!user.drop_item()) - return - I.forceMove(src) - inserted_id = I - interact(user) - return - - if(ismultitool(W) && panel_open) - input_dir = turn(input_dir, -90) - output_dir = turn(output_dir, -90) - to_chat(user, "You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].") - return - - if(istype(W, /obj/item/disk/design_disk)) - if(user.drop_item()) - W.forceMove(src) - inserted_disk = W - interact(user) - return TRUE - - return ..() - -/obj/machinery/mineral/ore_redemption/attack_hand(mob/user) - if(..()) - return - interact(user) - -/obj/machinery/mineral/ore_redemption/interact(mob/user) - var/dat = "This machine only accepts ore. Gibtonite and Slag are not accepted.

" - dat += "Current unclaimed points: [points]
" - - if(inserted_id) - dat += "You have [inserted_id.mining_points] mining points collected. Eject ID.
" - dat += "Claim points.

" - else - dat += "No ID inserted. Insert ID.

" - - 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) - var/sheet_amount = M.amount / MINERAL_MATERIAL_AMOUNT - dat += "[capitalize(M.name)]: [sheet_amount] " - if(sheet_amount >= 1) - dat += "Release
" - else - dat += "Release
" - - dat += "
Alloys:
" - - for(var/v in files.known_designs) - var/datum/design/D = files.known_designs[v] - if(can_smelt_alloy(D)) - dat += "[D.name]: Smelt
" - else - dat += "[D.name]: Smelt
" - - dat += "
Mineral Value List:
[get_ore_values()]
" - - if(inserted_disk) - dat += "Eject disk
" - dat += "
Uploadable designs:
" - - if(inserted_disk.blueprint) - var/datum/design/D = inserted_disk.blueprint - if(D.build_type & SMELTER) - dat += "Name: [D.name] Upload to smelter" - - dat += "

" - else - dat += "Insert design disk

" - - var/datum/browser/popup = new(user, "ore_redemption_machine", "Ore Redemption Machine", 400, 500) - popup.set_content(dat) - popup.open() - return - -/obj/machinery/mineral/ore_redemption/proc/get_ore_values() - var/dat = "" - for(var/ore in ore_values) - var/value = ore_values[ore] - dat += "" - dat += "
[capitalize(ore)][value * point_upgrade]
" - return dat - -/obj/machinery/mineral/ore_redemption/Topic(href, href_list) - if(..()) - return - GET_COMPONENT(materials, /datum/component/material_container) - if(href_list["eject_id"]) - usr.put_in_hands(inserted_id) - inserted_id = null - if(href_list["claim"]) - if(inserted_id) - if(req_access_reclaim in inserted_id.access) - inserted_id.mining_points += points - points = 0 - else - to_chat(usr, "Required access not found.") - else if(href_list["insert_id"]) - var/obj/item/card/id/I = usr.get_active_hand() - if(istype(I)) - if(!usr.drop_item()) - return - I.forceMove(src) - inserted_id = I - else - to_chat(usr, "Not a valid ID!") - if(href_list["eject_disk"]) - if(inserted_disk) - inserted_disk.forceMove(loc) - inserted_disk = null - if(href_list["insert_disk"]) - var/obj/item/disk/design_disk/D = usr.get_active_hand() - if(istype(D)) - if(!usr.drop_item()) - return - D.forceMove(src) - inserted_disk = D - if(href_list["upload"]) - if(inserted_disk && inserted_disk.blueprint) - files.AddDesign2Known(inserted_disk.blueprint) - - if(href_list["release"]) - if(check_access(inserted_id) || allowed(usr)) //Check the ID inside, otherwise check the user - var/mat_id = href_list["release"] - if(!materials.materials[mat_id]) - return - - var/datum/material/mat = materials.materials[mat_id] - var/stored_amount = mat.amount / MINERAL_MATERIAL_AMOUNT - - if(!stored_amount) - return - - var/desired = input("How many sheets?", "How many sheets to eject?", 1) as null|num - var/sheets_to_remove = round(min(desired,50,stored_amount)) - - var/out = get_step(src, output_dir) - materials.retrieve_sheets(sheets_to_remove, mat_id, out) - - else - to_chat(usr, "Required access not found.") - - if(href_list["alloy"]) - var/alloy_id = href_list["alloy"] - var/datum/design/alloy = files.FindDesignByID(alloy_id) - if((check_access(inserted_id) || allowed(usr)) && alloy) - var/desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num - if(desired < 1) // Stops an exploit that lets you build negative alloys and get free materials - return - var/smelt_amount = can_smelt_alloy(alloy) - var/amount = round(min(desired,50,smelt_amount)) - materials.use_amount(alloy.materials, amount) - - var/output = new alloy.build_path(src) - if(istype(output, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/mineral/produced_alloy = output - produced_alloy.amount = amount - unload_mineral(produced_alloy) - else - unload_mineral(output) - - else - to_chat(usr, "Required access not found.") - updateUsrDialog() - -/obj/machinery/mineral/ore_redemption/ex_act(severity, target) - do_sparks(5, 1, src) - if(severity == 1) - if(prob(50)) - qdel(src) - else if(severity == 2) - if(prob(25)) - qdel(src) - -/obj/machinery/mineral/ore_redemption/power_change() - ..() - update_icon() - if(inserted_id && !powered()) - visible_message("The ID slot indicator light flickers on [src] as it spits out a card before powering down.") - inserted_id.forceMove(loc) - -/obj/machinery/mineral/ore_redemption/update_icon() - if(powered()) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]-off" - -/**********************Mining Equipment Locker**************************/ - -/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 = 1 - anchored = 1.0 - 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("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("Stabilizing Serum", /obj/item/hivelordstabilizer, 400), - new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000), - new /datum/data/mining_equipment("Point Transfer Card", /obj/item/card/mining_point_card, 500), - 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("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("Survival Medipen", /obj/item/reagent_containers/hypospray/autoinjector/survival, 500), - new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600), - new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600), - new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750), - new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750), - new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750), - 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("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/duffel/mining_conscript, 1500), - new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000), - new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/storage/box/mininghardsuit, 2000), - new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 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("Nanotrasen Minebot", /obj/item/mining_drone_cube, 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/sentience/mining, 1000), - new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100), - new /datum/data/mining_equipment("Lazarus Capsule", /obj/item/mobcapsule, 800), - new /datum/data/mining_equipment("Lazarus Capsule belt", /obj/item/storage/belt/lazarus, 200), - 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) - ) - -/obj/machinery/mineral/equipment_vendor/golem - name = "golem ship equipment vendor" - -/obj/machinery/mineral/equipment_vendor/golem/New() - ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/mining_equipment_vendor/golem(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/console_screen(null) - RefreshParts() - -/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/golem, 250), - new /datum/data/mining_equipment("Science Backpack", /obj/item/storage/backpack/science, 250), - new /datum/data/mining_equipment("Full Toolbelt", /obj/item/storage/belt/utility/full/multitool, 250), - new /datum/data/mining_equipment("Monkey Cube", /obj/item/reagent_containers/food/snacks/monkeycube, 250), - new /datum/data/mining_equipment("Royal Cape of the Liberator", /obj/item/bedsheet/rd/royal_cape, 500), - new /datum/data/mining_equipment("Grey Slime Extract", /obj/item/slime_extract/grey, 1000), - new /datum/data/mining_equipment("KA Trigger Modification Kit", /obj/item/borg/upgrade/modkit/trigger_guard, 1000), - new /datum/data/mining_equipment("Shuttle Console Board", /obj/item/circuitboard/shuttle/golem_ship, 2000), - new /datum/data/mining_equipment("The Liberator's Legacy", /obj/item/storage/box/rndboards, 2000) - - ) - -/datum/data/mining_equipment - var/equipment_name = "generic" - var/equipment_path = null - var/cost = 0 - -/datum/data/mining_equipment/New(name, path, equipment_cost) - equipment_name = name - equipment_path = path - cost = equipment_cost - -/obj/machinery/mineral/equipment_vendor/New() - ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/mining_equipment_vendor(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/matter_bin(null) - component_parts += new /obj/item/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/mineral/equipment_vendor/power_change() - ..() - update_icon() - if(inserted_id && !powered()) - visible_message("The ID slot indicator light flickers on \the [src] as it spits out a card before powering down.") - inserted_id.forceMove(loc) - -/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/attack_hand(mob/user) - if(..()) - return - interact(user) - -/obj/machinery/mineral/equipment_vendor/attack_ghost(mob/user) - interact(user) - -/obj/machinery/mineral/equipment_vendor/interact(mob/user) - user.set_machine(src) - - var/dat - dat +="
" - if(istype(inserted_id)) - dat += "You have [inserted_id.mining_points] mining points collected. Eject ID.
" - else - dat += "No ID inserted. Insert ID.
" - dat += "
" - dat += "
Equipment point cost list:
" - for(var/datum/data/mining_equipment/prize in prize_list) - dat += "" - dat += "
[prize.equipment_name][prize.cost]Purchase
" - var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 350) - popup.set_content(dat) - popup.open() - -/obj/machinery/mineral/equipment_vendor/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["choice"]) - if(istype(inserted_id)) - if(href_list["choice"] == "eject") - inserted_id.loc = loc - inserted_id.verb_pickup() - inserted_id = null - else if(href_list["choice"] == "insert") - var/obj/item/card/id/I = usr.get_active_hand() - if(istype(I)) - if(!usr.drop_item()) - return - I.loc = src - inserted_id = I - else - to_chat(usr, "No valid ID.") - - if(href_list["purchase"]) - if(istype(inserted_id)) - var/datum/data/mining_equipment/prize = locate(href_list["purchase"]) - if(!prize || !(prize in prize_list) || prize.cost > inserted_id.mining_points) - return - - inserted_id.mining_points -= prize.cost - new prize.equipment_path(src.loc) - updateUsrDialog() - -/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, "mining-open", "mining", I)) - updateUsrDialog() - return - if(panel_open) - if(istype(I, /obj/item/crowbar)) - if(inserted_id) - inserted_id.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it. - default_deconstruction_crowbar(I) - return 1 - if(istype(I, /obj/item/mining_voucher)) - if(!powered()) - return - else - RedeemVoucher(I, user) - return - if(istype(I,/obj/item/card/id)) - if(!powered()) - return - else - var/obj/item/card/id/C = usr.get_active_hand() - if(istype(C) && !istype(inserted_id)) - if(!usr.drop_item()) - return - C.forceMove(src) - inserted_id = C - interact(user) - 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(drop_location) - if("Resonator Kit") - new /obj/item/extinguisher/mini(drop_location) - new /obj/item/resonator(drop_location) - if("Minebot Kit") - new /obj/item/mining_drone_cube(drop_location) - new /obj/item/weldingtool/hugetank(drop_location) - new /obj/item/clothing/head/welding(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/kinetic_crusher(drop_location) - if("Mining Conscription Kit") - new /obj/item/storage/backpack/duffel/mining_conscript(drop_location) - - qdel(voucher) - -/obj/machinery/mineral/equipment_vendor/ex_act(severity, target) - do_sparks(5, 1, src) - if(prob(50 / severity) && severity < 3) - qdel(src) - -/**********************Mining Equipment Locker 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/items.dmi' - icon_state = "mining_voucher" - w_class = WEIGHT_CLASS_TINY - -/**********************Mining Point Card**********************/ - -/obj/item/card/mining_point_card - name = "mining point card" - desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard." - icon_state = "data" - var/points = 500 - -/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, "You transfer [points] points to [C].") - points = 0 - else - to_chat(user, "There's no points left on [src].") - ..() - -/obj/item/card/mining_point_card/examine(mob/user) - ..(user) - to_chat(user, "There's [points] points on the card.") - -/**********************Conscription Kit**********************/ - -/obj/item/card/id/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/id/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 |= list(access_mining, access_mining_station, access_mineral_storeroom, access_cargo) - to_chat(user, "You upgrade [I] with mining access.") - qdel(src) - -/obj/item/storage/backpack/duffel/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/duffel/mining_conscript/New() - ..() - 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(src) - new /obj/item/encryptionkey/headset_cargo(src) - new /obj/item/clothing/mask/gas/explorer(src) - new /obj/item/card/id/mining_access_card(src) - new /obj/item/gun/energy/kinetic_accelerator(src) - new /obj/item/kitchen/knife/combat/survival(src) - new /obj/item/flashlight/seclite(src) - -/**********************Jaunter**********************/ - -/obj/item/wormhole_jaunter - name = "wormhole jaunter" - desc = "A single use device harnessing outdated wormhole technology, Nanotrasen has since turned its eyes to bluespace 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/items.dmi' - icon_state = "Jaunter" - item_state = "electronic" - throwforce = 0 - w_class = WEIGHT_CLASS_SMALL - throw_speed = 3 - throw_range = 5 - origin_tech = "bluespace=2" - slot_flags = SLOT_BELT - -/obj/item/wormhole_jaunter/attack_self(mob/user) - user.visible_message("[user.name] activates the [name]!") - activate(user, TRUE) - -/obj/item/wormhole_jaunter/proc/turf_check(mob/user) - var/turf/device_turf = get_turf(user) - if(!device_turf || !is_teleport_allowed(device_turf.z)) - to_chat(user, "You're having difficulties getting the [name] to work.") - return FALSE - return TRUE - -/obj/item/wormhole_jaunter/proc/get_destinations(mob/user) - var/list/destinations = list() - - for(var/obj/item/radio/beacon/B in world) - 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, "The [name] found no beacons in the world to anchor a wormhole to.") - return - var/chosen_beacon = pick(L) - var/obj/effect/portal/jaunt_tunnel/J = new(get_turf(src), get_turf(chosen_beacon), src, 100) - if(adjacent) - try_move_adjacent(J) - else - J.teleport(user) - playsound(src,'sound/effects/sparks4.ogg',50,1) - qdel(src) - -/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!") - activate(user, FALSE) - else - to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.") - -/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." - failchance = 0 - -/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.Weaken(6) - if(ishuman(L)) - shake_camera(L, 20, 1) - addtimer(CALLBACK(L, /mob/living/carbon.proc/vomit), 20) - -/**********************Resonator**********************/ - -/obj/item/resonator - name = "resonator" - icon = 'icons/obj/items.dmi' - icon_state = "resonator" - item_state = "resonator" - origin_tech = "magnets=3;engineering=3" - desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in a vaccuum." - w_class = WEIGHT_CLASS_NORMAL - force = 15 - throwforce = 10 - var/burst_time = 30 - var/fieldlimit = 4 - 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." - icon_state = "resonator_u" - origin_tech = "materials=4;powerstorage=3;engineering=3;magnets=3" - fieldlimit = 6 - quick_burst_mod = 1 - -/obj/item/resonator/attack_self(mob/user) - if(burst_time == 50) - burst_time = 30 - to_chat(user, "You set the resonator's fields to detonate after 3 seconds.") - else - burst_time = 50 - to_chat(user, "You set the resonator's fields to detonate after 5 seconds.") - -/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_attackby(atom/target, mob/user, params) - if(check_allowed_items(target, 1)) - CreateResonance(target, user) - return TRUE - -/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 = 'icons/effects/effects.dmi' - icon_state = "shield1" - duration = 50 - var/resonance_damage = 20 - var/damage_multiplier = 1 - var/creator - var/obj/item/resonator/res - -/obj/effect/temp_visual/resonance/New(loc, 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 - return ..() - -/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/simulated/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) - add_attack_logs(creator, L, "Resonance field'ed") - to_chat(L, "[src] ruptured with you in it!") - 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/New() - ..() - transform = matrix()*1.5 - animate(src, transform = matrix() * 0.1, alpha = 50, time = 4) - -/**********************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 - - -/**********************Mining drone cube**********************/ - -/obj/item/mining_drone_cube - name = "mining drone cube" - desc = "Compressed mining drone, ready for deployment. Just press the button to activate!" - w_class = WEIGHT_CLASS_SMALL - icon = 'icons/obj/aibots.dmi' - icon_state = "minedronecube" - item_state = "electronic" - -/obj/item/mining_drone_cube/attack_self(mob/user) - user.visible_message("\The [src] suddenly expands into a fully functional mining drone!", \ - "You press center button on \the [src]. The device suddenly expands into a fully functional mining drone!") - new /mob/living/simple_animal/hostile/mining_drone(get_turf(src)) - qdel(src) - -/**********************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/hypo.dmi' - icon_state = "lazarus_hypo" - item_state = "hypo" - origin_tech = "biotech=4;magnets=6" - 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(istype(target, /mob/living) && proximity_flag) - if(istype(target, /mob/living/simple_animal)) - var/mob/living/simple_animal/M = target - if(M.sentience_type != revive_type) - to_chat(user, "[src] does not work on this sort of creature.") - return - if(M.stat == DEAD) - M.faction = list("neutral") - M.revive() - M.can_collar = 1 - if(istype(target, /mob/living/simple_animal/hostile)) - 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("[user] has revived hostile mob [target] with a malfunctioning lazarus injector") - else - H.attack_same = 0 - loaded = 0 - user.visible_message("[user] injects [M] with [src], reviving it.") - playsound(src,'sound/effects/refill.ogg',50,1) - icon_state = "lazarus_empty" - return - else - to_chat(user, "[src] is only effective on the dead.") - return - else - to_chat(user, "[src] is only effective on lesser beings.") - return - -/obj/item/lazarus_injector/emag_act(mob/user) - if(!malfunctioning) - malfunctioning = 1 - to_chat(user, "You override [src]'s safety protocols.") - -/obj/item/lazarus_injector/emp_act() - if(!malfunctioning) - malfunctioning = 1 - -/obj/item/lazarus_injector/examine(mob/user) - ..(user) - if(!loaded) - to_chat(user, "[src] is empty.") - if(malfunctioning) - to_chat(user, "The display on [src] seems to be flickering.") - -/**********************Mining Scanner**********************/ - -/obj/item/mining_scanner - desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." - name = "manual mining scanner" - icon = 'icons/obj/device.dmi' - icon_state = "mining1" - item_state = "analyzer" - w_class = WEIGHT_CLASS_SMALL - flags = CONDUCT - slot_flags = SLOT_BELT - var/cooldown = 0 - origin_tech = "engineering=1;magnets=1" - -/obj/item/mining_scanner/attack_self(mob/user) - if(!user.client) - return - if(!cooldown) - cooldown = 1 - spawn(40) - cooldown = 0 - var/list/mobs = list() - mobs |= user - mineral_scan_pulse(mobs, 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/simulated/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. Wear meson scanners for optimal results. This one has an extended range." - name = "advanced automatic mining scanner" - icon_state = "mining0" - item_state = "analyzer" - w_class = WEIGHT_CLASS_SMALL - flags = CONDUCT - slot_flags = SLOT_BELT - var/cooldown = 35 - var/on_cooldown = 0 - var/range = 7 - var/meson = TRUE - origin_tech = "engineering=3;magnets=3" - -/obj/item/t_scanner/adv_mining_scanner/cyborg - flags = CONDUCT | NODROP - -/obj/item/t_scanner/adv_mining_scanner/material - meson = FALSE - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results. This one has an extended range." - -/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. Wear meson scanners for optimal results." - range = 4 - cooldown = 50 - -/obj/item/t_scanner/adv_mining_scanner/lesser/material - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." - meson = FALSE - -/obj/item/t_scanner/adv_mining_scanner/scan() - if(!on_cooldown) - on_cooldown = 1 - spawn(cooldown) - on_cooldown = 0 - var/turf/t = get_turf(src) - var/list/mobs = recursive_mob_check(t, client_check = 1, sight_check = 0, include_radio = 0) - if(!mobs.len) - return - if(meson) - mineral_scan_pulse(mobs, t, range) - else - mineral_scan_pulse_material(mobs, t, range) - -//For use with mesons -/proc/mineral_scan_pulse(list/mobs, turf/T, range = world.view) - var/list/minerals = list() - for(var/turf/simulated/mineral/M in range(range, T)) - if(M.scan_state) - minerals += M - if(minerals.len) - for(var/mob/user in mobs) - if(user.client) - var/client/C = user.client - for(var/turf/simulated/mineral/M in minerals) - var/turf/F = get_turf(M) - var/image/I = image('icons/turf/mining.dmi', loc = F, icon_state = M.scan_state, layer = 18) - C.images += I - spawn(30) - if(C) - C.images -= I - -//For use with material scanners -/proc/mineral_scan_pulse_material(list/mobs, turf/T, range = world.view) - var/list/minerals = list() - for(var/turf/simulated/mineral/M in range(range, T)) - if(M.scan_state) - minerals += M - if(minerals.len) - for(var/turf/simulated/mineral/M in minerals) - 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 - layer = 18 - icon = 'icons/turf/mining.dmi' - anchored = 1 - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - duration = 30 - pixel_x = -4 - pixel_y = -4 - -/**********************Xeno Warning Sign**********************/ -/obj/structure/sign/xeno_warning_mining - name = "DANGEROUS ALIEN LIFE" - desc = "A sign that warns would be travellers of hostile alien life in the vicinity." - icon = 'icons/obj/mining.dmi' - icon_state = "xeno_warning" - -/**********************Mining Jetpack**********************/ -/obj/item/tank/jetpack/carbondioxide/mining - name = "mining jetpack" - icon_state = "jetpack-mining" - item_state = "jetpack-mining" - origin_tech = "materials=4;magnets=4;engineering=5" - desc = "A tank of compressed carbon dioxide for miners to use as propulsion in local space. The compact size allows for easy storage at the cost of capacity." - volume = 40 - throw_range = 7 - w_class = WEIGHT_CLASS_NORMAL //same as syndie harness - -/*********************Hivelord stabilizer****************/ - -/obj/item/hivelordstabilizer - name = "hivelord stabilizer" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle19" - desc = "Inject a hivelord core with this stabilizer to preserve its healing powers indefinitely." - w_class = WEIGHT_CLASS_TINY - origin_tech = "biotech=3" - -/obj/item/hivelordstabilizer/afterattack(obj/item/organ/internal/M, mob/user) - var/obj/item/organ/internal/hivelord_core/C = M - if(!istype(C, /obj/item/organ/internal/hivelord_core)) - to_chat(user, "The stabilizer only works on hivelord cores.") - return ..() - C.preserved = 1 - to_chat(user, "You inject the hivelord core with the stabilizer. It will no longer go inert.") - qdel(src) \ No newline at end of file diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 03b8404b1f0..46daf596f8c 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -7,7 +7,7 @@ var/output_dir = SOUTH /obj/machinery/mineral/proc/unload_mineral(atom/movable/S) - S.forceMove(loc) + S.forceMove(drop_location()) var/turf/T = get_step(src,output_dir) if(T) S.forceMove(T) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm new file mode 100644 index 00000000000..696be4c6bfb --- /dev/null +++ b/code/modules/mining/machine_redemption.dm @@ -0,0 +1,391 @@ +/**********************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 + anchored = TRUE + input_dir = NORTH + output_dir = SOUTH + req_access = list(access_mineral_storeroom) + speed_process = TRUE + layer = BELOW_OBJ_LAYER + var/req_access_reclaim = access_mining_station + 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("sand" = 1, "iron" = 1, "plasma" = 15, "silver" = 16, "gold" = 18, "titanium" = 30, "uranium" = 30, "diamond" = 50, "bluespace crystal" = 50, "bananium" = 60, "tranquillite" = 60) + var/message_sent = FALSE + var/list/ore_buffer = list() + var/datum/research/files + var/obj/item/disk/design_disk/inserted_disk + var/list/supply_consoles = list("Science", "Robotics", "Research Director's Desk", "Mechanic", "Engineering" = list("metal", "glass", "plasma"), "Chief Engineer's Desk" = list("metal", "glass", "plasma"), "Atmospherics" = list("metal", "glass", "plasma"), "Bar" = list("uranium", "plasma"), "Virology" = list("plasma", "uranium", "gold")) + +/obj/machinery/mineral/ore_redemption/New() + ..() + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), INFINITY, FALSE, /obj/item/stack) + files = new /datum/research/smelter(src) + component_parts = list() + component_parts += new /obj/item/circuitboard/ore_redemption(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/manipulator(null) + component_parts += new /obj/item/stock_parts/micro_laser(null) + component_parts += new /obj/item/assembly/igniter(null) + component_parts += new /obj/item/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/mineral/ore_redemption/upgraded/New() + ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/ore_redemption(null) + component_parts += new /obj/item/stock_parts/matter_bin/super(null) + component_parts += new /obj/item/stock_parts/manipulator/pico(null) + component_parts += new /obj/item/stock_parts/micro_laser/ultra(null) + component_parts += new /obj/item/assembly/igniter(null) + component_parts += new /obj/item/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/mineral/ore_redemption/golem + req_access = list(access_free_golems) + req_access_reclaim = access_free_golems + +/obj/machinery/mineral/ore_redemption/golem/New() + ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/ore_redemption/golem(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/manipulator(null) + component_parts += new /obj/item/stock_parts/micro_laser(null) + component_parts += new /obj/item/assembly/igniter(null) + component_parts += new /obj/item/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/mineral/ore_redemption/Destroy() + QDEL_NULL(files) + GET_COMPONENT(materials, /datum/component/material_container) + materials.retrieve_all() + 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) + + ore_buffer -= O + + if(O && O.refined_type) + points += O.points * point_upgrade * O.amount + + GET_COMPONENT(materials, /datum/component/material_container) + var/material_amount = materials.get_item_material_amount(O) + + if(!material_amount) + qdel(O) //no materials, incinerate it + + else if(!materials.has_space(material_amount * sheet_per_ore * O.amount)) //if there is no space, eject it + unload_mineral(O) + + else + materials.insert_item(O, sheet_per_ore) //insert it + qdel(O) + +/obj/machinery/mineral/ore_redemption/proc/can_smelt_alloy(datum/design/D) + if(D.make_reagents.len) + return FALSE + + var/build_amount = 0 + + GET_COMPONENT(materials, /datum/component/material_container) + for(var/mat_id in D.materials) + var/M = D.materials[mat_id] + var/datum/material/redemption_mat = materials.materials[mat_id] + + if(!M || !redemption_mat) + return FALSE + + var/smeltable_sheets = round(redemption_mat.amount / M) + + 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() + if(!is_station_level(z)) + return + message_sent = TRUE + var/area/A = get_area(src) + var/msg = "Now available in [A]:
" + + var/has_minerals = FALSE + var/mineral_name = null + GET_COMPONENT(materials, /datum/component/material_container) + for(var/mat_id in materials.materials) + var/datum/material/M = materials.materials[mat_id] + var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT + mineral_name = capitalize(M.name) + if(mineral_amount) + has_minerals = TRUE + msg += "[mineral_name]: [mineral_amount] sheets
" + + if(!has_minerals) + return + + for(var/obj/machinery/requests_console/D in allConsoles) + if(D.department in src.supply_consoles) + if(supply_consoles[D.department] == null || (mineral_name in supply_consoles[D.department])) + D.createMessage("Ore Redemption Machine", "New Minerals Available!", msg, 1) + +/obj/machinery/mineral/ore_redemption/process() + if(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(exchange_parts(user, W)) + return + 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_hand() + if(istype(I) && !istype(inserted_id)) + if(!user.drop_item()) + return + I.forceMove(src) + inserted_id = I + interact(user) + return + + if(ismultitool(W) && panel_open) + input_dir = turn(input_dir, -90) + output_dir = turn(output_dir, -90) + to_chat(user, "You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].") + return + + if(istype(W, /obj/item/disk/design_disk)) + if(user.drop_item()) + W.forceMove(src) + inserted_disk = W + interact(user) + return TRUE + + return ..() + +/obj/machinery/mineral/ore_redemption/attack_hand(mob/user) + if(..()) + return + interact(user) + +/obj/machinery/mineral/ore_redemption/interact(mob/user) + var/dat = "This machine only accepts ore. Gibtonite and Slag are not accepted.

" + dat += "Current unclaimed points: [points]
" + + if(inserted_id) + dat += "You have [inserted_id.mining_points] mining points collected. Eject ID.
" + dat += "Claim points.

" + else + dat += "No ID inserted. Insert ID.

" + + 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) + var/sheet_amount = M.amount / MINERAL_MATERIAL_AMOUNT + dat += "[capitalize(M.name)]: [sheet_amount] " + if(sheet_amount >= 1) + dat += "Release
" + else + dat += "Release
" + + dat += "
Alloys:
" + + for(var/v in files.known_designs) + var/datum/design/D = files.known_designs[v] + if(can_smelt_alloy(D)) + dat += "[D.name]: Smelt
" + else + dat += "[D.name]: Smelt
" + + dat += "
Mineral Value List:
[get_ore_values()]
" + + if(inserted_disk) + dat += "Eject disk
" + dat += "
Uploadable designs:
" + + if(inserted_disk.blueprint) + var/datum/design/D = inserted_disk.blueprint + if(D.build_type & SMELTER) + dat += "Name: [D.name] Upload to smelter" + + dat += "

" + else + dat += "Insert design disk

" + + var/datum/browser/popup = new(user, "ore_redemption_machine", "Ore Redemption Machine", 400, 500) + popup.set_content(dat) + popup.open() + return + +/obj/machinery/mineral/ore_redemption/proc/get_ore_values() + var/dat = "" + for(var/ore in ore_values) + var/value = ore_values[ore] + dat += "" + dat += "
[capitalize(ore)][value * point_upgrade]
" + return dat + +/obj/machinery/mineral/ore_redemption/Topic(href, href_list) + if(..()) + return + GET_COMPONENT(materials, /datum/component/material_container) + if(href_list["eject_id"]) + usr.put_in_hands(inserted_id) + inserted_id = null + if(href_list["claim"]) + if(inserted_id) + if(req_access_reclaim in inserted_id.access) + inserted_id.mining_points += points + points = 0 + else + to_chat(usr, "Required access not found.") + else if(href_list["insert_id"]) + var/obj/item/card/id/I = usr.get_active_hand() + if(istype(I)) + if(!usr.drop_item()) + return + I.forceMove(src) + inserted_id = I + else + to_chat(usr, "Not a valid ID!") + if(href_list["eject_disk"]) + if(inserted_disk) + inserted_disk.forceMove(loc) + inserted_disk = null + if(href_list["insert_disk"]) + var/obj/item/disk/design_disk/D = usr.get_active_hand() + if(istype(D)) + if(!usr.drop_item()) + return + D.forceMove(src) + inserted_disk = D + if(href_list["upload"]) + if(inserted_disk && inserted_disk.blueprint) + files.AddDesign2Known(inserted_disk.blueprint) + + if(href_list["release"]) + if(check_access(inserted_id) || allowed(usr)) //Check the ID inside, otherwise check the user + var/mat_id = href_list["release"] + if(!materials.materials[mat_id]) + return + + var/datum/material/mat = materials.materials[mat_id] + var/stored_amount = mat.amount / MINERAL_MATERIAL_AMOUNT + + if(!stored_amount) + return + + var/desired = input("How many sheets?", "How many sheets to eject?", 1) as null|num + var/sheets_to_remove = round(min(desired,50,stored_amount)) + + var/out = get_step(src, output_dir) + materials.retrieve_sheets(sheets_to_remove, mat_id, out) + + else + to_chat(usr, "Required access not found.") + + if(href_list["alloy"]) + var/alloy_id = href_list["alloy"] + var/datum/design/alloy = files.FindDesignByID(alloy_id) + if((check_access(inserted_id) || allowed(usr)) && alloy) + var/desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num + if(desired < 1) // Stops an exploit that lets you build negative alloys and get free materials + return + var/smelt_amount = can_smelt_alloy(alloy) + var/amount = round(min(desired,50,smelt_amount)) + materials.use_amount(alloy.materials, amount) + + var/output = new alloy.build_path(src) + if(istype(output, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/mineral/produced_alloy = output + produced_alloy.amount = amount + unload_mineral(produced_alloy) + else + unload_mineral(output) + + else + to_chat(usr, "Required access not found.") + updateUsrDialog() + +/obj/machinery/mineral/ore_redemption/ex_act(severity, target) + do_sparks(5, 1, src) + if(severity == 1) + if(prob(50)) + qdel(src) + else if(severity == 2) + if(prob(25)) + qdel(src) + +/obj/machinery/mineral/ore_redemption/power_change() + ..() + update_icon() + if(inserted_id && !powered()) + visible_message("The ID slot indicator light flickers on [src] as it spits out a card before powering down.") + inserted_id.forceMove(loc) + +/obj/machinery/mineral/ore_redemption/update_icon() + if(powered()) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]-off" \ No newline at end of file diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm new file mode 100644 index 00000000000..4851ac5b7c3 --- /dev/null +++ b/code/modules/mining/machine_vending.dm @@ -0,0 +1,311 @@ +/**********************Mining Equipment Locker**************************/ + +/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 = 1 + anchored = 1.0 + 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("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("Stabilizing Serum", /obj/item/hivelordstabilizer, 400), + new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000), + new /datum/data/mining_equipment("Point Transfer Card", /obj/item/card/mining_point_card, 500), + 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("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("Survival Medipen", /obj/item/reagent_containers/hypospray/autoinjector/survival, 500), + new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600), + new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600), + new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750), + new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750), + new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750), + 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("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/duffel/mining_conscript, 1500), + new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000), + new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/storage/box/mininghardsuit, 2000), + new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 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("Nanotrasen Minebot", /obj/item/mining_drone_cube, 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/sentience/mining, 1000), + new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100), + new /datum/data/mining_equipment("Lazarus Capsule", /obj/item/mobcapsule, 800), + new /datum/data/mining_equipment("Lazarus Capsule belt", /obj/item/storage/belt/lazarus, 200), + 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) + ) + +/obj/machinery/mineral/equipment_vendor/golem + name = "golem ship equipment vendor" + +/obj/machinery/mineral/equipment_vendor/golem/New() + ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/mining_equipment_vendor/golem(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/console_screen(null) + RefreshParts() + +/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/golem, 250), + new /datum/data/mining_equipment("Science Backpack", /obj/item/storage/backpack/science, 250), + new /datum/data/mining_equipment("Full Toolbelt", /obj/item/storage/belt/utility/full/multitool, 250), + new /datum/data/mining_equipment("Monkey Cube", /obj/item/reagent_containers/food/snacks/monkeycube, 250), + new /datum/data/mining_equipment("Royal Cape of the Liberator", /obj/item/bedsheet/rd/royal_cape, 500), + new /datum/data/mining_equipment("Grey Slime Extract", /obj/item/slime_extract/grey, 1000), + new /datum/data/mining_equipment("KA Trigger Modification Kit", /obj/item/borg/upgrade/modkit/trigger_guard, 1000), + new /datum/data/mining_equipment("Shuttle Console Board", /obj/item/circuitboard/shuttle/golem_ship, 2000), + new /datum/data/mining_equipment("The Liberator's Legacy", /obj/item/storage/box/rndboards, 2000) + + ) + +/datum/data/mining_equipment + var/equipment_name = "generic" + var/equipment_path = null + var/cost = 0 + +/datum/data/mining_equipment/New(name, path, equipment_cost) + equipment_name = name + equipment_path = path + cost = equipment_cost + +/obj/machinery/mineral/equipment_vendor/New() + ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/mining_equipment_vendor(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/matter_bin(null) + component_parts += new /obj/item/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/mineral/equipment_vendor/power_change() + ..() + update_icon() + if(inserted_id && !powered()) + visible_message("The ID slot indicator light flickers on \the [src] as it spits out a card before powering down.") + inserted_id.forceMove(loc) + +/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/attack_hand(mob/user) + if(..()) + return + interact(user) + +/obj/machinery/mineral/equipment_vendor/attack_ghost(mob/user) + interact(user) + +/obj/machinery/mineral/equipment_vendor/interact(mob/user) + user.set_machine(src) + + var/dat + dat +="
" + if(istype(inserted_id)) + dat += "You have [inserted_id.mining_points] mining points collected. Eject ID.
" + else + dat += "No ID inserted. Insert ID.
" + dat += "
" + dat += "
Equipment point cost list:
" + for(var/datum/data/mining_equipment/prize in prize_list) + dat += "" + dat += "
[prize.equipment_name][prize.cost]Purchase
" + var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 350) + popup.set_content(dat) + popup.open() + +/obj/machinery/mineral/equipment_vendor/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["choice"]) + if(istype(inserted_id)) + if(href_list["choice"] == "eject") + inserted_id.loc = loc + inserted_id.verb_pickup() + inserted_id = null + else if(href_list["choice"] == "insert") + var/obj/item/card/id/I = usr.get_active_hand() + if(istype(I)) + if(!usr.drop_item()) + return + I.loc = src + inserted_id = I + else + to_chat(usr, "No valid ID.") + + if(href_list["purchase"]) + if(istype(inserted_id)) + var/datum/data/mining_equipment/prize = locate(href_list["purchase"]) + if(!prize || !(prize in prize_list) || prize.cost > inserted_id.mining_points) + return + + inserted_id.mining_points -= prize.cost + new prize.equipment_path(src.loc) + updateUsrDialog() + +/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params) + if(default_deconstruction_screwdriver(user, "mining-open", "mining", I)) + updateUsrDialog() + return + if(panel_open) + if(istype(I, /obj/item/crowbar)) + if(inserted_id) + inserted_id.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it. + default_deconstruction_crowbar(I) + return 1 + if(istype(I, /obj/item/mining_voucher)) + if(!powered()) + return + else + RedeemVoucher(I, user) + return + if(istype(I,/obj/item/card/id)) + if(!powered()) + return + else + var/obj/item/card/id/C = usr.get_active_hand() + if(istype(C) && !istype(inserted_id)) + if(!usr.drop_item()) + return + C.forceMove(src) + inserted_id = C + interact(user) + 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(drop_location) + if("Resonator Kit") + new /obj/item/extinguisher/mini(drop_location) + new /obj/item/resonator(drop_location) + if("Minebot Kit") + new /obj/item/mining_drone_cube(drop_location) + new /obj/item/weldingtool/hugetank(drop_location) + new /obj/item/clothing/head/welding(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/kinetic_crusher(drop_location) + if("Mining Conscription Kit") + new /obj/item/storage/backpack/duffel/mining_conscript(drop_location) + + qdel(voucher) + +/obj/machinery/mineral/equipment_vendor/ex_act(severity, target) + do_sparks(5, 1, src) + if(prob(50 / severity) && severity < 3) + qdel(src) + +/**********************Mining Equipment Locker 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/items.dmi' + icon_state = "mining_voucher" + w_class = WEIGHT_CLASS_TINY + +/**********************Mining Point Card**********************/ + +/obj/item/card/mining_point_card + name = "mining point card" + desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard." + icon_state = "data" + var/points = 500 + +/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, "You transfer [points] points to [C].") + points = 0 + else + to_chat(user, "There's no points left on [src].") + ..() + +/obj/item/card/mining_point_card/examine(mob/user) + ..(user) + to_chat(user, "There's [points] points on the card.") + +/**********************Conscription Kit**********************/ + +/obj/item/card/id/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/id/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 |= list(access_mining, access_mining_station, access_mineral_storeroom, access_cargo) + to_chat(user, "You upgrade [I] with mining access.") + qdel(src) + +/obj/item/storage/backpack/duffel/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/duffel/mining_conscript/New() + ..() + 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(src) + new /obj/item/encryptionkey/headset_cargo(src) + new /obj/item/clothing/mask/gas/explorer(src) + new /obj/item/card/id/mining_access_card(src) + new /obj/item/gun/energy/kinetic_accelerator(src) + new /obj/item/kitchen/knife/combat/survival(src) + new /obj/item/flashlight/seclite(src) \ No newline at end of file diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 87b919ea238..f350633a4c2 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -75,157 +75,6 @@ desc = "A mining lantern." brightness_on = 6 // luminosity when on -/*****************************Pickaxe********************************/ - -/obj/item/pickaxe - name = "pickaxe" - icon = 'icons/obj/items.dmi' - icon_state = "pickaxe" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 15 - throwforce = 10 - item_state = "pickaxe" - w_class = WEIGHT_CLASS_BULKY - materials = list(MAT_METAL=2000) //one sheet, but where can you make them? - origin_tech = "materials=2;engineering=3" - attack_verb = list("hit", "pierced", "sliced", "attacked") - var/list/digsound = list('sound/effects/picaxe1.ogg','sound/effects/picaxe2.ogg','sound/effects/picaxe3.ogg') - var/drill_verb = "picking" - sharp = 1 - var/excavation_amount = 100 - usesound = 'sound/effects/picaxe1.ogg' - toolspeed = 1 - -/obj/item/pickaxe/proc/playDigSound() - playsound(src, pick(digsound),20,1) - -/obj/item/pickaxe/emergency - name = "emergency disembarkation tool" - desc = "For extracting yourself from rough landings." - -/obj/item/pickaxe/safety - name = "safety pickaxe" - desc = "A pickaxe designed to be only effective at digging rock and ore, very ineffective as a weapon." - force = 1 - throwforce = 1 - attack_verb = list("ineffectively hit") - -/obj/item/pickaxe/mini - name = "compact pickaxe" - desc = "A smaller, compact version of the standard pickaxe." - icon_state = "minipick" - force = 10 - throwforce = 7 - w_class = WEIGHT_CLASS_NORMAL - materials = list(MAT_METAL = 1000) - -/obj/item/pickaxe/silver - name = "silver-plated pickaxe" - icon_state = "spickaxe" - item_state = "spickaxe" - origin_tech = "materials=3;engineering=4" - desc = "A silver-plated pickaxe that mines slightly faster than standard-issue." - toolspeed = 0.75 - -/obj/item/pickaxe/gold - name = "golden pickaxe" - icon_state = "gpickaxe" - item_state = "gpickaxe" - origin_tech = "materials=4;engineering=4" - desc = "A gold-plated pickaxe that mines faster than standard-issue." - toolspeed = 0.6 - -/obj/item/pickaxe/diamond - name = "diamond-tipped pickaxe" - icon_state = "dpickaxe" - item_state = "dpickaxe" - origin_tech = "materials=5;engineering=4" - desc = "A pickaxe with a diamond pick head. Extremely robust at cracking rock walls and digging up dirt." - toolspeed = 0.5 - -/obj/item/pickaxe/drill - name = "mining drill" - icon_state = "handdrill" - item_state = "jackhammer" - digsound = list('sound/weapons/drill.ogg') - hitsound = 'sound/weapons/drill.ogg' - usesound = 'sound/weapons/drill.ogg' - origin_tech = "materials=2;powerstorage=2;engineering=3" - desc = "An electric mining drill for the especially scrawny." - toolspeed = 0.5 - -/obj/item/pickaxe/drill/cyborg - name = "cyborg mining drill" - desc = "An integrated electric mining drill." - flags = NODROP - -/obj/item/pickaxe/drill/diamonddrill - name = "diamond-tipped mining drill" - icon_state = "diamonddrill" - origin_tech = "materials=6;powerstorage=4;engineering=4" - desc = "Yours is the drill that will pierce the heavens!" - toolspeed = 0.25 - -/obj/item/pickaxe/diamonddrill/traitor //Pocket-sized traitor diamond drill. - name = "supermatter drill" - icon_state = "smdrill" - origin_tech = "materials=6;powerstorage=4;engineering=4;syndicate=3" - desc = "Microscopic supermatter crystals cover the head of this tiny drill." - w_class = WEIGHT_CLASS_SMALL - -/obj/item/pickaxe/drill/cyborg/diamond //This is the BORG version! - name = "diamond-tipped cyborg mining drill" //To inherit the NODROP flag, and easier to change borg specific drill mechanics. - icon_state = "diamonddrill" - toolspeed = 0.25 - -/obj/item/pickaxe/drill/jackhammer - name = "sonic jackhammer" - icon_state = "jackhammer" - item_state = "jackhammer" - origin_tech = "materials=6;powerstorage=4;engineering=5;magnets=4" - digsound = list('sound/weapons/sonic_jackhammer.ogg') - hitsound = 'sound/weapons/sonic_jackhammer.ogg' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - desc = "Cracks rocks with sonic blasts, and doubles as a demolition power tool for smashing walls." - toolspeed = 0.1 - -/*****************************Shovel********************************/ - -/obj/item/shovel - name = "shovel" - desc = "A large tool for digging and moving dirt." - icon = 'icons/obj/items.dmi' - icon_state = "shovel" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 8 - throwforce = 4 - item_state = "shovel" - w_class = WEIGHT_CLASS_NORMAL - materials = list(MAT_METAL=50) - origin_tech = "materials=2;engineering=2" - attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked") - usesound = 'sound/effects/shovel_dig.ogg' - toolspeed = 1 - -/obj/item/shovel/spade - name = "spade" - desc = "A small tool for digging and moving dirt." - icon_state = "spade" - item_state = "spade" - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - toolspeed = 2 - -/obj/item/shovel/safety - name = "safety shovel" - desc = "A large tool for digging and moving dirt. Was modified with extra safety, making it ineffective as a weapon." - force = 1 - throwforce = 1 - attack_verb = list("ineffectively hit") - /**********************Mining car (Crate like thing, not the rail car)**************************/ /obj/structure/closet/crate/miningcar @@ -234,60 +83,4 @@ icon_state = "miningcar" density = 1 icon_opened = "miningcaropen" - icon_closed = "miningcar" - -/*********************Mob Capsule*************************/ - -/obj/item/mobcapsule - name = "lazarus capsule" - desc = "It allows you to store and deploy lazarus-injected creatures easier." - icon = 'icons/obj/mobcap.dmi' - icon_state = "mobcap0" - w_class = WEIGHT_CLASS_TINY - throw_range = 20 - var/mob/living/simple_animal/captured = null - var/colorindex = 0 - -/obj/item/mobcapsule/Destroy() - if(captured) - captured.ghostize() - QDEL_NULL(captured) - return ..() - -/obj/item/mobcapsule/attack(var/atom/A, mob/user, prox_flag) - if(!istype(A, /mob/living/simple_animal) || isbot(A)) - return ..() - capture(A, user) - return 1 - -/obj/item/mobcapsule/proc/capture(var/mob/target, var/mob/U as mob) - var/mob/living/simple_animal/T = target - if(captured) - to_chat(U, "Capture failed!: The capsule already has a mob registered to it!") - else - if(istype(T) && "neutral" in T.faction) - T.forceMove(src) - T.name = "[U.name]'s [initial(T.name)]" - T.cancel_camera() - name = "Lazarus Capsule: [initial(T.name)]" - to_chat(U, "You placed a [T.name] inside the Lazarus Capsule!") - captured = T - else - to_chat(U, "You can't capture that mob!") - -/obj/item/mobcapsule/throw_impact(atom/A, mob/user) - ..() - if(captured) - dump_contents(user) - -/obj/item/mobcapsule/proc/dump_contents(mob/user) - if(captured) - captured.forceMove(get_turf(src)) - captured = null - -/obj/item/mobcapsule/attack_self(mob/user) - colorindex += 1 - if(colorindex >= 6) - colorindex = 0 - icon_state = "mobcap[colorindex]" - update_icon() + icon_closed = "miningcar" \ No newline at end of file diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 2ff2a686439..e7036ad4f2f 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -303,6 +303,7 @@ qdel(src) //AI + /obj/item/slimepotion/sentience/mining name = "minebot AI upgrade" desc = "Can be used to grant sentience to minebots." @@ -325,5 +326,21 @@ if(M.stored_gun) M.stored_gun.overheat_time += base_cooldown_add +/**********************Mining drone cube**********************/ + +/obj/item/mining_drone_cube + name = "mining drone cube" + desc = "Compressed mining drone, ready for deployment. Just press the button to activate!" + w_class = WEIGHT_CLASS_SMALL + icon = 'icons/obj/aibots.dmi' + icon_state = "minedronecube" + item_state = "electronic" + +/obj/item/mining_drone_cube/attack_self(mob/user) + user.visible_message("\The [src] suddenly expands into a fully functional mining drone!", \ + "You press center button on \the [src]. The device suddenly expands into a fully functional mining drone!") + new /mob/living/simple_animal/hostile/mining_drone(get_turf(src)) + qdel(src) + #undef MINEDRONE_COLLECT -#undef MINEDRONE_ATTACK +#undef MINEDRONE_ATTACK \ No newline at end of file diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ores_coins.dm similarity index 70% rename from code/modules/mining/ore.dm rename to code/modules/mining/ores_coins.dm index 236bcec1231..120dacad800 100644 --- a/code/modules/mining/ore.dm +++ b/code/modules/mining/ores_coins.dm @@ -303,8 +303,165 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ qdel(src) -/obj/item/stack/ore/ex_act() - return +/obj/item/stack/ore/ex_act(severity) + if(!severity || severity >= 2) + return + qdel(src) + + +/*****************************Coin********************************/ + +/obj/item/coin + icon = 'icons/obj/economy.dmi' + name = "coin" + icon_state = "coin__heads" + flags = CONDUCT + 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/credits = 10 + +/obj/item/coin/New() + pixel_x = rand(0,16)-8 + pixel_y = rand(0,8)-8 + + icon_state = "coin_[cmineral]_[sideslist[1]]" + if(cmineral) + name = "[cmineral] coin" + +/obj/item/coin/gold + cmineral = "gold" + icon_state = "coin_gold_heads" + materials = list(MAT_GOLD = 400) + credits = 160 + +/obj/item/coin/silver + cmineral = "silver" + icon_state = "coin_silver_heads" + materials = list(MAT_SILVER = 400) + credits = 40 + +/obj/item/coin/diamond + cmineral = "diamond" + icon_state = "coin_diamond_heads" + materials = list(MAT_DIAMOND = 400) + credits = 120 + +/obj/item/coin/iron + cmineral = "iron" + icon_state = "coin_iron_heads" + materials = list(MAT_METAL = 400) + credits = 20 + +/obj/item/coin/plasma + cmineral = "plasma" + icon_state = "coin_plasma_heads" + materials = list(MAT_PLASMA = 400) + credits = 80 + +/obj/item/coin/uranium + cmineral = "uranium" + icon_state = "coin_uranium_heads" + materials = list(MAT_URANIUM = 400) + credits = 160 + +/obj/item/coin/clown + cmineral = "bananium" + icon_state = "coin_bananium_heads" + materials = list(MAT_BANANIUM = 400) + credits = 600 //makes the clown cri + +/obj/item/coin/mime + cmineral = "tranquillite" + icon_state = "coin_tranquillite_heads" + materials = list(MAT_TRANQUILLITE = 400) + credits = 600 //makes the mime cri + +/obj/item/coin/adamantine + cmineral = "adamantine" + icon_state = "coin_adamantine_heads" + credits = 400 + +/obj/item/coin/mythril + cmineral = "mythril" + icon_state = "coin_mythril_heads" + credits = 400 + +/obj/item/coin/twoheaded + cmineral = "iron" + icon_state = "coin_iron_heads" + desc = "Hey, this coin's the same on both sides!" + sideslist = list("heads") + credits = 20 + +/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") + credits = 20 + +/obj/item/coin/antagtoken/syndicate + name = "syndicate coin" + credits = 160 + +/obj/item/coin/attackby(obj/item/W as obj, mob/user as mob, params) + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/CC = W + if(string_attached) + to_chat(user, "There already is a string attached to this coin.") + return + + if(CC.use(1)) + overlays += image('icons/obj/economy.dmi',"coin_string_overlay") + string_attached = 1 + to_chat(user, "You attach a string to the coin.") + else + to_chat(user, "You need one length of cable to attach a string to the coin.") + return + + else if(istype(W,/obj/item/wirecutters)) + if(!string_attached) + ..() + return + + var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) + CC.amount = 1 + CC.update_icon() + overlays = list() + string_attached = null + to_chat(user, "You detach the string from the coin.") + else if(istype(W,/obj/item/weldingtool)) + var/obj/item/weldingtool/WT = W + if(WT.welding && WT.remove_fuel(0, user)) + var/typelist = list("iron" = /obj/item/clothing/gloves/ring, + "silver" = /obj/item/clothing/gloves/ring/silver, + "gold" = /obj/item/clothing/gloves/ring/gold, + "plasma" = /obj/item/clothing/gloves/ring/plasma, + "uranium" = /obj/item/clothing/gloves/ring/uranium) + var/typekey = typelist[cmineral] + if(ispath(typekey)) + to_chat(user, "You make [src] into a ring.") + new typekey(get_turf(loc)) + qdel(src) + else ..() + +/obj/item/coin/attack_self(mob/user as mob) + if(cooldown < world.time - 15) + var/coinflip = pick(sideslist) + cooldown = world.time + flick("coin_[cmineral]_flip", src) + icon_state = "coin_[cmineral]_[coinflip]" + playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1) + if(do_after(user, 15, target = src)) + user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \ + "You flip [src]. It lands on [coinflip].", \ + "You hear the clattering of loose change.") #undef GIBTONITE_QUALITY_LOW #undef GIBTONITE_QUALITY_MEDIUM diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 06043025f7c..51d5820d2bf 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -107,6 +107,8 @@ aiRestorePowerRoutine = 0 update_blind_effects() update_sight() + to_chat(src, "Here are your current laws:") + show_laws() return switch(PRP) @@ -126,8 +128,6 @@ theAPC.attack_ai(src) apc_override = 0 aiRestorePowerRoutine = 3 - to_chat(src, "Here are your current laws:") - src.show_laws() //WHY THE FUCK IS THIS HERE sleep(50) theAPC = null diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index c90a06a9fb8..43d239c59ce 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -55,80 +55,6 @@ return FALSE mouse_opacity = MOUSE_OPACITY_ICON -/obj/item/organ/internal/hivelord_core - name = "hivelord remains" - desc = "All that remains of a hivelord, it seems to be what allows it to break pieces of itself off without being hurt... its healing properties will soon become inert if not used quickly." - icon_state = "roro core 2" - 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/internal/hivelord_core/New() - ..() - addtimer(CALLBACK(src, .proc/inert_check), 2400) - -/obj/item/organ/internal/hivelord_core/proc/inert_check() - if(owner) - preserved(implanted = 1) - else if(preserved) - preserved() - else - go_inert() - -/obj/item/organ/internal/hivelord_core/proc/preserved(implanted = 0) - inert = FALSE - preserved = TRUE - update_icon() - - if(implanted) - feedback_add_details("hivelord_core", "[type]|implanted") - else - feedback_add_details("hivelord_core", "[type]|stabilizer") - - -/obj/item/organ/internal/hivelord_core/proc/go_inert() - inert = TRUE - desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested." - feedback_add_details("hivelord_core", "[src.type]|inert") - update_icon() - -/obj/item/organ/internal/hivelord_core/ui_action_click() - owner.revive() - qdel(src) - -/obj/item/organ/internal/hivelord_core/on_life() - ..() - if(owner.health < HEALTH_THRESHOLD_CRIT) - ui_action_click() - -/obj/item/organ/internal/hivelord_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, "[src] has become inert, its healing properties are no more.") - return - else - if(H.stat == DEAD) - to_chat(user, "[src] are useless on the dead.") - return - if(H != user) - H.visible_message("[user] forces [H] to apply [src]... They quickly regenerate all injuries!") - feedback_add_details("hivelord_core","[src.type]|used|other") - else - to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") - feedback_add_details("hivelord_core","[src.type]|used|self") - playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) - H.revive() - user.drop_item() - qdel(src) - ..() - -/obj/item/organ/internal/hivelord_core/prepare_eat() - return null - /mob/living/simple_animal/hostile/asteroid/hivelordbrood name = "hivelord brood" desc = "A fragment of the original Hivelord, rallying behind its original. One isn't much of a threat, but..." @@ -326,34 +252,6 @@ H.forceMove(L) qdel(src) -/obj/item/organ/internal/hivelord_core/legion - name = "legion's soul" - desc = "A strange rock that still crackles with power... its \ - healing properties will soon become inert if not used quickly." - icon_state = "legion_soul" - -/obj/item/organ/internal/hivelord_core/legion/New() - ..() - update_icon() - -/obj/item/organ/internal/hivelord_core/legion/update_icon() - icon_state = inert ? "legion_soul_inert" : "legion_soul" - overlays.Cut() - if(!inert && !preserved) - overlays += image(icon, "legion_soul_crackle") - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() - -/obj/item/organ/internal/hivelord_core/legion/go_inert() - . = ..() - desc = "[src] has become inert, it crackles no more and is useless for \ - healing injuries." - -/obj/item/organ/internal/hivelord_core/legion/preserved(implanted = 0) - ..() - desc = "[src] has been stabilized. It no longer crackles with power, but it's healing properties are preserved indefinitely." - /obj/item/legion_skull name = "legion's head" desc = "The once living, now empty eyes of the former human's skull cut deep into your soul." diff --git a/code/modules/nano/interaction/base.dm b/code/modules/nano/interaction/base.dm index e4e5dd1a33b..e7f06137781 100644 --- a/code/modules/nano/interaction/base.dm +++ b/code/modules/nano/interaction/base.dm @@ -24,6 +24,8 @@ return STATUS_UPDATE // Ghosts can view updates /mob/living/silicon/ai/shared_nano_interaction() + if(apc_override) + return STATUS_INTERACTIVE if(lacks_power()) return STATUS_CLOSE if(check_unable(1, 0)) diff --git a/code/modules/vehicle/ambulance.dm b/code/modules/vehicle/ambulance.dm index 6b15018de49..ac225003c52 100644 --- a/code/modules/vehicle/ambulance.dm +++ b/code/modules/vehicle/ambulance.dm @@ -102,6 +102,10 @@ anchored = FALSE throw_pressure_limit = INFINITY //Throwing an ambulance trolley can kill the process scheduler. +/obj/structure/bed/amb_trolley/examine(mob/user) + . = ..() + to_chat(user, "Drag [src]'s sprite over the ambulance to (de)attach it.") + /obj/structure/bed/amb_trolley/MouseDrop(obj/over_object as obj) ..() if(istype(over_object, /obj/vehicle/ambulance)) diff --git a/html/changelogs/AutoChangeLog-pr-11941.yml b/html/changelogs/AutoChangeLog-pr-11941.yml new file mode 100644 index 00000000000..5654ca5bdcf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11941.yml @@ -0,0 +1,10 @@ +author: "farie82" +delete-after: True +changes: + - rscadd: "Adds tip text to the examine text of the ambulance trolley about how to attach it" + - rscadd: "Adds tip text to the nuke when trying to use the NAD before deploying it" + - rscadd: "Adds tip text to the fire axe cabinet about how to lock/unlock it" + - rscadd: "Adds tip text to airlocks if they have a note on them about how to remove the note" + - bugfix: "Can't put the NAD in the nuke now when it has the NODROP flag" + - bugfix: "Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep" + - bugfix: "Can't put a nodrop fire axe in fire axe cabinets now. Duping them" diff --git a/html/changelogs/AutoChangeLog-pr-11948.yml b/html/changelogs/AutoChangeLog-pr-11948.yml new file mode 100644 index 00000000000..a7048eee037 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11948.yml @@ -0,0 +1,9 @@ +author: "EmanTheAlmighty" +delete-after: True +changes: + - rscadd: "Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs." + - rscadd: "Blobbernauts and blobs can now communicate with each other." + - rscadd: "Blobbernauts now regenerate health overtime when standing on blob structures." + - rscadd: "Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. +balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. +balance: Blob's \"Produce Blobbernaut\" ability has been made more expensive to use, now costing 60 resources instead of 20." diff --git a/html/changelogs/AutoChangeLog-pr-12038.yml b/html/changelogs/AutoChangeLog-pr-12038.yml new file mode 100644 index 00000000000..f241cfc6c23 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12038.yml @@ -0,0 +1,4 @@ +author: "Shadow-Quill" +delete-after: True +changes: + - bugfix: "AIs not being able to restore their own power if in an area with an APC." diff --git a/html/changelogs/AutoChangeLog-pr-12066.yml b/html/changelogs/AutoChangeLog-pr-12066.yml new file mode 100644 index 00000000000..71c585e6514 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-12066.yml @@ -0,0 +1,11 @@ +author: "Fox McCloud" +delete-after: True +changes: + - tweak: "Ores can be destroyed by devastating explosions" + - tweak: "silver, gold, and diamond pickaxes do a bit more damage and mine faster than before" + - tweak: "drills slightly slower, but diamond drills slightly faster" + - tweak: "Spade is the same speed as a shovel" + - tweak: "Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert" + - tweak: "can use a hivelord core in your active hand to apply it to yourself" + - rscadd: "soulstone in the abandoned locked crates can now be used by anyone" + - rscadd: "Adds firelemon seeds to the abandoned locked crates as potential loot" diff --git a/paradise.dme b/paradise.dme index 69d9e4ddacd..882e18551be 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1651,23 +1651,30 @@ #include "code\modules\martial_arts\sleeping_carp.dm" #include "code\modules\martial_arts\wrestleing.dm" #include "code\modules\mining\abandonedcrates.dm" -#include "code\modules\mining\coins.dm" -#include "code\modules\mining\equipment_locker.dm" -#include "code\modules\mining\explorer_gear.dm" #include "code\modules\mining\fulton.dm" #include "code\modules\mining\machine_processing.dm" +#include "code\modules\mining\machine_redemption.dm" #include "code\modules\mining\machine_stacking.dm" #include "code\modules\mining\machine_unloading.dm" +#include "code\modules\mining\machine_vending.dm" #include "code\modules\mining\mine_items.dm" #include "code\modules\mining\minebot.dm" #include "code\modules\mining\mint.dm" #include "code\modules\mining\money_bag.dm" -#include "code\modules\mining\ore.dm" +#include "code\modules\mining\ores_coins.dm" #include "code\modules\mining\satchel_ore_boxdm.dm" #include "code\modules\mining\shelters.dm" +#include "code\modules\mining\equipment\explorer_gear.dm" #include "code\modules\mining\equipment\kinetic_crusher.dm" +#include "code\modules\mining\equipment\lazarus_injector.dm" #include "code\modules\mining\equipment\marker_beacons.dm" +#include "code\modules\mining\equipment\mineral_scanner.dm" +#include "code\modules\mining\equipment\mining_tools.dm" +#include "code\modules\mining\equipment\regenerative_core.dm" +#include "code\modules\mining\equipment\resonator.dm" #include "code\modules\mining\equipment\survival_pod.dm" +#include "code\modules\mining\equipment\vendor_items.dm" +#include "code\modules\mining\equipment\wormhole_jaunter.dm" #include "code\modules\mining\laborcamp\laborshuttle.dm" #include "code\modules\mining\laborcamp\laborstacker.dm" #include "code\modules\mining\lavaland\ash_flora.dm"