Merge branch 'master' of git@github.com:ParadiseSS13/Paradise.git

This commit is contained in:
IAmBigCoat
2015-05-11 01:34:45 -04:00
102 changed files with 6081 additions and 4772 deletions
+5
View File
@@ -57,6 +57,7 @@
/obj/effect/hotspot/New()
..()
air_master.hotspots += src
perform_exposure()
/obj/effect/hotspot/proc/perform_exposure()
var/turf/simulated/floor/location = loc
@@ -175,3 +176,7 @@
air_update_turf()
return
/obj/effect/hotspot/Crossed(mob/living/L)
..()
if(isliving(L))
L.fire_act()
+13 -1
View File
@@ -1670,4 +1670,16 @@ atom/proc/GetTypeInAllContents(typepath)
if(prob(chance))
step(AM, pick(alldirs))
chance = max(chance - (initial_chance / steps), 0)
steps--
steps--
/proc/get_random_colour(var/simple, var/lower, var/upper)
var/colour
if(simple)
colour = pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))
else
for(var/i=1;i<=3;i++)
var/temp_col = "[num2hex(rand(lower,upper))]"
if(length(temp_col )<2)
temp_col = "0[temp_col]"
colour += temp_col
return colour
+1 -1
View File
@@ -120,7 +120,7 @@ datum/controller/game_controller/proc/setup_objects()
//Set up roundstart seed list.
populate_seed_list()
//populate_seed_list()
world << "\red \b Initializations complete."
sleep(-1)
+47 -30
View File
@@ -34,11 +34,12 @@
* */
/datum/recipe
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal
var/time = 100 // 1/10 part of second
var/byproduct //example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
var/list/items // example: = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
var/list/fruit // example: = list("fruit" = 3)
var/result // example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal
var/time = 100 // 1/10 part of second
var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash
/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous
@@ -54,25 +55,44 @@
return -1
return .
/datum/recipe/proc/check_items(var/obj/container as obj) //1=precisely, 0=insufficiently, -1=superfluous
if (!items)
if (locate(/obj/) in container)
return -1
else
return 1
/datum/recipe/proc/check_fruit(var/obj/container)
. = 1
var/list/checklist = items.Copy()
for (var/obj/O in container)
var/found = 0
for (var/type in checklist)
if (istype(O,type))
checklist-=type
found = 1
break
if (!found)
if(fruit && fruit.len)
var/list/checklist = list()
// You should trust Copy().
checklist = fruit.Copy()
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in container)
if(!G.seed || !G.seed.kitchen_tag || isnull(checklist[G.seed.kitchen_tag]))
continue
checklist[G.seed.kitchen_tag]--
for(var/ktag in checklist)
if(!isnull(checklist[ktag]))
if(checklist[ktag] < 0)
. = 0
else if(checklist[ktag] > 0)
. = -1
break
return .
/datum/recipe/proc/check_items(var/obj/container as obj)
. = 1
if (items && items.len)
var/list/checklist = list()
checklist = items.Copy() // You should really trust Copy
for(var/obj/O in container)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
break
if (!found)
. = 0
if (checklist.len)
. = -1
if (checklist.len)
return 0
return .
//general version
@@ -101,22 +121,19 @@
exact = -1
var/list/datum/recipe/possible_recipes = new
for (var/datum/recipe/recipe in avaiable_recipes)
if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact)
if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact && recipe.check_fruit(obj)==exact)
possible_recipes+=recipe
if (possible_recipes.len==0)
return null
else if (possible_recipes.len==1)
return possible_recipes[1]
else //okay, let's select the most complicated recipe
var/r_count = 0
var/i_count = 0
var/highest_count = 0
. = possible_recipes[1]
for (var/datum/recipe/recipe in possible_recipes)
var/N_i = (recipe.items)?(recipe.items.len):0
var/N_r = (recipe.reagents)?(recipe.reagents.len):0
if (N_i > i_count || (N_i== i_count && N_r > r_count ))
r_count = N_r
i_count = N_i
var/count = ((recipe.items)?(recipe.items.len):0) + ((recipe.reagents)?(recipe.reagents.len):0) + ((recipe.fruit)?(recipe.fruit.len):0)
if (count >= highest_count)
highest_count = count
. = recipe
return .
+3 -1
View File
@@ -910,7 +910,9 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/seeds/amanitamycelium,
/obj/item/seeds/reishimycelium,
/obj/item/seeds/bananaseed,
/obj/item/seeds/eggyseed)
/obj/item/seeds/random,
/obj/item/seeds/random,
)
cost = 15
containername = "exotic seeds crate"
File diff suppressed because it is too large Load Diff
+4
View File
@@ -245,6 +245,10 @@ its easier to just keep the beam vertical.
/atom/proc/relaymove()
return
/atom/proc/set_dir(new_dir)
. = new_dir != dir
dir = new_dir
/atom/proc/ex_act()
return
+2
View File
@@ -282,3 +282,5 @@
/atom/movable/proc/canSingulothPull(var/obj/machinery/singularity/singulo)
return 1
/atom/movable/proc/water_act(var/volume, var/temperature, var/source) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins)
return 1
+1 -1
View File
@@ -18,7 +18,7 @@
if(resource_delay > world.time)
return 0
resource_delay = world.time + 120 // 12 seconds
resource_delay = world.time + 40 // 4 seconds
if(overmind)
overmind.add_points(1)
@@ -67,6 +67,14 @@
return 1
update_connected_network()
if(!connected_port)
return
var/datum/pipe_network/network = connected_port.return_network(src)
if (network)
network.update = 1
disconnect()
if(!connected_port)
return 0
+121 -13
View File
@@ -14,10 +14,104 @@
var/gib_throw_dir = WEST // Direction to spit meat and gibs in. Defaults to west.
var/gibtime = 40 // Time from starting until meat appears
var/list/victims = list()
use_power = 1
idle_power_usage = 2
active_power_usage = 500
//gibs anything that stands on it's input
/obj/machinery/gibber/autogibber
var/acceptdir = NORTH
var/lastacceptdir = NORTH
var/turf/lturf
/obj/machinery/gibber/autogibber/New()
..()
spawn(5)
var/turf/T = get_step(src, acceptdir)
if(istype(T))
lturf = T
/obj/machinery/gibber/autogibber/process()
if(!lturf || occupant || locked || dirty || operating)
return
if(acceptdir != lastacceptdir)
lturf = null
lastacceptdir = acceptdir
var/turf/T = get_step(src, acceptdir)
if(istype(T))
lturf = T
for(var/mob/living/carbon/human/H in lturf)
if(istype(H) && H.loc == lturf)
visible_message({"<span class='danger'>\The [src] states, "Food detected!"</span>"})
sleep(30)
if(H.loc == lturf) //still standing there
if(force_move_into_gibber(H))
ejectclothes(occupant)
cleanbay()
startgibbing(null, 1)
break
/obj/machinery/gibber/autogibber/proc/force_move_into_gibber(var/mob/living/carbon/human/victim)
if(!istype(victim)) return 0
visible_message("<span class='danger'>\The [victim.name] gets sucked into \the [src]!</span>")
if(victim.client)
victim.client.perspective = EYE_PERSPECTIVE
victim.client.eye = src
victim.loc = src
src.occupant = victim
update_icon()
feedinTopanim()
return 1
/obj/machinery/gibber/autogibber/proc/ejectclothes(var/mob/living/carbon/human/H)
if(!istype(H)) return 0
if(H != occupant) return 0 //only using H as a shortcut to typecast
for(var/obj/O in H)
if(istype(O,/obj/item/clothing)) //clothing gets skipped to avoid cleaning out shit
continue
if(istype(O,/obj/item/weapon/implant))
var/obj/item/weapon/implant/I = O
if(I.implanted)
continue
if(istype(O,/obj/item/organ))
continue
if(O.flags & NODROP)
qdel(O) //they are already dead by now
H.unEquip(O)
O.loc = src.loc
O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15)
sleep(1)
for(var/obj/item/clothing/C in H)
if(C.flags & NODROP)
qdel(C)
H.unEquip(C)
C.loc = src.loc
C.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15)
sleep(1)
visible_message("<span class='warning'>\The [src] spits out \the [H.name]'s possessions!")
/obj/machinery/gibber/autogibber/proc/cleanbay()
var/spats = 0 //keeps track of how many items get spit out. Don't show a message if none are found.
for(var/obj/O in src)
if(istype(O))
O.loc = src.loc
O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15)
spats++
sleep(1)
if(spats)
visible_message("<span class='warning'>\The [src] spits out more possessions!</span>")
/*
//auto-gibs anything that bumps into it
/obj/machinery/gibber/autogibber
var/turf/input_plate
@@ -46,7 +140,7 @@
if(M.loc == input_plate)
M.loc = src
M.gib()
*/
/obj/machinery/gibber/New()
..()
@@ -233,9 +327,18 @@
sleep(1)
overlays -= feedee
overlays -= gibberoverlay
src.layer = 3
/obj/machinery/gibber/proc/startgibbing(mob/user as mob)
/obj/machinery/gibber/proc/startgibbing(var/mob/user, var/UserOverride=0)
if(!istype(user) && !UserOverride)
log_debug("Some shit just went down with the gibber at X[x], Y[y], Z[z] with an invalid user. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
return
if(UserOverride)
msg_admin_attack("[occupant] ([occupant.ckey]) was gibbed by an autogibber (\the [src]) at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
if(src.operating)
return
@@ -266,20 +369,25 @@
new /obj/effect/decal/cleanable/blood/gibs(src)
src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by <b>[user]/[user.ckey]</b>" //One shall not simply gib a mob unnoticed!
user.attack_log += "\[[time_stamp()]\] Gibbed <b>[src.occupant]/[src.occupant.ckey]</b>"
if(!UserOverride)
src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by <b>[user]/[user.ckey]</b>" //One shall not simply gib a mob unnoticed!
user.attack_log += "\[[time_stamp()]\] Gibbed <b>[src.occupant]/[src.occupant.ckey]</b>"
if(src.occupant.ckey)
msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] gibbed [src.occupant] ([src.occupant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
if(src.occupant.ckey)
msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] gibbed [src.occupant] ([src.occupant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
if(!iscarbon(user))
src.occupant.LAssailant = null
else
src.occupant.LAssailant = user
if(!iscarbon(user))
src.occupant.LAssailant = null
else
src.occupant.LAssailant = user
if(UserOverride) //this looks ugly but it's better than a copy-pasted startgibbing proc override
occupant.attack_log += "\[[time_stamp()]\] Was gibbed by <b>an autogibber (\the [src])</b>"
src.occupant.emote("scream")
playsound(src.loc, 'sound/effects/gib.ogg', 50, 1)
victims += "\[[time_stamp()]\] [occupant.name] ([occupant.ckey]) killed by [UserOverride ? "Autogibbing" : "[user] ([user.ckey])"]" //have to do this before ghostizing
src.occupant.death(1)
src.occupant.ghostize()
@@ -293,12 +401,12 @@
for (var/obj/item/thing in contents) //Meat is spawned inside the gibber and thrown out afterwards.
thing.loc = get_turf(thing) // Drop it onto the turf for throwing.
thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) // Being pelted with bits of meat and bone would hurt.
sleep(1)
for (var/obj/effect/gibs in contents) //throw out the gibs too
gibs.loc = get_turf(gibs) //drop onto turf for throwing
gibs.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15)
sleep(1)
src.operating = 0
update_icon()
update_icon()
+23 -14
View File
@@ -10,17 +10,21 @@
idle_power_usage = 5
active_power_usage = 100
var/obj/item/weapon/reagent_containers/beaker = null
var/global/list/allowed_items = list (
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato = "tomatojuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot = "carrotjuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/berries = "berryjuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/banana = "banana",
/obj/item/weapon/reagent_containers/food/snacks/grown/potato = "potato",
/obj/item/weapon/reagent_containers/food/snacks/grown/lemon = "lemonjuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/orange = "orangejuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/lime = "limejuice",
var/global/list/allowed_items = list(
/obj/item/weapon/reagent_containers/food/snacks/watermelonslice = "watermelonjuice",
/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice",
/obj/item/weapon/reagent_containers/food/snacks/grown = "water",
)
var/global/list/allowed_tags = list (
"tomato" = "tomatojuice",
"carrot" = "carrotjuice",
"berries" = "berryjuice",
"banana" = "banana",
"potato" = "potato",
"lemon" = "lemonjuice",
"orange" = "orangejuice",
"lime" = "limejuice",
"poisonberries" = "poisonberryjuice",
)
/obj/machinery/juicer/New()
@@ -132,10 +136,15 @@
beaker = null
update_icon()
/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/grown/O)
for (var/i in allowed_items)
if (istype(O, i))
return allowed_items[i]
/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/O)
if (istype(O, /obj/item/weapon/reagent_containers/food/snacks/watermelonslice))
return "watermelonjuice"
else if(istype(O, /obj.item/weapon/reagent_containers/food/snacks/grown))
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
for(var/i in allowed_tags)
if(G.seed.kitchen_tag == allowed_tags[i])
return allowed_tags[i]
return "water"
/obj/machinery/juicer/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O)
if (!istype(O))
+1
View File
@@ -43,6 +43,7 @@
acceptable_reagents |= reagent
if (recipe.items)
max_n_of_items = max(max_n_of_items,recipe.items.len)
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/microwave(null)
+9 -5
View File
@@ -34,19 +34,19 @@
output = /obj/item/weapon/reagent_containers/food/snacks/meatball
/datum/food_processor_process/potato
input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato
input = "potato"
output = /obj/item/weapon/reagent_containers/food/snacks/fries
/datum/food_processor_process/carrot
input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot
input = "carrot"
output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries
/datum/food_processor_process/soybeans
input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans
input = "soybeans"
output = /obj/item/weapon/reagent_containers/food/snacks/soydope
/datum/food_processor_process/wheat
input = /obj/item/weapon/reagent_containers/food/snacks/grown/wheat
input = "wheat"
output = /obj/item/weapon/reagent_containers/food/snacks/flour
/datum/food_processor_process/spaghetti
@@ -111,7 +111,11 @@
/obj/machinery/processor/proc/select_recipe(var/X)
for (var/Type in typesof(/datum/food_processor_process) - /datum/food_processor_process - /datum/food_processor_process/mob)
var/datum/food_processor_process/P = new Type()
if (!istype(X, P.input))
if(istype(X, /obj/item/weapon/reagent_containers/food/snacks/grown))
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = X
if(G.seed.kitchen_tag != P.input)
continue
else if (!istype(X, P.input))
continue
return P
return 0
+26 -11
View File
@@ -39,44 +39,59 @@
ui_interact(user)
/obj/machinery/poolcontroller/process()
updateMobs() //Call the mob affecting proc
updatePool() //Call the mob affecting/decal cleaning proc
/obj/machinery/poolcontroller/proc/updateMobs()
/obj/machinery/poolcontroller/proc/updatePool()
for(var/turf/simulated/floor/beach/water/W in linkedturfs) //Check for pool-turfs linked to the controller.
for(var/mob/M in W) //Check for mobs in the linked pool-turfs.
//Sanity checks, don't affect robuts, AI eyes, and observers
if(isAIEye(M))
return
continue
if(issilicon(M))
return
continue
if(isobserver(M))
return
continue
//End sanity checks, go on
switch(temperature) //Apply different effects based on what the temperature is set to.
if("scalding") //Burn the mob.
M.bodytemperature = min(500, M.bodytemperature + 35) //heat mob at 35k(elvin) per cycle
M << "<span class='danger'>The water is searing hot!</span>"
return
if("frigid") //Freeze the mob.
M.bodytemperature = max(80, M.bodytemperature - 35) //cool mob at -35k per cycle
M << "<span class='danger'>The water is freezing!</span>"
return
if("normal") //Normal temp does nothing, because it's just room temperature water.
return
if("warm") //Gently warm the mob.
M.bodytemperature = min(330, M.bodytemperature + 10) //Heats up mobs to just over normal, not enough to burn
if(prob(50)) //inform the mob of warm water half the time
M << "<span class='warning'>The water is quite warm.</span>" //Inform the mob it's warm water.
return
if("cool") //Gently cool the mob.
M.bodytemperature = max(290, M.bodytemperature - 10) //Cools mobs to just below normal, not enough to burn
if(prob(50)) //inform the mob of cold water half the time
M << "<span class='warning'>The water is chilly.</span>" //Inform the mob it's chilly water.
return
if(ishuman(M)) //Make sure they are human before typecasting.
var/mob/living/carbon/human/drownee = M //Typecast them as human.
if(drownee.stat == DEAD) //Check stat, if they are dead, ignore them.
continue
if(drownee && drownee.lying && !drownee.internal && !(drownee.species.flags & NO_BREATHE) && !(drownee.species.reagent_tag == IS_SKRELL) && !(NO_BREATH in drownee.mutations))
//Establish that there is a mob, the mob is lying down, has no internals, species does breathe, is not a skrell, and does not have NO_BREATHE
if(drownee.stat != CONSCIOUS) //Mob is in critical.
drownee.adjustOxyLoss(9) //Kill em quickly.
drownee << "<span class='danger'>You're quickly drowning!</span>" //inform them that they are fucked.
else
if(!drownee.internal) //double check they have no internals, just in case.
drownee.adjustOxyLoss(5) //5 oxyloss per cycle.
if(prob(35)) //35% chance to tell them what is going on. They should probably figure it out before then.
drownee << "<span class='danger'>You're lacking air!</span>" //*gasp* *gasp* *gasp* *gasp* *gasp*
for(var/obj/effect/decal/cleanable/decal in W)
animate(decal, alpha = 10, time = 20)
spawn(25)
qdel(decal)
/obj/machinery/poolcontroller/proc/miston() //Spawn /obj/effect/mist (from the shower) on all linked pool tiles
for(var/turf/simulated/floor/beach/water/W in linkedturfs)
@@ -89,7 +104,7 @@
/obj/machinery/poolcontroller/proc/mistoff() //Delete all /obj/effect/mist from all linked pool tiles.
for(var/obj/effect/mist/M in linkedmist)
del(M)
qdel(M)
misted = 0 //no mist left, turn off the tracking var
/obj/machinery/poolcontroller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+2 -2
View File
@@ -16,10 +16,10 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob
var/datum/seed/new_seed_type
if(istype(O, /obj/item/weapon/grown))
var/obj/item/weapon/grown/F = O
new_seed_type = seed_types[F.plantname]
new_seed_type = plant_controller.seeds[F.plantname]
else
var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O
new_seed_type = seed_types[F.plantname]
new_seed_type = plant_controller.seeds[F.plantname]
if(new_seed_type)
user << "<span class='notice'>You extract some seeds from [O].</span>"
@@ -1,394 +1,210 @@
/obj/structure/signpost
icon = 'icons/obj/stationobjs.dmi'
icon_state = "signpost"
anchored = 1
density = 1
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
return attack_hand(user)
attack_hand(mob/user as mob)
user << "Civilians: NT is recruiting! Please head SOUTH to the NT Recruitment office to join the station's crew!"
/obj/structure/ninjatele
name = "Long-Distance Teleportation Console"
desc = "A console used to send a Spider Clan operative long distances rapidly."
icon = 'icons/obj/ninjaobjects.dmi'
icon_state = "teleconsole"
anchored = 1
density = 0
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
return attack_hand(user)
attack_hand(mob/user as mob)
if (user.mind.special_role=="Ninja")
switch(alert("Phase Jaunt relay primed, target locked as [station_name()], initiate VOID-shift translocation? (Warning! Internals required!)",,"Yes","No"))
if("Yes")
if(user.z != src.z) return
user.loc.loc.Exited(user)
user.loc = pick(carplist) // In the future, possibly make specific NinjaTele landmarks, and give him an option to teleport to North/South/East/West of SS13 instead of just hijacking a carpspawn.
playsound(user.loc, 'sound/effects/phasein.ogg', 25, 1)
playsound(user.loc, 'sound/effects/sparks2.ogg', 50, 1)
anim(user.loc,user,'icons/mob/mob.dmi',,"phasein",,user.dir)
user <<"\blue <b>VOID-Shift</b> translocation successful"
if("No")
user <<"\red <b>Process aborted!</b>"
return
else
user<< "\red <B>FĆAL �Rr�R</B>: µ§er n¤t rec¤gnized, c-c¤ntr-r¤£§-£§ £¤cked."
/obj/effect/mark
var/mark = ""
icon = 'icons/misc/mark.dmi'
icon_state = "blank"
anchored = 1
layer = 99
mouse_opacity = 0
unacidable = 1//Just to be sure.
/obj/effect/beam
name = "beam"
unacidable = 1//Just to be sure.
var/def_zone
pass_flags = PASSTABLE
/obj/effect/begin
name = "begin"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "begin"
anchored = 1.0
unacidable = 1
/*
* This item is completely unused, but removing it will break something in R&D and Radio code causing PDA and Ninja code to fail on compile
*/
/obj/effect/datacore
name = "datacore"
var/medical[] = list()
var/general[] = list()
var/security[] = list()
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list()
/obj/effect/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = new()
var/list/sec = new()
var/list/eng = new()
var/list/med = new()
var/list/sci = new()
var/list/supp = new()
var/list/bot = new()
var/list/misc = new()
var/list/isactive = new()
var/dat = {"
<head><style>
.manifest {border-collapse:collapse;}
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
.manifest td:first-child {text-align:right}
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
</style></head>
<table class="manifest" width='350px'>
<tr class='head'><th>Name</th><th>Rank</th><th>Activity</th></tr>
"}
var/even = 0
// sort mobs
for(var/datum/data/record/t in data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/real_rank = t.fields["real_rank"]
if(OOC)
var/active = 0
for(var/mob/M in player_list)
if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
active = 1
break
isactive[name] = active ? "Active" : "Inactive"
else
isactive[name] = t.fields["p_stat"]
//world << "[name]: [rank]"
//cael - to prevent multiple appearances of a player/job combination, add a continue after each line
var/department = 0
if(real_rank in command_positions)
heads[name] = rank
department = 1
if(real_rank in security_positions)
sec[name] = rank
department = 1
if(real_rank in engineering_positions)
eng[name] = rank
department = 1
if(real_rank in medical_positions)
med[name] = rank
department = 1
if(real_rank in science_positions)
sci[name] = rank
department = 1
if(real_rank in support_positions)
supp[name] = rank
department = 1
if(real_rank in nonhuman_positions)
bot[name] = rank
department = 1
if(!department && !(name in heads))
misc[name] = rank
if(heads.len > 0)
dat += "<tr><th colspan=3>Heads</th></tr>"
for(name in heads)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sec.len > 0)
dat += "<tr><th colspan=3>Security</th></tr>"
for(name in sec)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(eng.len > 0)
dat += "<tr><th colspan=3>Engineering</th></tr>"
for(name in eng)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(med.len > 0)
dat += "<tr><th colspan=3>Medical</th></tr>"
for(name in med)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sci.len > 0)
dat += "<tr><th colspan=3>Science</th></tr>"
for(name in sci)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(supp.len > 0)
dat += "<tr><th colspan=3>Support</th></tr>"
for(name in supp)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[supp[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
// in case somebody is insane and added them to the manifest, why not
if(bot.len > 0)
dat += "<tr><th colspan=3>Silicon</th></tr>"
for(name in bot)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
// misc guys
if(misc.len > 0)
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
for(name in misc)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
dat += "</table>"
dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
dat = replacetext(dat, "\t", "")
return dat
/*
We can't just insert in HTML into the nanoUI so we need the raw data to play with.
Instead of creating this list over and over when someone leaves their PDA open to the page
we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change
using /obj/effect/datacore/proc/manifest_inject( ), or manifest_insert( )
*/
var/global/list/PDA_Manifest = list()
/obj/effect/datacore/proc/get_manifest_json()
if(PDA_Manifest.len)
return PDA_Manifest
var/heads[0]
var/sec[0]
var/eng[0]
var/med[0]
var/sci[0]
var/supp[0]
var/bot[0]
var/misc[0]
for(var/datum/data/record/t in data_core.general)
var/name = sanitize(t.fields["name"])
var/rank = sanitize(t.fields["rank"])
var/real_rank = t.fields["real_rank"]
var/isactive = t.fields["p_stat"]
var/department = 0
var/depthead = 0 // Department Heads will be placed at the top of their lists.
if(real_rank in command_positions)
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
depthead = 1
if(rank=="Captain" && heads.len != 1)
heads.Swap(1,heads.len)
if(real_rank in security_positions)
sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && sec.len != 1)
sec.Swap(1,sec.len)
if(real_rank in engineering_positions)
eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && eng.len != 1)
eng.Swap(1,eng.len)
if(real_rank in medical_positions)
med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && med.len != 1)
med.Swap(1,med.len)
if(real_rank in science_positions)
sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && sci.len != 1)
sci.Swap(1,sci.len)
if(real_rank in support_positions)
supp[++supp.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && supp.len != 1)
supp.Swap(1,supp.len)
if(real_rank in nonhuman_positions)
bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(!department && !(name in heads))
misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
PDA_Manifest = list(\
"heads" = heads,\
"sec" = sec,\
"eng" = eng,\
"med" = med,\
"sci" = sci,\
"supp" = supp,\
"bot" = bot,\
"misc" = misc\
)
return PDA_Manifest
/obj/effect/laser
name = "laser"
desc = "IT BURNS!!!"
icon = 'icons/obj/projectiles.dmi'
var/damage = 0.0
var/range = 10.0
/obj/effect/list_container
name = "list container"
/obj/effect/list_container/mobl
name = "mobl"
var/master = null
var/list/container = list( )
/*
/obj/structure/cable
level = 1
anchored =1
var/datum/powernet/powernet
name = "power cable"
desc = "A flexible superconducting cable for heavy-duty power transfer"
icon = 'icons/obj/power_cond_red.dmi'
icon_state = "0-1"
var/d1 = 0
var/d2 = 1
layer = 2.44 //Just below unary stuff, which is at 2.45 and above pipes, which are at 2.4
var/_color = "red"
var/obj/structure/powerswitch/power_switch
var/obj/item/device/powersink/attached // holding this here for qdel
/obj/structure/cable/yellow
_color = "yellow"
icon = 'icons/obj/power_cond_yellow.dmi'
/obj/structure/cable/green
_color = "green"
icon = 'icons/obj/power_cond_green.dmi'
/obj/structure/cable/blue
_color = "blue"
icon = 'icons/obj/power_cond_blue.dmi'
/obj/structure/cable/pink
_color = "pink"
icon = 'icons/obj/power_cond_pink.dmi'
/obj/structure/cable/orange
_color = "orange"
icon = 'icons/obj/power_cond_orange.dmi'
/obj/structure/cable/cyan
_color = "cyan"
icon = 'icons/obj/power_cond_cyan.dmi'
/obj/structure/cable/white
_color = "white"
icon = 'icons/obj/power_cond_white.dmi'
*/
/obj/effect/projection
name = "Projection"
desc = "This looks like a projection of something."
anchored = 1.0
/obj/effect/shut_controller
name = "shut controller"
var/moving = null
var/list/parts = list( )
/obj/structure/showcase
name = "Showcase"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "showcase_1"
desc = "A stand with the empty body of a cyborg bolted to it."
density = 1
anchored = 1
unacidable = 1//temporary until I decide whether the borg can be removed. -veyveyr
/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER
/obj/item/weapon/beach_ball
icon = 'icons/misc/beach.dmi'
icon_state = "ball"
name = "beach ball"
item_state = "beachball"
density = 0
anchored = 0
w_class = 1.0
force = 0.0
throwforce = 0.0
throw_speed = 1
throw_range = 20
flags = CONDUCT
/obj/effect/stop
var/victim = null
icon_state = "empty"
name = "Geas"
desc = "You can't resist."
// name = ""
/obj/effect/spawner
name = "object spawner"
//This item is not completely unused- the central datacore datum uses it.
/*
* This item is completely unused, but removing it will break something in R&D and Radio code causing PDA and Ninja code to fail on compile
*/
/obj/effect/datacore
name = "datacore"
var/medical[] = list()
var/general[] = list()
var/security[] = list()
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list()
/obj/effect/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = new()
var/list/sec = new()
var/list/eng = new()
var/list/med = new()
var/list/sci = new()
var/list/supp = new()
var/list/bot = new()
var/list/misc = new()
var/list/isactive = new()
var/dat = {"
<head><style>
.manifest {border-collapse:collapse;}
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
.manifest td:first-child {text-align:right}
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
</style></head>
<table class="manifest" width='350px'>
<tr class='head'><th>Name</th><th>Rank</th><th>Activity</th></tr>
"}
var/even = 0
// sort mobs
for(var/datum/data/record/t in data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/real_rank = t.fields["real_rank"]
if(OOC)
var/active = 0
for(var/mob/M in player_list)
if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
active = 1
break
isactive[name] = active ? "Active" : "Inactive"
else
isactive[name] = t.fields["p_stat"]
//world << "[name]: [rank]"
//cael - to prevent multiple appearances of a player/job combination, add a continue after each line
var/department = 0
if(real_rank in command_positions)
heads[name] = rank
department = 1
if(real_rank in security_positions)
sec[name] = rank
department = 1
if(real_rank in engineering_positions)
eng[name] = rank
department = 1
if(real_rank in medical_positions)
med[name] = rank
department = 1
if(real_rank in science_positions)
sci[name] = rank
department = 1
if(real_rank in support_positions)
supp[name] = rank
department = 1
if(real_rank in nonhuman_positions)
bot[name] = rank
department = 1
if(!department && !(name in heads))
misc[name] = rank
if(heads.len > 0)
dat += "<tr><th colspan=3>Heads</th></tr>"
for(name in heads)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sec.len > 0)
dat += "<tr><th colspan=3>Security</th></tr>"
for(name in sec)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(eng.len > 0)
dat += "<tr><th colspan=3>Engineering</th></tr>"
for(name in eng)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(med.len > 0)
dat += "<tr><th colspan=3>Medical</th></tr>"
for(name in med)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(sci.len > 0)
dat += "<tr><th colspan=3>Science</th></tr>"
for(name in sci)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
if(supp.len > 0)
dat += "<tr><th colspan=3>Support</th></tr>"
for(name in supp)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[supp[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
// in case somebody is insane and added them to the manifest, why not
if(bot.len > 0)
dat += "<tr><th colspan=3>Silicon</th></tr>"
for(name in bot)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
// misc guys
if(misc.len > 0)
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
for(name in misc)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td><td>[isactive[name]]</td></tr>"
even = !even
dat += "</table>"
dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
dat = replacetext(dat, "\t", "")
return dat
/*
We can't just insert in HTML into the nanoUI so we need the raw data to play with.
Instead of creating this list over and over when someone leaves their PDA open to the page
we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change
using /obj/effect/datacore/proc/manifest_inject( ), or manifest_insert( )
*/
var/global/list/PDA_Manifest = list()
/obj/effect/datacore/proc/get_manifest_json()
if(PDA_Manifest.len)
return PDA_Manifest
var/heads[0]
var/sec[0]
var/eng[0]
var/med[0]
var/sci[0]
var/supp[0]
var/bot[0]
var/misc[0]
for(var/datum/data/record/t in data_core.general)
var/name = sanitize(t.fields["name"])
var/rank = sanitize(t.fields["rank"])
var/real_rank = t.fields["real_rank"]
var/isactive = t.fields["p_stat"]
var/department = 0
var/depthead = 0 // Department Heads will be placed at the top of their lists.
if(real_rank in command_positions)
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
depthead = 1
if(rank=="Captain" && heads.len != 1)
heads.Swap(1,heads.len)
if(real_rank in security_positions)
sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && sec.len != 1)
sec.Swap(1,sec.len)
if(real_rank in engineering_positions)
eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && eng.len != 1)
eng.Swap(1,eng.len)
if(real_rank in medical_positions)
med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && med.len != 1)
med.Swap(1,med.len)
if(real_rank in science_positions)
sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && sci.len != 1)
sci.Swap(1,sci.len)
if(real_rank in support_positions)
supp[++supp.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && supp.len != 1)
supp.Swap(1,supp.len)
if(real_rank in nonhuman_positions)
bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(!department && !(name in heads))
misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
PDA_Manifest = list(\
"heads" = heads,\
"sec" = sec,\
"eng" = eng,\
"med" = med,\
"sci" = sci,\
"supp" = supp,\
"bot" = bot,\
"misc" = misc\
)
return PDA_Manifest
@@ -171,6 +171,16 @@
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
/obj/effect/decal/cleanable/fruit_smudge
name = "smudge"
desc = "Some kind of fruit smear."
density = 0
anchored = 1
layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
/obj/effect/decal/cleanable/fungus
name = "space fungus"
desc = "A fungal growth. Looks pretty nasty."
+45 -9
View File
@@ -79,6 +79,9 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/effect/water/Bump(atom/A)
if(reagents)
reagents.reaction(A)
if(istype(A,/atom/movable))
var/atom/movable/AM = A
AM.water_act(life, 310.15, src)
return ..()
@@ -423,6 +426,28 @@ steam.start() -- spawns the effect
return
// Spores
/datum/effect/effect/system/chem_smoke_spread/spores
var/datum/seed/seed
/datum/effect/effect/system/chem_smoke_spread/spores/New(seed_name)
if(seed_name && plant_controller)
seed = plant_controller.seeds[seed_name]
if(!seed)
del(src)
..()
/datum/effect/effect/system/chem_smoke_spread/New()
..()
chemholder = new/obj()
var/datum/reagents/R = new/datum/reagents(500)
chemholder.reagents = R
R.my_atom = chemholder
/datum/effect/effect/system/chem_smoke_spread
var/total_smoke = 0 // To stop it being spammed and lagging!
var/direction
@@ -460,16 +485,20 @@ steam.start() -- spawns the effect
var/where = "[A.name] | [location.x], [location.y]"
var/whereLink = "<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>[where]</a>"
if(carry.my_atom.fingerprintslast)
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
more = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</a>)"
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
if(carry && carry.my_atom)
if(carry.my_atom.fingerprintslast)
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
more = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</a>)"
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
else
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
else
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.")
start(effect_range = 2)
var/i = 0
@@ -482,6 +511,13 @@ steam.start() -- spawns the effect
var/mob/living/carbon/C = A
if(!(C.wear_mask && (C.internals != null || C.wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)))
chemholder.reagents.copy_to(C, chemholder.reagents.total_volume)
if(istype(A, /obj/machinery/portable_atmospherics/hydroponics))
var/obj/machinery/portable_atmospherics/hydroponics/tray = A
chemholder.reagents.copy_to(tray, chemholder.reagents.total_volume)
if(istype(A, /obj/effect/plant))
var/obj/effect/plant/plant = A
if(chemholder.reagents.has_reagent("atrazine"))
plant.die_off()
qdel(smokeholder)
for(i=0, i<src.number, i++)
if(src.total_smoke > 20)
+87 -1
View File
@@ -1,3 +1,21 @@
//MISC EFFECTS
//This file is for effects that are less than 20 lines and don't fit very well in any other category.
/*CURRENT CONTENTS
Strange Present
Mark
Beam
Laser
Begin
Stop
Projection
Shut_controller
Showcase
Spawner
List_container
*/
//The effect when you wrap a dead body in gift wrap
/obj/effect/spresent
name = "strange present"
@@ -5,4 +23,72 @@
icon = 'icons/obj/items.dmi'
icon_state = "strangepresent"
density = 1
anchored = 0
anchored = 0
/obj/effect/mark
var/mark = ""
icon = 'icons/misc/mark.dmi'
icon_state = "blank"
anchored = 1
layer = 99
mouse_opacity = 0
unacidable = 1//Just to be sure.
/obj/effect/beam
name = "beam"
unacidable = 1//Just to be sure.
var/def_zone
pass_flags = PASSTABLE
/obj/effect/laser
name = "laser"
desc = "IT BURNS!!!"
icon = 'icons/obj/projectiles.dmi'
var/damage = 0.0
var/range = 10.0
/obj/effect/begin
name = "begin"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "begin"
anchored = 1.0
unacidable = 1
/obj/effect/stop
var/victim = null
icon_state = "empty"
name = "Geas"
desc = "You can't resist."
// name = ""
/obj/effect/projection
name = "Projection"
desc = "This looks like a projection of something."
anchored = 1.0
/obj/effect/shut_controller
name = "shut controller"
var/moving = null
var/list/parts = list( )
/obj/structure/showcase
name = "Showcase"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "showcase_1"
desc = "A stand with the empty body of a cyborg bolted to it."
density = 1
anchored = 1
unacidable = 1//temporary until I decide whether the borg can be removed. -veyveyr
/obj/effect/spawner
name = "object spawner"
/obj/effect/list_container
name = "list container"
/obj/effect/list_container/mobl
name = "mobl"
var/master = null
var/list/container = list( )
+3
View File
@@ -93,6 +93,9 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
else dist = 0
if(T)
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
var/atom/movable/AM = atom_movable
if(AM) AM.ex_act(dist)
// if(flame_dist && prob(40) && !istype(T, /turf/space) && !T.density)
// PoolOrNew(/obj/effect/hotspot, T) //Mostly for ambience!
if(dist > 0)
+24
View File
@@ -0,0 +1,24 @@
//MISC items
//These items don't belong anywhere else, so they have this file.
//Current contents:
/*
mouse_drag_pointer
Beach Ball
*/
/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER
/obj/item/weapon/beach_ball
icon = 'icons/misc/beach.dmi'
icon_state = "ball"
name = "beach ball"
item_state = "beachball"
density = 0
anchored = 0
w_class = 1.0
force = 0.0
throwforce = 0.0
throw_speed = 1
throw_range = 20
flags = CONDUCT
+2 -2
View File
@@ -198,7 +198,7 @@
B.desc = "Looks like the label fell off."
// B.identify_probability = 0
/*
/obj/structure/closet/crate/bin/flowers
name = "flower barrel"
desc = "A bin full of fresh flowers for the bereaved."
@@ -211,7 +211,6 @@
AM.pixel_x = rand(-10,10)
AM.pixel_y = rand(-5,5)
/obj/structure/closet/crate/bin/plants
name = "plant barrel"
desc = "Caution: Contents may contain vitamins and minerals. It is recommended that you deep fry them before eating."
@@ -234,6 +233,7 @@
var/obj/O = new ptype(src)
O.pixel_x = rand(-10,10)
O.pixel_y = rand(-5,5)
*/
/obj/structure/closet/secure_closet/random_drinks
name = "Unlabelled Booze"
@@ -0,0 +1,66 @@
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
name = "wet floor sign"
icon = 'icons/obj/janitor.dmi'
icon_state = "caution"
force = 1.0
throwforce = 3.0
throw_speed = 1
throw_range = 5
w_class = 2.0
attack_verb = list("warned", "cautioned", "smashed")
proximity_sign
var/timing = 0
var/armed = 0
var/timepassed = 0
attack_self(mob/user as mob)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.mind.assigned_role != "Janitor")
return
if(armed)
armed = 0
user << "\blue You disarm \the [src]."
return
timing = !timing
if(timing)
processing_objects.Add(src)
else
armed = 0
timepassed = 0
H << "\blue You [timing ? "activate \the [src]'s timer, you have 15 seconds." : "de-activate \the [src]'s timer."]"
process()
if(!timing)
processing_objects.Remove(src)
timepassed++
if(timepassed >= 15 && !armed)
armed = 1
timing = 0
HasProximity(atom/movable/AM as mob|obj)
if(armed)
if(istype(AM, /mob/living/carbon) && !istype(AM, /mob/living/carbon/brain))
var/mob/living/carbon/C = AM
if(C.m_intent != "walk")
src.visible_message("The [src.name] beeps, \"Running on wet floors is hazardous to your health.\"")
explosion(src.loc,-1,0,2)
if(ishuman(C))
dead_legs(C)
if(src)
qdel(src)
proc/dead_legs(mob/living/carbon/human/H as mob)
var/obj/item/organ/external/l = H.get_organ("l_leg")
var/obj/item/organ/external/r = H.get_organ("r_leg")
if(l && !(l.status & ORGAN_DESTROYED))
l.status |= ORGAN_DESTROYED
if(r && !(r.status & ORGAN_DESTROYED))
r.status |= ORGAN_DESTROYED
/obj/item/weapon/caution/cone
desc = "This cone is trying to warn you of something!"
name = "warning cone"
icon_state = "cone"
@@ -245,6 +245,16 @@ CIGARETTE PACKETS ARE IN FANCY.DM
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
/obj/item/clothing/mask/cigarette/handroll
name = "hand-rolled cigarette"
desc = "A roll of tobacco and nicotine, freshly rolled by hand."
icon_state = "hr_cigoff"
item_state = "hr_cigoff"
icon_on = "hr_cigon" //Note - these are in masks.dmi not in cigarette.dmi
icon_off = "hr_cigoff"
type_butt = /obj/item/weapon/cigbutt
chem_volume = 50
////////////
// CIGARS //
////////////
@@ -498,7 +508,7 @@ obj/item/weapon/rollingpaper
name = "rolling paper"
desc = "A thin piece of paper used to make fine smokeables."
icon = 'icons/obj/cigarettes.dmi'
icon_state = "cig paper"
icon_state = "cig_paper"
w_class = 1
@@ -8,6 +8,18 @@
/*
* Banana Peals
*/
/obj/item/weapon/bananapeel
name = "banana peel"
desc = "A peel from a banana."
icon = 'icons/obj/items.dmi'
icon_state = "banana_peel"
item_state = "banana_peel"
w_class = 1.0
throwforce = 0
throw_speed = 4
throw_range = 20
/obj/item/weapon/bananapeel/Crossed(AM as mob|obj)
if (istype(AM, /mob/living/carbon))
var/mob/M = AM
@@ -66,6 +78,21 @@
/*
* Bike Horns
*/
/obj/item/weapon/bikehorn
name = "bike horn"
desc = "A horn off of a bicycle."
icon = 'icons/obj/items.dmi'
icon_state = "bike_horn"
item_state = "bike_horn"
hitsound = 'sound/items/bikehorn.ogg'
throwforce = 3
w_class = 1.0
throw_speed = 3
throw_range = 15
attack_verb = list("HONKED")
var/spam_flag = 0
/obj/item/weapon/bikehorn/attack_self(mob/user as mob)
if (spam_flag == 0)
spam_flag = 1
+15
View File
@@ -0,0 +1,15 @@
/obj/item/weapon/disk
name = "disk"
icon = 'icons/obj/items.dmi'
/obj/item/weapon/disk/nuclear
name = "nuclear authentication disk"
desc = "Better keep this safe."
icon_state = "nucleardisk"
item_state = "card-id"
w_class = 1.0
/*
/obj/item/weapon/disk/nuclear/pickup(mob/living/user as mob)
if(issyndicate(user))
set_security_level(3)*/ //Nuke Ops rework makes stealth approach significantly harder; this makes it damn near impossible; besides, it's horrendously meta.
@@ -0,0 +1,48 @@
/obj/item/weapon/holosign_creator
name = "holographic sign projector"
desc = "A handy-dandy hologaphic projector that displays a janitorial sign."
icon = 'icons/obj/janitor.dmi'
icon_state = "signmaker"
item_state = "electronic"
force = 5
w_class = 2
throwforce = 0
throw_speed = 3
throw_range = 7
origin_tech = "programming=3"
var/list/signs = list()
var/max_signs = 10
/obj/item/weapon/holosign_creator/afterattack(atom/target, mob/user, flag)
if(flag)
var/turf/T = get_turf(target)
var/obj/effect/overlay/holograph/H = locate() in T
if(H)
user << "<span class='notice'>You use [src] to destroy [H].</span>"
signs -= H
qdel(H)
else
if(signs.len < max_signs)
H = new(get_turf(target))
signs += H
user << "<span class='notice'>You create \a [H] with [src].</span>"
else
user << "<span class='notice'>[src] is projecting at max capacity!</span>"
/obj/item/weapon/holosign_creator/attack(mob/living/carbon/human/M, mob/user)
return
/obj/item/weapon/holosign_creator/attack_self(mob/user)
if(signs.len)
var/list/L = signs.Copy()
for(var/sign in L)
qdel(sign)
signs -= sign
user << "<span class='notice'>You clear all active holograms.</span>"
/obj/effect/overlay/holograph
name = "wet floor sign"
desc = "The words flicker as if they mean nothing."
icon = 'icons/obj/janitor.dmi'
icon_state = "holosign"
anchored = 1
@@ -146,7 +146,7 @@
if(!user.gloves)
user << "\red The [name] burns your bare hand!"
user.adjustFireLoss(rand(1,5))
/*
/*
* Nettle
*/
@@ -237,3 +237,4 @@
new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc)
del(src)
return
*/
+210
View File
@@ -0,0 +1,210 @@
/obj/item/weapon/legcuffs
name = "legcuffs"
desc = "Use this to keep prisoners in line."
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "handcuff"
flags = CONDUCT
throwforce = 0
w_class = 3.0
origin_tech = "materials=1"
var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute
/obj/item/weapon/legcuffs/beartrap
name = "bear trap"
throw_speed = 1
throw_range = 1
icon_state = "beartrap0"
desc = "A trap used to catch bears and other legged creatures."
var/armed = 0
var/obj/item/weapon/grenade/iedcasing/IED = null
suicide_act(mob/user)
viewers(user) << "<span class='suicide'>[user] is putting the [src.name] on \his head! It looks like \he's trying to commit suicide.</span>"
return (BRUTELOSS)
/obj/item/weapon/legcuffs/beartrap/attack_self(mob/user as mob)
..()
if(ishuman(user) && !user.stat && !user.restrained())
armed = !armed
icon_state = "beartrap[armed]"
user << "<span class='notice'>[src] is now [armed ? "armed" : "disarmed"]</span>"
/obj/item/weapon/legcuffs/beartrap/attackby(var/obj/item/I, mob/user as mob) //Let's get explosive.
if(istype(I, /obj/item/weapon/grenade/iedcasing))
if(IED)
user << "<span class='warning'>This beartrap already has an IED hooked up to it!</span>"
return
IED = I
switch(IED.assembled)
if(0,1) //if it's not fueled/hooked up
user << "<span class='warning'>You haven't prepared this IED yet!</span>"
IED = null
return
if(2,3)
user.drop_item(src)
I.loc = src
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
var/log_str = "[key_name(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A> has rigged a beartrap with an IED at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>."
message_admins(log_str)
log_game(log_str)
user << "<span class='notice'>You sneak the [IED] underneath the pressure plate and connect the trigger wire.</span>"
desc = "A trap used to catch bears and other legged creatures. <span class='warning'>There is an IED hooked up to it.</span>"
else
user << "<span class='danger'>You shouldn't be reading this message! Contact a coder or someone, something broke!</span>"
IED = null
return
if(istype(I, /obj/item/weapon/screwdriver))
if(IED)
IED.loc = get_turf(src.loc)
IED = null
user << "<span class='notice'>You remove the IED from the [src].</span>"
return
..()
/obj/item/weapon/legcuffs/beartrap/Crossed(AM as mob|obj)
if(armed)
if(IED && isturf(src.loc))
IED.active = 1
IED.overlays -= image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled")
IED.icon_state = initial(icon_state) + "_active"
IED.assembled = 3
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
var/log_str = "[key_name(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[AM]'>?</A> has triggered an IED-rigged [name] at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>."
message_admins(log_str)
log_game(log_str)
spawn(IED.det_time)
IED.prime()
if(ishuman(AM))
if(isturf(src.loc))
var/mob/living/carbon/H = AM
if(H.m_intent == "run")
if(H.lying)
H.apply_damage(20,BRUTE,"chest")
else
H.apply_damage(20,BRUTE,(pick("l_leg", "r_leg")))
armed = 0
icon_state = "beartrap0"
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
H.visible_message("<span class='danger'>[H] triggers \the [src].</span>", \
"<span class='userdanger'>You trigger \the [src]!</span>")
H.legcuffed = src
src.loc = H
H.update_inv_legcuffed()
H << "<span class='danger'>You step on \the [src]!</span>"
if(IED && IED.active)
H << "<span class='danger'>The [src]'s IED has been activated!</span>"
feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart.
for(var/mob/O in viewers(H, null))
if(O == H)
continue
O.show_message("\red <B>[H] steps on \the [src].</B>", 1)
if(isanimal(AM) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator))
armed = 0
icon_state = "beartrap0"
var/mob/living/simple_animal/SA = AM
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
SA.visible_message("<span class='danger'>[SA] triggers \the [src].</span>", \
"<span class='userdanger'>You trigger \the [src]!</span>")
SA.health -= 20
..()
/obj/item/weapon/legcuffs/bolas
name = "bolas"
desc = "An entangling bolas. Throw at your foes to trip them and prevent them from running."
gender = NEUTER
icon = 'icons/obj/weapons.dmi'
icon_override = 'icons/mob/in-hand/swords.dmi'
icon_state = "bolas"
siemens_coefficient = 1
slot_flags = SLOT_BELT
throwforce = 2
w_class = 2
origin_tech = "materials=1"
attack_verb = list("lashed", "bludgeoned", "whipped")
force = 4
breakouttime = 50 //10 seconds
throw_speed = 1
throw_range = 10
var/dispenser = 0
var/throw_sound = 'sound/weapons/whip.ogg'
var/trip_prob = 60
var/thrown_from
/obj/item/weapon/legcuffs/bolas/suicide_act(mob/living/user)
viewers(user) << "<span class='danger'>[user] is wrapping the [src.name] around \his neck! It looks like \he's trying to commit suicide.</span>"
return(OXYLOSS)
/obj/item/weapon/legcuffs/bolas/throw_at(var/atom/A, throw_range, throw_speed)
if(usr && !istype(thrown_from, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas)) //if there is a user, but not a mech
if(istype(usr, /mob/living/carbon/human)) //if the user is human
var/mob/living/carbon/human/H = usr
if((CLUMSY in H.mutations) && prob(50))
H <<"<span class='warning'>You smack yourself in the face while swinging the [src]!</span>"
H.Stun(2)
H.drop_item(src)
return
if (!thrown_from && usr) //if something hasn't set it already (like a mech does when it launches)
thrown_from = usr //then the user must have thrown it
if (!istype(thrown_from, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas))
playsound(src, throw_sound, 20, 1) //because mechs play the sound anyways
var/turf/target = get_turf(A)
var/atom/movable/adjtarget = new /atom/movable
var/xadjust = 0
var/yadjust = 0
var/scaler = 0 //used to changed the normalised vector to the proper size
scaler = throw_range / max(abs(target.x - src.x), abs(target.y - src.y)) //whichever is larger magnitude is what we normalise to
if (target.x - src.x != 0) //just to avoid fucking with math for no reason
xadjust = round((target.x - src.x) * scaler) //normalised vector is now scaled up to throw_range
adjtarget.x = src.x + xadjust //the new target at max range
else
adjtarget.x = src.x
if (target.y - src.y != 0)
yadjust = round((target.y - src.y) * scaler)
adjtarget.y = src.y + yadjust
else
adjtarget.y = src.y
// log_admin("Adjusted target of [adjtarget.x] and [adjtarget.y], adjusted with [xadjust] and [yadjust] from [scaler]")
..(get_turf(adjtarget), throw_range, throw_speed)
thrown_from = null
/obj/item/weapon/legcuffs/bolas/throw_impact(atom/hit_atom) //Pomf was right, I was wrong - Comic
if(isliving(hit_atom) && hit_atom != usr) //if the target is a live creature other than the thrower
var/mob/living/M = hit_atom
if(ishuman(M)) //if they're a human species
var/mob/living/carbon/human/H = M
if(H.m_intent == "run") //if they're set to run (though not necessarily running at that moment)
if(prob(trip_prob)) //this probability is up for change and mostly a placeholder - Comic
step(H, H.dir)
H.visible_message("<span class='warning'>[H] was tripped by the bolas!</span>","<span class='warning'>Your legs have been tangled!</span>");
H.Stun(2) //used instead of setting damage in vars to avoid non-human targets being affected
H.Weaken(4)
H.legcuffed = src //applies legcuff properties inherited through legcuffs
src.loc = H
H.update_inv_legcuffed()
if(!H.legcuffed) //in case it didn't happen, we need a safety net
throw_failed()
else if(H.legcuffed) //if the target is already legcuffed (has to be walking)
throw_failed()
return
else //walking, but uncuffed, or the running prob() failed
H << "<span class='notice'>You stumble over the thrown bolas</span>"
step(H, H.dir)
H.Stun(1)
throw_failed()
return
else
M.Stun(2) //minor stun damage to anything not human
throw_failed()
return
/obj/item/weapon/legcuffs/bolas/proc/throw_failed() //called when the throw doesn't entangle
//log_admin("Logged as [thrown_from]")
if(!thrown_from || !istype(thrown_from, /mob/living)) //in essence, if we don't know whether a person threw it
qdel(src) //destroy it, to stop infinite bolases
/obj/item/weapon/legcuffs/bolas/Bump()
..()
throw_failed() //allows a mech bolas to be destroyed
+136
View File
@@ -0,0 +1,136 @@
//MISC WEAPONS
//This file contains /obj/item/weapon's that do not fit in any other category and are not big enough to warrant individual files.
/*CURRENT CONTENTS
Ball Toy
Cane
Cardboard Tube
Fan
Gaming Kit
Gift
Kidan Globe
Lightning
Newton Cradle
PAI cable
Red Phone
*/
/obj/item/weapon/balltoy
name = "ball toy"
icon = 'icons/obj/decorations.dmi'
icon_state = "rollball"
desc = "A device bored paper pushers use to remind themselves that the time did not stop yet."
/obj/item/weapon/cane
name = "cane"
desc = "A cane used by a true gentlemen. Or a clown."
icon = 'icons/obj/weapons.dmi'
icon_state = "cane"
item_state = "stick"
flags = CONDUCT
force = 5.0
throwforce = 7.0
w_class = 2.0
m_amt = 50
attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
/obj/item/weapon/c_tube
name = "cardboard tube"
desc = "A tube... of cardboard."
icon = 'icons/obj/items.dmi'
icon_state = "c_tube"
throwforce = 1
w_class = 1.0
throw_speed = 4
throw_range = 5
/obj/item/weapon/fan
name = "desk fan"
icon = 'icons/obj/decorations.dmi'
icon_state = "fan"
desc = "A smal desktop fan. Button seems to be stuck in the 'on' position."
/*
/obj/item/weapon/game_kit
name = "Gaming Kit"
icon = 'icons/obj/items.dmi'
icon_state = "game_kit"
var/selected = null
var/board_stat = null
var/data = ""
var/base_url = "http://svn.slurm.us/public/spacestation13/misc/game_kit"
item_state = "sheet-metal"
w_class = 5.0
*/
/obj/item/weapon/gift
name = "gift"
desc = "A wrapped item."
icon = 'icons/obj/items.dmi'
icon_state = "gift3"
var/size = 3.0
var/obj/item/gift = null
item_state = "gift"
w_class = 4.0
/obj/item/weapon/kidanglobe
name = "Kidan homeworld globe"
icon = 'icons/obj/decorations.dmi'
icon_state = "kidanglobe"
desc = "A globe of the Kidan homeworld."
/obj/item/weapon/lightning
name = "lightning"
icon = 'icons/obj/lightning.dmi'
icon_state = "lightning"
desc = "test lightning"
New()
icon = midicon
icon_state = "1"
afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
var/angle = get_angle(A, user)
//world << angle
angle = round(angle) + 45
if(angle > 180)
angle -= 180
else
angle += 180
if(!angle)
angle = 1
//world << "adjusted [angle]"
icon_state = "[angle]"
//world << "[angle] [(get_dist(user, A) - 1)]"
user.Beam(A, "lightning", 'icons/obj/zap.dmi', 50, 15)
/obj/item/weapon/newton
name = "newton cradle"
icon = 'icons/obj/decorations.dmi'
icon_state = "newton"
desc = "A device bored paper pushers use to remind themselves that the time did not stop yet. Contains gravity."
/obj/item/weapon/pai_cable
desc = "A flexible coated cable with a universal jack on one end."
name = "data cable"
icon = 'icons/obj/power.dmi'
icon_state = "wire1"
var/obj/machinery/machine
/obj/item/weapon/phone
name = "red phone"
desc = "Should anything ever go wrong..."
icon = 'icons/obj/items.dmi'
icon_state = "red_phone"
flags = CONDUCT
force = 3.0
throwforce = 2.0
throw_speed = 1
throw_range = 4
w_class = 2
attack_verb = list("called", "rang")
hitsound = 'sound/weapons/ring.ogg'
+32
View File
@@ -0,0 +1,32 @@
/obj/item/weapon/module
icon = 'icons/obj/module.dmi'
icon_state = "std_module"
w_class = 2.0
item_state = "electronic"
flags = CONDUCT
var/mtype = 1 // 1=electronic 2=hardware
/obj/item/weapon/module/card_reader
name = "card reader module"
icon_state = "card_mod"
desc = "An electronic module for reading data and ID cards."
/obj/item/weapon/module/power_control
name = "power control module"
icon_state = "power_mod"
desc = "Heavy-duty switching circuits for power control."
/obj/item/weapon/module/id_auth
name = "\improper ID authentication module"
icon_state = "id_mod"
desc = "A module allowing secure authorization of ID cards."
/obj/item/weapon/module/cell_power
name = "power cell regulator module"
icon_state = "power_mod"
desc = "A converter and regulator allowing the use of power cells."
/obj/item/weapon/module/cell_power
name = "power cell charger module"
icon_state = "power_mod"
desc = "Charging circuits for power cells."
+28
View File
@@ -0,0 +1,28 @@
/obj/item/weapon/soap
name = "soap"
desc = "A cheap bar of soap. Doesn't smell."
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "soap"
w_class = 1.0
throwforce = 0
throw_speed = 4
throw_range = 20
discrete = 1
var/cleanspeed = 50 //slower than mop
/obj/item/weapon/soap/nanotrasen
desc = "A Nanotrasen brand bar of soap. Smells of plasma."
icon_state = "soapnt"
/obj/item/weapon/soap/deluxe
icon_state = "soapdeluxe"
/obj/item/weapon/soap/deluxe/New()
desc = "A deluxe Waffle Co. brand bar of soap. Smells of comdoms."
cleanspeed = 40 //same speed as mop because deluxe -- captain gets one of these
/obj/item/weapon/soap/syndie
desc = "An untrustworthy bar of soap made of strong chemical agents that dissolve blood faster."
icon_state = "soapsyndie"
cleanspeed = 10 //much faster than mop so it is useful for traitors who want to clean crime scenes
+31
View File
@@ -0,0 +1,31 @@
/obj/item/weapon/staff
name = "wizards staff"
desc = "Apparently a staff used by the wizard."
icon = 'icons/obj/wizard.dmi'
icon_state = "staff"
force = 3.0
throwforce = 5.0
throw_speed = 1
throw_range = 5
w_class = 2.0
flags = NOSHIELD
attack_verb = list("bludgeoned", "whacked", "disciplined")
/obj/item/weapon/staff/broom
name = "broom"
desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
icon = 'icons/obj/wizard.dmi'
icon_state = "broom"
/obj/item/weapon/staff/stick
name = "stick"
desc = "A great tool to drag someone else's drinks across the bar."
icon = 'icons/obj/weapons.dmi'
icon_state = "stick"
item_state = "stick"
force = 3.0
throwforce = 5.0
throw_speed = 1
throw_range = 5
w_class = 2.0
flags = NOSHIELD
@@ -0,0 +1,238 @@
///////////////////////////////////////Stock Parts /////////////////////////////////
/obj/item/weapon/storage/part_replacer
name = "Rapid Part Exchange Device"
desc = "Special mechanical module made to store, sort, and apply standard machine parts."
icon_state = "RPED"
item_state = "RPED"
icon_override = 'icons/mob/in-hand/tools.dmi'
w_class = 5
can_hold = list("/obj/item/weapon/stock_parts")
storage_slots = 50
use_to_pickup = 1
allow_quick_gather = 1
allow_quick_empty = 1
collection_mode = 1
display_contents_with_number = 1
max_w_class = 3
max_combined_w_class = 100
/obj/item/weapon/storage/part_replacer/proc/play_rped_sound()
//Plays the sound for RPED exchanging or installing parts.
playsound(src, 'sound/items/rped.ogg', 40, 1)
//Sorts stock parts inside an RPED by their rating.
//Only use /obj/item/weapon/stock_parts/ with this sort proc!
/proc/cmp_rped_sort(var/obj/item/weapon/stock_parts/A, var/obj/item/weapon/stock_parts/B)
return B.rating - A.rating
/obj/item/weapon/stock_parts
name = "stock part"
desc = "What?"
gender = PLURAL
icon = 'icons/obj/stock_parts.dmi'
w_class = 2.0
var/rating = 1
New()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
//Rank 1
/obj/item/weapon/stock_parts/console_screen
name = "console screen"
desc = "Used in the construction of computers and other devices with a interactive console."
icon_state = "screen"
origin_tech = "materials=1"
g_amt = 200
/obj/item/weapon/stock_parts/capacitor
name = "capacitor"
desc = "A basic capacitor used in the construction of a variety of devices."
icon_state = "capacitor"
origin_tech = "powerstorage=1"
m_amt = 50
g_amt = 50
/obj/item/weapon/stock_parts/scanning_module
name = "scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module"
origin_tech = "magnets=1"
m_amt = 50
g_amt = 20
/obj/item/weapon/stock_parts/manipulator
name = "micro-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "micro_mani"
origin_tech = "materials=1;programming=1"
m_amt = 30
/obj/item/weapon/stock_parts/micro_laser
name = "micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "micro_laser"
origin_tech = "magnets=1"
m_amt = 10
g_amt = 20
/obj/item/weapon/stock_parts/matter_bin
name = "matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "matter_bin"
origin_tech = "materials=1"
m_amt = 80
//Rank 2
/obj/item/weapon/stock_parts/capacitor/adv
name = "advanced capacitor"
desc = "An advanced capacitor used in the construction of a variety of devices."
icon_state = "adv_capacitor"
origin_tech = "powerstorage=3"
rating = 2
m_amt = 50
g_amt = 50
/obj/item/weapon/stock_parts/scanning_module/adv
name = "advanced scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "adv_scan_module"
origin_tech = "magnets=3"
rating = 2
m_amt = 50
g_amt = 20
/obj/item/weapon/stock_parts/manipulator/nano
name = "nano-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "nano_mani"
origin_tech = "materials=3,programming=2"
rating = 2
m_amt = 30
/obj/item/weapon/stock_parts/micro_laser/high
name = "high-power micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "high_micro_laser"
origin_tech = "magnets=3"
rating = 2
m_amt = 10
g_amt = 20
/obj/item/weapon/stock_parts/matter_bin/adv
name = "advanced matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "advanced_matter_bin"
origin_tech = "materials=3"
rating = 2
m_amt = 80
//Rating 3
/obj/item/weapon/stock_parts/capacitor/super
name = "super capacitor"
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
icon_state = "super_capacitor"
origin_tech = "powerstorage=5;materials=4"
rating = 3
m_amt = 50
g_amt = 50
/obj/item/weapon/stock_parts/scanning_module/phasic
name = "phasic scanning module"
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
icon_state = "super_scan_module"
origin_tech = "magnets=5"
rating = 3
m_amt = 50
g_amt = 20
/obj/item/weapon/stock_parts/manipulator/pico
name = "pico-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "pico_mani"
origin_tech = "materials=5,programming=2"
rating = 3
m_amt = 30
/obj/item/weapon/stock_parts/micro_laser/ultra
name = "ultra-high-power micro-laser"
icon_state = "ultra_high_micro_laser"
desc = "A tiny laser used in certain devices."
origin_tech = "magnets=5"
rating = 3
m_amt = 10
g_amt = 20
/obj/item/weapon/stock_parts/matter_bin/super
name = "super matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "super_matter_bin"
origin_tech = "materials=5"
rating = 3
m_amt = 80
// Subspace stock parts
/obj/item/weapon/stock_parts/subspace/ansible
name = "subspace ansible"
icon_state = "subspace_ansible"
desc = "A compact module capable of sensing extradimensional activity."
origin_tech = "programming=2;magnets=3;materials=2;bluespace=1"
m_amt = 30
g_amt = 10
/obj/item/weapon/stock_parts/subspace/filter
name = "hyperwave filter"
icon_state = "hyperwave_filter"
desc = "A tiny device capable of filtering and converting super-intense radiowaves."
origin_tech = "programming=2;magnets=1"
m_amt = 30
g_amt = 10
/obj/item/weapon/stock_parts/subspace/amplifier
name = "subspace amplifier"
icon_state = "subspace_amplifier"
desc = "A compact micro-machine capable of amplifying weak subspace transmissions."
origin_tech = "programming=2;magnets=2;materials=1;bluespace=1"
m_amt = 30
g_amt = 10
/obj/item/weapon/stock_parts/subspace/treatment
name = "subspace treatment disk"
icon_state = "treatment_disk"
desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves."
origin_tech = "programming=2;magnets=1;materials=3;bluespace=1"
m_amt = 30
g_amt = 10
/obj/item/weapon/stock_parts/subspace/analyzer
name = "subspace wavelength analyzer"
icon_state = "wavelength_analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
origin_tech = "programming=2;magnets=2;materials=2;bluespace=1"
m_amt = 30
g_amt = 10
/obj/item/weapon/stock_parts/subspace/crystal
name = "ansible crystal"
icon_state = "ansible_crystal"
desc = "A crystal made from pure glass used to transmit laser databursts to subspace."
origin_tech = "magnets=2;materials=2;bluespace=1"
g_amt = 50
/obj/item/weapon/stock_parts/subspace/transmitter
name = "subspace transmitter"
icon_state = "subspace_transmitter"
desc = "A large piece of equipment used to open a window into the subspace dimension."
origin_tech = "magnets=3;materials=3;bluespace=2"
m_amt = 50
/obj/item/weapon/research//Makes testing much less of a pain -Sieve
name = "research"
icon = 'icons/obj/stock_parts.dmi'
icon_state = "capacitor"
desc = "A debug item for research."
origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8"
@@ -0,0 +1,38 @@
/*/obj/item/weapon/syndicate_uplink
name = "station bounced radio"
desc = "Remain silent about this..."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
var/temp = null
var/uses = 10.0
var/selfdestruct = 0.0
var/traitor_frequency = 0.0
var/mob/currentUser = null
var/obj/item/device/radio/origradio = null
flags = CONDUCT | ONBELT
w_class = 2.0
item_state = "radio"
throw_speed = 4
throw_range = 20
m_amt = 100
origin_tech = "magnets=2;syndicate=3"*/
/obj/item/weapon/SWF_uplink
name = "station-bounced radio"
desc = "used to comunicate it appears."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
var/temp = null
var/uses = 4.0
var/selfdestruct = 0.0
var/traitor_frequency = 0.0
var/obj/item/device/radio/origradio = null
flags = CONDUCT
slot_flags = SLOT_BELT
item_state = "radio"
throwforce = 5
w_class = 2.0
throw_speed = 4
throw_range = 20
m_amt = 100
origin_tech = "magnets=1"
@@ -6,7 +6,43 @@
* Rack Parts
*/
/obj/item/weapon/table_parts
name = "table parts"
desc = "Parts of a table. Poor table."
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "table_parts"
m_amt = 3750
flags = CONDUCT
attack_verb = list("slammed", "bashed", "battered", "bludgeoned", "thrashed", "whacked")
/obj/item/weapon/table_parts/reinforced
name = "reinforced table parts"
desc = "Hard table parts. Well...harder..."
icon = 'icons/obj/items.dmi'
icon_state = "reinf_tableparts"
m_amt = 7500
flags = CONDUCT
/obj/item/weapon/table_parts/wood
name = "wooden table parts"
desc = "Keep away from fire."
icon_state = "wood_tableparts"
flags = null
/obj/item/weapon/table_parts/glass
name = "glass table parts"
desc = "fragile!"
icon_state = "glass_tableparts"
flags = null
/obj/item/weapon/rack_parts
name = "rack parts"
desc = "Parts of a rack."
icon = 'icons/obj/items.dmi'
icon_state = "rack_parts"
flags = CONDUCT
m_amt = 3750
/*
* Table Parts
+16
View File
@@ -1,5 +1,21 @@
// WIRES
/obj/item/weapon/wire
desc = "This is just a simple piece of regular insulated wire."
name = "wire"
icon = 'icons/obj/power.dmi'
icon_state = "item_wire"
var/amount = 1.0
var/laying = 0.0
var/old_lay = null
m_amt = 40
attack_verb = list("whipped", "lashed", "disciplined", "tickled")
suicide_act(mob/user)
viewers(user) << "\red <b>[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.</b>"
return (OXYLOSS)
/obj/item/weapon/wire/proc/update()
if (src.amount > 1)
src.icon_state = "spool_wire"
+59
View File
@@ -0,0 +1,59 @@
//MISC structures- if it is less than 100 lines and doesn't fit in a category, toss it in here!
/*CURRENT CONTENTS:
NT recruitment signpost
Ninja Teleportation Console
*/
/obj/structure/signpost
icon = 'icons/obj/stationobjs.dmi'
icon_state = "signpost"
anchored = 1
density = 1
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
return attack_hand(user)
attack_hand(mob/user as mob)
user << "Civilians: NT is recruiting! Please head SOUTH to the NT Recruitment office to join the station's crew!"
/obj/structure/ninjatele
name = "Long-Distance Teleportation Console"
desc = "A console used to send a Spider Clan operative long distances rapidly."
icon = 'icons/obj/ninjaobjects.dmi'
icon_state = "teleconsole"
anchored = 1
density = 0
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
return attack_hand(user)
attack_hand(mob/user as mob)
if (user.mind.special_role=="Ninja")
switch(alert("Phase Jaunt relay primed, target locked as [station_name()], initiate VOID-shift translocation? (Warning! Internals required!)",,"Yes","No"))
if("Yes")
if(user.z != src.z) return
user.loc.loc.Exited(user)
user.loc = pick(carplist) // In the future, possibly make specific NinjaTele landmarks, and give him an option to teleport to North/South/East/West of SS13 instead of just hijacking a carpspawn.
playsound(user.loc, 'sound/effects/phasein.ogg', 25, 1)
playsound(user.loc, 'sound/effects/sparks2.ogg', 50, 1)
anim(user.loc,user,'icons/mob/mob.dmi',,"phasein",,user.dir)
user <<"\blue <b>VOID-Shift</b> translocation successful"
if("No")
user <<"\red <b>Process aborted!</b>"
return
else
user<< "\red <B>FĆAL �Rr�R</B>: µ§er n¤t rec¤gnized, c-c¤ntr-r¤£§-£§ £¤cked."
+21 -4
View File
@@ -146,8 +146,10 @@
if (M.loc == loc)
wash(M)
check_heat(M)
M.water_act(100, convertHeat(), src)
for (var/atom/movable/G in src.loc)
G.clean_blood()
G.water_act(100, convertHeat(), src)
/obj/machinery/shower/attackby(obj/item/I as obj, mob/user as mob, params)
if(I.type == /obj/item/device/analyzer)
@@ -163,6 +165,8 @@
if("boiling")
watertemp = "normal"
user.visible_message("<span class='notice'>[user] adjusts the shower with the [I].</span>", "<span class='notice'>You adjust the shower with the [I].</span>")
if(on)
I.water_act(100, convertHeat(), src)
/obj/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up
overlays.Cut() //once it's been on for a while, in addition to handling the water overlay.
@@ -201,10 +205,21 @@
mobpresent -= 1
..()
/obj/machinery/shower/proc/convertHeat()
switch(watertemp)
if("boiling")
return 340.15
if("normal")
return 310.15
if("freezing")
return 230.15
//Yes, showers are super powerful as far as washing goes.
/obj/machinery/shower/proc/wash(atom/movable/O as obj|mob)
if(!on) return
O.water_act(100, convertHeat(), src)
if(isliving(O))
var/mob/living/L = O
L.ExtinguishMob()
@@ -293,22 +308,22 @@
check_heat(C)
/obj/machinery/shower/proc/check_heat(mob/M as mob)
M.water_act(100, convertHeat(), src) //convenience
if(!on || watertemp == "normal") return
if(iscarbon(M))
var/mob/living/carbon/C = M
if(watertemp == "freezing")
C.bodytemperature = max(80, C.bodytemperature - 80)
//C.bodytemperature = max(80, C.bodytemperature - 80)
C << "<span class='warning'>The water is freezing!</span>"
return
if(watertemp == "boiling")
C.bodytemperature = min(500, C.bodytemperature + 35)
//C.bodytemperature = min(500, C.bodytemperature + 35)
C.adjustFireLoss(5)
C << "<span class='danger'>The water is searing!</span>"
return
/obj/item/weapon/bikehorn/rubberducky
name = "rubber ducky"
desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl
@@ -372,7 +387,9 @@
user.visible_message("\blue [user] fills the [RG] using \the [src].","\blue You fill the [RG] using \the [src].")
return
else if (istype(O, /obj/item/weapon/melee/baton))
O.water_act(20,310.15,src)
if (istype(O, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = O
if (B.bcell.charge > 0 && B.status == 1)
flick("baton_active", src)
+1
View File
@@ -43,6 +43,7 @@
acceptable_reagents |= reagent
if (recipe.items)
max_n_of_items = max(max_n_of_items,recipe.items.len)
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/candy_maker(null)
+1
View File
@@ -44,6 +44,7 @@
acceptable_reagents |= reagent
if (recipe.items)
max_n_of_items = max(max_n_of_items,recipe.items.len)
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/grill(null)
+1
View File
@@ -44,6 +44,7 @@
acceptable_reagents |= reagent
if (recipe.items)
max_n_of_items = max(max_n_of_items,recipe.items.len)
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/oven(null)
File diff suppressed because it is too large Load Diff
+36 -66
View File
@@ -51,11 +51,11 @@
/datum/recipe/oven/bananabread
reagents = list("milk" = 5, "sugar" = 15)
fruit = list("banana" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/grown/banana,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread
@@ -68,13 +68,11 @@
/datum/recipe/oven/carrotcake
reagents = list("milk" = 5, "sugar" = 15)
fruit = list("carrot" = 3)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot,
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot,
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake
@@ -121,24 +119,24 @@
/datum/recipe/oven/pie
reagents = list("sugar" = 5)
fruit = list("banana" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/banana,
)
result = /obj/item/weapon/reagent_containers/food/snacks/pie
/datum/recipe/oven/cherrypie
reagents = list("sugar" = 10)
fruit = list("cherries" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries,
)
result = /obj/item/weapon/reagent_containers/food/snacks/cherrypie
/datum/recipe/oven/berryclafoutis
fruit = list("berries" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/berries,
)
result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis
@@ -157,8 +155,8 @@
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread
/datum/recipe/oven/loadedbakedpotato
fruit = list("potato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/grown/potato,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
)
result = /obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato
@@ -194,73 +192,65 @@
return .
/datum/recipe/oven/pizzamargherita
fruit = list("tomato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita
/datum/recipe/oven/meatpizza
fruit = list("tomato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/meat,
/obj/item/weapon/reagent_containers/food/snacks/meat,
/obj/item/weapon/reagent_containers/food/snacks/meat,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza
/datum/recipe/oven/syntipizza
fruit = list("tomato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh,
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh,
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza
/datum/recipe/oven/mushroompizza
fruit = list("mushroom" = 5, "tomato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza
/datum/recipe/oven/vegetablepizza
fruit = list("eggplant" = 1, "carrot" = 1, "corn" = 1, "tomato" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant,
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot,
/obj/item/weapon/reagent_containers/food/snacks/grown/corn,
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza
/datum/recipe/oven/amanita_pie
fruit = list("amanita" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita,
)
result = /obj/item/weapon/reagent_containers/food/snacks/amanita_pie
/datum/recipe/oven/plump_pie
fruit = list("plumphelmet" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet,
)
result = /obj/item/weapon/reagent_containers/food/snacks/plump_pie
@@ -300,74 +290,58 @@
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bread
/datum/recipe/oven/applepie
fruit = list("apple" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
/obj/item/weapon/reagent_containers/food/snacks/grown/apple,
)
result = /obj/item/weapon/reagent_containers/food/snacks/applepie
/datum/recipe/oven/applecake
reagents = list("milk" = 5, "sugar" = 5)
fruit = list("apple" = 2)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/grown/apple,
/obj/item/weapon/reagent_containers/food/snacks/grown/apple,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake
/datum/recipe/oven/orangecake
reagents = list("milk" = 5)
fruit = list("orange" = 2)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/grown/orange,
/obj/item/weapon/reagent_containers/food/snacks/grown/orange,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake
/datum/recipe/oven/limecake
reagents = list("milk" = 5)
fruit = list("lime" = 2)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/grown/lime,
/obj/item/weapon/reagent_containers/food/snacks/grown/lime,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake
/datum/recipe/oven/lemoncake
reagents = list("milk" = 5)
fruit = list("lemon" = 2)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/grown/lemon,
/obj/item/weapon/reagent_containers/food/snacks/grown/lemon,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake
/datum/recipe/oven/chocolatecake
reagents = list("milk" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
)
@@ -376,33 +350,29 @@
/datum/recipe/oven/braincake
reagents = list("milk" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/organ/brain
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake
/datum/recipe/oven/pumpkinpie
reagents = list("milk" = 5, "sugar" = 5)
fruit = list("pumpkin" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie
/datum/recipe/oven/appletart
reagents = list("sugar" = 5, "milk" = 5)
fruit = list("goldapple" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple,
)
result = /obj/item/weapon/reagent_containers/food/snacks/appletart
+58
View File
@@ -0,0 +1,58 @@
//Misc
#define DEAD_PLANT_COLOUR "#C2A180"
// Definitions for genes (trait groupings)
#define GENE_BIOCHEMISTRY "biochemistry"
#define GENE_HARDINESS "hardiness"
#define GENE_ENVIRONMENT "environment"
#define GENE_METABOLISM "metabolism"
#define GENE_STRUCTURE "appearance"
#define GENE_DIET "diet"
#define GENE_PIGMENT "pigment"
#define GENE_OUTPUT "output"
#define GENE_ATMOSPHERE "atmosphere"
#define GENE_VIGOUR "vigour"
#define GENE_FRUIT "fruit"
#define GENE_SPECIAL "special"
#define ALL_GENES list(GENE_BIOCHEMISTRY,GENE_HARDINESS,GENE_ENVIRONMENT,GENE_METABOLISM,GENE_STRUCTURE,GENE_DIET,GENE_PIGMENT,GENE_OUTPUT,GENE_ATMOSPHERE,GENE_VIGOUR,GENE_FRUIT,GENE_SPECIAL)
//Definitions for traits (individual descriptors)
#define TRAIT_CHEMS 1
#define TRAIT_EXUDE_GASSES 2
#define TRAIT_ALTER_TEMP 3
#define TRAIT_POTENCY 4
#define TRAIT_HARVEST_REPEAT 5
#define TRAIT_PRODUCES_POWER 6
#define TRAIT_JUICY 7
#define TRAIT_PRODUCT_ICON 8
#define TRAIT_PLANT_ICON 0
#define TRAIT_CONSUME_GASSES 10
#define TRAIT_REQUIRES_NUTRIENTS 11
#define TRAIT_NUTRIENT_CONSUMPTION 12
#define TRAIT_REQUIRES_WATER 13
#define TRAIT_WATER_CONSUMPTION 14
#define TRAIT_CARNIVOROUS 15
#define TRAIT_PARASITE 16
#define TRAIT_STINGS 17
#define TRAIT_IDEAL_HEAT 18
#define TRAIT_HEAT_TOLERANCE 19
#define TRAIT_IDEAL_LIGHT 20
#define TRAIT_LIGHT_TOLERANCE 21
#define TRAIT_LOWKPA_TOLERANCE 22
#define TRAIT_HIGHKPA_TOLERANCE 23
#define TRAIT_EXPLOSIVE 24
#define TRAIT_TOXINS_TOLERANCE 25
#define TRAIT_PEST_TOLERANCE 26
#define TRAIT_WEED_TOLERANCE 27
#define TRAIT_ENDURANCE 28
#define TRAIT_YIELD 29
#define TRAIT_SPREAD 30
#define TRAIT_MATURATION 31
#define TRAIT_PRODUCTION 32
#define TRAIT_TELEPORTING 33
#define TRAIT_PLANT_COLOUR 34
#define TRAIT_PRODUCT_COLOUR 35
#define TRAIT_BIOLUM 36
#define TRAIT_BIOLUM_COLOUR 37
#define TRAIT_IMMUTABLE 38
+394
View File
@@ -0,0 +1,394 @@
//Grown foods.
/obj/item/weapon/reagent_containers/food/snacks/grown
name = "fruit"
icon = 'icons/obj/hydroponics_products.dmi'
icon_state = "blank"
desc = "Nutritious! Probably."
var/plantname
var/datum/seed/seed
var/potency = -1
/obj/item/weapon/reagent_containers/food/snacks/grown/New(newloc,planttype)
..()
if(!dried_type)
dried_type = type
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
// Fill the object up with the appropriate reagents.
if(planttype)
plantname = planttype
if(!plantname)
return
if(!plant_controller)
sleep(250) // ugly hack, should mean roundstart plants are fine.
if(!plant_controller)
world << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
del(src)
return
seed = plant_controller.seeds[plantname]
if(!seed)
return
name = "[seed.seed_name]"
update_icon()
if(!seed.chems)
return
potency = seed.get_trait(TRAIT_POTENCY)
for(var/rid in seed.chems)
var/list/reagent_data = seed.chems[rid]
if(reagent_data && reagent_data.len)
var/rtotal = reagent_data[1]
if(reagent_data.len > 1 && potency > 0)
rtotal += round(potency/reagent_data[2])
reagents.add_reagent(rid,max(1,rtotal))
update_desc()
if(reagents.total_volume > 0)
bitesize = 1+round(reagents.total_volume / 2, 1)
/obj/item/weapon/reagent_containers/food/snacks/grown/proc/update_desc()
if(!seed)
return
if(!plant_controller)
sleep(250) // ugly hack, should mean roundstart plants are fine.
if(!plant_controller)
world << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
del(src)
return
if(plant_controller.product_descs["[seed.uid]"])
desc = plant_controller.product_descs["[seed.uid]"]
else
var/list/descriptors = list()
if(reagents.has_reagent("sugar") || reagents.has_reagent("cherryjelly") || reagents.has_reagent("honey") || reagents.has_reagent("berryjuice"))
descriptors |= "sweet"
if(reagents.has_reagent("anti_toxin"))
descriptors |= "astringent"
if(reagents.has_reagent("frostoil"))
descriptors |= "numbing"
if(reagents.has_reagent("nutriment"))
descriptors |= "nutritious"
if(reagents.has_reagent("condensedcapsaicin") || reagents.has_reagent("capsaicin"))
descriptors |= "spicy"
if(reagents.has_reagent("coco"))
descriptors |= "bitter"
if(reagents.has_reagent("orangejuice") || reagents.has_reagent("lemonjuice") || reagents.has_reagent("limejuice"))
descriptors |= "sweet-sour"
if(reagents.has_reagent("radium") || reagents.has_reagent("uranium"))
descriptors |= "radioactive"
if(reagents.has_reagent("amatoxin") || reagents.has_reagent("toxin"))
descriptors |= "poisonous"
if(reagents.has_reagent("psilocybin") || reagents.has_reagent("space_drugs"))
descriptors |= "hallucinogenic"
if(reagents.has_reagent("bicaridine"))
descriptors |= "medicinal"
if(reagents.has_reagent("gold"))
descriptors |= "shiny"
if(reagents.has_reagent("lube"))
descriptors |= "slippery"
if(reagents.has_reagent("pacid") || reagents.has_reagent("sacid"))
descriptors |= "acidic"
if(seed.get_trait(TRAIT_JUICY))
descriptors |= "juicy"
if(seed.get_trait(TRAIT_STINGS))
descriptors |= "stinging"
if(seed.get_trait(TRAIT_TELEPORTING))
descriptors |= "glowing"
if(seed.get_trait(TRAIT_EXPLOSIVE))
descriptors |= "bulbous"
var/descriptor_num = rand(2,4)
var/descriptor_count = descriptor_num
desc = "A"
while(descriptors.len && descriptor_num > 0)
var/chosen = pick(descriptors)
descriptors -= chosen
desc += "[(descriptor_count>1 && descriptor_count!=descriptor_num) ? "," : "" ] [chosen]"
descriptor_num--
if(seed.seed_noun == "spores")
desc += " mushroom"
else
desc += " fruit"
plant_controller.product_descs["[seed.uid]"] = desc
desc += ". Delicious! Probably."
/obj/item/weapon/reagent_containers/food/snacks/grown/update_icon()
if(!seed || !plant_controller || !plant_controller.plant_icon_cache)
return
overlays.Cut()
var/image/plant_icon
var/icon_key = "fruit-[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"
if(plant_controller.plant_icon_cache[icon_key])
plant_icon = plant_controller.plant_icon_cache[icon_key]
else
plant_icon = image('icons/obj/hydroponics_products.dmi',"blank")
var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product")
fruit_base.color = "[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"
plant_icon.overlays |= fruit_base
if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in icon_states('icons/obj/hydroponics_products.dmi'))
var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf")
fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]"
plant_icon.overlays |= fruit_leaves
plant_controller.plant_icon_cache[icon_key] = plant_icon
overlays |= plant_icon
/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M)
if(seed && seed.get_trait(TRAIT_JUICY) == 2)
if(istype(M))
if(M.buckled)
return
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.shoes && H.shoes.flags & NOSLIP)
return
M.stop_pulling()
M << "<span class='notice'>You slipped on the [name]!</span>"
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
M.Stun(8)
M.Weaken(5)
seed.thrown_at(src,M)
sleep(-1)
if(src) del(src)
return
/obj/item/weapon/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom)
..()
if(seed) seed.thrown_at(src,hit_atom)
/obj/item/weapon/reagent_containers/food/snacks/grown/attackby(var/obj/item/weapon/W, var/mob/user)
if(seed)
if(seed.get_trait(TRAIT_PRODUCES_POWER) && istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(C.use(5))
//TODO: generalize this.
user << "<span class='notice'>You add some cable to the [src.name] and slide it inside the battery casing.</span>"
var/obj/item/weapon/stock_parts/cell/potato/pocell = new /obj/item/weapon/stock_parts/cell/potato(get_turf(user))
if(src.loc == user && !(user.l_hand && user.r_hand) && istype(user,/mob/living/carbon/human))
user.put_in_hands(pocell)
pocell.maxcharge = src.potency * 10
pocell.charge = pocell.maxcharge
del(src)
return
else if(W.sharp)
if(seed.kitchen_tag == "pumpkin") // Ugggh these checks are awful.
user.show_message("<span class='notice'>You carve a face into [src]!</span>", 1)
new /obj/item/clothing/head/hardhat/pumpkinhead (user.loc)
del(src)
return
else if(seed.kitchen_tag == "potato")
user << "You slice \the [src] into sticks."
new /obj/item/weapon/reagent_containers/food/snacks/rawsticks(get_turf(src))
del(src)
return
else if(seed.kitchen_tag == "carrot")
user << "You slice \the [src] into sticks."
new /obj/item/weapon/reagent_containers/food/snacks/carrotfries(get_turf(src))
del(src)
return
else if(seed.kitchen_tag == "watermelon")
user << "You slice \the [src] into large slices."
for(var/i=0,i<5,i++)
new /obj/item/weapon/reagent_containers/food/snacks/watermelonslice(get_turf(src))
del(src)
return
else if(seed.kitchen_tag == "soybeans")
user << "You roughly chop up \the [src]."
new /obj/item/weapon/reagent_containers/food/snacks/soydope(get_turf(src))
del(src)
return
else if(seed.chems)
if(istype(W,/obj/item/weapon/hatchet) && !isnull(seed.chems["woodpulp"]))
user.show_message("<span class='notice'>You make planks out of \the [src]!</span>", 1)
for(var/i=0,i<2,i++)
var/obj/item/stack/sheet/wood/NG = new (user.loc)
NG.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
for (var/obj/item/stack/sheet/wood/G in user.loc)
if(G==NG)
continue
if(G.amount>=G.max_amount)
continue
G.attackby(NG, user)
user << "You add the newly-formed wood to the stack. It now contains [NG.amount] planks."
del(src)
return
else if(istype(W, /obj/item/weapon/rollingpaper))
if(seed.kitchen_tag == "ambrosia" || seed.kitchen_tag == "ambrosiadeus" || seed.kitchen_tag == "tobacco" || seed.kitchen_tag == "stobacco")
user.unEquip(W)
if(seed.kitchen_tag == "ambrosia")
var/obj/item/clothing/mask/cigarette/joint/J = new /obj/item/clothing/mask/cigarette/joint(user.loc)
J.chem_volume = src.reagents.total_volume
src.reagents.trans_to(J, J.chem_volume)
del(W)
user.put_in_active_hand(J)
else if(seed.kitchen_tag == "ambrosiadeus")
var/obj/item/clothing/mask/cigarette/joint/deus/J = new /obj/item/clothing/mask/cigarette/joint/deus(user.loc)
J.chem_volume = src.reagents.total_volume
src.reagents.trans_to(J, J.chem_volume)
del(W)
user.put_in_active_hand(J)
else if(seed.kitchen_tag == "tobacco" || seed.kitchen_tag == "stobacco")
var/obj/item/clothing/mask/cigarette/handroll/J = new /obj/item/clothing/mask/cigarette/handroll(user.loc)
J.chem_volume = src.reagents.total_volume
src.reagents.trans_to(J, J.chem_volume)
del(W)
user.put_in_active_hand(J)
user << "\blue You roll the [src] into a rolling paper."
del(src)
else
user << "\red You can't roll a smokable from the [src]."
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/attack(var/mob/living/carbon/M, var/mob/user, var/def_zone)
if(user == M)
return ..()
if(user.a_intent == "hurt")
// This is being copypasted here because reagent_containers (WHY DOES FOOD DESCEND FROM THAT) overrides it completely.
// TODO: refactor all food paths to be less horrible and difficult to work with in this respect. ~Z
if(!istype(M) || (can_operate(M) && do_surgery(M,user,src))) return 0
user.lastattacked = M
M.lastattacker = user
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/hit = H.attacked_by(src, user, def_zone)
if(hit && hitsound)
playsound(loc, hitsound, 50, 1, -1)
return hit
else
if(attack_verb.len)
user.visible_message("<span class='danger'>[M] has been [pick(attack_verb)] with [src] by [user]!</span>")
else
user.visible_message("<span class='danger'>[M] has been attacked with [src] by [user]!</span>")
if (hitsound)
playsound(loc, hitsound, 50, 1, -1)
switch(damtype)
if("brute")
M.take_organ_damage(force)
if(prob(33))
var/turf/simulated/location = get_turf(M)
if(istype(location)) location.add_blood_floor(M)
if("fire")
if (!(RESIST_COLD in M.mutations))
M.take_organ_damage(0, force)
M.updatehealth()
if(seed && seed.get_trait(TRAIT_STINGS))
if(!reagents || reagents.total_volume <= 0)
return
reagents.remove_any(rand(1,3))
seed.thrown_at(src,M)
sleep(-1)
if(!src)
return
if(prob(35))
if(user)
user << "<span class='danger'>\The [src] has fallen to bits.</span>"
//user.drop_from_inventory(src)
del(src)
add_fingerprint(user)
return 1
else
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/attack_self(mob/user as mob)
if(!seed)
return
if(istype(user.loc,/turf/space))
return
if(user.a_intent == "hurt")
user.visible_message("<span class='danger'>\The [user] squashes \the [src]!</span>")
seed.thrown_at(src,user)
sleep(-1)
if(src) del(src)
return
if(seed.kitchen_tag == "grass")
user.show_message("<span class='notice'>You make a grass tile out of \the [src]!</span>", 1)
for(var/i=0,i<2,i++)
var/obj/item/stack/tile/grass/G = new (user.loc)
G.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
for (var/obj/item/stack/tile/grass/NG in user.loc)
if(G==NG)
continue
if(NG.amount>=NG.max_amount)
continue
NG.attackby(G, user)
user << "You add the newly-formed grass to the stack. It now contains [G.amount] tiles."
del(src)
return
if(seed.get_trait(TRAIT_SPREAD) > 0)
user << "<span class='notice'>You plant the [src.name].</span>"
new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(get_turf(user),src.seed)
new /obj/effect/plant(get_turf(user), src.seed)
del(src)
return
/*
if(seed.kitchen_tag)
switch(seed.kitchen_tag)
if("shand")
var/obj/item/stack/medical/bruise_pack/tajaran/poultice = new /obj/item/stack/medical/bruise_pack/tajaran(user.loc)
poultice.heal_brute = potency
user << "<span class='notice'>You mash the leaves into a poultice.</span>"
del(src)
return
if("mtear")
var/obj/item/stack/medical/ointment/tajaran/poultice = new /obj/item/stack/medical/ointment/tajaran(user.loc)
poultice.heal_burn = potency
user << "<span class='notice'>You mash the petals into a poultice.</span>"
del(src)
return
*/
/obj/item/weapon/reagent_containers/food/snacks/grown/pickup(mob/user)
..()
if(!seed)
return
if(seed.get_trait(TRAIT_BIOLUM))
user.SetLuminosity(user.luminosity + seed.get_trait(TRAIT_BIOLUM))
SetLuminosity(0)
if(seed.get_trait(TRAIT_STINGS))
var/mob/living/carbon/human/H = user
if(istype(H) && H.gloves)
return
if(!reagents || reagents.total_volume <= 0)
return
reagents.remove_any(rand(1,3)) //Todo, make it actually remove the reagents the seed uses.
seed.do_thorns(H,src)
seed.do_sting(H,src,pick("r_hand","l_hand"))
/obj/item/weapon/reagent_containers/food/snacks/grown/dropped(mob/user)
..()
if(seed && seed.get_trait(TRAIT_BIOLUM))
user.SetLuminosity(user.luminosity - seed.get_trait(TRAIT_BIOLUM))
SetLuminosity(seed.get_trait(TRAIT_BIOLUM))
+25 -149
View File
@@ -8,7 +8,7 @@
var/plantname
var/potency = 1
/obj/item/weapon/grown/New()
/obj/item/weapon/grown/New(newloc,planttype)
..()
@@ -17,112 +17,20 @@
R.my_atom = src
//Handle some post-spawn var stuff.
spawn(1)
// Fill the object up with the appropriate reagents.
if(!isnull(plantname))
var/datum/seed/S = seed_types[plantname]
if(!S || !S.chems)
return
potency = S.potency
for(var/rid in S.chems)
var/list/reagent_data = S.chems[rid]
var/rtotal = reagent_data[1]
if(reagent_data.len > 1 && potency > 0)
rtotal += round(potency/reagent_data[2])
reagents.add_reagent(rid,max(1,rtotal))
/obj/item/weapon/grown/proc/changePotency(newValue) //-QualityVan
potency = newValue
/obj/item/weapon/grown/log
name = "towercap"
name = "tower-cap log"
desc = "It's better than bad, it's good!"
icon = 'icons/obj/harvest.dmi'
icon_state = "logs"
force = 5
throwforce = 5
w_class = 3.0
throw_speed = 3
throw_range = 3
origin_tech = "materials=1"
attack_verb = list("bashed", "battered", "bludgeoned", "whacked")
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || (istype(W, /obj/item/weapon/twohanded/fireaxe) && W:wielded) || istype(W, /obj/item/weapon/melee/energy))
user.show_message("<span class='notice'>You make planks out of \the [src]!</span>", 1)
for(var/i=0,i<2,i++)
var/obj/item/stack/sheet/wood/NG = new (user.loc)
for (var/obj/item/stack/sheet/wood/G in user.loc)
if(G==NG)
continue
if(G.amount>=G.max_amount)
continue
G.attackby(NG, user, params)
usr << "You add the newly-formed wood to the stack. It now contains [NG.amount] planks."
del(src)
if(planttype)
plantname = planttype
var/datum/seed/S = plant_controller.seeds[plantname]
if(!S || !S.chems)
return
/obj/item/weapon/grown/sunflower // FLOWER POWER!
plantname = "sunflowers"
name = "sunflower"
desc = "It's beautiful! A certain person might beat you to death if you trample these."
icon = 'icons/obj/harvest.dmi'
icon_state = "sunflower"
damtype = "fire"
force = 0
throwforce = 1
w_class = 1.0
throw_speed = 1
throw_range = 3
potency = S.get_trait(TRAIT_POTENCY)
/obj/item/weapon/grown/sunflower/attack(mob/M as mob, mob/user as mob)
M << "<font color='green'><b> [user] smacks you with a sunflower!</font><font color='yellow'><b>FLOWER POWER<b></font>"
user << "<font color='green'> Your sunflower's </font><font color='yellow'><b>FLOWER POWER</b></font><font color='green'> strikes [M]</font>"
/obj/item/weapon/grown/nettle // -- Skie
plantname = "nettle"
desc = "It's probably <B>not</B> wise to touch it with bare hands..."
icon = 'icons/obj/weapons.dmi'
name = "nettle"
icon_state = "nettle"
damtype = "fire"
force = 15
throwforce = 1
w_class = 2.0
throw_speed = 1
throw_range = 3
origin_tech = "combat=1"
New()
..()
spawn(5)
force = round((5+potency/5), 1)
/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user as mob)
if(!user.gloves)
user << "\red The nettle burns your bare hand!"
if(istype(user, /mob/living/carbon/human))
var/organ = ((user.hand ? "l_":"r_") + "arm")
var/obj/item/organ/external/affecting = user.get_organ(organ)
if(affecting.take_damage(0,force))
user.UpdateDamageIcon()
else
user.take_organ_damage(0,force)
/obj/item/weapon/grown/nettle/afterattack(atom/A as mob|obj, mob/user as mob, proximity)
if(!proximity) return
if(force > 0)
force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
else
usr << "All the leaves have fallen off the nettle from violent whacking."
del(src)
/obj/item/weapon/grown/nettle/changePotency(newValue) //-QualityVan
potency = newValue
force = round((5+potency/5), 1)
for(var/rid in S.chems)
var/list/reagent_data = S.chems[rid]
var/rtotal = reagent_data[1]
if(reagent_data.len > 1 && potency > 0)
rtotal += round(potency/reagent_data[2])
reagents.add_reagent(rid,max(1,rtotal))
/obj/item/weapon/grown/deathnettle // -- Skie
plantname = "deathnettle"
@@ -147,53 +55,10 @@
viewers(user) << "\red <b>[user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.</b>"
return (BRUTELOSS|TOXLOSS)
/obj/item/weapon/grown/deathnettle/pickup(mob/living/carbon/human/user as mob)
if(!user.gloves)
if(istype(user, /mob/living/carbon/human))
var/organ = ((user.hand ? "l_":"r_") + "arm")
var/obj/item/organ/external/affecting = user.get_organ(organ)
if(affecting.take_damage(0,force))
user.UpdateDamageIcon()
else
user.take_organ_damage(0,force)
if(prob(50))
user.Paralyse(5)
user << "\red You are stunned by the Deathnettle when you try picking it up!"
/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M as mob, mob/user as mob)
if(!..()) return
if(istype(M, /mob/living))
M << "\red You are stunned by the powerful acid of the Deathnettle!"
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Had the [src.name] used on them by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] on [M.name] ([M.ckey])</font>")
msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used the [src.name] on [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
M.eye_blurry += force/7
if(prob(20))
M.Paralyse(force/6)
M.Weaken(force/15)
M.drop_item()
/obj/item/weapon/grown/deathnettle/afterattack(atom/A as mob|obj, mob/user as mob, proximity)
if(!proximity) return
if (force > 0)
force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off
else
usr << "All the leaves have fallen off the deathnettle from violent whacking."
del(src)
/obj/item/weapon/grown/deathnettle/changePotency(newValue) //-QualityVan
potency = newValue
force = round((5+potency/2.5), 1)
/obj/item/weapon/corncob
name = "corn cob"
desc = "A reminder of meals gone by."
icon = 'icons/obj/harvest.dmi'
icon = 'icons/obj/trash.dmi'
icon_state = "corncob"
item_state = "corncob"
w_class = 2.0
@@ -201,10 +66,21 @@
throw_speed = 4
throw_range = 20
/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchen/utensil/knife) || istype(W, /obj/item/weapon/kitchenknife) || istype(W, /obj/item/weapon/kitchenknife/ritual))
user << "<span class='notice'>You use [W] to fashion a pipe out of the corn cob!</span>"
new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc)
del(src)
return
/obj/item/weapon/bananapeel
name = "banana peel"
desc = "A peel from a banana."
icon = 'icons/obj/items.dmi'
icon_state = "banana_peel"
item_state = "banana_peel"
w_class = 2.0
throwforce = 0
throw_speed = 4
throw_range = 20
@@ -0,0 +1,40 @@
// Predefined types for placing on the map.
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap
plantname = "libertycap"
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris
plantname = "ambrosia"
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato
plantname = "tomato"
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot
plantname = "carrot"
/obj/item/weapon/reagent_containers/food/snacks/grown/berries
plantname = "berries"
/obj/item/weapon/reagent_containers/food/snacks/grown/banana
plantname = "banana"
/obj/item/weapon/reagent_containers/food/snacks/grown/chili
plantname = "chili"
/obj/item/weapon/reagent_containers/food/snacks/grown/lemon
plantname = "lemon"
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries
plantname = "cherry"
/obj/item/weapon/reagent_containers/food/snacks/grown/orange
plantname = "orange"
/obj/item/weapon/reagent_containers/food/snacks/grown/corn
plantname = "corn"
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita
plantname = "amanita"
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus
plantname = "ambrosiadeus"
+743
View File
@@ -0,0 +1,743 @@
/datum/plantgene
var/genetype // Label used when applying trait.
var/list/values // Values to copy into the target seed datum.
/datum/seed
//Tracking.
var/uid // Unique identifier.
var/name // Index for global list.
var/seed_name // Plant name for seed packet.
var/seed_noun = "seeds" // Descriptor for packet.
var/display_name // Prettier name.
var/roundstart // If set, seed will not display variety number.
var/mysterious // Only used for the random seed packets.
var/can_self_harvest = 0 // Mostly used for living mobs.
var/growth_stages = 0 // Number of stages the plant passes through before it is mature.
var/list/traits = list() // Initialized in New()
var/list/mutants // Possible predefined mutant varieties, if any.
var/list/chems // Chemicals that plant produces in products/injects into victim.
var/list/consume_gasses // The plant will absorb these gasses during its life.
var/list/exude_gasses // The plant will exude these gasses during its life.
var/kitchen_tag // Used by the reagent grinder.
var/trash_type // Garbage item produced when eaten.
var/splat_type = /obj/effect/decal/cleanable/fruit_smudge // Graffiti decal.
var/has_mob_product
/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, "#46B543") // Colour of the plant icon.
spawn(5)
sleep(-1)
update_growth_stages()
/datum/seed/proc/get_trait(var/trait)
return traits["[trait]"]
/datum/seed/proc/set_trait(var/trait,var/nval,var/ubound,var/lbound, var/degrade)
if(!isnull(degrade)) nval *= degrade
if(!isnull(ubound)) nval = min(nval,ubound)
if(!isnull(lbound)) nval = max(nval,lbound)
traits["[trait]"] = nval
/datum/seed/proc/create_spores(var/turf/T, var/obj/item/thrown)
if(!T)
return
if(!istype(T))
T = get_turf(T)
if(!T)
return
var/datum/reagents/R = new/datum/reagents(100)
R.my_atom = thrown
if(chems.len)
for(var/rid in chems)
var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/3))
R.add_reagent(rid,injecting)
var/datum/effect/effect/system/chem_smoke_spread/S = new()
S.attach(T)
S.set_up(R, round(get_trait(TRAIT_POTENCY)/4), 0, T)
S.start()
// Does brute damage to a target.
/datum/seed/proc/do_thorns(var/mob/living/carbon/human/target, var/obj/item/fruit, var/target_limb)
if(!get_trait(TRAIT_CARNIVOROUS))
return
if(!istype(target))
if(istype(target, /mob/living/simple_animal/mouse) || istype(target, /mob/living/simple_animal/lizard))
new /obj/effect/decal/cleanable/blood/splatter(get_turf(target))
del(target)
return
if(!target_limb) target_limb = pick("l_foot","r_foot","l_leg","r_leg","l_hand","r_hand","l_arm", "r_arm","head","chest","groin")
var/obj/item/organ/external/affecting = target.get_organ(target_limb)
var/damage = 0
if(get_trait(TRAIT_CARNIVOROUS))
if(get_trait(TRAIT_CARNIVOROUS) == 2)
if(affecting)
target << "<span class='danger'>\The [fruit]'s thorns pierce your [affecting.name] greedily!</span>"
else
target << "<span class='danger'>\The [fruit]'s thorns pierce your flesh greedily!</span>"
damage = get_trait(TRAIT_POTENCY)/2
else
if(affecting)
target << "<span class='danger'>\The [fruit]'s thorns dig deeply into your [affecting.name]!</span>"
else
target << "<span class='danger'>\The [fruit]'s thorns dig deeply into your flesh!</span>"
damage = get_trait(TRAIT_POTENCY)/5
else
return
if(affecting)
affecting.take_damage(damage, 0)
affecting.add_autopsy_data("Thorns",damage)
else
target.adjustBruteLoss(damage)
target.UpdateDamageIcon()
target.updatehealth()
// Adds reagents to a target.
/datum/seed/proc/do_sting(var/mob/living/carbon/human/target, var/obj/item/fruit)
if(!get_trait(TRAIT_STINGS))
return
if(chems && chems.len)
var/body_coverage = HEAD|HEADCOVERSMOUTH|HEADCOVERSEYES|UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
for(var/obj/item/clothing/clothes in target)
if(target.l_hand == clothes|| target.r_hand == clothes)
continue
body_coverage &= ~(clothes.body_parts_covered)
if(!body_coverage)
return
target << "<span class='danger'>You are stung by \the [fruit]!</span>"
for(var/rid in chems)
var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/5))
target.reagents.add_reagent(rid,injecting)
//Splatter a turf.
/datum/seed/proc/splatter(var/turf/T,var/obj/item/thrown)
if(splat_type)
var/obj/effect/plant/splat = new splat_type(T, src)
if(!istype(splat)) // Plants handle their own stuff.
splat.name = "[thrown.name] [pick("smear","smudge","splatter")]"
if(get_trait(TRAIT_BIOLUM))
if(get_trait(TRAIT_BIOLUM_COLOUR))
splat.l_color = get_trait(TRAIT_BIOLUM_COLOUR)
splat.SetLuminosity(get_trait(TRAIT_BIOLUM))
if(get_trait(TRAIT_PRODUCT_COLOUR))
splat.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(chems)
for(var/mob/living/M in T.contents)
if(!M.reagents)
continue
for(var/chem in chems)
var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/3))
M.reagents.add_reagent(chem,injecting)
//Applies an effect to a target atom.
/datum/seed/proc/thrown_at(var/obj/item/thrown,var/atom/target, var/force_explode)
var/splatted
var/turf/origin_turf = get_turf(target)
if(force_explode || get_trait(TRAIT_EXPLOSIVE))
create_spores(origin_turf, thrown)
var/flood_dist = min(10,max(1,get_trait(TRAIT_POTENCY)/15))
var/list/open_turfs = list()
var/list/closed_turfs = list()
var/list/valid_turfs = list()
open_turfs |= origin_turf
// Flood fill to get affected turfs.
while(open_turfs.len)
var/turf/T = pick(open_turfs)
open_turfs -= T
closed_turfs |= T
valid_turfs |= T
for(var/dir in alldirs)
var/turf/neighbor = get_step(T,dir)
if(!neighbor || (neighbor in closed_turfs) || (neighbor in open_turfs))
continue
if(neighbor.density || get_dist(neighbor,origin_turf) > flood_dist || istype(neighbor,/turf/space))
closed_turfs |= neighbor
continue
// Check for windows.
var/no_los
var/turf/last_turf = origin_turf
for(var/turf/target_turf in getline(origin_turf,neighbor))
if(!last_turf.Enter(target_turf) || target_turf.density)
no_los = 1
break
last_turf = target_turf
if(!no_los && !origin_turf.Enter(neighbor))
no_los = 1
if(no_los)
closed_turfs |= neighbor
continue
open_turfs |= neighbor
for(var/turf/T in valid_turfs)
for(var/mob/living/M in T.contents)
apply_special_effect(M)
splatter(T,thrown)
origin_turf.visible_message("<span class='danger'>The [thrown.name] explodes!</span>")
del(thrown)
return
if(istype(target,/mob/living))
splatted = apply_special_effect(target,thrown)
else if(istype(target,/turf))
splatted = 1
for(var/mob/living/M in target.contents)
apply_special_effect(M)
if(get_trait(TRAIT_JUICY) && splatted)
splatter(origin_turf,thrown)
origin_turf.visible_message("<span class='danger'>The [thrown.name] splatters against [target]!</span>")
del(thrown)
/datum/seed/proc/handle_environment(var/turf/current_turf, var/datum/gas_mixture/environment, var/light_supplied, var/check_only)
var/health_change = 0
/*
// Handle gas consumption.
if(consume_gasses && consume_gasses.len)
var/missing_gas = 0
for(var/gas in consume_gasses)
if(environment && environment.gas && environment.gas[gas] && \
environment.gas[gas] >= consume_gasses[gas])
if(!check_only)
environment.adjust_gas(gas,-consume_gasses[gas],1)
else
missing_gas++
if(missing_gas > 0)
health_change += missing_gas * HYDRO_SPEED_MULTIPLIER
*/
// Process it.
var/pressure = environment.return_pressure()
if(pressure < get_trait(TRAIT_LOWKPA_TOLERANCE)|| pressure > get_trait(TRAIT_HIGHKPA_TOLERANCE))
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
if(abs(environment.temperature - get_trait(TRAIT_IDEAL_HEAT)) > get_trait(TRAIT_HEAT_TOLERANCE))
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
/*
// Handle gas production.
if(exude_gasses && exude_gasses.len && !check_only)
for(var/gas in exude_gasses)
environment.adjust_gas(gas, max(1,round((exude_gasses[gas]*(get_trait(TRAIT_POTENCY)/5))/exude_gasses.len)))
*/
// Handle light requirements.
if(!light_supplied)
var/area/A = get_area(current_turf)
if(A)
if(A.lighting_use_dynamic)
light_supplied = max(0,min(10,current_turf.lighting_lumcount)-5)
else
light_supplied = 5
if(light_supplied)
if(abs(light_supplied - get_trait(TRAIT_IDEAL_LIGHT)) > get_trait(TRAIT_LIGHT_TOLERANCE))
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
return health_change
/datum/seed/proc/apply_special_effect(var/mob/living/target,var/obj/item/thrown)
var/impact = 1
do_sting(target,thrown)
do_thorns(target,thrown)
// Bluespace tomato code copied over from grown.dm.
if(get_trait(TRAIT_TELEPORTING))
//Plant potency determines radius of teleport.
var/outer_teleport_radius = get_trait(TRAIT_POTENCY)/5
var/inner_teleport_radius = get_trait(TRAIT_POTENCY)/15
var/list/turfs = list()
if(inner_teleport_radius > 0)
for(var/turf/T in orange(target,outer_teleport_radius))
if(get_dist(target,T) >= inner_teleport_radius)
turfs |= T
if(turfs.len)
// Moves the mob, causes sparks.
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, get_turf(target))
s.start()
var/turf/picked = get_turf(pick(turfs)) // Just in case...
new/obj/effect/decal/cleanable/molten_item(get_turf(target)) // Leave a pile of goo behind for dramatic effect...
target.loc = picked // And teleport them to the chosen location.
impact = 1
return impact
//Creates a random seed. MAKE SURE THE LINE HAS DIVERGED BEFORE THIS IS CALLED.
/datum/seed/proc/randomize()
roundstart = 0
seed_name = "strange plant" // TODO: name generator.
display_name = "strange plants" // TODO: name generator.
mysterious = 1
seed_noun = pick("spores","nodes","cuttings","seeds")
set_trait(TRAIT_POTENCY,rand(5,30),200,0)
set_trait(TRAIT_PRODUCT_ICON,pick(plant_controller.plant_product_sprites))
set_trait(TRAIT_PLANT_ICON,pick(plant_controller.plant_sprites))
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))
set_trait(TRAIT_HARVEST_REPEAT,1)
if(prob(15))
if(prob(15))
set_trait(TRAIT_JUICY,2)
else
set_trait(TRAIT_JUICY,1)
if(prob(5))
set_trait(TRAIT_STINGS,1)
if(prob(5))
set_trait(TRAIT_PRODUCES_POWER,1)
if(prob(1))
set_trait(TRAIT_EXPLOSIVE,1)
else if(prob(1))
set_trait(TRAIT_TELEPORTING,1)
if(prob(5))
consume_gasses = list()
var/gas = pick("oxygen","nitrogen","plasma","carbon_dioxide")
consume_gasses[gas] = rand(3,9)
if(prob(5))
exude_gasses = list()
var/gas = pick("oxygen","nitrogen","plasma","carbon_dioxide")
exude_gasses[gas] = rand(3,9)
chems = list()
if(prob(80))
chems["nutriment"] = list(rand(1,10),rand(10,20))
var/additional_chems = rand(0,5)
if(additional_chems)
var/list/possible_chems = list(
"woodpulp",
"styptic_powder",
"methamphetamine",
"cryoxadone",
"blood",
"water",
"potassium",
"plasticide",
"mutationtoxin",
"amutationtoxin",
"epinephrine",
"space_drugs",
"salglu_solution",
"mercury",
"sugar",
"radium",
"mutadone",
"mannitol",
"thermite",
"sal_acid",
"atropine",
"omnizine",
"salbutamol",
"plasma",
"synaptizine",
"haloperidol",
"potass_iodide",
"mitocholide",
"toxin",
"rezadone",
"antihol",
"slimejelly",
"cyanide",
"lsd",
"morphine"
)
for(var/x=1;x<=additional_chems;x++)
if(!possible_chems.len)
break
var/new_chem = pick(possible_chems)
possible_chems -= new_chem
chems[new_chem] = list(rand(1,10),rand(10,20))
if(prob(90))
set_trait(TRAIT_REQUIRES_NUTRIENTS,1)
set_trait(TRAIT_NUTRIENT_CONSUMPTION,rand(25)/25)
else
set_trait(TRAIT_REQUIRES_NUTRIENTS,0)
if(prob(90))
set_trait(TRAIT_REQUIRES_WATER,1)
set_trait(TRAIT_WATER_CONSUMPTION,rand(10))
else
set_trait(TRAIT_REQUIRES_WATER,0)
set_trait(TRAIT_IDEAL_HEAT, rand(100,400))
set_trait(TRAIT_HEAT_TOLERANCE, rand(10,30))
set_trait(TRAIT_IDEAL_LIGHT, rand(2,10))
set_trait(TRAIT_LIGHT_TOLERANCE, rand(2,7))
set_trait(TRAIT_TOXINS_TOLERANCE, rand(2,7))
set_trait(TRAIT_PEST_TOLERANCE, rand(2,7))
set_trait(TRAIT_WEED_TOLERANCE, rand(2,7))
set_trait(TRAIT_LOWKPA_TOLERANCE, rand(10,50))
set_trait(TRAIT_HIGHKPA_TOLERANCE,rand(100,300))
if(prob(5))
set_trait(TRAIT_ALTER_TEMP,rand(-5,5))
if(prob(1))
set_trait(TRAIT_IMMUTABLE,-1)
var/carnivore_prob = rand(100)
if(carnivore_prob < 5)
set_trait(TRAIT_CARNIVOROUS,2)
else if(carnivore_prob < 10)
set_trait(TRAIT_CARNIVOROUS,1)
if(prob(10))
set_trait(TRAIT_PARASITE,1)
var/vine_prob = rand(100)
if(vine_prob < 5)
set_trait(TRAIT_SPREAD,2)
else if(vine_prob < 10)
set_trait(TRAIT_SPREAD,1)
if(prob(5))
set_trait(TRAIT_BIOLUM,1)
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))
set_trait(TRAIT_MATURATION,rand(5,15))
set_trait(TRAIT_PRODUCTION,get_trait(TRAIT_MATURATION)+rand(2,5))
//Returns a key corresponding to an entry in the global seed list.
/datum/seed/proc/get_mutant_variant()
if(!mutants || !mutants.len || get_trait(TRAIT_IMMUTABLE) > 0) return 0
return pick(mutants)
//Mutates the plant overall (randomly).
/datum/seed/proc/mutate(var/degree,var/turf/source_turf)
if(!degree || get_trait(TRAIT_IMMUTABLE) > 0) return
source_turf.visible_message("<span class='notice'>\The [display_name] quivers!</span>")
//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,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>")
if(1)
set_trait(TRAIT_NUTRIENT_CONSUMPTION,get_trait(TRAIT_NUTRIENT_CONSUMPTION)+rand(-(degree*0.1),(degree*0.1)),5,0)
set_trait(TRAIT_WATER_CONSUMPTION, get_trait(TRAIT_WATER_CONSUMPTION) +rand(-degree,degree),50,0)
set_trait(TRAIT_JUICY, !get_trait(TRAIT_JUICY))
set_trait(TRAIT_STINGS, !get_trait(TRAIT_STINGS))
if(2)
set_trait(TRAIT_IDEAL_HEAT, get_trait(TRAIT_IDEAL_HEAT) + (rand(-5,5)*degree),800,70)
set_trait(TRAIT_HEAT_TOLERANCE, get_trait(TRAIT_HEAT_TOLERANCE) + (rand(-5,5)*degree),800,70)
set_trait(TRAIT_LOWKPA_TOLERANCE, get_trait(TRAIT_LOWKPA_TOLERANCE)+ (rand(-5,5)*degree),80,0)
set_trait(TRAIT_HIGHKPA_TOLERANCE, get_trait(TRAIT_HIGHKPA_TOLERANCE)+(rand(-5,5)*degree),500,110)
set_trait(TRAIT_EXPLOSIVE,1)
if(3)
set_trait(TRAIT_IDEAL_LIGHT, get_trait(TRAIT_IDEAL_LIGHT)+(rand(-1,1)*degree),30,0)
set_trait(TRAIT_LIGHT_TOLERANCE, get_trait(TRAIT_LIGHT_TOLERANCE)+(rand(-2,2)*degree),10,0)
if(4)
set_trait(TRAIT_TOXINS_TOLERANCE, get_trait(TRAIT_TOXINS_TOLERANCE)+(rand(-2,2)*degree),10,0)
if(5)
set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0)
if(prob(degree*5))
set_trait(TRAIT_CARNIVOROUS, get_trait(TRAIT_CARNIVOROUS)+rand(-degree,degree),2, 0)
if(get_trait(TRAIT_CARNIVOROUS))
source_turf.visible_message("<span class='notice'>\The [display_name] shudders hungrily.</span>")
if(6)
set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0)
if(prob(degree*5))
set_trait(TRAIT_PARASITE,!get_trait(TRAIT_PARASITE))
if(7)
if(get_trait(TRAIT_YIELD) != -1)
set_trait(TRAIT_YIELD, get_trait(TRAIT_YIELD)+(rand(-2,2)*degree),10,0)
if(8)
set_trait(TRAIT_ENDURANCE, get_trait(TRAIT_ENDURANCE)+(rand(-5,5)*degree),100,10)
set_trait(TRAIT_PRODUCTION, get_trait(TRAIT_PRODUCTION)+(rand(-1,1)*degree),10, 1)
set_trait(TRAIT_POTENCY, get_trait(TRAIT_POTENCY)+(rand(-20,20)*degree),200, 0)
if(prob(degree*5))
set_trait(TRAIT_SPREAD, get_trait(TRAIT_SPREAD)+rand(-1,1),2, 0)
source_turf.visible_message("<span class='notice'>\The [display_name] spasms visibly, shifting in the tray.</span>")
if(9)
set_trait(TRAIT_MATURATION, get_trait(TRAIT_MATURATION)+(rand(-1,1)*degree),30, 0)
if(prob(degree*5))
set_trait(TRAIT_HARVEST_REPEAT, !get_trait(TRAIT_HARVEST_REPEAT))
if(10)
if(prob(degree*2))
set_trait(TRAIT_BIOLUM, !get_trait(TRAIT_BIOLUM))
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,"#[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)
set_trait(TRAIT_TELEPORTING,1)
return
//Mutates a specific trait/set of traits.
/datum/seed/proc/apply_gene(var/datum/plantgene/gene)
if(!gene || !gene.values || get_trait(TRAIT_IMMUTABLE) > 0) return
// Splicing products has some detrimental effects on yield and lifespan.
// We handle this before we do the rest of the looping, as normal traits don't really include lists.
switch(gene.genetype)
if(GENE_BIOCHEMISTRY)
for(var/trait in list(TRAIT_YIELD, TRAIT_ENDURANCE))
if(get_trait(trait) > 0) set_trait(trait,get_trait(trait),null,1,0.85)
if(!chems) chems = list()
var/list/gene_value = gene.values["[TRAIT_CHEMS]"]
for(var/rid in gene_value)
var/list/gene_chem = gene_value[rid]
if(!chems[rid])
chems[rid] = gene_chem.Copy()
continue
for(var/i=1;i<=gene_chem.len;i++)
if(isnull(gene_chem[i])) gene_chem[i] = 0
if(chems[rid][i])
chems[rid][i] = max(1,round((gene_chem[i] + chems[rid][i])/2))
else
chems[rid][i] = gene_chem[i]
var/list/new_gasses = gene.values["[TRAIT_EXUDE_GASSES]"]
if(islist(new_gasses))
if(!exude_gasses) exude_gasses = list()
exude_gasses |= new_gasses
for(var/gas in exude_gasses)
exude_gasses[gas] = max(1,round(exude_gasses[gas]*0.8))
gene.values["[TRAIT_EXUDE_GASSES]"] = null
gene.values["[TRAIT_CHEMS]"] = null
if(GENE_DIET)
var/list/new_gasses = gene.values["[TRAIT_CONSUME_GASSES]"]
consume_gasses |= new_gasses
gene.values["[TRAIT_CONSUME_GASSES]"] = null
if(GENE_METABOLISM)
has_mob_product = gene.values["mob_product"]
gene.values["mob_product"] = null
for(var/trait in gene.values)
set_trait(trait,gene.values["[trait]"])
update_growth_stages()
//Returns a list of the desired trait values.
/datum/seed/proc/get_gene(var/genetype)
if(!genetype) return 0
var/list/traits_to_copy
var/datum/plantgene/P = new()
P.genetype = genetype
P.values = list()
switch(genetype)
if(GENE_BIOCHEMISTRY)
P.values["[TRAIT_CHEMS]"] = chems
P.values["[TRAIT_EXUDE_GASSES]"] = exude_gasses
traits_to_copy = list(TRAIT_POTENCY)
if(GENE_OUTPUT)
traits_to_copy = list(TRAIT_PRODUCES_POWER,TRAIT_BIOLUM)
if(GENE_ATMOSPHERE)
traits_to_copy = list(TRAIT_HEAT_TOLERANCE,TRAIT_LOWKPA_TOLERANCE,TRAIT_HIGHKPA_TOLERANCE)
if(GENE_HARDINESS)
traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE,TRAIT_ENDURANCE)
if(GENE_METABOLISM)
P.values["mob_product"] = has_mob_product
traits_to_copy = list(TRAIT_REQUIRES_NUTRIENTS,TRAIT_REQUIRES_WATER,TRAIT_ALTER_TEMP)
if(GENE_VIGOUR)
traits_to_copy = list(TRAIT_PRODUCTION,TRAIT_MATURATION,TRAIT_YIELD,TRAIT_SPREAD)
if(GENE_DIET)
P.values["[TRAIT_CONSUME_GASSES]"] = consume_gasses
traits_to_copy = list(TRAIT_CARNIVOROUS,TRAIT_PARASITE,TRAIT_NUTRIENT_CONSUMPTION,TRAIT_WATER_CONSUMPTION)
if(GENE_ENVIRONMENT)
traits_to_copy = list(TRAIT_IDEAL_HEAT,TRAIT_IDEAL_LIGHT,TRAIT_LIGHT_TOLERANCE)
if(GENE_PIGMENT)
traits_to_copy = list(TRAIT_PLANT_COLOUR,TRAIT_PRODUCT_COLOUR,TRAIT_BIOLUM_COLOUR)
if(GENE_STRUCTURE)
traits_to_copy = list(TRAIT_PLANT_ICON,TRAIT_PRODUCT_ICON,TRAIT_HARVEST_REPEAT)
if(GENE_FRUIT)
traits_to_copy = list(TRAIT_STINGS,TRAIT_EXPLOSIVE,TRAIT_JUICY)
if(GENE_SPECIAL)
traits_to_copy = list(TRAIT_TELEPORTING)
for(var/trait in traits_to_copy)
P.values["[trait]"] = get_trait(trait)
return (P ? P : 0)
//Place the plant products at the feet of the user.
/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample,var/force_amount)
if(!user)
return
if(!force_amount && get_trait(TRAIT_YIELD) == 0 && !harvest_sample)
if(istype(user)) user << "<span class='danger'>You fail to harvest anything useful.</span>"
else
if(istype(user)) user << "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name]."
//This may be a new line. Update the global if it is.
if(name == "new line" || !(name in plant_controller.seeds))
uid = plant_controller.seeds.len + 1
name = "[uid]"
plant_controller.seeds[name] = src
if(harvest_sample)
var/obj/item/seeds/seeds = new(get_turf(user))
seeds.seed_type = name
seeds.update_seed()
return
var/total_yield = 0
if(!isnull(force_amount))
total_yield = force_amount
else
if(get_trait(TRAIT_YIELD) > -1)
if(isnull(yield_mod) || yield_mod < 1)
yield_mod = 0
total_yield = get_trait(TRAIT_YIELD)
else
total_yield = get_trait(TRAIT_YIELD) + rand(yield_mod)
total_yield = max(1,total_yield)
currently_querying = list()
for(var/i = 0;i<total_yield;i++)
var/obj/item/product
if(has_mob_product)
product = new has_mob_product(get_turf(user),name)
else
product = new /obj/item/weapon/reagent_containers/food/snacks/grown(get_turf(user),name)
if(get_trait(TRAIT_PRODUCT_COLOUR))
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(istype(product,/obj/item/weapon/reagent_containers/food))
var/obj/item/weapon/reagent_containers/food/food = product
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(mysterious)
product.name += "?"
product.desc += " On second thought, something about this one looks strange."
if(get_trait(TRAIT_BIOLUM))
if(get_trait(TRAIT_BIOLUM_COLOUR))
product.l_color = get_trait(TRAIT_BIOLUM_COLOUR)
product.SetLuminosity(get_trait(TRAIT_BIOLUM))
//Handle spawning in living, mobile products (like dionaea).
if(istype(product,/mob/living))
product.visible_message("<span class='notice'>The pod disgorges [product]!</span>")
handle_living_product(product)
// When the seed in this machine mutates/is modified, the tray seed value
// is set to a new datum copied from the original. This datum won't actually
// be put into the global datum list until the product is harvested, though.
/datum/seed/proc/diverge(var/modified)
if(get_trait(TRAIT_IMMUTABLE) > 0) return
//Set up some basic information.
var/datum/seed/new_seed = new
new_seed.name = "new line"
new_seed.uid = 0
new_seed.roundstart = 0
new_seed.can_self_harvest = can_self_harvest
new_seed.kitchen_tag = kitchen_tag
new_seed.trash_type = trash_type
new_seed.has_mob_product = has_mob_product
//Copy over everything else.
if(mutants) new_seed.mutants = mutants.Copy()
if(chems) new_seed.chems = chems.Copy()
if(consume_gasses) new_seed.consume_gasses = consume_gasses.Copy()
if(exude_gasses) new_seed.exude_gasses = exude_gasses.Copy()
new_seed.seed_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][seed_name]"
new_seed.display_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][display_name]"
new_seed.seed_noun = seed_noun
new_seed.traits = traits.Copy()
new_seed.update_growth_stages()
return new_seed
/datum/seed/proc/update_growth_stages()
if(get_trait(TRAIT_PLANT_ICON))
growth_stages = plant_controller.plant_sprites[get_trait(TRAIT_PLANT_ICON)]
else
growth_stages = 0
+150
View File
@@ -0,0 +1,150 @@
// Attempts to offload processing for the spreading plants from the MC.
// Processes vines/spreading plants.
#define PLANTS_PER_TICK 500 // Cap on number of plant segments processed.
#define PLANT_TICK_TIME 75 // Number of ticks between the plant processor cycling.
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
if(!holder) return
if(!plant_controller || !plant_controller.gene_tag_masks)
usr << "Gene masks not set."
return
for(var/mask in plant_controller.gene_tag_masks)
usr << "[mask]: [plant_controller.gene_tag_masks[mask]]"
var/global/datum/controller/plants/plant_controller // Set in New().
/datum/controller/plants
var/plants_per_tick = PLANTS_PER_TICK
var/plant_tick_time = PLANT_TICK_TIME
var/list/product_descs = list() // Stores generated fruit descs.
var/list/plant_queue = list() // All queued plants.
var/list/seeds = list() // All seed data stored here.
var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
var/list/plant_icon_cache = list() // Stores images of growth, fruits and seeds.
var/list/plant_sprites = list() // List of all harvested product sprites.
var/list/plant_product_sprites = list() // List of all growth sprites plus number of growth stages.
//var/processing = 0 // Off/on.
/datum/controller/plants/New()
if(plant_controller && plant_controller != src)
log_debug("Rebuilding plant controller.")
del(plant_controller)
plant_controller = src
setup()
process()
// Predefined/roundstart varieties use a string key to make it
// easier to grab the new variety when mutating. Post-roundstart
// and mutant varieties use their uid converted to a string instead.
// Looks like shit but it's sort of necessary.
/datum/controller/plants/proc/setup()
// Build the icon lists.
for(var/icostate in icon_states('icons/obj/hydroponics_growing.dmi'))
var/split = findtext(icostate,"-")
if(!split)
// invalid icon_state
continue
var/ikey = copytext(icostate,(split+1))
if(ikey == "dead")
// don't count dead icons
continue
ikey = text2num(ikey)
var/base = copytext(icostate,1,split)
if(!(plant_sprites[base]) || (plant_sprites[base]<ikey))
plant_sprites[base] = ikey
for(var/icostate in icon_states('icons/obj/hydroponics_products.dmi'))
var/split = findtext(icostate,"-")
if(split)
plant_product_sprites |= copytext(icostate,1,split)
// Populate the global seed datum list.
for(var/type in typesof(/datum/seed)-/datum/seed)
var/datum/seed/S = new type
seeds[S.name] = S
S.uid = "[seeds.len]"
S.roundstart = 1
// Make sure any seed packets that were mapped in are updated
// correctly (since the seed datums did not exist a tick ago).
for(var/obj/item/seeds/S in world)
S.update_seed()
//Might as well mask the gene types while we're at it.
var/list/used_masks = list()
var/list/plant_traits = ALL_GENES
while(plant_traits && plant_traits.len)
var/gene_tag = pick(plant_traits)
var/gene_mask = "[uppertext(num2hex(rand(0,255)))]"
while(gene_mask in used_masks)
gene_mask = "[uppertext(num2hex(rand(0,255)))]"
used_masks += gene_mask
plant_traits -= gene_tag
gene_tag_masks[gene_tag] = gene_mask
// Proc for creating a random seed type.
/datum/controller/plants/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = plant_controller.seeds.len + 1
seed.name = "[seed.uid]"
seeds[seed.name] = seed
if(survive_on_station)
if(seed.consume_gasses)
seed.consume_gasses["plasma"] = null
seed.consume_gasses["carbon_dioxide"] = null
if(seed.chems && !isnull(seed.chems["pacid"]))
seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous.
seed.chems -= null // Setting to null does not actually remove the entry, which is weird.
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
/datum/controller/plants/proc/process()
processing = 1
spawn(0)
set background = 1
var/processed = 0
while(1)
if(!processing)
sleep(plant_tick_time)
else
processed = 0
if(plant_queue.len)
var/target_to_process = min(plant_queue.len,plants_per_tick)
for(var/x=0;x<target_to_process;x++)
if(!plant_queue.len)
break
var/obj/effect/plant/plant = pick(plant_queue)
plant_queue -= plant
if(!istype(plant))
continue
plant.process()
processed++
sleep(1) // Stagger processing out so previous tick can resolve (overlapping plant segments etc)
sleep(max(1,(plant_tick_time-processed)))
/datum/controller/plants/proc/add_plant(var/obj/effect/plant/plant)
plant_queue |= plant
/datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant)
plant_queue -= plant
File diff suppressed because it is too large Load Diff
+18 -21
View File
@@ -1,7 +1,7 @@
/obj/item/weapon/disk/botany
name = "flora data disk"
desc = "A small disk used for carrying data on plant genetics."
icon = 'icons/obj/hydroponics.dmi'
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "disk"
w_class = 1.0
@@ -16,7 +16,7 @@
/obj/item/weapon/disk/botany/attack_self(var/mob/user as mob)
if(genes.len)
var/choice = alert(user, "Are you sure you want to wipe the disk?", "Xenobotany Data", "No", "Yes")
if(src && user && genes && choice == "Yes")
if(src && user && genes && choice && choice == "Yes" && user.Adjacent(get_turf(src)))
user << "You wipe the disk data."
name = initial(name)
desc = initial(name)
@@ -33,7 +33,7 @@
new /obj/item/weapon/disk/botany(src)
/obj/machinery/botany
icon = 'icons/obj/hydroponics.dmi'
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "hydrotray3"
density = 1
anchored = 1
@@ -44,7 +44,7 @@
var/open = 0
var/active = 0
var/action_time = 100
var/action_time = 5
var/last_action = 0
var/eject_disk = 0
var/failed_task = 0
@@ -58,9 +58,6 @@
if(world.time > last_action + action_time)
finished_task()
/obj/machinery/botany/attack_paw(mob/user as mob)
return attack_hand(user)
/obj/machinery/botany/attack_ai(mob/user as mob)
return attack_hand(user)
@@ -82,13 +79,13 @@
visible_message("\icon[src] [src] beeps and spits out [loaded_disk].")
loaded_disk = null
/obj/machinery/botany/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
/obj/machinery/botany/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/seeds))
if(seed)
user << "There is already a seed loaded."
return
var/obj/item/seeds/S =W
if(S.seed && S.seed.immutable > 0)
if(S.seed && S.seed.get_trait(TRAIT_IMMUTABLE) > 0)
user << "That seed is not compatible with our genetics technology."
else
user.drop_item(W)
@@ -99,7 +96,7 @@
if(istype(W,/obj/item/weapon/screwdriver))
open = !open
user << "\blue You [open ? "open" : "close"] the maintenance panel."
user << "<span class='notice'>You [open ? "open" : "close"] the maintenance panel.</span>"
return
if(open)
@@ -147,8 +144,8 @@
var/list/data = list()
var/list/geneMasks[0]
for(var/gene_tag in gene_tag_masks)
geneMasks.Add(list(list("tag" = gene_tag, "mask" = gene_tag_masks[gene_tag])))
for(var/gene_tag in plant_controller.gene_tag_masks)
geneMasks.Add(list(list("tag" = gene_tag, "mask" = plant_controller.gene_tag_masks[gene_tag])))
data["geneMasks"] = geneMasks
data["activity"] = active
@@ -189,10 +186,10 @@
if(!seed) return
seed.loc = get_turf(src)
if(seed.seed.name == "new line" || isnull(seed_types[seed.seed.name]))
seed.seed.uid = seed_types.len + 1
if(seed.seed.name == "new line" || isnull(plant_controller.seeds[seed.seed.name]))
seed.seed.uid = plant_controller.seeds.len + 1
seed.seed.name = "[seed.seed.uid]"
seed_types[seed.seed.name] = seed.seed
plant_controller.seeds[seed.seed.name] = seed.seed
seed.update_seed()
visible_message("\icon[src] [src] beeps and spits out [seed].")
@@ -245,8 +242,8 @@
if(!genetics.roundstart)
loaded_disk.genesource += " (variety #[genetics.uid])"
loaded_disk.name += " ([gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])"
loaded_disk.desc += " The label reads \'gene [gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'."
loaded_disk.name += " ([plant_controller.gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])"
loaded_disk.desc += " The label reads \'gene [plant_controller.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'."
eject_disk = 1
degradation += rand(20,60)
@@ -291,7 +288,7 @@
for(var/datum/plantgene/P in loaded_disk.genes)
if(data["locus"] != "") data["locus"] += ", "
data["locus"] += "[gene_tag_masks[P.genetype]]"
data["locus"] += "[plant_controller.gene_tag_masks[P.genetype]]"
else
data["disk"] = 0
@@ -321,7 +318,7 @@
last_action = world.time
active = 1
if(!isnull(seed_types[seed.seed.name]))
if(!isnull(plant_controller.seeds[seed.seed.name]))
seed.seed = seed.seed.diverge(1)
seed.seed_type = seed.seed.name
seed.update_seed()
@@ -335,4 +332,4 @@
seed.modified += rand(5,10)
usr.set_machine(src)
src.add_fingerprint(usr)
src.add_fingerprint(usr)
+16 -16
View File
@@ -1,5 +1,4 @@
/datum/seed
var/product_requires_player // If yes, product will ask for a player among the ghosts.
var/list/currently_querying // Used to avoid asking the same ghost repeatedly.
// The following procs are used to grab players for mobs produced by a seed (mostly for dionaea).
@@ -7,25 +6,26 @@
/*
if(!host || !istype(host)) return
if(product_requires_player)
spawn(0)
request_player(host)
spawn(75)
if(!host.ckey && !host.client)
host.death() // This seems redundant, but a lot of mobs don't
host.stat = 2 // handle death() properly. Better safe than etc.
host.visible_message("\red <b>[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.")
spawn(0)
request_player(host)
if(istype(host,/mob/living/simple_animal))
return
spawn(75)
if(!host.ckey && !host.client)
host.death() // This seems redundant, but a lot of mobs don't
host.stat = 2 // handle death() properly. Better safe than etc.
host.visible_message("<span class='danger'>[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.</span>")
var/total_yield = rand(1,3)
for(var/j = 0;j<=total_yield;j++)
var/obj/item/seeds/S = new(get_turf(host))
S.seed_type = name
S.update_seed()
var/total_yield = rand(1,3)
for(var/j = 0;j<=total_yield;j++)
var/obj/item/seeds/S = new(get_turf(host))
S.seed_type = name
S.update_seed()
/datum/seed/proc/request_player(var/mob/living/host)
if(!host) return
for(var/mob/dead/observer/O in player_list)
if(jobban_isbanned(O, "Dionaea") || (!is_alien_whitelisted(src, "Diona") && config.usealienwhitelist))
if(jobban_isbanned(O, "Dionaea"))
continue
if(O.client)
if(O.client.prefs.be_special & BE_PLANT && !(O.client in currently_querying))
@@ -69,7 +69,7 @@
host << "\green <B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B>"
// This is a hack, replace with some kind of species blurb proc.
if(istype(host,/mob/living/carbon/monkey/diona))
if(istype(host,/mob/living/carbon/alien/diona))
host << "<B>You are [host], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>"
host << "<B>Too much darkness will send you into shock and starve you, but light will help you heal.</B>"
@@ -1,8 +1,10 @@
var/global/list/plant_seed_sprites = list()
//Seed packet object/procs.
/obj/item/seeds
name = "packet of seeds"
icon = 'icons/obj/seeds.dmi'
icon_state = "seed"
icon_state = "blank"
w_class = 2.0
var/seed_type
@@ -10,26 +12,57 @@
var/modified = 0
/obj/item/seeds/New()
while(!plant_controller)
sleep(30)
update_seed()
..()
//Grabs the appropriate seed datum from the global list.
/obj/item/seeds/proc/update_seed()
if(!seed && seed_type && !isnull(seed_types) && seed_types[seed_type])
seed = seed_types[seed_type]
if(!seed && seed_type && !isnull(plant_controller.seeds) && plant_controller.seeds[seed_type])
seed = plant_controller.seeds[seed_type]
update_appearance()
//Updates strings and icon appropriately based on seed datum.
/obj/item/seeds/proc/update_appearance()
if(!seed) return
icon_state = seed.packet_icon
src.name = "packet of [seed.seed_name] [seed.seed_noun]"
src.desc = "It has a picture of [seed.display_name] on the front."
/obj/item/seeds/examine()
..()
// Update icon.
overlays.Cut()
var/is_seeds = ((seed.seed_noun in list("seeds","pits","nodes")) ? 1 : 0)
var/image/seed_mask
var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : "spores"]"
if(plant_seed_sprites[seed_base_key])
seed_mask = plant_seed_sprites[seed_base_key]
else
seed_mask = image('icons/obj/seeds.dmi',"[is_seeds ? "seed" : "spore"]-mask")
if(is_seeds) // Spore glass bits aren't coloured.
seed_mask.color = seed.get_trait(TRAIT_PLANT_COLOUR)
plant_seed_sprites[seed_base_key] = seed_mask
var/image/seed_overlay
var/seed_overlay_key = "[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"
if(plant_seed_sprites[seed_overlay_key])
seed_overlay = plant_seed_sprites[seed_overlay_key]
else
seed_overlay = image('icons/obj/seeds.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]")
seed_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
plant_seed_sprites[seed_overlay_key] = seed_overlay
overlays |= seed_mask
overlays |= seed_overlay
if(is_seeds)
src.name = "packet of [seed.seed_name] [seed.seed_noun]"
src.desc = "It has a picture of [seed.display_name] on the front."
else
src.name = "sample of [seed.seed_name] [seed.seed_noun]"
src.desc = "It's labelled as coming from [seed.display_name]."
/obj/item/seeds/examine(mob/user)
..(user)
if(seed && !seed.roundstart)
usr << "It's tagged as variety #[seed.uid]."
user << "It's tagged as variety #[seed.uid]."
/obj/item/seeds/cutting
name = "cuttings"
@@ -39,12 +72,17 @@
..()
src.name = "packet of [seed.seed_name] cuttings"
/obj/item/seeds/random
seed_type = null
/obj/item/seeds/random/New()
seed = plant_controller.create_random_seed()
seed_type = seed.name
update_seed()
/obj/item/seeds/replicapod
seed_type = "diona"
/obj/item/seeds/poppyseed
seed_type = "poppies"
/obj/item/seeds/chiliseed
seed_type = "chili"
@@ -81,9 +119,6 @@
/obj/item/seeds/eggplantseed
seed_type = "eggplant"
/obj/item/seeds/eggyseed
seed_type = "realeggplant"
/obj/item/seeds/bloodtomatoseed
seed_type = "bloodtomato"
@@ -114,9 +149,6 @@
/obj/item/seeds/soyaseed
seed_type = "soybean"
/obj/item/seeds/koiseed
seed_type = "koibean"
/obj/item/seeds/wheatseed
seed_type = "wheat"
@@ -222,11 +254,38 @@
/obj/item/seeds/cherryseed
seed_type = "cherry"
/obj/item/seeds/tobaccoseed
seed_type = "tobacco"
/obj/item/seeds/kudzuseed
seed_type = "kudzu"
/obj/item/seeds/tobaccoseed
seed_type = "tobacco"
/obj/item/seeds/jurlmah
seed_type = "jurlmah"
/obj/item/seeds/amauri
seed_type = "amauri"
/obj/item/seeds/gelthi
seed_type = "gelthi"
/obj/item/seeds/vale
seed_type = "vale"
/obj/item/seeds/surik
seed_type = "surik"
/obj/item/seeds/telriis
seed_type = "telriis"
/obj/item/seeds/thaadra
seed_type = "thaadra"
/obj/item/seeds/clown
seed_type = "clown"
/obj/item/seeds/test
seed_type = "test"
/obj/item/seeds/stobaccoseed
seed_type = "stobacco"
@@ -242,10 +301,3 @@
/obj/item/seeds/coffeerseed
seed_type = "coffeer"
/obj/item/seeds/moonflowerseed
seed_type = "moonflower"
/obj/item/seeds/novaflowerseed
seed_type = "novaflower"
+245
View File
@@ -0,0 +1,245 @@
/datum/seed_pile
var/name
var/amount
var/datum/seed/seed_type // Keeps track of what our seed is
var/list/obj/item/seeds/seeds = list() // Tracks actual objects contained in the pile
var/ID
/datum/seed_pile/New(var/obj/item/seeds/O, var/ID)
name = O.name
amount = 1
seed_type = O.seed
seeds += O
src.ID = ID
/datum/seed_pile/proc/matches(var/obj/item/seeds/O)
if (O.seed == seed_type)
return 1
return 0
/obj/machinery/seed_storage
name = "Seed storage"
desc = "It stores, sorts, and dispenses seeds."
icon = 'icons/obj/vending.dmi'
icon_state = "seeds"
density = 1
anchored = 1
use_power = 1
idle_power_usage = 100
var/initialized = 0 // Map-placed ones break if seeds are loaded right at the start of the round, so we do it on the first interaction
var/list/datum/seed_pile/piles = list()
var/list/starting_seeds = list()
var/list/scanner = list() // What properties we can view
/obj/machinery/seed_storage/random // This is mostly for testing, but I guess admins could spawn it
name = "Random seed storage"
scanner = list("stats", "produce", "soil", "temperature", "light")
starting_seeds = list(/obj/item/seeds/random = 50)
/obj/machinery/seed_storage/garden
name = "Garden seed storage"
scanner = list("stats")
starting_seeds = list(/obj/item/seeds/appleseed = 3, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3)
/obj/machinery/seed_storage/xenobotany
name = "Xenobotany seed storage"
scanner = list("stats", "produce", "soil", "temperature", "light")
starting_seeds = list(/obj/item/seeds/ambrosiavulgarisseed = 3, /obj/item/seeds/appleseed = 3, /obj/item/seeds/amanitamycelium = 2, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/glowshroom = 2, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/libertymycelium = 2, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/nettleseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plastiseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/reishimycelium = 2, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3)
/obj/machinery/seed_storage/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/seed_storage/interact(mob/user as mob)
if (..())
return
if (!initialized)
for(var/typepath in starting_seeds)
var/amount = starting_seeds[typepath]
if(isnull(amount)) amount = 1
for (var/i = 1 to amount)
var/O = new typepath
add(O)
initialized = 1
var/dat = "<center><h1>Seed storage contents</h1></center>"
if (piles.len == 0)
dat += "<font color='red'>No seeds</font>"
else
dat += "<table style='text-align:center;border-style:solid;border-width:1px;padding:4px'><tr><td>Name</td>"
dat += "<td>Variety</td>"
if ("stats" in scanner)
dat += "<td>E</td><td>Y</td><td>M</td><td>Pr</td><td>Pt</td><td>Harvest</td>"
if ("temperature" in scanner)
dat += "<td>Temp</td>"
if ("light" in scanner)
dat += "<td>Light</td>"
if ("soil" in scanner)
dat += "<td>Nutri</td><td>Water</td>"
dat += "<td>Notes</td><td>Amount</td><td></td></tr>"
for (var/datum/seed_pile/S in piles)
var/datum/seed/seed = S.seed_type
if(!seed)
continue
dat += "<tr>"
dat += "<td>[seed.seed_name]</td>"
dat += "<td>#[seed.uid]</td>"
if ("stats" in scanner)
dat += "<td>[seed.get_trait(TRAIT_ENDURANCE)]</td><td>[seed.get_trait(TRAIT_YIELD)]</td><td>[seed.get_trait(TRAIT_MATURATION)]</td><td>[seed.get_trait(TRAIT_PRODUCTION)]</td><td>[seed.get_trait(TRAIT_POTENCY)]</td>"
if(seed.get_trait(TRAIT_HARVEST_REPEAT))
dat += "<td>Multiple</td>"
else
dat += "<td>Single</td>"
if ("temperature" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_HEAT)] K</td>"
if ("light" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_LIGHT)] L</td>"
if ("soil" in scanner)
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS) > 0.2)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
if(seed.get_trait(TRAIT_REQUIRES_WATER))
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
dat += "<td>"
switch(seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
dat += "CARN "
if(2)
dat += "<font color='red'>CARN </font>"
switch(seed.get_trait(TRAIT_SPREAD))
if(1)
dat += "VINE "
if(2)
dat += "<font color='red'>VINE </font>"
if ("pressure" in scanner)
if(seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
dat += "LP "
if(seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
dat += "HP "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
dat += "TEMRES "
else if(seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
dat += "TEMSEN "
if ("light" in scanner)
if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
dat += "LIGRES "
else if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
dat += "LIGSEN "
if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
dat += "TOXSEN "
else if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
dat += "TOXRES "
if(seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
dat += "PESTSEN "
else if(seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
dat += "PESTRES "
if(seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
dat += "WEEDSEN "
else if(seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
dat += "WEEDRES "
if(seed.get_trait(TRAIT_PARASITE))
dat += "PAR "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_ALTER_TEMP) > 0)
dat += "TEMP+ "
if(seed.get_trait(TRAIT_ALTER_TEMP) < 0)
dat += "TEMP- "
if(seed.get_trait(TRAIT_BIOLUM))
dat += "LUM "
dat += "</td>"
dat += "<td>[S.amount]</td>"
dat += "<td><a href='byond://?src=\ref[src];task=vend;id=[S.ID]'>Vend</a> <a href='byond://?src=\ref[src];task=purge;id=[S.ID]'>Purge</a></td>"
dat += "</tr>"
dat += "</table>"
user << browse(dat, "window=seedstorage")
onclose(user, "seedstorage")
/obj/machinery/seed_storage/Topic(var/href, var/list/href_list)
if (..())
return
var/task = href_list["task"]
var/ID = text2num(href_list["id"])
for (var/datum/seed_pile/N in piles)
if (N.ID == ID)
if (task == "vend")
var/obj/O = pick(N.seeds)
if (O)
--N.amount
N.seeds -= O
if (N.amount <= 0 || N.seeds.len <= 0)
piles -= N
del(N)
O.loc = src.loc
else
piles -= N
del(N)
else if (task == "purge")
for (var/obj/O in N.seeds)
del(O)
piles -= N
del(N)
break
updateUsrDialog()
/obj/machinery/seed_storage/attackby(var/obj/item/O as obj, var/mob/user as mob)
if (istype(O, /obj/item/seeds))
add(O)
user.visible_message("[user] puts \the [O.name] into \the [src].", "You put \the [O] into \the [src].")
return
else if (istype(O, /obj/item/weapon/storage/bag/plants))
var/obj/item/weapon/storage/P = O
var/loaded = 0
for(var/obj/item/seeds/G in P.contents)
++loaded
add(G)
if (loaded)
user.visible_message("[user] puts the seeds from \the [O.name] into \the [src].", "You put the seeds from \the [O.name] into \the [src].")
else
user << "<span class='notice'>There are no seeds in \the [O.name].</span>"
return
else if(istype(O, /obj/item/weapon/wrench))
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
anchored = !anchored
user << "You [anchored ? "wrench" : "unwrench"] \the [src]."
/obj/machinery/seed_storage/proc/add(var/obj/item/seeds/O as obj)
if (istype(O.loc, /mob))
var/mob/user = O.loc
user.drop_item(O)
else if(istype(O.loc,/obj/item/weapon/storage))
var/obj/item/weapon/storage/S = O.loc
S.remove_from_storage(O, src)
O.loc = src
var/newID = 0
for (var/datum/seed_pile/N in piles)
if (N.matches(O))
++N.amount
N.seeds += (O)
return
else if(N.ID >= newID)
newID = N.ID + 1
piles += new /datum/seed_pile(O, newID)
return
@@ -0,0 +1,262 @@
#define DEFAULT_SEED "glowshroom"
#define VINE_GROWTH_STAGES 5
/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 = plant_controller.create_random_seed(1)
seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines.
seed.set_trait(TRAIT_POTENCY,rand(70,100)) // 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
color = DEAD_PLANT_COLOUR
/obj/effect/dead_plant/attack_hand()
del(src)
/obj/effect/dead_plant/attackby()
..()
for(var/obj/effect/plant/neighbor in range(1))
neighbor.update_neighbors()
del(src)
/obj/effect/plant
name = "plant"
anchored = 1
opacity = 0
density = 0
icon = 'icons/obj/hydroponics_growing.dmi'
icon_state = "bush4-1"
layer = 3
pass_flags = PASSTABLE
var/health = 10
var/max_health = 100
var/growth_threshold = 0
var/growth_type = 0
var/max_growth = 0
var/list/neighbors = list()
var/obj/effect/plant/parent
var/datum/seed/seed
var/floor = 0
var/spread_chance = 40
var/spread_distance = 3
var/evolve_chance = 2
var/last_tick = 0
var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/plant
var/mob/living/buckled_mob = null
var/movable = 0
/obj/effect/plant/Del()
if(plant_controller)
plant_controller.remove_plant(src)
for(var/obj/effect/plant/neighbor in range(1,src))
plant_controller.add_plant(neighbor)
..()
/obj/effect/plant/single
spread_chance = 0
/obj/effect/plant/New(var/newloc, var/datum/seed/newseed, var/obj/effect/plant/newparent)
..()
if(!newparent)
parent = src
else
parent = newparent
if(!plant_controller)
sleep(250) // ugly hack, should mean roundstart plants are fine.
if(!plant_controller)
world << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
del(src)
return
if(!istype(newseed))
newseed = plant_controller.seeds[DEFAULT_SEED]
seed = newseed
if(!seed)
del(src)
return
name = seed.display_name
max_health = round(seed.get_trait(TRAIT_ENDURANCE)/2)
if(seed.get_trait(TRAIT_SPREAD)==2)
max_growth = VINE_GROWTH_STAGES
growth_threshold = 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 = 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_chance = seed.get_trait(TRAIT_POTENCY) * 4
spread_distance = ((growth_type>0) ? round(spread_chance*0.6) : round(spread_chance*0.3))
update_icon()
spawn(1) // Plants will sometimes be spawned in the turf adjacent to the one they need to end up in, for the sake of correct dir/etc being set.
set_dir(calc_dir())
update_icon()
plant_controller.add_plant(src)
// Some plants eat through plating.
if(!isnull(seed.chems["facid"]))
var/turf/T = get_turf(src)
T.ex_act(prob(80) ? 3 : 2)
/obj/effect/plant/update_icon()
//TODO: should really be caching this.
refresh_icon()
if(growth_type == 0 && !floor)
src.transform = null
var/matrix/M = matrix()
// should make the plant flush against the wall it's meant to be growing from.
M.Translate(0,-(rand(12,14)))
switch(dir)
if(WEST)
M.Turn(90)
if(NORTH)
M.Turn(180)
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)/20))
if(seed.get_trait(TRAIT_BIOLUM_COLOUR))
l_color = seed.get_trait(TRAIT_BIOLUM_COLOUR)
else
l_color = null
return
else
SetLuminosity(0)
/obj/effect/plant/proc/refresh_icon()
var/growth = min(max_growth,round(health/growth_threshold))
var/at_fringe = get_dist(src,parent)
if(spread_distance > 5)
if(at_fringe >= (spread_distance-3))
max_growth--
if(at_fringe >= (spread_distance-2))
max_growth--
max_growth = max(1,max_growth)
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]"
if(growth>2 && growth == max_growth)
layer = 5
opacity = 1
if(!isnull(seed.chems["woodpulp"]))
density = 1
else
layer = 3
density = 0
/obj/effect/plant/proc/calc_dir(turf/location = loc)
set background = 1
var/direction = 16
for(var/wallDir in cardinal)
var/turf/newTurf = get_step(location,wallDir)
if(newTurf.density)
direction |= wallDir
for(var/obj/effect/plant/shroom in location)
if(shroom == src)
continue
if(shroom.floor) //special
direction &= ~16
else
direction &= ~shroom.dir
var/list/dirList = list()
for(var/i=1,i<=16,i <<= 1)
if(direction & i)
dirList += i
if(dirList.len)
var/newDir = pick(dirList)
if(newDir == 16)
floor = 1
newDir = 1
return newDir
floor = 1
return 1
/obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user)
plant_controller.add_plant(src)
if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
if(!seed)
user << "There is nothing to take a sample from."
return
seed.harvest(user,0,1)
health -= (rand(3,5)*10)
else
..()
if(W.force)
health -= W.force
check_health()
/obj/effect/plant/ex_act(severity)
switch(severity)
if(1.0)
die_off()
return
if(2.0)
if (prob(50))
die_off()
return
if(3.0)
if (prob(5))
die_off()
return
else
return
/obj/effect/plant/proc/check_health()
if(health <= 0)
die_off()
/obj/effect/plant/proc/is_mature()
return (health >= (max_health/3))
@@ -0,0 +1,106 @@
#define NEIGHBOR_REFRESH_TIME 100
/obj/effect/plant/proc/get_cardinal_neighbors()
var/list/cardinal_neighbors = list()
for(var/check_dir in cardinal)
var/turf/simulated/T = get_step(get_turf(src), check_dir)
if(istype(T))
cardinal_neighbors |= T
return cardinal_neighbors
/obj/effect/plant/proc/update_neighbors()
// Update our list of valid neighboring turfs.
neighbors = list()
for(var/turf/simulated/floor in get_cardinal_neighbors())
if(get_dist(parent, floor) > spread_distance)
continue
if((locate(/obj/effect/plant) in floor.contents) || (locate(/obj/effect/dead_plant) in floor.contents) )
continue
if(floor.density)
if(!isnull(seed.chems["pacid"]))
spawn(rand(5,25)) floor.ex_act(3)
continue
if(!Adjacent(floor) || !floor.Enter(src))
continue
neighbors |= floor
// Update all of our friends.
var/turf/T = get_turf(src)
for(var/obj/effect/plant/neighbor in range(1,src))
neighbor.neighbors -= T
/obj/effect/plant/process()
// Something is very wrong, kill ourselves.
if(!seed)
die_off()
return 0
/* MOVED INTO code\game\objects\effects\effect_system.dm
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
if(smoke.reagents.has_reagent("plantbgone"))
die_off()
return
*/
// Handle life.
var/turf/simulated/T = get_turf(src)
if(istype(T))
health -= seed.handle_environment(T,T.return_air(),null,1)
if(health < max_health)
health += rand(3,5)
refresh_icon()
if(health > max_health)
health = max_health
else if(health == max_health && !plant)
plant = new(T,seed)
plant.dir = src.dir
plant.transform = src.transform
plant.age = seed.get_trait(TRAIT_MATURATION)-1
plant.update_icon()
if(growth_type==0) //Vines do not become invisible.
invisibility = INVISIBILITY_MAXIMUM
else
plant.layer = layer + 0.1
if(buckled_mob)
seed.do_sting(buckled_mob,src)
if(seed.get_trait(TRAIT_CARNIVOROUS))
seed.do_thorns(buckled_mob,src)
if(world.time >= last_tick+NEIGHBOR_REFRESH_TIME)
last_tick = world.time
update_neighbors()
if(is_mature() && neighbors.len && prob(spread_chance))
for(var/i=1,i<=seed.get_trait(TRAIT_YIELD),i++)
if(prob(spread_chance))
sleep(rand(3,5))
if(!neighbors.len)
break
var/turf/target_turf = pick(neighbors)
var/obj/effect/plant/child = new(get_turf(src),seed,parent)
spawn(1) // This should do a little bit of animation.
child.loc = target_turf
child.update_icon()
// Update neighboring squares.
for(var/obj/effect/plant/neighbor in range(1,target_turf))
neighbor.neighbors -= target_turf
// We shouldn't have spawned if the controller doesn't exist.
check_health()
if(neighbors.len || health != max_health)
plant_controller.add_plant(src)
/obj/effect/plant/proc/die_off()
// Kill off our plant.
if(plant) plant.die()
// This turf is clear now, let our buddies know.
for(var/turf/simulated/check_turf in get_cardinal_neighbors())
if(!istype(check_turf))
continue
for(var/obj/effect/plant/neighbor in check_turf.contents)
neighbor.neighbors |= check_turf
plant_controller.add_plant(neighbor)
spawn(1) if(src) del(src)
#undef NEIGHBOR_REFRESH_TIME
@@ -0,0 +1,78 @@
/obj/effect/plant/HasProximity(var/atom/movable/AM)
if(!is_mature() || seed.get_trait(TRAIT_SPREAD) != 2)
return
var/mob/living/M = AM
if(!istype(M))
return
if(!buckled_mob && !M.buckled && !M.anchored && (M.small || prob(round(seed.get_trait(TRAIT_POTENCY)/2))))
entangle(M)
/obj/effect/plant/attack_hand(mob/user as mob)
// Todo, cause damage.
manual_unbuckle(user)
/obj/effect/plant/proc/trodden_on(var/mob/living/victim)
if(!is_mature())
return
var/mob/living/carbon/human/H = victim
if(istype(H) && H.shoes)
return
seed.do_thorns(victim,src)
seed.do_sting(victim,src,pick("r_foot","l_foot","r_leg","l_leg"))
/obj/effect/plant/proc/unbuckle()
if(buckled_mob)
if(buckled_mob.buckled == src)
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
buckled_mob = null
return
/obj/effect/plant/proc/manual_unbuckle(mob/user as mob)
if(buckled_mob)
if(prob(seed ? min(max(0,100 - seed.get_trait(TRAIT_POTENCY)/2),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 \the [src].</span>",\
"<span class='notice'>[user.name] frees you from \the [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 \the [src].</span>",\
"<span class='notice'>You untangle \the [src] from around yourself.</span>",\
"<span class='warning'>You hear shredding and ripping.</span>")
unbuckle()
else
var/text = pick("rip","tear","pull")
user.visible_message(\
"<span class='notice'>[user.name] [text]s at \the [src].</span>",\
"<span class='notice'>You [text] at \the [src].</span>",\
"<span class='warning'>You hear shredding and ripping.</span>")
return
/obj/effect/plant/proc/entangle(var/mob/living/victim)
if(buckled_mob)
return
if(!Adjacent(victim))
return
victim.buckled = src
victim.update_canmove()
buckled_mob = victim
if(!victim.anchored && !victim.buckled && victim.loc != get_turf(src))
var/can_grab = 1
if(istype(victim, /mob/living/carbon/human))
var/mob/living/carbon/human/H = victim
if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))
can_grab = 0
if(can_grab)
src.visible_message("<span class='danger'>Tendrils lash out from \the [src] and drag \the [victim] in!</span>")
victim.loc = src.loc
victim << "<span class='danger'>Tendrils [pick("wind", "tangle", "tighten")] around you!</span>"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,240 @@
//http://www.youtube.com/watch?v=-1GadTfGFvU
//i could have done these as just an ordinary plant, but fuck it - there would have been too much snowflake code
/obj/machinery/apiary
name = "apiary tray"
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "hydrotray3"
density = 1
anchored = 1
var/nutrilevel = 0
var/yieldmod = 1
var/mut = 1
var/toxic = 0
var/dead = 0
var/health = -1
var/maxhealth = 100
var/lastcycle = 0
var/cycledelay = 100
var/harvestable_honey = 0
var/beezeez = 0
var/swarming = 0
var/bees_in_hive = 0
var/list/owned_bee_swarms = list()
var/hydrotray_type = /obj/machinery/portable_atmospherics/hydroponics
//overwrite this after it's created if the apiary needs a custom machinery sprite
/obj/machinery/apiary/New()
..()
overlays += image('icons/obj/apiary_bees_etc.dmi', icon_state="apiary")
/obj/machinery/apiary/bullet_act(var/obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables.
if(istype(Proj ,/obj/item/projectile/energy/floramut))
mut++
else if(istype(Proj ,/obj/item/projectile/energy/florayield))
if(!yieldmod)
yieldmod += 1
//world << "Yield increased by 1, from 0, to a total of [myseed.yield]"
else if (prob(1/(yieldmod * yieldmod) *100))//This formula gives you diminishing returns based on yield. 100% with 1 yield, decreasing to 25%, 11%, 6, 4, 2...
yieldmod += 1
//world << "Yield increased by 1, to a total of [myseed.yield]"
else
..()
return
/obj/machinery/apiary/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/queen_bee))
if(health > 0)
user << "\red There is already a queen in there."
else
health = 10
nutrilevel += 10
user.drop_item()
del(O)
user << "\blue You carefully insert the queen into [src], she gets busy making a hive."
bees_in_hive = 0
else if(istype(O, /obj/item/beezeez))
beezeez += 100
nutrilevel += 10
user.drop_item()
if(health > 0)
user << "\blue You insert [O] into [src]. A relaxed humming appears to pick up."
else
user << "\blue You insert [O] into [src]. Now it just needs some bees."
del(O)
else if(istype(O, /obj/item/weapon/minihoe))
if(health > 0)
user << "\red <b>You begin to dislodge the apiary from the tray, the bees don't like that.</b>"
angry_swarm(user)
else
user << "\blue You begin to dislodge the dead apiary from the tray."
if(do_after(user, 50))
new hydrotray_type(src.loc)
new /obj/item/apiary(src.loc)
user << "\red You dislodge the apiary from the tray."
del(src)
else if(istype(O, /obj/item/weapon/bee_net))
var/obj/item/weapon/bee_net/N = O
if(N.caught_bees > 0)
user << "\blue You empty the bees into the apiary."
bees_in_hive += N.caught_bees
N.caught_bees = 0
else
user << "\blue There are no more bees in the net."
else if(istype(O, /obj/item/weapon/reagent_containers/glass))
var/obj/item/weapon/reagent_containers/glass/G = O
if(harvestable_honey > 0)
if(health > 0)
user << "\red You begin to harvest the honey. The bees don't seem to like it."
angry_swarm(user)
else
user << "\blue You begin to harvest the honey."
if(do_after(user,50))
G.reagents.add_reagent("honey",harvestable_honey)
harvestable_honey = 0
user << "\blue You successfully harvest the honey."
else
user << "\blue There is no honey left to harvest."
else
angry_swarm(user)
..()
/obj/machinery/apiary/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
else
return 0
/obj/machinery/apiary/process()
if(swarming > 0)
swarming -= 1
if(swarming <= 0)
for(var/mob/living/simple_animal/bee/B in src.loc)
bees_in_hive += B.strength
del(B)
else if(bees_in_hive < 10)
for(var/mob/living/simple_animal/bee/B in src.loc)
bees_in_hive += B.strength
del(B)
if(world.time > (lastcycle + cycledelay))
lastcycle = world.time
if(health < 0)
return
//magical bee formula
if(beezeez > 0)
beezeez -= 1
nutrilevel += 2
health += 1
toxic = max(0, toxic - 1)
//handle nutrients
nutrilevel -= bees_in_hive / 10 + owned_bee_swarms.len / 5
if(nutrilevel > 0)
bees_in_hive += 1 * yieldmod
if(health < maxhealth)
health++
else
//nutrilevel is less than 1, so we're effectively subtracting here
health += max(nutrilevel - 1, round(-health / 2))
bees_in_hive += max(nutrilevel - 1, round(-bees_in_hive / 2))
if(owned_bee_swarms.len)
var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms)
B.target_turf = get_turf(src)
//clear out some toxins
if(toxic > 0)
toxic -= 1
health -= 1
if(health <= 0)
return
//make a bit of honey
if(harvestable_honey < 50)
harvestable_honey += 0.5
//make some new bees
if(bees_in_hive >= 10 && prob(bees_in_hive * 10))
var/mob/living/simple_animal/bee/B = new(get_turf(src), src)
owned_bee_swarms.Add(B)
B.mut = mut
B.toxic = toxic
bees_in_hive -= 1
//find some plants, harvest
for(var/obj/machinery/portable_atmospherics/hydroponics/H in view(7, src))
if(H.seed && !H.dead && prob(owned_bee_swarms.len * 10))
src.nutrilevel++
H.nutrilevel++
if(mut < H.mutation_mod - 1)
mut = H.mutation_mod - 1
else if(mut > H.mutation_mod - 1)
H.mutation_mod = mut
//flowers give us pollen (nutrients)
/* - All plants should be giving nutrients to the hive.
if(H.myseed.type == /obj/item/seeds/harebell || H.myseed.type == /obj/item/seeds/sunflowerseed)
src.nutrilevel++
H.nutrilevel++
*/
//have a few beneficial effects on nearby plants
if(prob(10))
H.lastcycle -= 5
if(prob(10))
H.seed.set_trait(TRAIT_ENDURANCE,max(H.seed.get_trait(TRAIT_ENDURANCE)*1.5,H.seed.get_trait(TRAIT_ENDURANCE)+1))
if(H.toxins && prob(10))
H.toxins = min(0, H.toxins - 1)
toxic++
/obj/machinery/apiary/proc/die()
if(owned_bee_swarms.len)
var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms)
B.target_turf = get_turf(src)
B.strength -= 1
if(B.strength <= 0)
del(B)
else if(B.strength <= 5)
B.icon_state = "bees[B.strength]"
bees_in_hive = 0
health = 0
/obj/machinery/apiary/proc/angry_swarm(var/mob/M)
for(var/mob/living/simple_animal/bee/B in owned_bee_swarms)
B.feral = 25
B.target_mob = M
swarming = 25
while(bees_in_hive > 0)
var/spawn_strength = bees_in_hive
if(bees_in_hive >= 5)
spawn_strength = 6
var/mob/living/simple_animal/bee/B = new(get_turf(src), src)
B.target_mob = M
B.strength = spawn_strength
B.feral = 25
B.mut = mut
B.toxic = toxic
bees_in_hive -= spawn_strength
/obj/machinery/apiary/verb/harvest_honeycomb()
set src in oview(1)
set name = "Harvest honeycomb"
set category = "Object"
while(health > 15)
health -= 15
var/obj/item/weapon/reagent_containers/food/snacks/honeycomb/H = new(src.loc)
if(toxic > 0)
H.reagents.add_reagent("toxin", toxic)
usr << "\blue You harvest the honeycomb from the hive. There is a wild buzzing!"
angry_swarm(usr)
@@ -0,0 +1,124 @@
/obj/machinery/portable_atmospherics/hydroponics/process()
/* MOVED INTO code\game\objects\effects\effect_system.dm
// Handle nearby smoke if any.
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
if(smoke.reagents.total_volume)
smoke.reagents.copy_to(src, 5)
*/
//Do this even if we're not ready for a plant cycle.
process_reagents()
// Update values every cycle rather than every process() tick.
if(force_update)
force_update = 0
else if(world.time < (lastcycle + cycledelay))
return
lastcycle = world.time
// Weeds like water and nutrients, there's a chance the weed population will increase.
// Bonus chance if the tray is unoccupied.
if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 5 : 1))
weedlevel += 1 * HYDRO_SPEED_MULTIPLIER
// There's a chance for a weed explosion to happen if the weeds take over.
// Plants that are themselves weeds (weed_tolerance > 10) are unaffected.
if (weedlevel >= 10 && prob(10))
if(!seed || weedlevel >= seed.get_trait(TRAIT_WEED_TOLERANCE))
weed_invasion()
// If there is no seed data (and hence nothing planted),
// or the plant is dead, process nothing further.
if(!seed || dead)
if(mechanical) update_icon() //Harvesting would fail to set alert icons properly.
return
// Advance plant age.
if(prob(30)) age += 1 * HYDRO_SPEED_MULTIPLIER
//Highly mutable plants have a chance of mutating every tick.
if(seed.get_trait(TRAIT_IMMUTABLE) == -1)
var/mut_prob = rand(1,100)
if(mut_prob <= 5) mutate(mut_prob == 1 ? 2 : 1)
// Maintain tray nutrient and water levels.
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0 && nutrilevel > 0 && prob(25))
nutrilevel -= max(0,seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER)
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 0 && waterlevel > 0 && prob(25))
waterlevel -= max(0,seed.get_trait(TRAIT_WATER_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER)
// Make sure the plant is not starving or thirsty. Adequate
// water and nutrients will cause a plant to become healthier.
var/healthmod = rand(1,3) * HYDRO_SPEED_MULTIPLIER
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS) && prob(35))
health += (nutrilevel < 2 ? -healthmod : healthmod)
if(seed.get_trait(TRAIT_REQUIRES_WATER) && prob(35))
health += (waterlevel < 10 ? -healthmod : healthmod)
// Check that pressure, heat and light are all within bounds.
// First, handle an open system or an unconnected closed system.
var/turf/T = loc
var/datum/gas_mixture/environment
// If we're closed, take from our internal sources.
if(closed_system && (connected_port || holding))
environment = air_contents
// If atmos input is not there, grab from turf.
if(!environment && istype(T)) environment = T.return_air()
if(!environment) return
// Seed datum handles gasses, light and pressure.
if(mechanical && closed_system)
health -= seed.handle_environment(T,environment,tray_light)
else
health -= seed.handle_environment(T,environment)
// If we're attached to a pipenet, then we should let the pipenet know we might have modified some gasses
if (closed_system && connected_port)
update_connected_network()
// Toxin levels beyond the plant's tolerance cause damage, but
// toxins are sucked up each tick and slowly reduce over time.
if(toxins > 0)
var/toxin_uptake = max(1,round(toxins/10))
if(toxins > seed.get_trait(TRAIT_TOXINS_TOLERANCE))
health -= toxin_uptake
toxins -= toxin_uptake
// Check for pests and weeds.
// Some carnivorous plants happily eat pests.
if(pestlevel > 0)
if(seed.get_trait(TRAIT_CARNIVOROUS))
health += HYDRO_SPEED_MULTIPLIER
pestlevel -= HYDRO_SPEED_MULTIPLIER
else if (pestlevel >= seed.get_trait(TRAIT_PEST_TOLERANCE))
health -= HYDRO_SPEED_MULTIPLIER
// Some plants thrive and live off of weeds.
if(weedlevel > 0)
if(seed.get_trait(TRAIT_PARASITE))
health += HYDRO_SPEED_MULTIPLIER
weedlevel -= HYDRO_SPEED_MULTIPLIER
else if (weedlevel >= seed.get_trait(TRAIT_WEED_TOLERANCE))
health -= HYDRO_SPEED_MULTIPLIER
// Handle life and death.
// When the plant dies, weeds thrive and pests die off.
check_health()
// If enough time (in cycles, not ticks) has passed since the plant was harvested, we're ready to harvest again.
if((age > seed.get_trait(TRAIT_MATURATION)) && \
((age - lastproduce) > seed.get_trait(TRAIT_PRODUCTION)) && \
(!harvest && !dead))
harvest = 1
lastproduce = age
if(prob(3)) // On each tick, there's a chance the pest population will increase
pestlevel += 0.1 * HYDRO_SPEED_MULTIPLIER
// Some seeds will self-harvest if you don't keep a lid on them.
if(seed && seed.can_self_harvest && harvest && !closed_system && prob(5))
harvest()
check_health()
return
@@ -0,0 +1,126 @@
/obj/item/weapon/plantspray
icon = 'icons/obj/hydroponics_machines.dmi'
item_state = "spray"
flags = OPENCONTAINER | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 4
w_class = 2.0
throw_speed = 2
throw_range = 10
var/toxicity = 4
var/pest_kill_str = 0
var/weed_kill_str = 0
/obj/item/weapon/plantspray/weeds // -- Skie
name = "weed-spray"
desc = "It's a toxic mixture, in spray form, to kill small weeds."
icon_state = "weedspray"
weed_kill_str = 6
/obj/item/weapon/plantspray/pests
name = "pest-spray"
desc = "It's some pest eliminator spray! <I>Do not inhale!</I>"
icon_state = "pestspray"
pest_kill_str = 6
/obj/item/weapon/plantspray/pests/old
name = "bottle of pestkiller"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
/obj/item/weapon/plantspray/pests/old/carbaryl
name = "bottle of carbaryl"
icon_state = "bottle16"
toxicity = 4
pest_kill_str = 2
/obj/item/weapon/plantspray/pests/old/lindane
name = "bottle of lindane"
icon_state = "bottle18"
toxicity = 6
pest_kill_str = 4
/obj/item/weapon/plantspray/pests/old/phosmet
name = "bottle of phosmet"
icon_state = "bottle15"
toxicity = 8
pest_kill_str = 7
// *************************************
// Weedkiller defines for hydroponics
// *************************************
/obj/item/weedkiller
name = "bottle of weedkiller"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
flags = OPENCONTAINER | NOBLUDGEON
var/toxicity = 0
var/weed_kill_str = 0
/obj/item/weedkiller/triclopyr
name = "bottle of glyphosate"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
toxicity = 4
weed_kill_str = 2
/obj/item/weedkiller/lindane
name = "bottle of triclopyr"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle18"
toxicity = 6
weed_kill_str = 4
/obj/item/weedkiller/D24
name = "bottle of 2,4-D"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle15"
toxicity = 8
weed_kill_str = 7
// *************************************
// Nutrient defines for hydroponics
// *************************************
/obj/item/weapon/reagent_containers/glass/fertilizer
name = "fertilizer bottle"
desc = "A small glass bottle. Can hold up to 10 units."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
flags = OPENCONTAINER
possible_transfer_amounts = null
w_class = 2.0
var/fertilizer //Reagent contained, if any.
//Like a shot glass!
amount_per_transfer_from_this = 10
volume = 10
/obj/item/weapon/reagent_containers/glass/fertilizer/New()
..()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
if(fertilizer)
reagents.add_reagent(fertilizer,10)
/obj/item/weapon/reagent_containers/glass/fertilizer/ez
name = "bottle of E-Z-Nutrient"
icon_state = "bottle16"
fertilizer = "eznutrient"
/obj/item/weapon/reagent_containers/glass/fertilizer/l4z
name = "bottle of Left 4 Zed"
icon_state = "bottle18"
fertilizer = "left4zed"
/obj/item/weapon/reagent_containers/glass/fertilizer/rh
name = "bottle of Robust Harvest"
icon_state = "bottle15"
fertilizer = "robustharvest"
@@ -0,0 +1,67 @@
/obj/machinery/portable_atmospherics/hydroponics/soil
name = "soil"
icon_state = "soil"
density = 0
use_power = 0
mechanical = 0
tray_light = 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/tank))
return
else
..()
/obj/machinery/portable_atmospherics/hydroponics/soil/New()
..()
verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/close_lid_verb
verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/remove_label
verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/set_light
/obj/machinery/portable_atmospherics/hydroponics/soil/CanPass()
return 1
// Holder for vine plants.
// Icons for plants are generated as overlays, so setting it to invisible wouldn't work.
// Hence using a blank icon.
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible
name = "plant"
icon = 'icons/obj/seeds.dmi'
icon_state = "blank"
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/New(var/newloc,var/datum/seed/newseed)
..()
seed = newseed
dead = 0
age = 1
health = seed.get_trait(TRAIT_ENDURANCE)
lastcycle = world.time
pixel_y = rand(-5,5)
check_health()
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/remove_dead()
..()
del(src)
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/harvest()
..()
if(!seed) // Repeat harvests are a thing.
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)
..()
@@ -1,4 +1,4 @@
//Analyzer, pestkillers, weedkillers, nutrients, hatchets, cutters.
//Analyzer, pestkillers, weedkillers, nutrients, hatchets, cutters, Rapid-Seed-Producer (RSP), corn cob.
/obj/item/weapon/wirecutters/clippers
name = "plant clippers"
@@ -9,8 +9,38 @@
icon = 'icons/obj/device.dmi'
icon_state = "hydro"
item_state = "analyzer"
var/form_title
var/last_data
/obj/item/device/analyzer/plant_analyzer/proc/print_report_verb()
set name = "Print Plant Report"
set category = "Object"
set src = usr
if(usr.stat || usr.restrained() || usr.lying)
return
print_report(usr)
/obj/item/device/analyzer/plant_analyzer/Topic(href, href_list)
if(..())
return
if(href_list["print"])
print_report(usr)
/obj/item/device/analyzer/plant_analyzer/proc/print_report(var/mob/living/user)
if(!last_data)
user << "There is no scan data to print."
return
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
P.name = "paper - [form_title]"
P.info = "[last_data]"
if(istype(user,/mob/living/carbon/human) && !(user.l_hand && user.r_hand))
user.put_in_hands(P)
user.visible_message("\The [src] spits out a piece of paper.")
return
/obj/item/device/analyzer/plant_analyzer/attack_self(mob/user as mob)
print_report(user)
return 0
/obj/item/device/analyzer/plant_analyzer/afterattack(obj/target, mob/user, flag)
@@ -29,16 +59,18 @@
var/tray_mutation_mod //mutation modifier of the tray
//--FalseIncarnate
if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown))
if(istype(target,/obj/structure/table))
return ..()
else if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown))
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = target
grown_seed = seed_types[G.plantname]
grown_seed = plant_controller.seeds[G.plantname]
grown_reagents = G.reagents
else if(istype(target,/obj/item/weapon/grown))
var/obj/item/weapon/grown/G = target
grown_seed = seed_types[G.plantname]
grown_seed = plant_controller.seeds[G.plantname]
grown_reagents = G.reagents
else if(istype(target,/obj/item/seeds))
@@ -66,21 +98,21 @@
grown_reagents = H.reagents
if(!grown_seed)
user << "\red [src] can tell you nothing about [target]."
user << "<span class='danger'>[src] can tell you nothing about \the [target].</span>"
return
var/dat = "<h3>Plant data for [target]</h3>"
user.visible_message("\blue [user] runs the scanner over [target].")
form_title = "[grown_seed.seed_name] (#[grown_seed.uid])"
var/dat = "<h3>Plant data for [form_title]</h3>"
user.visible_message("<span class='notice'>[user] runs the scanner over \the [target].</span>")
dat += "<h2>General Data</h2>"
dat += "<table>"
dat += "<tr><td><b>Endurance</b></td><td>[grown_seed.endurance]</td></tr>"
dat += "<tr><td><b>Yield</b></td><td>[grown_seed.yield]</td></tr>"
dat += "<tr><td><b>Lifespan</b></td><td>[grown_seed.lifespan]</td></tr>"
dat += "<tr><td><b>Maturation time</b></td><td>[grown_seed.maturation]</td></tr>"
dat += "<tr><td><b>Production time</b></td><td>[grown_seed.production]</td></tr>"
dat += "<tr><td><b>Potency</b></td><td>[grown_seed.potency]</td></tr>"
dat += "<tr><td><b>Endurance</b></td><td>[grown_seed.get_trait(TRAIT_ENDURANCE)]</td></tr>"
dat += "<tr><td><b>Yield</b></td><td>[grown_seed.get_trait(TRAIT_YIELD)]</td></tr>"
dat += "<tr><td><b>Maturation time</b></td><td>[grown_seed.get_trait(TRAIT_MATURATION)]</td></tr>"
dat += "<tr><td><b>Production time</b></td><td>[grown_seed.get_trait(TRAIT_PRODUCTION)]</td></tr>"
dat += "<tr><td><b>Potency</b></td><td>[grown_seed.get_trait(TRAIT_POTENCY)]</td></tr>"
//--FalseIncarnate
//Tray-specific stats like Age and Mutation Modifier, not shown if target was not a hydroponics tray or soil
@@ -105,29 +137,26 @@
dat += "<h2>Other Data</h2>"
if(grown_seed.harvest_repeat)
if(grown_seed.get_trait(TRAIT_HARVEST_REPEAT))
dat += "This plant can be harvested repeatedly.<br>"
if(grown_seed.immutable == -1)
if(grown_seed.get_trait(TRAIT_IMMUTABLE) == -1)
dat += "This plant is highly mutable.<br>"
else if(grown_seed.immutable > 0)
else if(grown_seed.get_trait(TRAIT_IMMUTABLE) > 0)
dat += "This plant does not possess genetics that are alterable.<br>"
if(grown_seed.products && grown_seed.products.len)
dat += "The mature plant will produce [grown_seed.products.len == 1 ? "fruit" : "[grown_seed.products.len] varieties of fruit"].<br>"
if(grown_seed.requires_nutrients)
if(grown_seed.nutrient_consumption < 0.05)
if(grown_seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
dat += "It consumes a small amount of nutrient fluid.<br>"
else if(grown_seed.nutrient_consumption > 0.2)
else if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
dat += "It requires a heavy supply of nutrient fluid.<br>"
else
dat += "It requires a supply of nutrient fluid.<br>"
if(grown_seed.requires_water)
if(grown_seed.water_consumption < 1)
if(grown_seed.get_trait(TRAIT_REQUIRES_WATER))
if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
dat += "It requires very little water.<br>"
else if(grown_seed.water_consumption > 5)
else if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
dat += "It requires a large amount of water.<br>"
else
dat += "It requires a stable supply of water.<br>"
@@ -135,120 +164,84 @@
if(grown_seed.mutants && grown_seed.mutants.len)
dat += "It exhibits a high degree of potential subspecies shift.<br>"
dat += "It thrives in a temperature of [grown_seed.ideal_heat] Kelvin."
dat += "It thrives in a temperature of [grown_seed.get_trait(TRAIT_IDEAL_HEAT)] Kelvin."
if(grown_seed.lowkpa_tolerance < 20)
if(grown_seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
dat += "<br>It is well adapted to low pressure levels."
if(grown_seed.highkpa_tolerance > 220)
if(grown_seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
dat += "<br>It is well adapted to high pressure levels."
if(grown_seed.heat_tolerance > 30)
if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
dat += "<br>It is well adapted to a range of temperatures."
else if(grown_seed.heat_tolerance < 10)
else if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
dat += "<br>It is very sensitive to temperature shifts."
dat += "<br>It thrives in a light level of [grown_seed.ideal_light] lumen[grown_seed.ideal_light == 1 ? "" : "s"]."
dat += "<br>It thrives in a light level of [grown_seed.get_trait(TRAIT_IDEAL_LIGHT)] lumen[grown_seed.get_trait(TRAIT_IDEAL_LIGHT) == 1 ? "" : "s"]."
if(grown_seed.light_tolerance > 10)
if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
dat += "<br>It is well adapted to a range of light levels."
else if(grown_seed.light_tolerance < 3)
else if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
dat += "<br>It is very sensitive to light level shifts."
if(grown_seed.toxins_tolerance < 3)
if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to toxins."
else if(grown_seed.toxins_tolerance > 6)
else if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to toxins."
if(grown_seed.pest_tolerance < 3)
if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to pests."
else if(grown_seed.pest_tolerance > 6)
else if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to pests."
if(grown_seed.weed_tolerance < 3)
if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to weeds."
else if(grown_seed.weed_tolerance > 6)
else if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to weeds."
switch(grown_seed.spread)
switch(grown_seed.get_trait(TRAIT_SPREAD))
if(1)
dat += "<br>It is capable of growing beyond the confines of a tray."
dat += "<br>It is able to be planted outside of a tray."
if(2)
dat += "<br>It is a robust and vigorous vine that will spread rapidly."
switch(grown_seed.carnivorous)
switch(grown_seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
dat += "<br>It is carniovorous and will eat tray pests for sustenance."
if(2)
dat += "<br>It is carnivorous and poses a significant threat to living things around it."
if(grown_seed.parasite)
if(grown_seed.get_trait(TRAIT_PARASITE))
dat += "<br>It is capable of parisitizing and gaining sustenance from tray weeds."
if(grown_seed.alter_temp)
dat += "<br>It will periodically alter the local temperature by [grown_seed.alter_temp] degrees Kelvin."
if(grown_seed.get_trait(TRAIT_ALTER_TEMP))
dat += "<br>It will periodically alter the local temperature by [grown_seed.get_trait(TRAIT_ALTER_TEMP)] degrees Kelvin."
if(grown_seed.biolum)
dat += "<br>It is [grown_seed.biolum_colour ? "<font color='[grown_seed.biolum_colour]'>bio-luminescent</font>" : "bio-luminescent"]."
if(grown_seed.flowers)
dat += "<br>It has [grown_seed.flower_colour ? "<font color='[grown_seed.flower_colour]'>flowers</font>" : "flowers"]."
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_PRODUCES_POWER))
dat += "<br>The fruit will function as a battery if prepared appropriately."
if(grown_seed.get_trait(TRAIT_STINGS))
dat += "<br>The fruit is covered in stinging spines."
if(grown_seed.get_trait(TRAIT_JUICY) == 1)
dat += "<br>The fruit is soft-skinned and juicy."
else if(grown_seed.get_trait(TRAIT_JUICY) == 2)
dat += "<br>The fruit is excessively juicy."
if(grown_seed.get_trait(TRAIT_EXPLOSIVE))
dat += "<br>The fruit is internally unstable."
if(grown_seed.get_trait(TRAIT_TELEPORTING))
dat += "<br>The fruit is temporal/spatially unstable."
if(dat)
last_data = dat
dat += "<br><br>\[<a href='?src=\ref[src];print=1'>print report</a>\]"
user << browse(dat,"window=plant_analyzer")
return
// *************************************
// Hydroponics Tools
// *************************************
/obj/item/weapon/plantspray
icon = 'icons/obj/hydroponics.dmi'
item_state = "spray"
flags = OPENCONTAINER | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 4
w_class = 2.0
throw_speed = 2
throw_range = 10
var/toxicity = 4
var/pest_kill_str = 0
var/weed_kill_str = 0
/obj/item/weapon/plantspray/weeds // -- Skie
name = "weed-spray"
desc = "It's a toxic mixture, in spray form, to kill small weeds."
icon_state = "weedspray"
weed_kill_str = 2
/obj/item/weapon/plantspray/pests
name = "pest-spray"
desc = "It's some pest eliminator spray! <I>Do not inhale!</I>"
icon_state = "pestspray"
pest_kill_str = 2
/obj/item/weapon/plantspray/pests/old
name = "bottle of pestkiller"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
/obj/item/weapon/plantspray/pests/old/carbaryl
name = "bottle of carbaryl"
icon_state = "bottle16"
toxicity = 4
pest_kill_str = 2
/obj/item/weapon/plantspray/pests/old/lindane
name = "bottle of lindane"
icon_state = "bottle18"
toxicity = 6
pest_kill_str = 4
/obj/item/weapon/plantspray/pests/old/phosmet
name = "bottle of phosmet"
icon_state = "bottle15"
toxicity = 8
pest_kill_str = 7
/obj/item/weapon/minihoe // -- Numbers
name = "mini hoe"
desc = "It's used for removing weeds or scratching your back."
@@ -259,85 +252,9 @@
force = 5.0
throwforce = 7.0
w_class = 2.0
m_amt = 50
attack_verb = list("slashed", "sliced", "cut", "clawed")
// *************************************
// Weedkiller defines for hydroponics
// *************************************
/obj/item/weedkiller
name = "bottle of weedkiller"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
var/toxicity = 0
var/weed_kill_str = 0
/obj/item/weedkiller/triclopyr
name = "bottle of glyphosate"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
toxicity = 4
weed_kill_str = 2
/obj/item/weedkiller/lindane
name = "bottle of triclopyr"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle18"
toxicity = 6
weed_kill_str = 4
/obj/item/weedkiller/D24
name = "bottle of 2,4-D"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle15"
toxicity = 8
weed_kill_str = 7
// *************************************
// Nutrient defines for hydroponics
// *************************************
/obj/item/weapon/reagent_containers/glass/fertilizer
name = "fertilizer bottle"
desc = "A small glass bottle. Can hold up to 10 units."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
flags = OPENCONTAINER
possible_transfer_amounts = null
w_class = 2.0
var/fertilizer //Reagent contained, if any.
//Like a shot glass!
amount_per_transfer_from_this = 10
volume = 10
/obj/item/weapon/reagent_containers/glass/fertilizer/New()
..()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
if(fertilizer)
reagents.add_reagent(fertilizer,10)
/obj/item/weapon/reagent_containers/glass/fertilizer/ez
name = "bottle of E-Z-Nutrient"
icon_state = "bottle16"
fertilizer = "eznutrient"
/obj/item/weapon/reagent_containers/glass/fertilizer/l4z
name = "bottle of Left 4 Zed"
icon_state = "bottle18"
fertilizer = "left4zed"
/obj/item/weapon/reagent_containers/glass/fertilizer/rh
name = "bottle of Robust Harvest"
icon_state = "bottle15"
fertilizer = "robustharvest"
//Hatchets and things to kill kudzu
/obj/item/weapon/hatchet
name = "hatchet"
@@ -346,21 +263,17 @@
icon_state = "hatchet"
flags = CONDUCT
force = 12.0
sharp = 1
edge = 1
w_class = 2.0
throwforce = 15.0
throw_speed = 4
throw_range = 4
sharp = 1
edge = 1
m_amt = 10000
m_amt = 15000
origin_tech = "materials=2;combat=1"
attack_verb = list("chopped", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
/obj/item/weapon/hatchet/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
return ..()
//If it's a hatchet it goes here. I guess
/obj/item/weapon/hatchet/unathiknife
name = "duelling knife"
desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude."
@@ -368,24 +281,70 @@
icon_state = "unathiknife"
attack_verb = list("ripped", "torn", "cut")
/obj/item/weapon/hatchet/tacknife
name = "tactical knife"
desc = "You'd be killing loads of people if this was Medal of Valor: Heroes of Nyx."
icon = 'icons/obj/weapons.dmi'
icon_state = "tacknife"
item_state = "knife"
attack_verb = list("stabbed", "chopped", "cut")
/obj/item/weapon/scythe
icon_state = "scythe0"
name = "scythe"
desc = "A sharp and curved blade on a long fibremetal handle, this tool makes it easy to reap what you sow."
force = 13.0
throwforce = 5.0
throw_speed = 1
sharp = 1
edge = 1
throw_speed = 2
throw_range = 3
w_class = 4.0
flags = NOSHIELD
slot_flags = SLOT_BACK
origin_tech = "materials=2;combat=2"
attack_verb = list("chopped", "sliced", "cut", "reaped")
hitsound = 'sound/weapons/bladeslice.ogg'
/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
del A
B.die_off(1)
qdel(A)
/obj/item/weapon/rsp
name = "\improper Rapid-Seed-Producer (RSP)"
desc = "A device used to rapidly deploy seeds."
icon = 'icons/obj/items.dmi'
icon_state = "rcd"
opacity = 0
density = 0
anchored = 0.0
var/matter = 0
var/mode = 1
w_class = 3.0
/obj/item/weapon/bananapeel
name = "banana peel"
desc = "A peel from a banana."
icon = 'icons/obj/items.dmi'
icon_state = "banana_peel"
item_state = "banana_peel"
w_class = 1.0
throwforce = 0
throw_speed = 4
throw_range = 20
/obj/item/weapon/corncob
name = "corn cob"
desc = "A reminder of meals gone by."
icon = 'icons/obj/harvest.dmi'
icon_state = "corncob"
item_state = "corncob"
w_class = 1.0
throwforce = 0
throw_speed = 4
throw_range = 20
@@ -0,0 +1,84 @@
//Refreshes the icon and sets the luminosity
/obj/machinery/portable_atmospherics/hydroponics/update_icon()
// Update name.
if(seed)
if(mechanical)
name = "[base_name] (#[seed.uid])"
else
name = "[seed.seed_name]"
else
name = initial(name)
if(labelled)
name += " ([labelled])"
overlays.Cut()
// Updates the plant overlay.
if(!isnull(seed))
if(mechanical && health <= (seed.get_trait(TRAIT_ENDURANCE) / 2))
overlays += "over_lowhealth3"
if(dead)
var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-dead"
var/image/dead_overlay = plant_controller.plant_icon_cache["[ikey]"]
if(!dead_overlay)
dead_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
dead_overlay.color = DEAD_PLANT_COLOUR
overlays |= dead_overlay
else
if(!seed.growth_stages)
seed.update_growth_stages()
if(!seed.growth_stages)
world << "<span class='danger'>Seed type [seed.get_trait(TRAIT_PLANT_ICON)] cannot find a growth stage value.</span>"
return
var/overlay_stage = 1
if(age >= seed.get_trait(TRAIT_MATURATION))
overlay_stage = seed.growth_stages
else
var/maturation = round(seed.get_trait(TRAIT_MATURATION)/seed.growth_stages)
overlay_stage = maturation ? max(1,round(age/maturation)) : 1
var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-[overlay_stage]"
var/image/plant_overlay = plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
if(!plant_overlay)
plant_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
plant_overlay.color = seed.get_trait(TRAIT_PLANT_COLOUR)
plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] = plant_overlay
overlays |= plant_overlay
if(harvest && overlay_stage == seed.growth_stages)
ikey = "[seed.get_trait(TRAIT_PRODUCT_ICON)]"
var/image/harvest_overlay = plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
if(!harvest_overlay)
harvest_overlay = image('icons/obj/hydroponics_products.dmi', "[ikey]")
harvest_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay
overlays |= harvest_overlay
//Draw the cover.
if(closed_system)
overlays += "hydrocover"
//Updated the various alert icons.
if(mechanical)
if(waterlevel <= 10)
overlays += "over_lowwater3"
if(nutrilevel <= 2)
overlays += "over_lownutri3"
if(weedlevel >= 5 || pestlevel >= 5 || toxins >= 40)
overlays += "over_alert3"
if(harvest)
overlays += "over_harvest3"
// Update bioluminescence.
if(seed)
if(seed.get_trait(TRAIT_BIOLUM))
SetLuminosity(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
SetLuminosity(0)
return
-386
View File
@@ -1,386 +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, params)
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
// 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/attack_paw(mob/user as mob)
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.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.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.
var/mob/living/M = buckled_mob
if(!istype(M)) return
var/mob/living/carbon/human/H = buckled_mob
// Drink some blood/cause some brute.
if(seed.carnivorous == 2)
buckled_mob << "<span class='danger'>\The [src] pierces your flesh greedily!</span>"
var/damage = rand(round(seed.potency/2),seed.potency)
if(!istype(H))
H.adjustBruteLoss(damage)
return
var/obj/item/organ/external/affecting = H.get_organ(pick("l_foot","r_foot","l_leg","r_leg","l_hand","r_hand","l_arm", "r_arm","head","chest","groin"))
if(affecting)
affecting.take_damage(damage, 0)
if(affecting.parent)
affecting.parent.add_autopsy_data("[plant_damage_noun]", damage)
else
H.adjustBruteLoss(damage)
H.UpdateDamageIcon()
H.updatehealth()
// Inject some chems.
if(seed.chems && seed.chems.len && istype(H))
H << "<span class='danger'>You feel something seeping into your skin!</span>"
for(var/rid in seed.chems)
var/injecting = min(5,max(1,seed.potency/5))
H.reagents.add_reagent(rid,injecting)
/obj/effect/plantsegment/proc/update()
if(!seed) return
// Update bioluminescence.
if(seed.biolum)
SetLuminosity(1+round(seed.potency/10))
if(seed.biolum_colour)
l_color = seed.biolum_colour
else
l_color = null
return
else
SetLuminosity(0)
// Update flower/product overlay.
overlays.Cut()
if(age >= seed.maturation)
if(prob(20) && seed.products && seed.products.len && !harvest && ((age-lastproduce) > seed.production))
harvest = 1
lastproduce = age
if(harvest)
var/image/fruit_overlay = image('icons/obj/hydroponics.dmi',"")
if(seed.product_colour)
fruit_overlay.color = seed.product_colour
overlays += fruit_overlay
if(seed.flowers)
var/image/flower_overlay = image('icons/obj/hydroponics.dmi',"[seed.flower_icon]")
if(seed.flower_colour)
flower_overlay.color = seed.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)
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.lowkpa_tolerance || pressure > seed.highkpa_tolerance)
die()
return
if(abs(environment.temperature - seed.ideal_heat) > seed.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.ideal_light) > seed.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.potency * collapse_limit : 250) && !reached_collapse_size)
reached_collapse_size = 1
if(vines.len >= (seed ? seed.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.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.energy < 2) //If tile isn't fully grown
var/chance
if(seed)
chance = limited_growth ? round(seed.potency/2,1) : seed.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
@@ -152,6 +152,10 @@
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
/mob/living/carbon/alien/proc/handle_wetness()
if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
return
/mob/living/carbon/alien/IsAdvancedToolUser()
return has_fine_manipulation
@@ -53,6 +53,9 @@
//Handle being on fire
handle_fire()
//Decrease wetness over time
handle_wetness()
//Status updates, death etc.
handle_regular_status_updates()
update_canmove()
-1
View File
@@ -92,7 +92,6 @@ mob/living
return
return
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
if(status_flags & GODMODE) //godmode
return 0
@@ -14,4 +14,9 @@
visible_message("<span class='warning'>[src] catches [I]!</span>")
throw_mode_off()
return
..()
/mob/living/carbon/water_act(volume, temperature, source)
if(volume > 10) //anything over 10 volume will make the mob wetter.
wetlevel = min(wetlevel + 1,5)
..()
@@ -20,4 +20,5 @@
var/pulse = PULSE_NORM //current pulse level
var/heart_attack = 0
var/heart_attack = 0
var/wetlevel = 0 //how wet the mob is
@@ -231,6 +231,18 @@
if(fire_stacks < 0)
msg += "[t_He] looks a little soaked.\n"
switch(wetlevel)
if(1)
msg += "[t_He] looks a bit damp.\n"
if(2)
msg += "[t_He] looks a little bit wet.\n"
if(3)
msg += "[t_He] looks wet.\n"
if(4)
msg += "[t_He] looks very wet.\n"
if(5)
msg += "[t_He] looks absolutely soaked.\n"
if(nutrition < 100)
msg += "[t_He] [t_is] severely malnourished.\n"
else if(nutrition >= 500)
@@ -27,6 +27,7 @@ emp_act
P.current = curloc
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.Angle = ""//round(Get_Angle(P,P.original))
return -1 // complete projectile permutation
@@ -495,4 +496,9 @@ emp_act
var/obj/item/clothing/shoes/magboots/MB = shoes
if(MB.magpulse)
return 0
..()
..()
/mob/living/carbon/human/water_act(volume, temperature, source)
..()
if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature)
if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature)
@@ -108,6 +108,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
//Check if we're on fire
handle_fire()
//Decrease wetness over time
handle_wetness()
//stuff in the stomach
handle_stomach()
@@ -547,6 +550,10 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
return
//END FIRE CODE
proc/handle_wetness()
if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
return
/*
proc/adjust_body_temperature(current, loc_temp, boost)
@@ -32,6 +32,20 @@
if(10)
msg += "<span class='warning'><B>It is radiating with massive levels of electrical activity!</B></span>\n"
msg += "<span class='warning'>"
switch(wetlevel)
if(1)
msg += "It looks a bit damp.\n"
if(2)
msg += "It looks a little bit wet.\n"
if(3)
msg += "It looks wet.\n"
if(4)
msg += "It looks very wet.\n"
if(5)
msg += "It looks absolutely soaked.\n"
msg += "</span>"
msg += "*---------*</span>"
usr << msg
return
@@ -42,6 +42,8 @@
handle_regular_status_updates() // Status updates, death etc.
handle_wetness()
/mob/living/carbon/slime/proc/AIprocess() // the master AI process
if(AIproc || stat == DEAD || client) return
@@ -285,6 +287,11 @@
else
Evolve()
/mob/living/carbon/slime/proc/handle_wetness()
if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
return
/mob/living/carbon/slime/proc/handle_targets()
if(Tempstun)
if(!Victim) // not while they're eating!
@@ -40,6 +40,20 @@
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
msg += "</span>"
msg += "<span class='warning'>"
switch(wetlevel)
if(1)
msg += "It looks a bit damp.\n"
if(2)
msg += "It looks a little bit wet.\n"
if(3)
msg += "It looks wet.\n"
if(4)
msg += "It looks very wet.\n"
if(5)
msg += "It looks absolutely soaked.\n"
msg += "</span>"
if (src.digitalcamo)
msg += "It is repulsively uncanny!\n"
@@ -62,6 +62,9 @@
//Check if we're on fire
handle_fire()
//Decrease wetness over time
handle_wetness()
//Status updates, death etc.
handle_regular_status_updates()
update_canmove()
@@ -660,4 +663,9 @@
return
adjustFireLoss(6)
return
//END FIRE CODE
//END FIRE CODE
proc/handle_wetness()
if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
return
+5 -1
View File
@@ -342,7 +342,7 @@
their native tongue is a heavy hissing laungage called Sinta'Unathi."
flags = HAS_LIPS | HAS_UNDERWEAR
bodyflags = FEET_CLAWS | HAS_TAIL | HAS_SKIN_COLOR
bodyflags = FEET_CLAWS | HAS_TAIL | HAS_SKIN_COLOR | TAIL_WAGGING
cold_level_1 = 280 //Default 260 - Lower is better
cold_level_2 = 220 //Default 200
@@ -358,6 +358,10 @@
reagent_tag = IS_UNATHI
base_color = "#066000"
/datum/species/unathi/handle_death(var/mob/living/carbon/human/H)
H.stop_tail_wagging(1)
/datum/species/tajaran
name = "Tajaran"
icobase = 'icons/mob/human_races/r_tajaran.dmi'
@@ -238,6 +238,10 @@
//Mobs on Fire end
/mob/living/water_act(volume, temperature)
if(volume >= 20) fire_stacks -= 0.5
if(volume >= 50) fire_stacks -= 1
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
src.take_organ_damage(speed*5)
+2 -1
View File
@@ -67,6 +67,7 @@
if("Engineering") prefix = ":e "
if("Security") prefix = ":s "
if("Supply") prefix = ":u "
if("Service") prefix = ":z "
if("Binary") prefix = ":b "
if("Holopad") prefix = ":h "
else prefix = ""
@@ -158,4 +159,4 @@
list += {"<br><A href='byond://?src=\ref[src];lawr=1'>Channel: [src.lawchannel]</A><br>"}
list += {"<A href='byond://?src=\ref[src];laws=1'>State Laws</A>"}
usr << browse(list, "window=laws")
usr << browse(list, "window=laws")
@@ -46,8 +46,8 @@
if(udder && prob(5))
udder.add_reagent("milk", rand(5, 10))
if(locate(/obj/effect/plantsegment) in loc)
var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc
if(locate(/obj/effect/plant) in loc)
var/obj/effect/plant/SV = locate(/obj/effect/plant) in loc
del(SV)
if(prob(10))
say("Nom")
@@ -56,7 +56,7 @@
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
var/step = get_step(src, direction)
if(step)
if(locate(/obj/effect/plantsegment) in step)
if(locate(/obj/effect/plant) in step)
Move(step)
/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
@@ -66,8 +66,8 @@
/mob/living/simple_animal/hostile/retaliate/goat/Move()
..()
if(!stat)
if(locate(/obj/effect/plantsegment) in loc)
var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc
if(locate(/obj/effect/plant) in loc)
var/obj/effect/plant/SV = locate(/obj/effect/plant) in loc
del(SV)
if(prob(10))
say("Nom")
@@ -231,15 +231,19 @@ var/global/chicken_count = 0
chicken_count -= 1
/mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens
if(!stat && eggsleft < 8)
user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.")
user.drop_item()
del(O)
eggsleft += rand(1, 4)
//world << eggsleft
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) //feedin' dem chickens
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
if(G.seed.kitchen_tag == "wheat")
if(!stat && eggsleft < 8)
user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.")
user.drop_item()
del(O)
eggsleft += rand(1, 4)
//world << eggsleft
else
user << "\blue [name] doesn't seem hungry!"
else
user << "\blue [name] doesn't seem hungry!"
user << "\blue [name] doesn't seem interested in [O]!"
else
..()
+2 -1
View File
@@ -155,7 +155,8 @@
var/turf/new_loc = get_turf(A)
var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null
if(permutation == -1 || forcedodge)// the bullet passes through a dense object!
bumped = 0 // reset bumped variable!
spawn(1)
bumped = 0 // reset bumped variable... after a delay. We don't want the projectile to hit AGAIN. Fixes deflecting projectiles.
loc = new_loc
permutated.Add(A)
return 0
+46 -26
View File
@@ -1008,19 +1008,8 @@
/obj/item/stack/sheet/mineral/clown = list("banana" = 20),
/obj/item/stack/sheet/mineral/silver = list("silver" = 20),
/obj/item/stack/sheet/mineral/gold = list("gold" = 20),
/obj/item/weapon/grown/nettle = list("sacid" = 0),
/obj/item/weapon/grown/deathnettle = list("facid" = 0),
/obj/item/weapon/grown/novaflower = list("capsaicin" = 0),
//Blender Stuff
/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil" = 0),
///obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium = list("plasticide" = 5),
//archaeology!
/obj/item/weapon/rocksliver = list("ground_rock" = 50),
@@ -1032,20 +1021,33 @@
/obj/item/weapon/reagent_containers/food = list()
)
var/list/juice_items = list (
var/list/blend_tags = list (
"nettle" = list("sacid" = 0),
"deathnettle" = list("facid" = 0),
"soybeans" = list("soymilk" = 0),
"tomato" = list("ketchup" = 0),
///obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
"ricestalk" = list("rice" = -5),
"cherries" = list("cherryjelly" = 0),
"plastellium" = list("plasticide" = 5),
)
//Juicer Stuff
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice" = 0),
var/list/juice_items = list (
/obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/grapes = list("grapejuice" = 0),
)
var/list/juice_tags = list (
"tomato" = list("tomatojuice" = 0),
"carrot" = list("carrotjuice" = 0),
"berries" = list("berryjuice" = 0),
"banana" = list("banana" = 0),
"potato" = list("potato" = 0),
"lemon" = list("lemonjuice" = 0),
"orange" = list("orangejuice" = 0),
"lime" = list("limejuice" = 0),
"poisonberries" = list("poisonberryjuice" = 0),
"grapes" = list("grapejuice" = 0),
"corn" = list("cornoil" = 0),
)
@@ -1223,10 +1225,20 @@
return blend_items[i]
/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O)
for(var/i in juice_items)
for(var/i in juice_tags)
if(istype(O, i))
return juice_items[i]
/obj/machinery/reagentgrinder/proc/get_allowed_snack_by_tag(var/obj/item/weapon/reagent_containers/food/snacks/grown/O)
for(var/i in blend_tags)
if(O.seed.kitchen_tag == i)
return blend_tags[i]
/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_tag(var/obj/item/weapon/reagent_containers/food/snacks/grown/O)
for(var/i in juice_tags)
if(O.seed.kitchen_tag == i)
return juice_tags[i]
/obj/machinery/reagentgrinder/proc/get_grownweapon_amount(var/obj/item/weapon/grown/O)
if (!istype(O))
return 5
@@ -1263,7 +1275,11 @@
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
var/allowed = get_allowed_juice_by_id(O)
var/allowed = null
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
allowed = get_allowed_juice_by_tag(O)
else
allowed = get_allowed_juice_by_id(O)
if(isnull(allowed))
break
@@ -1296,7 +1312,11 @@
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
var/allowed = get_allowed_snack_by_id(O)
var/allowed = null
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
allowed = get_allowed_snack_by_tag(O)
else
allowed = get_allowed_snack_by_id(O)
if(isnull(allowed))
break
@@ -202,6 +202,16 @@ datum
return
*/
// Ported from Bay as part of the Botany Update
// Allows you to make planks from any plant that has this reagent in it.
// Also vines with this reagent are considered dense.
woodpulp
name = "Wood Pulp"
id = "woodpulp"
description = "A mass of wood fibers."
reagent_state = LIQUID
color = "#B97A57"
water
name = "Water"
id = "water"
+1 -1
View File
@@ -585,7 +585,7 @@ datum/reagent/atrazine/reaction_obj(var/obj/O, var/volume)
alien_weeds.healthcheck()
else if(istype(O,/obj/effect/glowshroom)) //even a small amount is enough to kill it
del(O)
else if(istype(O,/obj/effect/plantsegment))
else if(istype(O,/obj/effect/plant))
if(prob(50)) del(O) //Kills kudzu too.
// Damage that is done to growing plants is separately at code/game/machinery/hydroponics at obj/item/hydroponics
@@ -1722,6 +1722,9 @@
M.gib()
..()
water_act(volume, temperature)
if(volume >= 5) return Expand()
proc/Expand()
for(var/mob/M in viewers(src,7))
M << "\red \The [src] expands!"
@@ -46,7 +46,7 @@
category = list("Medical")
/datum/design/healthanalyzer
name = "Health Analyzer Upgrade"
name = "Health Analyzer"
desc = "A hand-held body scanner able to distinguish vital signs of the subject."
id = "healthanalyzer"
req_tech = list("biotech" = 2, "magnets" = 2)
+2
View File
@@ -964,6 +964,8 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF")
#define STATUS_DISABLED 0 // RED Visability
#define STATUS_CLOSE -1 // Close the interface
#define HYDRO_SPEED_MULTIPLIER 1
#define NANO_IGNORE_DISTANCE 1
//Click cooldowns, in tenths of a second
+1
View File
@@ -41,6 +41,7 @@
sleep_offline = 1
plant_controller = new()
// Create robolimbs for chargen.
populate_robolimb_list()