Collapsed space vines, glowshrooms and biomass into one spreading-plant system.

This commit is contained in:
Zuhayr
2015-01-31 14:34:41 +10:30
parent 43802dceb7
commit 09e4be2b1b
25 changed files with 266 additions and 870 deletions

View File

@@ -4,8 +4,8 @@
#define GENE_ENVIRONMENT "environment"
#define GENE_RESISTANCE "resistance"
#define GENE_VIGOUR "vigour"
#define GENE_FLOWERS "flowers"
#define ALL_TRAITS list(GENE_PRODUCTS,GENE_CONSUMPTION,GENE_ENVIRONMENT,GENE_RESISTANCE,GENE_VIGOUR,GENE_FLOWERS)
#define GENE_PIGMENT "appearance"
#define ALL_GENES list(GENE_PRODUCTS,GENE_CONSUMPTION,GENE_ENVIRONMENT,GENE_RESISTANCE,GENE_VIGOUR,GENE_PIGMENT)
//Definitions for traits (individual descriptors)
#define TRAIT_PRODUCTS 1
@@ -46,7 +46,4 @@
#define TRAIT_PRODUCT_COLOUR 36
#define TRAIT_BIOLUM 37
#define TRAIT_BIOLUM_COLOUR 38
#define TRAIT_FLOWERS 39
#define TRAIT_FLOWER_ICON 40
#define TRAIT_FLOWER_COLOUR 41
#define TRAIT_IMMUTABLE 42
#define TRAIT_IMMUTABLE 39

View File

@@ -152,8 +152,6 @@
if(grown_seed.get_trait(TRAIT_BIOLUM))
dat += "<br>It is [grown_seed.get_trait(TRAIT_BIOLUM_COLOUR) ? "<font color='[grown_seed.get_trait(TRAIT_BIOLUM_COLOUR)]'>bio-luminescent</font>" : "bio-luminescent"]."
if(grown_seed.get_trait(TRAIT_FLOWERS))
dat += "<br>It has [grown_seed.get_trait(TRAIT_FLOWER_COLOUR) ? "<font color='[grown_seed.get_trait(TRAIT_FLOWER_COLOUR)]'>flowers</font>" : "flowers"]."
if(grown_seed.get_trait(TRAIT_PRODUCES_POWER))
dat += "<br>The fruit will function as a battery if prepared appropriately."
@@ -366,8 +364,8 @@
/obj/item/weapon/scythe/afterattack(atom/A, mob/user as mob, proximity)
if(!proximity) return
if(istype(A, /obj/effect/plantsegment))
for(var/obj/effect/plantsegment/B in orange(A,1))
if(istype(A, /obj/effect/plant))
for(var/obj/effect/plant/B in orange(A,1))
if(prob(80))
del B
B.die_off(1)
del A

View File

@@ -139,6 +139,9 @@
nymph.visible_message("<font color='blue'><b>[nymph]</b> rolls around in [src] for a bit.</font>","<font color='blue'>You roll around in [src] for a bit.</font>")
return
/obj/machinery/portable_atmospherics/hydroponics/proc/can_label()
return 1
/obj/machinery/portable_atmospherics/hydroponics/New()
..()
temp_chem_holder = new()
@@ -629,20 +632,12 @@
return
user << "You plant the [S.seed.seed_name] [S.seed.seed_noun]."
if(S.seed.get_trait(TRAIT_SPREAD) == 2)
msg_admin_attack("[key_name(user)] has planted a spreading vine packet.")
var/obj/effect/plant_controller/PC = new(get_turf(src))
if(PC)
PC.seed = S.seed
else
seed = S.seed //Grab the seed datum.
dead = 0
age = 1
//Snowflakey, maybe move this to the seed datum
health = (istype(S, /obj/item/seeds/cutting) ? round(seed.get_trait(TRAIT_ENDURANCE)/rand(2,5)) : seed.get_trait(TRAIT_ENDURANCE))
lastcycle = world.time
seed = S.seed //Grab the seed datum.
dead = 0
age = 1
//Snowflakey, maybe move this to the seed datum
health = (istype(S, /obj/item/seeds/cutting) ? round(seed.get_trait(TRAIT_ENDURANCE)/rand(2,5)) : seed.get_trait(TRAIT_ENDURANCE))
lastcycle = world.time
del(O)
@@ -798,10 +793,7 @@
mechanical = 0
/obj/machinery/portable_atmospherics/hydroponics/soil/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/weapon/shovel))
user << "You clear up [src]!"
del(src)
else if(istype(O,/obj/item/weapon/shovel) || istype(O,/obj/item/weapon/tank))
if(istype(O,/obj/item/weapon/tank))
return
else
..()
@@ -810,6 +802,9 @@
..()
verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/close_lid
/obj/machinery/portable_atmospherics/hydroponics/soil/can_label()
return 0
/obj/machinery/portable_atmospherics/hydroponics/soil/CanPass()
return 1
@@ -840,10 +835,21 @@
if(!seed)
del(src)
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/die()
del(src)
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/process()
if(!seed)
del(src)
return
else if(name=="plant")
name = seed.display_name
..()
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/Del()
// Check if we're masking a decal that needs to be visible again.
for(var/obj/effect/plant/plant in get_turf(src))
if(plant.invisibility == INVISIBILITY_MAXIMUM)
plant.invisibility = initial(plant.invisibility)
plant.die_off()
..()

