mirror of
https://github.com/goonstation/goonstation-2016.git
synced 2026-07-20 05:22:47 +01:00
1169 lines
35 KiB
Plaintext
1169 lines
35 KiB
Plaintext
// TODO: merge this with the new ability system.
|
|
|
|
/datum/blob_ability
|
|
var/name = null
|
|
var/desc = null
|
|
var/icon = 'icons/mob/blob_ui.dmi'
|
|
var/icon_state = "blob-template"
|
|
var/bio_point_cost = 0
|
|
var/cooldown_time = 0
|
|
var/last_used = 0
|
|
var/targeted = 1
|
|
var/mob/living/intangible/blob_overmind/owner
|
|
var/obj/screen/blob/button
|
|
var/special_screen_loc = null
|
|
var/helpable = 1
|
|
|
|
New()
|
|
var/obj/screen/blob/B = new /obj/screen/blob(null)
|
|
B.icon = src.icon
|
|
B.icon_state = src.icon_state
|
|
B.ability = src
|
|
B.name = src.name
|
|
B.desc = src.desc
|
|
src.button = B
|
|
|
|
proc
|
|
onUse(var/turf/T)
|
|
if (!istype(owner))
|
|
return 1
|
|
if (bio_point_cost > 0)
|
|
if (!owner.hasPoints(bio_point_cost))
|
|
boutput(owner, "<span style=\"color:red\">You do not have enough bio points to use that ability.</span>")
|
|
return 1
|
|
if (cooldown_time > 0 && last_used > world.time)
|
|
boutput(owner, "<span style=\"color:red\">That ability is on cooldown for [round((last_used - world.time) / 10)] seconds.</span>")
|
|
return 1
|
|
return 0
|
|
|
|
deduct_bio_points()
|
|
if (bio_point_cost > 0)
|
|
owner.usePoints(bio_point_cost)
|
|
|
|
do_cooldown()
|
|
//boutput(world, "cooldown initiated, length of [cooldown_time]")
|
|
last_used = world.time + cooldown_time
|
|
owner.update_buttons()
|
|
spawn(cooldown_time + 5)
|
|
//boutput(world, "cooldown over, refreshing UI")
|
|
owner.update_buttons()
|
|
|
|
tutorial_check(var/id, var/turf/T)
|
|
if (owner)
|
|
if (owner.tutorial)
|
|
if (!owner.tutorial.PerformAction(id, T))
|
|
return 0
|
|
return 1
|
|
|
|
/datum/blob_ability/upgrade
|
|
name = "Toggle Upgrade Bar"
|
|
desc = "Expand or contract the upgrades bar."
|
|
icon_state = "blob-viewupgrades"
|
|
targeted = 0
|
|
special_screen_loc = "SOUTH,WEST"
|
|
helpable = 0
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (owner.viewing_upgrades)
|
|
owner.viewing_upgrades = 0
|
|
else
|
|
owner.viewing_upgrades = 1
|
|
owner.update_buttons()
|
|
|
|
/datum/blob_ability/help
|
|
name = "Toggle Help Mode"
|
|
desc = "Enter or exit help mode."
|
|
icon_state = "blob-help0"
|
|
targeted = 0
|
|
special_screen_loc = "SOUTH,EAST"
|
|
helpable = 0
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (owner.help_mode)
|
|
owner.help_mode = 0
|
|
else
|
|
owner.help_mode = 1
|
|
boutput(owner, "<span style=\"color:blue\">Help Mode has been activated To disable it, click on this button again.</span>")
|
|
src.button.icon_state = "blob-help[owner.help_mode]"
|
|
owner.update_buttons()
|
|
|
|
// STARTER ABILITIES
|
|
|
|
/datum/blob_ability/plant_nucleus
|
|
name = "Deploy"
|
|
icon_state = "blob-nucleus"
|
|
desc = "This will place the first blob on your current tile. You can only do this once."
|
|
targeted = 0
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
if (istype(T,/turf/space/))
|
|
boutput(owner, "<span style=\"color:red\">You can't start in space!</span>")
|
|
return
|
|
|
|
if (istype(T,/turf/unsimulated/))
|
|
boutput(owner, "<span style=\"color:red\">This kind of tile cannot support a blob.</span>")
|
|
return
|
|
|
|
if (T.density)
|
|
boutput(owner, "<span style=\"color:red\">You can't start inside a wall!</span>")
|
|
return
|
|
|
|
for (var/obj/O in T.contents)
|
|
if (O.density)
|
|
boutput(owner, "<span style=\"color:red\">That tile is blocked by [O].</span>")
|
|
return
|
|
|
|
for (var/mob/M in viewers(T, 7))
|
|
if (istype(M, /mob/living/silicon/robot) || istype(M, /mob/living/carbon/human))
|
|
if (M.stat != 2)
|
|
boutput(owner, "<span style=\"color:red\">You are being watched.</span>")
|
|
return
|
|
|
|
if (!tutorial_check("deploy", T))
|
|
return
|
|
|
|
var/obj/blob/nucleus/C = new /obj/blob/nucleus(get_turf(owner))
|
|
C.layer++
|
|
C.setOvermind(owner)
|
|
C.Life()
|
|
owner.started = 1
|
|
owner.remove_ability(/datum/blob_ability/plant_nucleus)
|
|
owner.remove_ability(/datum/blob_ability/set_color)
|
|
owner.remove_ability(/datum/blob_ability/tutorial)
|
|
owner.add_ability(/datum/blob_ability/spread)
|
|
owner.add_ability(/datum/blob_ability/attack)
|
|
owner.add_ability(/datum/blob_ability/consume)
|
|
owner.add_ability(/datum/blob_ability/repair)
|
|
owner.add_ability(/datum/blob_ability/absorb)
|
|
owner.add_ability(/datum/blob_ability/promote)
|
|
owner.add_ability(/datum/blob_ability/build/ribosome)
|
|
owner.add_ability(/datum/blob_ability/build/lipid)
|
|
owner.add_ability(/datum/blob_ability/build/mitochondria)
|
|
owner.add_ability(/datum/blob_ability/build/wall)
|
|
owner.add_ability(/datum/blob_ability/build/firewall)
|
|
owner.add_ability(/datum/blob_ability/upgrade)
|
|
for (var/X in typesof(/datum/blob_upgrade) - /datum/blob_upgrade)
|
|
owner.add_upgrade(X, 1)
|
|
|
|
/datum/blob_ability/set_color
|
|
name = "Set Color"
|
|
desc = "Choose what color you want your blob to be. This will be removed when you start the blob."
|
|
icon_state = "blob-color"
|
|
targeted = 0
|
|
|
|
onUse()
|
|
if (..())
|
|
return
|
|
owner.color = input("Select your Color","Blob") as color
|
|
owner.my_material.color = owner.color
|
|
|
|
/datum/blob_ability/tutorial
|
|
name = "Interactive Tutorial"
|
|
desc = "Check out the interactive blob tutorial to get started with blobs."
|
|
icon_state = "blob-help0"
|
|
targeted = 0
|
|
|
|
onUse()
|
|
if (..())
|
|
return
|
|
if (owner.tutorial)
|
|
boutput(owner, "<span style=\"color:red\">You're already in the tutorial!</span>")
|
|
return
|
|
owner.start_tutorial()
|
|
|
|
// BASIC ABILITIES
|
|
|
|
/datum/blob_ability/spread
|
|
name = "Spread"
|
|
icon_state = "blob-spread"
|
|
desc = "This spends two bio-points to spread to the desired tile. Blobs must be placed cardinally adjacent to other blobs. This ability is free of cost and cooldown until the first time you reach 40 tiles."
|
|
bio_point_cost = 2
|
|
cooldown_time = 20
|
|
|
|
onUse(var/turf/T)
|
|
if (!owner.starter_buff && ..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/B1 = T.can_blob_spread_here(owner)
|
|
if (!istype(B1))
|
|
return 1
|
|
|
|
if (!tutorial_check("spread", T))
|
|
return 1
|
|
|
|
var/obj/blob/B2 = new /obj/blob(T)
|
|
B2.setOvermind(owner)
|
|
if (owner.blobs.len < 40)
|
|
cooldown_time = max(12 - owner.spread_upgrade * 10 - owner.spread_mitigation * 0.5, 0)
|
|
else if (owner.blobs.len < 80)
|
|
cooldown_time = max(17 - owner.spread_upgrade * 10 - owner.spread_mitigation * 0.5, 0)
|
|
else if (owner.blobs.len < 160)
|
|
cooldown_time = max(27 - owner.spread_upgrade * 10 - owner.spread_mitigation * 0.5, 0)
|
|
else
|
|
cooldown_time = max(27 + (owner.blobs.len - 160) * 0.08 - owner.spread_upgrade * 10 - owner.spread_mitigation * 0.5, 0)
|
|
cooldown_time = max(cooldown_time, 6)
|
|
|
|
var/extra_spreads = round(owner.multi_spread / 100) + (prob(owner.multi_spread % 100) ? 1 : 0)
|
|
if (extra_spreads)
|
|
var/list/spreadability = list()
|
|
for (var/turf/simulated/floor/Q in view(7, owner))
|
|
if (locate(/obj/blob) in Q)
|
|
continue
|
|
var/obj/blob/B3 = Q.can_blob_spread_here(null)
|
|
if (B3)
|
|
spreadability += Q
|
|
|
|
|
|
for (var/i = 1, i <= extra_spreads && spreadability.len, i++)
|
|
var/turf/R = pick(spreadability)
|
|
var/obj/blob/B3 = new /obj/blob(R)
|
|
B3.setOvermind(owner)
|
|
spreadability -= R
|
|
|
|
if (!owner.starter_buff)
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
/datum/blob_ability/promote
|
|
name = "Promote to Nucleus"
|
|
icon_state = "blob-nucleus"
|
|
desc = "This ability allows you to plant extra nuclei. You are allowed to use this ability once for every 100 tiles of blob reached."
|
|
bio_point_cost = 0
|
|
cooldown_time = 1200
|
|
var/using = 0
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (using)
|
|
return 1
|
|
using = 1
|
|
if (!owner.extra_nuclei)
|
|
boutput(usr, "<span style=\"color:red\">You cannot place additional nuclei at this time.</span>")
|
|
using = 0
|
|
return 1
|
|
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
var/obj/blob/B = locate() in T
|
|
if (!B)
|
|
boutput(usr, "<span style=\"color:red\">No blob here to convert!</span>")
|
|
using = 0
|
|
return 1
|
|
if (B.type != /obj/blob)
|
|
boutput(usr, "<span style=\"color:red\">Cannot promote special blob tiles!</span>")
|
|
using = 0
|
|
return 1
|
|
owner.extra_nuclei--
|
|
var/obj/blob/nucleus/N = new(T)
|
|
N.setOvermind(owner)
|
|
N.setMaterial(B.material)
|
|
B.material = null
|
|
qdel(B)
|
|
deduct_bio_points()
|
|
do_cooldown()
|
|
using = 0
|
|
|
|
/datum/blob_ability/consume
|
|
name = "Consume"
|
|
icon_state = "blob-consume"
|
|
desc = "This ability can be used to remove an existing blob tile for biopoints. Any blob tile you own can be consumed."
|
|
bio_point_cost = 10
|
|
cooldown_time = 20
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
var/obj/blob/B = locate() in T
|
|
if (!B)
|
|
return
|
|
if (B.disposed)
|
|
return
|
|
if (B.overmind != owner)
|
|
return
|
|
if (istype(B, /obj/blob/nucleus))
|
|
boutput(usr, "<span style=\"color:red\">You cannot consume a nucleus!</span>")
|
|
return
|
|
if (!tutorial_check("consume", T))
|
|
return
|
|
playsound(T, 'sound/effects/blobattack.ogg', 50, 1)
|
|
B.visible_message("<span style=\"color:red\"><b>The blob consumes a piece of itself!</b></span>")
|
|
qdel(B)
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
/datum/blob_ability/attack
|
|
name = "Attack"
|
|
icon_state = "blob-attack"
|
|
desc = "This ability commands the blob to attack the selected tile instantly. It must be next to a blob."
|
|
bio_point_cost = 1
|
|
cooldown_time = 20
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/B
|
|
var/turf/checked
|
|
var/terminator = 0
|
|
for (var/dir in alldirs)
|
|
if (terminator)
|
|
break
|
|
checked = get_step(T, dir)
|
|
for (var/obj/blob/X in checked.contents)
|
|
if (X.can_attack_from_this)
|
|
B = X
|
|
terminator = 1
|
|
break
|
|
|
|
if (!istype(B))
|
|
boutput(owner, "<span style=\"color:red\">That tile is not adjacent to a blob capable of attacking.</span>")
|
|
return
|
|
|
|
if (!tutorial_check("attack", T))
|
|
return
|
|
|
|
|
|
B.attack(T)
|
|
for (var/obj/blob/C in orange(B, 7))
|
|
if (prob(25))
|
|
if (C.overmind == B.overmind)
|
|
C.attack_random()
|
|
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
/datum/blob_ability/repair
|
|
name = "Repair"
|
|
icon_state = "blob-repair"
|
|
desc = "This ability repairs a selected blob tile by 20 health."
|
|
bio_point_cost = 1
|
|
cooldown_time = 20
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
if (!tutorial_check("repair", T))
|
|
return
|
|
|
|
var/obj/blob/B = T.get_blob_on_this_turf()
|
|
|
|
if (B)
|
|
B.heal_damage(20)
|
|
B.update_icon()
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
else
|
|
boutput(owner, "<span style=\"color:red\">There is no blob there to repair.</span>")
|
|
|
|
/datum/blob_ability/absorb
|
|
name = "Absorb"
|
|
icon_state = "blob-absorb"
|
|
desc = "This will attempt to absorb a living being standing on one of your blob tiles. It takes a moment to work. If successful, it will grant four evo points."
|
|
bio_point_cost = 0
|
|
cooldown_time = 0
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/B = T.get_blob_on_this_turf()
|
|
if (!istype(B))
|
|
boutput(owner, "<span style=\"color:red\">There is no blob there to absorb someone with.</span>")
|
|
return
|
|
if (!B.can_absorb)
|
|
boutput(owner, "<span style=\"color:red\">[B] cannot absorb humans.</span>")
|
|
|
|
if (!tutorial_check("absorb", T))
|
|
return
|
|
|
|
var/mob/living/carbon/human/H = null
|
|
for (var/mob/living/carbon/human/C in T.contents)
|
|
if (C.decomp_stage == 4)
|
|
continue
|
|
H = C
|
|
break
|
|
if (!istype(H))
|
|
H = locate() in T
|
|
if (istype(H))
|
|
boutput(owner, "<span style=\"color:red\">There's no flesh left on [H.name] to absorb.</span>")
|
|
return
|
|
boutput(owner, "<span style=\"color:red\">There is no-one there that you can absorb.</span>")
|
|
return
|
|
|
|
B.visible_message("<span style=\"color:red\"><b>The blob starts trying to absorb [H.name]!</b></span>")
|
|
sleep(40)
|
|
T = get_turf(H)
|
|
if (T.get_blob_on_this_turf())
|
|
if (H.decomp_stage == 4)
|
|
return
|
|
H.decomp_stage = 4
|
|
H.visible_message("<span style=\"color:red\"><b>[H.name] is absorbed by the blob!</b></span>")
|
|
playsound(T, 'sound/effects/blobattack.ogg', 50, 1)
|
|
owner.evo_points += 4
|
|
H.transforming = 1
|
|
var/current_target_z = H.pixel_z
|
|
var/destination_z = current_target_z - 6
|
|
animate(H, time = 10, alpha = 1, pixel_z = destination_z, easing = LINEAR_EASING)
|
|
spawn(0)
|
|
if (istype(H))
|
|
sleep(10)
|
|
H.lying = 1
|
|
H.skeletonize()
|
|
H.transforming = 0
|
|
H.death()
|
|
H.update_face()
|
|
H.update_body()
|
|
H.update_clothing()
|
|
sleep(50)
|
|
// make sure they resurface on a blob tile or it'll look weird
|
|
if (!T.get_blob_on_this_turf())
|
|
var/turf/newblobtile = null
|
|
for(var/obj/blob/B2 in range(7,H))
|
|
newblobtile = get_turf(B2)
|
|
break
|
|
if (newblobtile)
|
|
H.set_loc(newblobtile)
|
|
else
|
|
H.ghostize()
|
|
qdel(H)
|
|
|
|
animate(H, time = 10, alpha = 255, pixel_z = current_target_z, easing = LINEAR_EASING)
|
|
else
|
|
H.ghostize()
|
|
qdel(H)
|
|
|
|
/datum/blob_ability/reinforce
|
|
name = "Reinforce Blob"
|
|
icon_state = "blob-reinforce"
|
|
desc = "Reinforce the selected blob bit with a material deposit on the same tile. Blob bits with reinforcements may be more durable or more heat resistant, or otherwise may bear special properties depending on the properties of the material. A single blob bit can be repeatedly reinforced to push its properties closer to that of the reinforcing material."
|
|
bio_point_cost = 2
|
|
cooldown_time = 20
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/B = locate() in T
|
|
if (!B)
|
|
boutput(owner, "<span style=\"color:red\">No blob there to reinforce.</span>")
|
|
return 1
|
|
|
|
var/list/deposits = list()
|
|
|
|
for (var/obj/material_deposit/M in T)
|
|
deposits += M
|
|
|
|
if (!deposits.len)
|
|
boutput(owner, "<span style=\"color:red\">No material deposits for reinforcement there.</span>")
|
|
return 1
|
|
|
|
var/obj/material_deposit/reinforcing = deposits[1]
|
|
|
|
if (deposits.len > 1)
|
|
reinforcing = input("Which material deposit?", "Reinforce blob", null) in deposits
|
|
|
|
if (reinforcing.disposed)
|
|
return 1
|
|
|
|
B.visible_message("<span style=\"color:red\"><b>[B] reinforces using [reinforcing]!</b></span>")
|
|
|
|
B.setMaterial(getInterpolatedMaterial(B.material, reinforcing.material, 0.17))
|
|
qdel(reinforcing)
|
|
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
|
|
/datum/blob_ability/reclaimer
|
|
name = "Build Reclaimer"
|
|
icon_state = "blob-reclaimer"
|
|
desc = "This will convert an untapped reagent deposit in the blob into a reclaimer. Reclaimers consume the reagents in the deposit and provide biopoints in exchange. When the deposit depletes, the reclaimer becomes a lipid."
|
|
bio_point_cost = 4
|
|
cooldown_time = 50
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/deposit/B = locate() in T
|
|
if (!B)
|
|
boutput(owner, "<span style=\"color:red\">Reclaimers must be placed on untapped reagent deposits.</span>")
|
|
return 1
|
|
if (B.type != /obj/blob/deposit)
|
|
boutput(owner, "<span style=\"color:red\">Reclaimers must be placed on untapped reagent deposits.</span>")
|
|
return 1
|
|
|
|
if (!tutorial_check("reclaimer", T))
|
|
return 1
|
|
|
|
B.build_reclaimer()
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
return
|
|
|
|
/datum/blob_ability/replicator
|
|
name = "Build Replicator"
|
|
icon_state = "blob-replicator"
|
|
desc = "This will convert an untapped reagent deposit in the blob into a replicator. Replicators use other reagent deposits to create more of the highest volume reagent in the deposit."
|
|
bio_point_cost = 4
|
|
cooldown_time = 50
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/deposit/B = locate() in T
|
|
if (!B)
|
|
boutput(owner, "<span style=\"color:red\">Replicators must be placed on untapped reagent deposits.</span>")
|
|
return 1
|
|
if (B.type != /obj/blob/deposit)
|
|
boutput(owner, "<span style=\"color:red\">Replicators must be placed on untapped reagent deposits.</span>")
|
|
return 1
|
|
|
|
if (!tutorial_check("replicator", T))
|
|
return 1
|
|
|
|
B.build_replicator()
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
return
|
|
|
|
/datum/blob_ability/bridge
|
|
name = "Build Bridge"
|
|
icon_state = "blob-bridge"
|
|
desc = "Creates a floor that you can cross through in space. The floor can be destroyed by fire or weldingtools, and does not act as a blob tile."
|
|
bio_point_cost = 15
|
|
cooldown_time = 200
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
if (!istype(T, /turf/space))
|
|
boutput(owner, "<span style=\"color:red\">Bridges must be placed on space tiles.</span>")
|
|
return 1
|
|
|
|
var/passed = 0
|
|
for (var/dir in cardinal)
|
|
var/turf/checked = get_step(T, dir)
|
|
for (var/obj/blob/B in checked.contents)
|
|
if (B.type != /obj/blob/mutant)
|
|
passed = 1
|
|
break
|
|
|
|
if (!passed)
|
|
boutput(owner, "<span style=\"color:red\">You require an adjacent blob tile to create a bridge.</span>")
|
|
return 1
|
|
|
|
if (!tutorial_check("bridge", T))
|
|
return 1
|
|
|
|
var/turf/simulated/floor/blob/B = new /turf/simulated/floor/blob(T)
|
|
B.setOvermind(owner)
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
return
|
|
|
|
/datum/blob_ability/devour_item
|
|
name = "Devour Item"
|
|
icon_state = "blob-digest"
|
|
desc = "This ability will attempt to devour and digest an object on or cardinally adjacent to a blob tile. This process takes 2 seconds, and it can be interrupted by the removal of the blobs in the item's vicinity or the item itself. If the item or any of its contents contained any reagents, a reagent deposit tile will be created on a nearby standard blob tile."
|
|
bio_point_cost = 3
|
|
cooldown_time = 0
|
|
|
|
proc/recursive_reagents(var/obj/O)
|
|
var/list/ret = list()
|
|
if (O.reagents)
|
|
for (var/id in O.reagents.reagent_list)
|
|
ret += O.reagents.reagent_list[id]
|
|
for (var/obj/P in O)
|
|
ret += recursive_reagents(P)
|
|
return ret
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
var/sel_target = T
|
|
if (isturf(T))
|
|
sel_target = null
|
|
else
|
|
T = get_turf(T)
|
|
var/list/items = list()
|
|
for (var/obj/item/I in T)
|
|
items += I
|
|
if (!items.len)
|
|
boutput(owner, "<span style=\"color:red\">Nothing to devour there.</span>")
|
|
return 1
|
|
|
|
var/obj/blob/Bleb = locate() in T
|
|
if (!Bleb)
|
|
for (var/D in cardinal)
|
|
var/turf/B = get_step(T, D)
|
|
Bleb = locate() in B
|
|
if (Bleb)
|
|
break
|
|
|
|
if (!Bleb)
|
|
boutput(owner, "<span style=\"color:red\">There is no blob nearby which can devour items.</span>")
|
|
return 1
|
|
|
|
if (!tutorial_check("devour", T))
|
|
return 1
|
|
|
|
var/obj/item/I = items[1]
|
|
if (!sel_target)
|
|
if (items.len > 1)
|
|
I = input("Which item?", "Item", null) as null|anything in items
|
|
else
|
|
I = sel_target
|
|
|
|
if (!I)
|
|
return 1
|
|
|
|
if (I.loc != T)
|
|
return 1
|
|
|
|
if (!Bleb) //Wire: Duplicated from above because there's an input() in-between (Fixes runtime: Cannot execute null.visible message())
|
|
boutput(owner, "<span style=\"color:red\">There is no blob nearby which can devour items.</span>")
|
|
return 1
|
|
|
|
Bleb.visible_message("<span style=\"color:red\"><b>The blobs starts devouring [I]!</b></span>")
|
|
sleep(20)
|
|
if (!I)
|
|
return 1
|
|
if (!isturf(I.loc))
|
|
return 1
|
|
Bleb = locate() in I.loc
|
|
if (!Bleb)
|
|
for (var/D in cardinal)
|
|
var/turf/B = get_step(I.loc, D)
|
|
Bleb = locate() in B
|
|
if (Bleb)
|
|
break
|
|
|
|
if (!Bleb)
|
|
return 1
|
|
|
|
Bleb.visible_message("<span style=\"color:red\"><b>The blob devours [I]!</b></span>")
|
|
|
|
if (I.material)
|
|
var/count = 2
|
|
if (istype(I, /obj/item/raw_material) || istype(I, /obj/item/material_piece))
|
|
count = 3
|
|
if (I.amount >= 10)
|
|
count *= round(I.amount / 10) + 1
|
|
for (var/i = 1, i <= count, i++)
|
|
new /obj/material_deposit(Bleb.loc, I.material, owner)
|
|
|
|
var/list/aggregated = recursive_reagents(I)
|
|
if (aggregated.len)
|
|
if (Bleb.type != /obj/blob)
|
|
Bleb = null
|
|
for (var/obj/blob/C in range(5, Bleb))
|
|
if (C.type == /obj/blob && C.overmind == owner)
|
|
Bleb = C
|
|
break
|
|
if (Bleb)
|
|
var/obj/blob/deposit/B2 = new /obj/blob/deposit(Bleb.loc)
|
|
B2.setOvermind(owner)
|
|
qdel(Bleb)
|
|
B2.reagents = new /datum/reagents(0)
|
|
B2.reagents.my_atom = B2
|
|
for (var/datum/reagent/R in aggregated)
|
|
if (!B2)
|
|
src.deduct_bio_points()
|
|
return
|
|
B2.reagents.maximum_volume += R.volume
|
|
B2.reagents.add_reagent(R.id, R.volume)
|
|
if (B2)
|
|
B2.update_reagent_overlay()
|
|
if (!B2.reagents.total_volume)
|
|
var/obj/blob/B3 = new /obj/blob(B2.loc)
|
|
B3.setOvermind(owner)
|
|
qdel(B2)
|
|
src.deduct_bio_points()
|
|
qdel(I)
|
|
|
|
// CONSTRUCTION ABILITIES
|
|
|
|
/datum/blob_ability/build
|
|
var/gen_rate_invest = 0
|
|
var/build_path = /obj/blob
|
|
cooldown_time = 100
|
|
var/buildname = "build"
|
|
|
|
onUse(var/turf/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(owner)
|
|
|
|
var/obj/blob/B = T.get_blob_on_this_turf()
|
|
|
|
if (!B)
|
|
boutput(owner, "<span style=\"color:red\">There is no blob there to convert.</span>")
|
|
return 1
|
|
|
|
if (gen_rate_invest > 0)
|
|
if (owner.get_gen_rate() < gen_rate_invest + 1)
|
|
boutput(owner, "<span style=\"color:red\">You do not have a high enough generation rate to use that ability.</span>")
|
|
boutput(owner, "<span style=\"color:red\">Keep in mind that you cannot reduce your generation rate to zero or below.</span>")
|
|
return 1
|
|
|
|
if (B.type != /obj/blob)
|
|
boutput(owner, "<span style=\"color:red\">You cannot convert special blob cells.</span>")
|
|
return 1
|
|
|
|
if (!tutorial_check(buildname, T))
|
|
return 1
|
|
|
|
var/obj/blob/L = new build_path(T)
|
|
L.setOvermind(owner)
|
|
L.setMaterial(B.material)
|
|
B.material = null
|
|
qdel(B)
|
|
if (gen_rate_invest)
|
|
owner.gen_rate_used++
|
|
src.deduct_bio_points()
|
|
src.do_cooldown()
|
|
|
|
/datum/blob_ability/build/lipid
|
|
name = "Build Lipid Cell"
|
|
icon_state = "blob-lipid"
|
|
desc = "This will convert a blob tile into a Lipid. Lipids act as a storage for 4 biopoints. When you try to spend more than your available biopoints, you will use up lipids to substitute for the missing points. If a lipid is destroyed, the stored points are lost."
|
|
bio_point_cost = 5
|
|
build_path = /obj/blob/lipid
|
|
buildname = "lipid"
|
|
|
|
/datum/blob_ability/build/ribosome
|
|
name = "Build Ribosome Cell"
|
|
icon_state = "blob-ribosome"
|
|
desc = "This will convert a blob tile into a Ribosome. Ribosomes reduce the penalty on spread cooldown induced by the size of the blob."
|
|
bio_point_cost = 5
|
|
build_path = /obj/blob/ribosome
|
|
buildname = "ribosome"
|
|
|
|
/datum/blob_ability/build/mitochondria
|
|
name = "Build Mitochondria Cell"
|
|
icon_state = "blob-mitochondria"
|
|
desc = "This will convert a blob tile into a Mitochondrion. Mitochondria heal nearby blob cells."
|
|
bio_point_cost = 5
|
|
build_path = /obj/blob/mitochondria
|
|
buildname = "mitochondria"
|
|
|
|
/datum/blob_ability/build/plasmaphyll
|
|
name = "Build Plasmaphyll Cell"
|
|
icon_state = "blob-plasmaphyll"
|
|
desc = "This will convert a blob tile into a Plasmaphyll. Plasmaphylls protect nearby blob pieces from sustained fires by absorbing plasma out of the air and converting it into biopoints."
|
|
bio_point_cost = 15
|
|
gen_rate_invest = 1
|
|
build_path = /obj/blob/plasmaphyll
|
|
buildname = "plasmaphyll"
|
|
|
|
/datum/blob_ability/build/ectothermid
|
|
name = "Build Ectothermid Cell"
|
|
icon_state = "blob-ectothermid"
|
|
desc = "This will convert a blob tile into a Ectothermid. Ectothermids provice heat protection in an area at the cost of for biopoints."
|
|
bio_point_cost = 15
|
|
gen_rate_invest = 1
|
|
build_path = /obj/blob/ectothermid
|
|
buildname = "ectothermid"
|
|
|
|
/datum/blob_ability/build/reflective
|
|
name = "Build Reflective Membrane Cell"
|
|
icon_state = "blob-reflective"
|
|
desc = "This will convert a blob tile into a reflective membrane. Reflective membranes are reflect energy projectiles back in the direction they were shot from."
|
|
bio_point_cost = 10
|
|
build_path = /obj/blob/reflective
|
|
buildname = "reflective"
|
|
|
|
/datum/blob_ability/build/launcher
|
|
name = "Build Slime Launcher"
|
|
icon_state = "blob-cannon"
|
|
desc = "This will convert a blob tile into a slime launcher. Slime launchers will fire weak projectiles at nearby humans and cyborgs at the cost of 2 biopoints. Click-drag any reagent deposit onto a slime launcher to load the reagents into the launcher. When loaded with reagents, the slime bullets are also infused with the reagents and while the reservoir lasts, firing the launcher does not cost biopoints."
|
|
bio_point_cost = 10
|
|
build_path = /obj/blob/launcher
|
|
buildname = "launcher"
|
|
|
|
/datum/blob_ability/build/wall
|
|
name = "Build Thick Membrane Cell"
|
|
icon_state = "blob-wall"
|
|
desc = "This will convert a blob tile into a wall. Wall cells are harder to destroy."
|
|
bio_point_cost = 5
|
|
build_path = /obj/blob/wall
|
|
buildname = "wall"
|
|
|
|
/datum/blob_ability/build/firewall
|
|
name = "Build Fire-resistant Membrane Cell"
|
|
icon_state = "blob-firewall"
|
|
desc = "This will convert a blob tile into a fire-resistant wall. Fire resistant walls are very resistant to fire damage."
|
|
bio_point_cost = 5
|
|
build_path = /obj/blob/firewall
|
|
buildname = "firewall"
|
|
|
|
//////////////
|
|
// UPGRADES //
|
|
//////////////
|
|
|
|
/datum/blob_upgrade
|
|
var/name = null
|
|
var/desc = null
|
|
var/icon = 'icons/mob/blob_ui.dmi'
|
|
var/icon_state = "blob-template"
|
|
var/evo_point_cost = 0
|
|
var/last_used = 0
|
|
var/repeatable = 0
|
|
var/initially_disabled = 0
|
|
var/scaling_cost_mult = 1
|
|
var/scaling_cost_add = 0
|
|
var/mob/living/intangible/blob_overmind/owner
|
|
var/obj/screen/blob/button
|
|
var/upgradename = "upgrade"
|
|
|
|
New()
|
|
var/obj/screen/blob/B = new /obj/screen/blob(null)
|
|
B.icon = src.icon
|
|
B.icon_state = src.icon_state
|
|
B.upgrade = src
|
|
B.name = src.name
|
|
B.desc = src.desc
|
|
src.button = B
|
|
|
|
proc/check_requirements()
|
|
if (!istype(owner))
|
|
return 0
|
|
if (owner.evo_points < evo_point_cost)
|
|
//boutput(owner, "<span style=\"color:red\">You need [bio_point_cost] bio-points to take this upgrade.</span>")
|
|
return 0
|
|
return 1
|
|
|
|
proc/deduct_evo_points()
|
|
if (evo_point_cost == 0)
|
|
return
|
|
owner.evo_points = max(0,round(owner.evo_points - evo_point_cost))
|
|
src.evo_point_cost = round(src.evo_point_cost * src.scaling_cost_mult)
|
|
src.evo_point_cost += scaling_cost_add
|
|
|
|
proc/take_upgrade()
|
|
if (!istype(owner))
|
|
return 1
|
|
if (!tutorial_check())
|
|
return 1
|
|
if (!(src in owner.upgrades))
|
|
owner.upgrades += src
|
|
if (repeatable > 0)
|
|
repeatable--
|
|
if (repeatable == 0)
|
|
owner.available_upgrades -= src
|
|
|
|
owner.update_buttons()
|
|
|
|
proc/tutorial_check()
|
|
if (owner)
|
|
if (owner.tutorial)
|
|
if (!owner.tutorial.PerformAction("upgrade-[upgradename]", null))
|
|
return 0
|
|
return 1
|
|
|
|
/datum/blob_upgrade/extra_genrate
|
|
name = "Passive: Increase Generation Rate"
|
|
icon_state = "blob-genrate"
|
|
desc = "Increases your BP generation rate by 2. Can be repeated."
|
|
evo_point_cost = 1
|
|
scaling_cost_add = 1
|
|
repeatable = -1
|
|
upgradename = "genrate"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.gen_rate_bonus += 2
|
|
owner.update_buttons()
|
|
|
|
/datum/blob_upgrade/quick_spread
|
|
name = "Passive: Quicker Spread"
|
|
icon_state = "blob-quickspread"
|
|
desc = "Reduces the cooldown of your Spread ability by 1 second. Can be repeated. The cooldown of Spread cannot go below 1 second."
|
|
evo_point_cost = 3
|
|
scaling_cost_add = 7
|
|
repeatable = -1
|
|
upgradename = "spread"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.spread_upgrade++
|
|
|
|
/datum/blob_upgrade/spread
|
|
name = "Passive: Spread Upgrade"
|
|
icon_state = "blob-spread"
|
|
desc = "When spreading, adds a cumulative 20% chance to spread off another, random tile on your screen. Every time your chance hits a multiple of 100%, the spread for that amount of tiles is guaranteed and a new chance is added for an extra tile. For example, at 120%, you have a 100% chance to spread twice; with a 20% chance to spread three times instead."
|
|
evo_point_cost = 1
|
|
scaling_cost_add = 1
|
|
repeatable = -1
|
|
upgradename = "multispread"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.multi_spread += 20
|
|
|
|
/datum/blob_upgrade/attack
|
|
name = "Passive: Attack Upgrade"
|
|
icon_state = "blob-attack"
|
|
desc = "Increases your attack damage and the chance of mob knockdown. Level 3+ of this upgrade will allow you to punch down girders. Can be repeated."
|
|
evo_point_cost = 1
|
|
scaling_cost_add = 1
|
|
repeatable = -1
|
|
upgradename = "attack"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.attack_power += 0.34
|
|
|
|
/datum/blob_upgrade/fire_resist
|
|
name = "Passive: Fire Resistance"
|
|
icon_state = "blob-fireresist"
|
|
desc = "Makes your blob become more resistant to fire and heat based attacks."
|
|
evo_point_cost = 3
|
|
upgradename = "fireres"
|
|
|
|
/datum/blob_upgrade/poison_resist
|
|
name = "Passive: Poison Resistance"
|
|
icon_state = "blob-poisonresist"
|
|
desc = "Makes your blob become more resistant to chemical attacks."
|
|
evo_point_cost = 3
|
|
upgradename = "poisonres"
|
|
|
|
/datum/blob_upgrade/devour_item
|
|
name = "Ability: Devour Item"
|
|
icon_state = "blob-digest"
|
|
desc = "Unlocks the Devour Item ability, which can be used to near-instantly break down any item adjacent to any blob tile. In addition, a reagent deposit is created in the blob if the item contained any reagents. Reagent deposits can be used with various blob elements. Material bearing objects will break down into material deposits, which can be used to reinforce your blob."
|
|
evo_point_cost = 1
|
|
upgradename = "digest"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/devour_item)
|
|
owner.add_upgrade(/datum/blob_upgrade/reclaimer)
|
|
owner.add_upgrade(/datum/blob_upgrade/replicator)
|
|
owner.add_upgrade(/datum/blob_upgrade/reinforce)
|
|
|
|
/datum/blob_upgrade/reinforce
|
|
name = "Ability: Reinforce"
|
|
icon_state = "blob-reinforce"
|
|
desc = "Unlocks the Reinforce ability, which can be used to strengthen a single blob bit. Blob bits with reinforcements may be more durable or more heat resistant, or otherwise may bear special properties depending on the properties of the material. A single blob bit can be repeatedly reinforced to push its properties closer to that of the reinforcing material."
|
|
evo_point_cost = 1
|
|
initially_disabled = 1
|
|
upgradename = "reinforce"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/reinforce)
|
|
owner.add_upgrade(/datum/blob_upgrade/reinforce_spread)
|
|
|
|
/datum/blob_upgrade/reinforce_spread
|
|
name = "Passive: Reinforced Spread"
|
|
icon_state = "blob-global-reinforce"
|
|
desc = "Reinforces the blob with material permanently. All existing blob tiles are reinforced with the average of the used materials, and all future blob bits will be created with the infusion. This upgrade requires 60 material deposits to be on your current tile."
|
|
evo_point_cost = 2
|
|
initially_disabled = 1
|
|
scaling_cost_add = 2
|
|
repeatable = -1
|
|
upgradename = "reinforce_spread"
|
|
var/required_deposits = 60
|
|
var/taking = 0
|
|
|
|
take_upgrade()
|
|
if (!istype(owner))
|
|
return 1
|
|
if (!tutorial_check())
|
|
return 1
|
|
var/count = 0
|
|
for (var/obj/material_deposit/M in view(owner))
|
|
if (M.overmind == owner && M.material)
|
|
count++
|
|
if (count < required_deposits)
|
|
boutput(usr, "<span style=\"color:red\"><b>You need more deposits on your screen! (Required: [required_deposits], have: [count])</b></span>")
|
|
return 1
|
|
if (taking)
|
|
boutput(usr, "<span style=\"color:red\">Cannot take this upgrade currently! Please wait.</span>")
|
|
return 1
|
|
taking = 1
|
|
var/list/mats = list()
|
|
var/list/weights = list()
|
|
var/list/deposits = list()
|
|
var/total = 0
|
|
var/max_id = null
|
|
for (var/obj/material_deposit/M in view(owner))
|
|
if (total >= required_deposits)
|
|
break
|
|
var/datum/material/Mat = M.material
|
|
if (!Mat)
|
|
continue
|
|
deposits += M
|
|
var/id = Mat.mat_id
|
|
if (!(id in mats))
|
|
mats[id] = Mat
|
|
weights[id] = 1
|
|
else
|
|
weights[id] = weights[id] + 1
|
|
total = 0
|
|
for (var/mid in weights)
|
|
if (weights[mid] > total)
|
|
total = weights[mid]
|
|
max_id = mid
|
|
if (!total)
|
|
return 1
|
|
if (total < required_deposits)
|
|
boutput(usr, "<span style=\"color:red\"><b>You need more deposits on your screen! (Required: [required_deposits], have (of highest material '[max_id]'): [count])</b></span>")
|
|
return 1
|
|
if (!mats.len)
|
|
return 1
|
|
var/datum/material/to_merge = copyMaterial(mats[max_id])
|
|
owner.my_material = getInterpolatedMaterial(owner.my_material, to_merge, 0.17)
|
|
for (var/obj/O in deposits)
|
|
qdel(O)
|
|
boutput(usr, "<span style=\"color:blue\">Applying upgrade to the blob...</span>")
|
|
spawn(0)
|
|
var/wg = 0
|
|
for (var/obj/blob/O in owner.blobs)
|
|
if (!O.material)
|
|
O.setMaterial(copyMaterial(owner.my_material))
|
|
else
|
|
O.setMaterial(getInterpolatedMaterial(O.material, to_merge, 0.17))
|
|
wg++
|
|
if (wg >= 20)
|
|
sleep(1)
|
|
wg = 0
|
|
boutput(usr, "<span style=\"color:blue\">Finished applying material upgrade!</span>")
|
|
taking = 0
|
|
if (!(src in owner.upgrades))
|
|
owner.upgrades += src
|
|
return 0
|
|
|
|
/datum/blob_upgrade/reclaimer
|
|
name = "Structure: Reclaimer"
|
|
icon_state = "blob-reclaimer"
|
|
desc = "Unlocks the Reclaimer blob bit, which can be placed on reagent deposits. The reclaimer produces biopoints over time using reagents. Once the deposit depletes, the blob piece is transformed into a lipid."
|
|
evo_point_cost = 2
|
|
initially_disabled = 1
|
|
upgradename = "reclaimer"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/reclaimer)
|
|
|
|
/datum/blob_upgrade/replicator
|
|
name = "Structure: Replicator"
|
|
icon_state = "blob-replicator"
|
|
desc = "Unlocks the Replicator blob bit, which can be placed on reagent deposits. The replicator replicates the highest volume reagent in the deposit using reagents from other deposits, at the cost of biopoints."
|
|
evo_point_cost = 3
|
|
initially_disabled = 1
|
|
upgradename = "replicator"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/replicator)
|
|
|
|
/datum/blob_upgrade/bridge
|
|
name = "Structure: Bridge"
|
|
icon_state = "blob-bridge"
|
|
desc = "Unlocks the Bridge blob bit, which can be placed on space tiles. Bridges are floor tiles, you still need to spread onto them, and cannot spread from them."
|
|
evo_point_cost = 3
|
|
initially_disabled = 0
|
|
upgradename = "bridge"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/bridge)
|
|
|
|
/datum/blob_upgrade/launcher
|
|
name = "Structure: Slime Launcher"
|
|
icon_state = "blob-cannon"
|
|
desc = "Unlocks the Slime Launcher blob bit, which fires at nearby mobs at the cost of biopoints. Slime inflicts a short stun and minimal damage."
|
|
upgradename = "launcher"
|
|
|
|
evo_point_cost = 2
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/build/launcher)
|
|
|
|
/datum/blob_upgrade/plasmaphyll
|
|
name = "Structural: Plasmaphyll"
|
|
icon_state = "blob-plasmaphyll"
|
|
desc = "Unlocks the plasmaphyll blob bit, which passively protects an area from plasma by converting it to biopoints."
|
|
evo_point_cost = 3
|
|
upgradename = "plasmaphyll"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/build/plasmaphyll)
|
|
|
|
/datum/blob_upgrade/ectothermid
|
|
name = "Structural: Ectothermid"
|
|
icon_state = "blob-ectothermid"
|
|
desc = "Unlocks the ectothermid blob bit, which passively an protects area from temperature. This protection consumes biopoints."
|
|
evo_point_cost = 3
|
|
upgradename = "ectothermid"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/build/ectothermid)
|
|
|
|
/datum/blob_upgrade/reflective
|
|
name = "Structural: Reflective Membrane"
|
|
icon_state = "blob-reflective"
|
|
desc = "Unlocks the reflective membrane, which is immune to energy projectiles."
|
|
evo_point_cost = 2
|
|
upgradename = "reflective"
|
|
|
|
take_upgrade()
|
|
if (..())
|
|
return 1
|
|
owner.add_ability(/datum/blob_ability/build/reflective) |