mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-21 19:17:50 +01:00
* WIP * changes * more changes * chnges * update * changes * I suck at TGUI if you see this please help * UI a bit better still figuring it out * More things * Eject Select, Select empty and autoselect empty implemented. can insert replaace stat/all stats from disk list * Ready to make a PR Disks can be loaded into the machine from boxed, an empty disk is automatically selected once an extraction is performed if one is available. All insert and replace buttons moved to the disk lists. Window size and scaling changed to fit LSD properly without wrapping. * minor ui tweak, fixes core stat disk being auto selected unintentionally. Loading via box now makes a sound. * rebuild TGUI * rebuild tgui * implemented RO button/indicator in UI, Added null checks for can_add * slightly shrink some buttons rebuild TGUI * Rebuild TGUI * use istype for type checks * removes the disk compartmentalizer from maps * removes Disk Compartmentalizer * actually removes the disk compartmentalizer * rebuild tgui and remove all remaining disk compartmentalizer sprites * fixes a message being output to world instead of the user * auto doc and readability improvements. * some fixes adjusts display name to display the new doubled percentages. Stored seed no longer counts as a disk for the purpose of reaching the disk capacity. * Rebuild TGUI
484 lines
15 KiB
Plaintext
484 lines
15 KiB
Plaintext
/datum/plant_gene
|
|
var/name
|
|
/// Used to determine if the trait should be logged when the holder is used
|
|
var/dangerous = FALSE
|
|
|
|
/datum/plant_gene/proc/get_name() // Used for manipulator display and gene disk name.
|
|
return name
|
|
|
|
/datum/plant_gene/proc/can_add(obj/item/seeds/S)
|
|
return !istype(S, /obj/item/seeds/sample) // Samples can't accept new genes
|
|
|
|
/datum/plant_gene/proc/Copy()
|
|
return new type
|
|
|
|
/datum/plant_gene/proc/apply_vars(obj/item/seeds/S) // currently used for fire resist, can prob. be further refactored
|
|
return
|
|
|
|
|
|
// Core plant genes store 5 main variables: lifespan, endurance, production, yield, potency
|
|
/datum/plant_gene/core
|
|
var/value
|
|
var/use_max = FALSE
|
|
|
|
/datum/plant_gene/core/get_name()
|
|
return "[name] [value]"
|
|
|
|
/datum/plant_gene/core/proc/apply_stat(obj/item/seeds/S)
|
|
return
|
|
|
|
/datum/plant_gene/core/New(i = null)
|
|
..()
|
|
if(!isnull(i))
|
|
value = i
|
|
|
|
/datum/plant_gene/core/Copy()
|
|
var/datum/plant_gene/core/C = ..()
|
|
C.value = value
|
|
return C
|
|
|
|
/datum/plant_gene/core/can_add(obj/item/seeds/S)
|
|
if(!..())
|
|
return FALSE
|
|
return S.get_gene(type)
|
|
|
|
/datum/plant_gene/core/proc/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder)
|
|
stack_trace("A plant gene ([get_name()]) tried to get a genemod variable without being in a genemodder.")
|
|
return
|
|
stack_trace("A plant gene ([get_name()]) tried to get a genemod variable, but had no override.")
|
|
|
|
/datum/plant_gene/core/lifespan
|
|
name = "Lifespan"
|
|
value = 25
|
|
|
|
/datum/plant_gene/core/lifespan/apply_stat(obj/item/seeds/S)
|
|
S.lifespan = value
|
|
|
|
/datum/plant_gene/core/lifespan/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.max_endurance // Yes, this is intended. It is used for both lifespan and endurance
|
|
|
|
|
|
/datum/plant_gene/core/endurance
|
|
name = "Endurance"
|
|
value = 15
|
|
|
|
/datum/plant_gene/core/endurance/apply_stat(obj/item/seeds/S)
|
|
S.endurance = value
|
|
|
|
/datum/plant_gene/core/endurance/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.max_endurance
|
|
|
|
|
|
/datum/plant_gene/core/production
|
|
name = "Production Speed"
|
|
value = 6
|
|
use_max = TRUE
|
|
|
|
/datum/plant_gene/core/production/apply_stat(obj/item/seeds/S)
|
|
S.production = value
|
|
|
|
/datum/plant_gene/core/production/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.min_production
|
|
|
|
/datum/plant_gene/core/yield
|
|
name = "Yield"
|
|
value = 3
|
|
|
|
/datum/plant_gene/core/yield/apply_stat(obj/item/seeds/S)
|
|
S.yield = value
|
|
|
|
/datum/plant_gene/core/yield/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.max_yield
|
|
|
|
|
|
/datum/plant_gene/core/potency
|
|
name = "Potency"
|
|
value = 10
|
|
|
|
/datum/plant_gene/core/potency/apply_stat(obj/item/seeds/S)
|
|
S.potency = value
|
|
|
|
/datum/plant_gene/core/potency/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.max_potency
|
|
|
|
|
|
/datum/plant_gene/core/weed_rate
|
|
name = "Weed Growth Rate"
|
|
value = 1
|
|
use_max = TRUE
|
|
|
|
/datum/plant_gene/core/weed_rate/apply_stat(obj/item/seeds/S)
|
|
S.weed_rate = value
|
|
|
|
/datum/plant_gene/core/weed_rate/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.min_weed_rate
|
|
|
|
|
|
/datum/plant_gene/core/weed_chance
|
|
name = "Weed Vulnerability"
|
|
value = 5
|
|
use_max = TRUE
|
|
|
|
/datum/plant_gene/core/weed_chance/apply_stat(obj/item/seeds/S)
|
|
S.weed_chance = value
|
|
|
|
/datum/plant_gene/core/weed_chance/get_genemod_variable(obj/machinery/plantgenes/modder)
|
|
if(!modder) // Let the parent handle it
|
|
return ..()
|
|
return modder.min_weed_chance
|
|
|
|
|
|
// Reagent genes store reagent ID and reagent ratio. Amount of reagent in the plant = 1 + (potency * rate)
|
|
/datum/plant_gene/reagent
|
|
name = "Nutriment"
|
|
var/reagent_id = "nutriment"
|
|
var/rate = 0.04
|
|
|
|
/datum/plant_gene/reagent/get_name()
|
|
return "[name] production [rate * 200]%" // Yes 200 is correct
|
|
|
|
/datum/plant_gene/reagent/proc/set_reagent(reag_id)
|
|
reagent_id = reag_id
|
|
name = "UNKNOWN"
|
|
|
|
var/datum/reagent/R = GLOB.chemical_reagents_list[reag_id]
|
|
if(R && R.id == reagent_id)
|
|
if(reagent_id == "holywater")
|
|
name = "Holy Water"
|
|
else
|
|
name = R.name
|
|
|
|
/datum/plant_gene/reagent/New(reag_id = null, reag_rate = 0)
|
|
..()
|
|
if(reag_id && reag_rate)
|
|
set_reagent(reag_id)
|
|
rate = reag_rate
|
|
|
|
/datum/plant_gene/reagent/Copy()
|
|
var/datum/plant_gene/reagent/G = ..()
|
|
G.name = name
|
|
G.reagent_id = reagent_id
|
|
G.rate = rate
|
|
return G
|
|
|
|
/datum/plant_gene/reagent/can_add(obj/item/seeds/S)
|
|
if(!..())
|
|
return FALSE
|
|
if(!S)
|
|
return FALSE
|
|
for(var/datum/plant_gene/reagent/R in S.genes)
|
|
if(R.reagent_id == reagent_id)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
|
|
// Various traits affecting the product. Each must be somehow useful.
|
|
/datum/plant_gene/trait
|
|
var/rate = 0.05
|
|
var/examine_line = ""
|
|
var/list/origin_tech = null
|
|
var/trait_id // must be set and equal for any two traits of the same type
|
|
|
|
/datum/plant_gene/trait/Copy()
|
|
var/datum/plant_gene/trait/G = ..()
|
|
G.rate = rate
|
|
return G
|
|
|
|
/datum/plant_gene/trait/can_add(obj/item/seeds/S)
|
|
if(!..())
|
|
return FALSE
|
|
if(!S)
|
|
return FALSE
|
|
for(var/datum/plant_gene/trait/R in S.genes)
|
|
if(trait_id && R.trait_id == trait_id)
|
|
return FALSE
|
|
if(type == R.type)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/plant_gene/trait/proc/on_new(obj/item/food/snacks/grown/G)
|
|
if(!origin_tech) // This ugly code segment adds RnD tech levels to resulting plants.
|
|
return
|
|
|
|
if(G.origin_tech)
|
|
var/list/tech = params2list(G.origin_tech)
|
|
for(var/t in origin_tech)
|
|
if(t in tech)
|
|
tech[t] = max(text2num(tech[t]), origin_tech[t])
|
|
else
|
|
tech[t] = origin_tech[t]
|
|
G.origin_tech = list2params(tech)
|
|
else
|
|
G.origin_tech = list2params(origin_tech)
|
|
|
|
/datum/plant_gene/trait/proc/on_consume(obj/item/food/snacks/grown/G, mob/living/carbon/target)
|
|
return
|
|
|
|
/datum/plant_gene/trait/proc/on_slip(obj/item/food/snacks/grown/G, mob/living/carbon/target)
|
|
return
|
|
|
|
/datum/plant_gene/trait/proc/on_squash(obj/item/food/snacks/grown/G, atom/target)
|
|
return
|
|
|
|
/datum/plant_gene/trait/proc/on_attackby(obj/item/food/snacks/grown/G, obj/item/I, mob/user)
|
|
return
|
|
|
|
/datum/plant_gene/trait/proc/on_throw_impact(obj/item/food/snacks/grown/G, atom/target)
|
|
return
|
|
|
|
/datum/plant_gene/trait/squash
|
|
// Allows the plant to be squashed when thrown or slipped on, leaving a colored mess and trash type item behind.
|
|
// Also splashes everything in target turf with reagents and applies other trait effects (teleporting, etc) to the target by on_squash.
|
|
// For code, see grown.dm
|
|
name = "Liquid Contents"
|
|
examine_line = "<span class='info'>It has a lot of liquid contents inside.</span>"
|
|
origin_tech = list("biotech" = 5)
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/slip
|
|
// Makes plant slippery, unless it has a grown-type trash. Then the trash gets slippery.
|
|
// Applies other trait effects (teleporting, etc) to the target by on_slip.
|
|
name = "Slippery Skin"
|
|
rate = 0.1
|
|
examine_line = "<span class='info'>It has a very slippery skin.</span>"
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/slip/on_new(obj/item/food/snacks/grown/G)
|
|
. = ..()
|
|
if(istype(G) && ispath(G.trash, /obj/item/grown))
|
|
return
|
|
|
|
var/stun_len = G.seed.potency * rate * 1.6 SECONDS
|
|
|
|
if(!istype(G, /obj/item/grown/bananapeel) && (!G.reagents || !G.reagents.has_reagent("lube")))
|
|
stun_len /= 3
|
|
|
|
stun_len = min(stun_len, 14 SECONDS)// No fun allowed
|
|
|
|
G.AddComponent(/datum/component/slippery, G, stun_len, 100, 0, FALSE)
|
|
|
|
/datum/plant_gene/trait/cell_charge
|
|
// Cell recharging trait. Charges all mob's power cells to (potency*rate)% mark when eaten.
|
|
// Generates sparks on squash.
|
|
// Small (potency*rate*5) chance to shock squish or slip target for damage (potency*rate*5).
|
|
// Multiplies max charge by (rate*100) when used in potato power cells.
|
|
name = "Electrical Activity"
|
|
rate = 0.2
|
|
origin_tech = list("powerstorage" = 5)
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/cell_charge/on_slip(obj/item/food/snacks/grown/G, mob/living/carbon/C)
|
|
var/power = G.seed.potency*rate
|
|
if(prob(power))
|
|
C.electrocute_act(round(power), G, 1, SHOCK_NOGLOVES)
|
|
|
|
/datum/plant_gene/trait/cell_charge/on_squash(obj/item/food/snacks/grown/G, atom/target)
|
|
if(isliving(target))
|
|
var/mob/living/carbon/C = target
|
|
var/power = G.seed.potency*rate
|
|
if(prob(power))
|
|
C.electrocute_act(round(power), G, 1, SHOCK_NOGLOVES)
|
|
|
|
/datum/plant_gene/trait/cell_charge/on_consume(obj/item/food/snacks/grown/G, mob/living/carbon/target)
|
|
if(!G.reagents.total_volume)
|
|
var/batteries_recharged = 0
|
|
for(var/obj/item/stock_parts/cell/C in target.GetAllContents())
|
|
var/newcharge = min(G.seed.potency*0.01*C.maxcharge, C.maxcharge)
|
|
if(C.charge < newcharge)
|
|
C.charge = newcharge
|
|
if(isobj(C.loc))
|
|
var/obj/O = C.loc
|
|
O.update_icon() //update power meters and such
|
|
C.update_icon()
|
|
batteries_recharged = 1
|
|
if(batteries_recharged)
|
|
target.reagents.add_reagent("teslium", 2)
|
|
to_chat(target, "<span class='notice'>Your batteries are recharged!</span>")
|
|
|
|
|
|
|
|
/datum/plant_gene/trait/glow
|
|
// Makes plant glow. Makes plant in tray glow too.
|
|
// Adds 1 + potency*rate light range and potency*(rate + 0.01) light_power to products.
|
|
name = "Bioluminescence"
|
|
rate = 0.03
|
|
examine_line = "<span class='info'>It emits a soft glow.</span>"
|
|
trait_id = "glow"
|
|
var/glow_color = "#C3E381"
|
|
|
|
/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/S)
|
|
return 1.4 + S.potency*rate
|
|
|
|
/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/S)
|
|
return max(S.potency*(rate + 0.01), 0.1)
|
|
|
|
/datum/plant_gene/trait/glow/on_new(obj/item/food/snacks/grown/G)
|
|
..()
|
|
G.set_light(glow_range(G.seed), glow_power(G.seed), glow_color)
|
|
|
|
/datum/plant_gene/trait/glow/shadow
|
|
//makes plant emit slightly purple shadows
|
|
//adds -potency*(rate*0.05) light power to products
|
|
name = "Shadow Emission"
|
|
rate = 0.04
|
|
glow_color = "#AAD84B"
|
|
|
|
/datum/plant_gene/trait/glow/shadow/glow_power(obj/item/seeds/S)
|
|
return -max(S.potency*(rate*0.05), 0.075)
|
|
|
|
/datum/plant_gene/trait/glow/red
|
|
name = "Red Electrical Glow"
|
|
glow_color = LIGHT_COLOR_RED
|
|
|
|
/datum/plant_gene/trait/glow/berry
|
|
name = "Strong Bioluminescence"
|
|
rate = 0.05
|
|
glow_color = null
|
|
|
|
/datum/plant_gene/trait/teleport
|
|
// Makes plant teleport people when squashed or slipped on.
|
|
// Teleport radius is calculated as max(round(potency*rate), 1)
|
|
name = "Bluespace Activity"
|
|
rate = 0.1
|
|
origin_tech = list("bluespace" = 5)
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/teleport/on_squash(obj/item/food/snacks/grown/G, atom/target)
|
|
if(isliving(target))
|
|
var/mob/living/L = target
|
|
var/teleport_radius = max(round(G.seed.potency / 10), 1)
|
|
var/turf/T = get_turf(L)
|
|
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
|
|
do_teleport(L, T, teleport_radius)
|
|
L.apply_status_effect(STATUS_EFFECT_TELEPORTSICK)
|
|
|
|
/datum/plant_gene/trait/teleport/on_slip(obj/item/food/snacks/grown/G, mob/living/carbon/C)
|
|
var/teleport_radius = max(round(G.seed.potency / 10), 1)
|
|
var/turf/T = get_turf(C)
|
|
if(do_teleport(C, T, teleport_radius))
|
|
to_chat(C, "<span class='warning'>You slip through spacetime!</span>")
|
|
if(prob(50))
|
|
do_teleport(G, T, teleport_radius)
|
|
C.apply_status_effect(STATUS_EFFECT_TELEPORTSICK)
|
|
else
|
|
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
|
|
qdel(G)
|
|
else
|
|
to_chat(C, "<span class='warning'>[src] sparks, and burns up!</span>")
|
|
new /obj/effect/decal/cleanable/molten_object(T)
|
|
qdel(G)
|
|
|
|
/datum/plant_gene/trait/maxchem
|
|
// 2x to max reagents volume.
|
|
name = "Densified Chemicals"
|
|
rate = 2
|
|
|
|
/datum/plant_gene/trait/maxchem/on_new(obj/item/food/snacks/grown/G)
|
|
..()
|
|
G.reagents.maximum_volume *= rate
|
|
|
|
/datum/plant_gene/trait/repeated_harvest
|
|
name = "Perennial Growth"
|
|
|
|
/datum/plant_gene/trait/repeated_harvest/can_add(obj/item/seeds/S)
|
|
if(!..())
|
|
return FALSE
|
|
if(istype(S, /obj/item/seeds/replicapod))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/plant_gene/trait/battery
|
|
name = "Capacitive Cell Production"
|
|
|
|
/datum/plant_gene/trait/battery/on_attackby(obj/item/food/snacks/grown/G, obj/item/I, mob/user)
|
|
if(istype(I, /obj/item/stack/cable_coil))
|
|
var/obj/item/stack/cable_coil/C = I
|
|
if(C.use(5))
|
|
to_chat(user, "<span class='notice'>You add some cable to [G] and slide it inside the battery encasing.</span>")
|
|
var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc)
|
|
pocell.icon_state = G.icon_state
|
|
pocell.maxcharge = max(G.seed.potency * 20, 1)
|
|
|
|
// The secret of potato supercells!
|
|
var/datum/plant_gene/trait/cell_charge/CG = G.seed.get_gene(/datum/plant_gene/trait/cell_charge)
|
|
if(CG) // 20x charge for deafult cell charge gene - 40 000 with 100 potency.
|
|
pocell.maxcharge *= CG.rate*100
|
|
pocell.charge = pocell.maxcharge
|
|
pocell.name = "[G] battery"
|
|
pocell.desc = "A rechargable plant based power cell. This one has a power rating of [pocell.maxcharge], and you should not swallow it."
|
|
|
|
if(G.reagents.has_reagent("plasma", 2))
|
|
pocell.rigged = 1
|
|
|
|
qdel(G)
|
|
else
|
|
to_chat(user, "<span class='warning'>You need five lengths of cable to make a [G] battery!</span>")
|
|
|
|
|
|
/datum/plant_gene/trait/stinging
|
|
name = "Hypodermic Prickles"
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/stinging/on_throw_impact(obj/item/food/snacks/grown/G, atom/target)
|
|
if(isliving(target) && G.reagents && G.reagents.total_volume)
|
|
var/mob/living/L = target
|
|
// It would be nice to inject the body part the original thrower aimed at,
|
|
// but we don't have this kind of information here. So pick something at random.
|
|
var/target_zone = pick("chest", "chest", "chest", "l_leg", "r_leg", "l_arm", "r_arm", "head")
|
|
if(L.reagents && L.can_inject(null, FALSE, target_zone))
|
|
var/injecting_amount = max(1, G.seed.potency*0.2) // Minimum of 1, max of 20
|
|
var/fraction = min(injecting_amount/G.reagents.total_volume, 1)
|
|
G.reagents.reaction(L, REAGENT_INGEST, fraction)
|
|
G.reagents.trans_to(L, injecting_amount)
|
|
to_chat(target, "<span class='danger'>You are pricked by [G]!</span>")
|
|
|
|
/datum/plant_gene/trait/smoke
|
|
name = "Gaseous Decomposition"
|
|
dangerous = TRUE
|
|
|
|
/datum/plant_gene/trait/smoke/on_squash(obj/item/food/snacks/grown/G, atom/target)
|
|
var/datum/effect_system/smoke_spread/chem/plant/S = new()
|
|
var/splat_location = get_turf(target)
|
|
var/smoke_amount = round(sqrt(G.seed.potency * 0.1), 1)
|
|
S.set_up(G.reagents, splat_location)
|
|
S.start(smoke_amount)
|
|
|
|
/// Lavaland
|
|
/datum/plant_gene/trait/fire_resistance
|
|
name = "Fire Resistance"
|
|
|
|
/datum/plant_gene/trait/fire_resistance/apply_vars(obj/item/seeds/S)
|
|
if(!(S.resistance_flags & FIRE_PROOF))
|
|
S.resistance_flags |= FIRE_PROOF
|
|
|
|
/datum/plant_gene/trait/fire_resistance/on_new(obj/item/food/snacks/grown/G)
|
|
if(!(G.resistance_flags & FIRE_PROOF))
|
|
G.resistance_flags |= FIRE_PROOF
|
|
|
|
/// Parent type
|
|
/datum/plant_gene/trait/plant_type
|
|
name = "you shouldn't see this"
|
|
trait_id = "plant_type"
|
|
|
|
/datum/plant_gene/trait/plant_type/weed_hardy
|
|
name = "Weed Adaptation"
|
|
|
|
/datum/plant_gene/trait/plant_type/fungal_metabolism
|
|
name = "Fungal Vitality"
|
|
|
|
/datum/plant_gene/trait/plant_type/alien_properties
|
|
name ="?????"
|