View File

@@ -2,6 +2,27 @@
var/global/list/plant_sprites = list() // List of all harvested product sprites.
var/global/list/plant_product_sprites = list() // List of all growth sprites plus number of growth stages.
// Proc for creating a random seed type.
/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = seed_types.len + 1
seed.name = "[seed.uid]"
seed_types[seed.name] = seed
if(survive_on_station)
if(seed.consume_gasses)
seed.consume_gasses["phoron"] = null
seed.consume_gasses["carbon_dioxide"] = null
seed.set_trait(TRAIT_IDEAL_HEAT,293)
seed.set_trait(TRAIT_HEAT_TOLERANCE,20)
seed.set_trait(TRAIT_IDEAL_LIGHT,8)
seed.set_trait(TRAIT_LIGHT_TOLERANCE,5)
seed.set_trait(TRAIT_LOWKPA_TOLERANCE,25)
seed.set_trait(TRAIT_HIGHKPA_TOLERANCE,200)
return seed
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
@@ -58,7 +79,7 @@ proc/populate_seed_list()
//Might as well mask the gene types while we're at it.
var/list/used_masks = list()
var/list/plant_traits = ALL_TRAITS
var/list/plant_traits = ALL_GENES
while(plant_traits && plant_traits.len)
var/gene_tag = pick(plant_traits)
var/gene_mask = "[num2hex(rand(0,255))]"
@@ -94,6 +115,48 @@ proc/populate_seed_list()
var/list/exude_gasses // The plant will exude these gasses during its life.
var/splat_type = /obj/effect/decal/cleanable/fruit_smudge // Graffiti decal.
/datum/seed/New()
set_trait(TRAIT_IMMUTABLE, 0) // If set, plant will never mutate. If -1, plant is highly mutable.
set_trait(TRAIT_HARVEST_REPEAT, 0) // If 1, this plant will fruit repeatedly.
set_trait(TRAIT_PRODUCES_POWER, 0) // Can be used to make a battery.
set_trait(TRAIT_JUICY, 0) // When thrown, causes a splatter decal.
set_trait(TRAIT_EXPLOSIVE, 0) // When thrown, acts as a grenade.
set_trait(TRAIT_CARNIVOROUS, 0) // 0 = none, 1 = eat pests in tray, 2 = eat living things (when a vine).
set_trait(TRAIT_PARASITE, 0) // 0 = no, 1 = gain health from weed level.
set_trait(TRAIT_STINGS, 0) // Can cause damage/inject reagents when thrown or handled.
set_trait(TRAIT_YIELD, 0) // Amount of product.
set_trait(TRAIT_SPREAD, 0) // 0 limits plant to tray, 1 = creepers, 2 = vines.
set_trait(TRAIT_MATURATION, 0) // Time taken before the plant is mature.
set_trait(TRAIT_PRODUCTION, 0) // Time before harvesting can be undertaken again.
set_trait(TRAIT_TELEPORTING, 0) // Uses the bluespace tomato effect.
set_trait(TRAIT_BIOLUM, 0) // Plant is bioluminescent.
set_trait(TRAIT_ALTER_TEMP, 0) // If set, the plant will periodically alter local temp by this amount.
set_trait(TRAIT_PRODUCT_ICON, 0) // Icon to use for fruit coming from this plant.
set_trait(TRAIT_PLANT_ICON, 0) // Icon to use for the plant growing in the tray.
set_trait(TRAIT_PRODUCT_COLOUR, 0) // Colour to apply to product icon.
set_trait(TRAIT_BIOLUM_COLOUR, 0) // The colour of the plant's radiance.
set_trait(TRAIT_POTENCY, 1) // General purpose plant strength value.
set_trait(TRAIT_REQUIRES_NUTRIENTS, 1) // The plant can starve.
set_trait(TRAIT_REQUIRES_WATER, 1) // The plant can become dehydrated.
set_trait(TRAIT_WATER_CONSUMPTION, 3) // Plant drinks this much per tick.
set_trait(TRAIT_LIGHT_TOLERANCE, 5) // Departure from ideal that is survivable.
set_trait(TRAIT_TOXINS_TOLERANCE, 5) // Resistance to poison.
set_trait(TRAIT_PEST_TOLERANCE, 5) // Threshold for pests to impact health.
set_trait(TRAIT_WEED_TOLERANCE, 5) // Threshold for weeds to impact health.
set_trait(TRAIT_IDEAL_LIGHT, 8) // Preferred light level in luminosity.
set_trait(TRAIT_HEAT_TOLERANCE, 20) // Departure from ideal that is survivable.
set_trait(TRAIT_LOWKPA_TOLERANCE, 25) // Low pressure capacity.
set_trait(TRAIT_ENDURANCE, 100) // Maximum plant HP when growing.
set_trait(TRAIT_HIGHKPA_TOLERANCE, 200) // High pressure capacity.
set_trait(TRAIT_IDEAL_HEAT, 293) // Preferred temperature in Kelvin.
set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.25) // Plant eats this much per tick.
set_trait(TRAIT_PLANT_COLOUR, "#6EF86A") // Colour of the plant icon.
spawn(5)
sleep(-1)
update_growth_stages()
/datum/seed/proc/get_trait(var/trait)
return traits["[trait]"]
@@ -198,43 +261,14 @@ proc/populate_seed_list()
continue
// Check for windows.
var/no_los
var/turf/last_turf = origin_turf
for(var/turf/target_turf in getline(origin_turf,neighbor))
if(target_turf.density)
if(!last_turf.Enter(target_turf) || target_turf.density)
no_los = 1
break
if(!no_los)
var/los_dir = get_dir(neighbor,origin_turf)
var/list/blocked = list()
for(var/obj/machinery/door/D in neighbor.contents)
if(istype(D,/obj/machinery/door/window))
blocked |= D.dir
else
if(D.density)
no_los = 1
break
for(var/obj/structure/window/W in neighbor.contents)
if(W.is_fulltile())
no_los = 1
break
blocked |= W.dir
if(!no_los)
switch(los_dir)
if(NORTHEAST)
if((NORTH in blocked) && (EAST in blocked))
no_los = 1
if(SOUTHEAST)
if((SOUTH in blocked) && (EAST in blocked))
no_los = 1
if(NORTHWEST)
if((NORTH in blocked) && (WEST in blocked))
no_los = 1
if(SOUTHWEST)
if((SOUTH in blocked) && (WEST in blocked))
no_los = 1
else
if(los_dir in blocked)
no_los = 1
last_turf = target_turf
if(!no_los && !origin_turf.Enter(neighbor))
no_los = 1
if(no_los)
closed_turfs |= neighbor
continue
@@ -348,8 +382,8 @@ proc/populate_seed_list()
set_trait(TRAIT_POTENCY,rand(5,30),200,0)
set_trait(TRAIT_PRODUCT_ICON,pick(plant_product_sprites))
set_trait(TRAIT_PLANT_ICON,pick(plant_sprites))
set_trait(TRAIT_PLANT_COLOUR,"#[pick(rainbow)]")
set_trait(TRAIT_PRODUCT_COLOUR,"#[pick(rainbow)]")
set_trait(TRAIT_PLANT_COLOUR,"#[get_random_colour(0,75,190)]")
set_trait(TRAIT_PRODUCT_COLOUR,"#[get_random_colour(0,75,190)]")
update_growth_stages()
if(prob(20))
@@ -478,7 +512,7 @@ proc/populate_seed_list()
if(prob(5))
set_trait(TRAIT_BIOLUM,1)
set_trait(TRAIT_BIOLUM_COLOUR,"#[pick(rainbow)]")
set_trait(TRAIT_BIOLUM_COLOUR,"#[get_random_colour(0,75,190)]")
set_trait(TRAIT_ENDURANCE,rand(60,100))
set_trait(TRAIT_YIELD,rand(3,15))
@@ -500,7 +534,7 @@ proc/populate_seed_list()
//This looks like shit, but it's a lot easier to read/change this way.
var/total_mutations = rand(1,1+degree)
for(var/i = 0;i<total_mutations;i++)
switch(rand(0,12))
switch(rand(0,11))
if(0) //Plant cancer!
set_trait(TRAIT_ENDURANCE,get_trait(TRAIT_ENDURANCE)-rand(10,20),null,0)
source_turf.visible_message("<span class='danger'>\The [display_name] withers rapidly!</span>")
@@ -550,21 +584,11 @@ proc/populate_seed_list()
if(get_trait(TRAIT_BIOLUM))
source_turf.visible_message("<span class='notice'>\The [display_name] begins to glow!</span>")
if(prob(degree*2))
set_trait(TRAIT_BIOLUM_COLOUR,"#[pick(rainbow)]")
set_trait(TRAIT_BIOLUM_COLOUR,"#[get_random_colour(0,75,190)]")
source_turf.visible_message("<span class='notice'>\The [display_name]'s glow </span><font color='[get_trait(TRAIT_BIOLUM_COLOUR)]'>changes colour</font>!")
else
source_turf.visible_message("<span class='notice'>\The [display_name]'s glow dims...</span>")
if(11)
if(prob(degree*2))
set_trait(TRAIT_FLOWERS,!get_trait(TRAIT_FLOWERS))
if(get_trait(TRAIT_FLOWERS))
source_turf.visible_message("<span class='notice'>\The [display_name] sprouts a bevy of flowers!</span>")
if(prob(degree*2))
set_trait(TRAIT_FLOWER_COLOUR,"#[pick(rainbow)]")
source_turf.visible_message("<span class='notice'>\The [display_name]'s flowers </span><font=[get_trait(TRAIT_FLOWER_COLOUR)]>changes colour</font>!")
else
source_turf.visible_message("<span class='notice'>\The [display_name]'s flowers wither and fall off.</span>")
if(12)
set_trait(TRAIT_TELEPORTING,1)
return
@@ -640,8 +664,8 @@ proc/populate_seed_list()
traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE)
if(GENE_VIGOUR)
traits_to_copy = list(TRAIT_ENDURANCE,TRAIT_YIELD,TRAIT_SPREAD,TRAIT_MATURATION,TRAIT_PRODUCTION,TRAIT_TELEPORTING)
if(GENE_FLOWERS)
traits_to_copy = list(TRAIT_PLANT_COLOUR,TRAIT_PRODUCT_COLOUR,TRAIT_BIOLUM,TRAIT_BIOLUM_COLOUR,TRAIT_FLOWERS,TRAIT_FLOWER_ICON,TRAIT_FLOWER_COLOUR)
if(GENE_PIGMENT)
traits_to_copy = list(TRAIT_PLANT_COLOUR,TRAIT_PRODUCT_COLOUR,TRAIT_BIOLUM,TRAIT_BIOLUM_COLOUR)
for(var/trait in traits_to_copy)
P.values["[trait]"] = get_trait(trait)
@@ -748,52 +772,6 @@ proc/populate_seed_list()
else
growth_stages = 0
/datum/seed/New()
set_trait(TRAIT_IMMUTABLE, 0) // If set, plant will never mutate. If -1, plant is highly mutable.
set_trait(TRAIT_HARVEST_REPEAT, 0) // If 1, this plant will fruit repeatedly.
set_trait(TRAIT_PRODUCES_POWER, 0) // Can be used to make a battery.
set_trait(TRAIT_JUICY, 0) // When thrown, causes a splatter decal.
set_trait(TRAIT_EXPLOSIVE, 0) // When thrown, acts as a grenade.
set_trait(TRAIT_CARNIVOROUS, 0) // 0 = none, 1 = eat pests in tray, 2 = eat living things (when a vine).
set_trait(TRAIT_PARASITE, 0) // 0 = no, 1 = gain health from weed level.
set_trait(TRAIT_STINGS, 0) // Can cause damage/inject reagents when thrown or handled.
set_trait(TRAIT_YIELD, 0) // Amount of product.
set_trait(TRAIT_SPREAD, 0) // 0 limits plant to tray, 1 = creepers, 2 = vines.
set_trait(TRAIT_MATURATION, 0) // Time taken before the plant is mature.
set_trait(TRAIT_PRODUCTION, 0) // Time before harvesting can be undertaken again.
set_trait(TRAIT_TELEPORTING, 0) // Uses the bluespace tomato effect.
set_trait(TRAIT_BIOLUM, 0) // Plant is bioluminescent.
set_trait(TRAIT_FLOWERS, 0) // Plant has a flower overlay.
set_trait(TRAIT_ALTER_TEMP, 0) // If set, the plant will periodically alter local temp by this amount.
set_trait(TRAIT_PRODUCT_ICON, 0) // Icon to use for fruit coming from this plant.
set_trait(TRAIT_PLANT_ICON, 0) // Icon to use for the plant growing in the tray.
set_trait(TRAIT_PRODUCT_COLOUR, 0) // Colour to apply to product icon.
set_trait(TRAIT_BIOLUM_COLOUR, 0) // The colour of the plant's radiance.
set_trait(TRAIT_FLOWER_COLOUR, 0) // Which colour to use.
set_trait(TRAIT_POTENCY, 1) // General purpose plant strength value.
set_trait(TRAIT_REQUIRES_NUTRIENTS, 1) // The plant can starve.
set_trait(TRAIT_REQUIRES_WATER, 1) // The plant can become dehydrated.
set_trait(TRAIT_WATER_CONSUMPTION, 3) // Plant drinks this much per tick.
set_trait(TRAIT_LIGHT_TOLERANCE, 5) // Departure from ideal that is survivable.
set_trait(TRAIT_TOXINS_TOLERANCE, 5) // Resistance to poison.
set_trait(TRAIT_PEST_TOLERANCE, 5) // Threshold for pests to impact health.
set_trait(TRAIT_WEED_TOLERANCE, 5) // Threshold for weeds to impact health.
set_trait(TRAIT_IDEAL_LIGHT, 8) // Preferred light level in luminosity.
set_trait(TRAIT_HEAT_TOLERANCE, 20) // Departure from ideal that is survivable.
set_trait(TRAIT_LOWKPA_TOLERANCE, 25) // Low pressure capacity.
set_trait(TRAIT_ENDURANCE, 100) // Maximum plant HP when growing.
set_trait(TRAIT_HIGHKPA_TOLERANCE, 200) // High pressure capacity.
set_trait(TRAIT_IDEAL_HEAT, 293) // Preferred temperature in Kelvin.
set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.25) // Plant eats this much per tick.
set_trait(TRAIT_PLANT_COLOUR, "#6EF86A") // Colour of the plant icon.
set_trait(TRAIT_FLOWER_ICON, "vine_fruit") // Which overlay to use.
spawn(5)
sleep(-1)
update_growth_stages()
// Actual roundstart seed types after this point.
// Chili plants/variants.
/datum/seed/chili

View File

@@ -74,13 +74,8 @@ var/global/list/plant_seed_sprites = list()
seed_type = null
/obj/item/seeds/random/New()
seed = new()
seed.randomize()
seed.uid = seed_types.len + 1
seed.name = "[seed.uid]"
seed_types[seed.name] = seed
seed = create_random_seed()
seed_type = seed.name
update_seed()
/obj/item/seeds/replicapod

View File

@@ -1,4 +1,34 @@
#define DEFAULT_SEED "glowshroom"
#define VINE_GROWTH_STAGES 4
/proc/spacevine_infestation()
spawn() //to stop the secrets panel hanging
var/list/turf/simulated/floor/turfs = list() //list of all the empty floor turfs in the hallway areas
for(var/areapath in typesof(/area/hallway))
var/area/A = locate(areapath)
for(var/area/B in A.related)
for(var/turf/simulated/floor/F in B.contents)
if(!F.contents.len)
turfs += F
if(turfs.len) //Pick a turf to spawn at if we can
var/turf/simulated/floor/T = pick(turfs)
var/datum/seed/seed = create_random_seed(1)
seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines.
seed.set_trait(TRAIT_POTENCY,rand(40,50)) // Guarantee a wide spread and powerful effects.
new /obj/effect/plant(T,seed)
message_admins("<span class='notice'>Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])</span>")
/obj/effect/dead_plant
anchored = 1
opacity = 0
density = 0
/obj/effect/dead_plant/attackby()
..()
for(var/obj/effect/plant/neighbor in view(1,src))
neighbor.hibernating = 0
del(src)
/obj/effect/plant
name = "plant"
@@ -7,16 +37,21 @@
density = 0
icon = 'icons/obj/hydroponics_growing.dmi'
icon_state = "bush4-1"
layer = 2.1
layer = 2
var/health = 100
var/health = 10
var/max_health = 100
var/growth_threshold = 0
var/growth_type = 0
var/max_growth = 0
var/list/children = list()
var/obj/effect/plant/parent
var/datum/seed/seed
var/floor = 0
var/spread_chance = 100 //40
var/spread_into_adjacent = 100 //60
var/spread_chance = 40
var/spread_distance = 3
var/spread_into_adjacent = 60
var/evolve_chance = 2
var/last_tick = 0
var/hibernating = 0
@@ -33,9 +68,31 @@
del(src)
return
layer = rand(3,4) // Will display over pipes/machines at all times and mobs half the time.
name = seed.display_name
max_health = round(seed.get_trait(TRAIT_ENDURANCE)/2)
health = max_health
if(seed.get_trait(TRAIT_SPREAD)==2)
max_growth = VINE_GROWTH_STAGES
growth_threshold = round(max_health/VINE_GROWTH_STAGES)
icon = 'icons/obj/hydroponics_vines.dmi'
growth_type = 2 // Vines by default.
if(seed.get_trait(TRAIT_CARNIVOROUS) == 2)
growth_type = 1 // WOOOORMS.
else if(!(seed.seed_noun in list("seeds","pits")))
if(seed.seed_noun == "nodes")
growth_type = 3 // Biomass
else
growth_type = 4 // Mold
else
max_growth = seed.growth_stages
growth_threshold = round(max_health/seed.growth_stages)
if(max_growth > 2 && prob(50))
max_growth-- //Ensure some variation in final sprite, makes the carpet of crap look less wonky.
spread_into_adjacent = round(seed.get_trait(TRAIT_POTENCY)/2)
spread_distance = ((growth_type>0) ? round(spread_into_adjacent/2) : round(spread_into_adjacent/15))
spread_chance = round(spread_into_adjacent/2)
set_dir(calc_dir())
update_icon()
@@ -44,14 +101,11 @@
/obj/effect/plant/update_icon()
// TODO: convert this to an icon cache.
icon_state = "[seed.get_trait(TRAIT_PLANT_ICON)]-[rand(1,max(1,seed.growth_stages-1))]"
color = seed.get_trait(TRAIT_PLANT_COLOUR)
if(!floor)
// This should make the plant grow flush against the wall it's meant to be growing from.
pixel_y = -(rand(8,12))
refresh_icon()
if(growth_type == 0 && !floor)
src.transform = null
var/matrix/M = matrix()
M.Translate(0,-(rand(12,14))) // should make the plant flush against the wall it's meant to be growing from.
switch(dir)
if(WEST)
M.Turn(90)
@@ -60,10 +114,12 @@
if(EAST)
M.Turn(270)
src.transform = M
var/icon_colour = seed.get_trait(TRAIT_PLANT_COLOUR)
if(icon_colour)
color = icon_colour
// Apply colour and light from seed datum.
if(seed.get_trait(TRAIT_BIOLUM))
SetLuminosity(1+round(seed.get_trait(TRAIT_POTENCY)/10))
SetLuminosity(1+round(seed.get_trait(TRAIT_POTENCY)/20))
if(seed.get_trait(TRAIT_BIOLUM_COLOUR))
l_color = seed.get_trait(TRAIT_BIOLUM_COLOUR)
else
@@ -72,26 +128,54 @@
else
SetLuminosity(0)
/obj/effect/plant/proc/refresh_icon()
var/growth = min(max_growth,max(1,round(health/growth_threshold)))
if(growth_type > 0)
switch(growth_type)
if(1)
icon_state = "worms"
if(2)
icon_state = "vines-[growth]"
if(3)
icon_state = "mass-[growth]"
if(4)
icon_state = "mold-[growth]"
else
icon_state = "[seed.get_trait(TRAIT_PLANT_ICON)]-[growth]"
/obj/effect/plant/Del()
processing_objects -= src
..()
/obj/effect/plant/examine()
..()
usr << "Max dist from parent is [round(seed.get_trait(TRAIT_POTENCY)/15)]."
usr << "Current dist is [get_dist(get_root(),src)]."
/obj/effect/plant/proc/die_off()
/obj/effect/plant/proc/die_off(var/no_remains)
// Remove ourselves from our parent.
if(parent && parent.children)
parent.children -= src
// Kill off any of our children (and add an added bonus, other plants in this area)
for(var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/plant in get_turf(src))
plant.dead = 1
plant.update_icon()
// Cause the plants around us to update.
if(children && children.len)
for(var/obj/effect/plant/child in children)
child.die_off()
for(var/obj/effect/plant/neighbor in view(1,src))
neighbor.hibernating = 0
if(!no_remains && !(locate(/obj/effect/dead_plant) in get_turf(src)))
var/obj/effect/dead_plant/plant_remains = new(get_turf(src))
plant_remains.icon = src.icon
plant_remains.icon_state = src.icon_state
del(src)
/obj/effect/plant/proc/get_dist_to_parent(var/current_count)
if(!parent)
return current_count
current_count++
return parent.get_dist_to_parent(current_count)
/obj/effect/plant/process()
// Something is very wrong, kill ourselves.
if(!seed)
die_off()
@@ -99,27 +183,35 @@
var/turf/simulated/T = get_turf(src)
if(istype(T))
health -= seed.handle_environment(T, T.return_air(),1)
if(health < max_health)
health += rand(3,5)
if(health > max_health)
health = max_health
refresh_icon()
// Hibernating or too far from parent, no chance of spreading.
if(hibernating || (parent && (get_dist(get_root(),src) > round(seed.get_trait(TRAIT_POTENCY)/15))))
// Damaged, young hibernating or too far from parent, no chance of spreading.
if(health < (max_health/2) || hibernating || (parent && (get_dist_to_parent(0) > spread_distance)))
return
// Count our neighbors and possible locations for spreading.
var/list/possible_locs = list()
var/count = 0
for(var/turf/simulated/floor/floor in view(1,src))
if(!floor.Adjacent(src) || floor.density || (locate(/obj/effect/plant) in floor.contents))
if((locate(/obj/effect/dead_plant) in floor.contents) || !floor.Enter(src) || floor.density)
continue
if(locate(/obj/effect/plant) in floor.contents)
count++
continue
possible_locs |= floor
//Entirely surrounded, spawn an actual plant.
if(count>=8)
hibernating = 1 // Suspend processing for now.
//Entirely surrounded, try to spawn an actual plant.
if(count>=8 && prob(5))
if(!(locate(/obj/machinery/portable_atmospherics/hydroponics/soil/invisible) in T.contents))
var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/new_plant = new(T,seed)
new_plant.age = seed.get_trait(TRAIT_MATURATION)
new_plant.age = seed.get_trait(TRAIT_MATURATION)-5
new_plant.update_icon()
if(growth_type==0) //Vines do not become invisible.
invisibility = INVISIBILITY_MAXIMUM
if(prob(spread_chance))
for(var/i=1,i<=seed.get_trait(TRAIT_YIELD),i++)
@@ -130,6 +222,14 @@
possible_locs -= target_turf
var/obj/effect/plant/child = new(target_turf, seed)
child.parent = get_root()
child.parent.children |= child
/*
var/need_hibernate = 0
if(need_hibernate)
hibernating = 1
world << "[src] at [x],[y] is hibernating"
*/
/obj/effect/plant/proc/get_root()
if(parent)
@@ -188,19 +288,19 @@
/obj/effect/plant/ex_act(severity)
switch(severity)
if(1.0)
del(src)
die_off()
return
if(2.0)
if (prob(50))
del(src)
die_off()
return
if(3.0)
if (prob(5))
del(src)
die_off()
return
else
return
/obj/effect/plant/proc/check_health()
if(health <= 0)
del(src)
die_off()

View File

@@ -1,355 +0,0 @@
// SPACE VINES (Note that this code is very similar to Biomass code)
/obj/effect/plantsegment
name = "space vines"
desc = "An extremely expansionistic species of vine."
icon = 'icons/effects/spacevines.dmi'
icon_state = "Light1"
anchored = 1
density = 0
layer = 5
pass_flags = PASSTABLE | PASSGRILLE
// Vars used by vines with seed data.
var/age = 0
var/lastproduce = 0
var/harvest = 0
var/list/chems
var/plant_damage_noun = "Thorns"
var/limited_growth = 0
// Life vars/
var/energy = 0
var/obj/effect/plant_controller/master = null
var/mob/living/buckled_mob
var/datum/seed/seed
/obj/effect/plantsegment/New()
return
/obj/effect/plantsegment/Del()
if(master)
master.vines -= src
master.growth_queue -= src
..()
/obj/effect/plantsegment/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (!W || !user || !W.type) return
switch(W.type)
if(/obj/item/weapon/circular_saw) del src
if(/obj/item/weapon/kitchen/utensil/knife) del src
if(/obj/item/weapon/scalpel) del src
if(/obj/item/weapon/twohanded/fireaxe) del src
if(/obj/item/weapon/hatchet) del src
if(/obj/item/weapon/melee/energy) del src
if(/obj/item/weapon/pickaxe/plasmacutter) del src
// Less effective weapons
if(/obj/item/weapon/wirecutters)
if(prob(25)) del src
if(/obj/item/weapon/shard)
if(prob(25)) del src
// Weapons with subtypes
else
if(istype(W, /obj/item/weapon/melee/energy/sword)) del src
else if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0, user)) del src
else
manual_unbuckle(user)
return
// Plant-b-gone damage is handled in its entry in chemistry-reagents.dm
..()
/obj/effect/plantsegment/attack_hand(mob/user as mob)
if(user.a_intent == "help" && seed && harvest)
seed.harvest(user,1)
harvest = 0
lastproduce = age
update()
return
manual_unbuckle(user)
/obj/effect/plantsegment/proc/unbuckle()
if(buckled_mob)
if(buckled_mob.buckled == src) //this is probably unneccesary, but it doesn't hurt
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
buckled_mob = null
return
/obj/effect/plantsegment/proc/manual_unbuckle(mob/user as mob)
if(buckled_mob)
if(prob(seed ? min(max(0,100 - seed.get_trait(TRAIT_POTENCY)),100) : 50))
if(buckled_mob.buckled == src)
if(buckled_mob != user)
buckled_mob.visible_message(\
"<span class='notice'>[user.name] frees [buckled_mob.name] from [src].</span>",\
"<span class='notice'>[user.name] frees you from [src].</span>",\
"<span class='warning'>You hear shredding and ripping.</span>")
else
buckled_mob.visible_message(\
"<span class='notice'>[buckled_mob.name] struggles free of [src].</span>",\
"<span class='notice'>You untangle [src] from around yourself.</span>",\
"<span class='warning'>You hear shredding and ripping.</span>")
unbuckle()
else
var/text = pick("rips","tears","pulls")
user.visible_message(\
"<span class='notice'>[user.name] [text] at [src].</span>",\
"<span class='notice'>You [text] at [src].</span>",\
"<span class='warning'>You hear shredding and ripping.</span>")
return
/obj/effect/plantsegment/proc/grow()
if(!energy)
src.icon_state = pick("Med1", "Med2", "Med3")
energy = 1
//Low-lying creepers do not block vision or grow thickly.
if(limited_growth)
energy = 2
return
src.opacity = 1
layer = 5
else if(!limited_growth)
src.icon_state = pick("Hvy1", "Hvy2", "Hvy3")
energy = 2
/obj/effect/plantsegment/proc/entangle_mob()
if(limited_growth)
return
if(prob(seed ? seed.get_trait(TRAIT_POTENCY) : 25))
if(!buckled_mob)
var/mob/living/carbon/V = locate() in src.loc
if(V && (V.stat != DEAD) && (V.buckled != src)) // If mob exists and is not dead or captured.
V.buckled = src
V.loc = src.loc
V.update_canmove()
src.buckled_mob = V
V << "<span class='danger'>The vines [pick("wind", "tangle", "tighten")] around you!</span>"
// FEED ME, SEYMOUR.
if(buckled_mob && seed && (buckled_mob.stat != DEAD)) //Don't bother with a dead mob.
seed.do_thorns(buckled_mob,src)
seed.do_sting(buckled_mob,src)
/obj/effect/plantsegment/proc/update()
if(!seed) return
// Update bioluminescence.
if(seed.get_trait(TRAIT_BIOLUM))
SetLuminosity(1+round(seed.get_trait(TRAIT_POTENCY)/10))
if(seed.get_trait(TRAIT_BIOLUM_COLOUR))
l_color = seed.get_trait(TRAIT_BIOLUM_COLOUR)
else
l_color = null
return
else
SetLuminosity(0)
// Update flower/product overlay.
overlays.Cut()
if(age >= seed.get_trait(TRAIT_MATURATION))
if(prob(20) && seed.products && seed.products.len && !harvest && ((age-lastproduce) > seed.get_trait(TRAIT_PRODUCTION)))
harvest = 1
lastproduce = age
if(harvest)
var/image/fruit_overlay = image('icons/obj/hydroponics_vines.dmi',"")
if(seed.get_trait(TRAIT_PRODUCT_COLOUR))
fruit_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
overlays += fruit_overlay
if(seed.get_trait(TRAIT_FLOWERS))
var/image/flower_overlay = image('icons/obj/hydroponics_vines.dmi',"[seed.get_trait(TRAIT_FLOWER_ICON)]")
if(seed.get_trait(TRAIT_FLOWER_COLOUR))
flower_overlay.color = seed.get_trait(TRAIT_FLOWER_COLOUR)
overlays += flower_overlay
/obj/effect/plantsegment/proc/spread()
var/direction = pick(cardinal)
var/step = get_step(src,direction)
if(istype(step,/turf/simulated/floor))
var/turf/simulated/floor/F = step
if(!locate(/obj/effect/plantsegment,F))
if(F.Enter(src))
if(master)
master.spawn_piece( F )
// Explosion damage.
/obj/effect/plantsegment/ex_act(severity)
switch(severity)
if(1.0)
die()
return
if(2.0)
if (prob(90))
die()
return
if(3.0)
if (prob(50))
die()
return
return
// Hotspots kill vines.
/obj/effect/plantsegment/fire_act(null, temp, volume)
del src
/obj/effect/plantsegment/proc/die()
if(seed && harvest && rand(5))
seed.harvest(src,1)
del(src)
/obj/effect/plantsegment/proc/life()
if(!seed)
return
if(prob(30))
age++
var/turf/T = loc
var/datum/gas_mixture/environment
if(T) environment = T.return_air()
if(!environment)
return
var/pressure = environment.return_pressure()
if(pressure < seed.get_trait(TRAIT_LOWKPA_TOLERANCE) || pressure > seed.get_trait(TRAIT_HIGHKPA_TOLERANCE))
die()
return
if(abs(environment.temperature - seed.get_trait(TRAIT_IDEAL_HEAT)) > seed.get_trait(TRAIT_HEAT_TOLERANCE))
die()
return
var/area/A = T.loc
if(A)
var/light_available
if(A.lighting_use_dynamic)
light_available = max(0,min(10,T.lighting_lumcount)-5)
else
light_available = 5
if(abs(light_available - seed.get_trait(TRAIT_IDEAL_LIGHT)) > seed.get_trait(TRAIT_LIGHT_TOLERANCE))
die()
return
/obj/effect/plant_controller
//What this does is that instead of having the grow minimum of 1, required to start growing, the minimum will be 0,
//meaning if you get the spacevines' size to something less than 20 plots, it won't grow anymore.
var/list/obj/effect/plantsegment/vines = list()
var/list/growth_queue = list()
var/reached_collapse_size
var/reached_slowdown_size
var/datum/seed/seed
var/collapse_limit = 250
var/slowdown_limit = 30
var/limited_growth = 0
/obj/effect/plant_controller/creeper
collapse_limit = 6
slowdown_limit = 3
limited_growth = 1
/obj/effect/plant_controller/New()
if(!istype(src.loc,/turf/simulated/floor))
del(src)
spawn(0)
spawn_piece(src.loc)
processing_objects.Add(src)
/obj/effect/plant_controller/Del()
processing_objects.Remove(src)
..()
/obj/effect/plant_controller/proc/spawn_piece(var/turf/location)
var/obj/effect/plantsegment/SV = new(location)
SV.limited_growth = src.limited_growth
growth_queue += SV
vines += SV
SV.master = src
if(seed)
SV.seed = seed
SV.name = "[seed.seed_name] vines"
SV.update()
/obj/effect/plant_controller/process()
// Space vines exterminated. Remove the controller
if(!vines)
del(src)
return
// Sanity check.
if(!growth_queue)
del(src)
return
// Check if we're too big for our own good.
if(vines.len >= (seed?seed.get_trait(TRAIT_POTENCY)*collapse_limit : 250)&&!reached_collapse_size)
reached_collapse_size = 1
if(vines.len >= (seed?seed.get_trait(TRAIT_POTENCY)*slowdown_limit : 30)&&!reached_slowdown_size)
reached_slowdown_size = 1
var/length = 0
if(reached_collapse_size)
length = 0
else if(reached_slowdown_size)
if(prob(seed ? seed.get_trait(TRAIT_POTENCY) : 25))
length = 1
else
length = 0
else
length = 1
length = min(30, max(length, vines.len/5))
// Update as many pieces of vine as we're allowed to.
// Append updated vines to the end of the growth queue.
var/i = 0
var/list/obj/effect/plantsegment/queue_end = list()
for(var/obj/effect/plantsegment/SV in growth_queue)
i++
queue_end += SV
growth_queue -= SV
SV.life()
if(!SV) continue
if(SV.energy < 2) //If tile isn't fully grown
var/chance
if(seed)
chance = limited_growth ? round(seed.get_trait(TRAIT_POTENCY)/2,1) : seed.get_trait(TRAIT_POTENCY)
else
chance = 20
if(prob(chance))
SV.grow()
else if(!seed || !limited_growth) //If tile is fully grown and not just a creeper.
SV.entangle_mob()
SV.update()
SV.spread()
if(i >= length)
break
growth_queue = growth_queue + queue_end