mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Merge pull request #32647 from adacovsk/tanks
Fish tanks QoL and new environment
This commit is contained in:
@@ -549,7 +549,7 @@ var/list/cheartstopper = list(/*"potassium_chloride",*/ CHEESYGLOOP) //this stop
|
||||
#define LEXORINS list(LEXORIN, CORIAMYRTIN)
|
||||
#define DEXALINS list(DEXALIN, THYMOL)
|
||||
#define PETRITRICINCURES list(SACID, PACID, FORMIC_ACID, PACID, PHENOL, ACIDSPIT, ACIDTEA)
|
||||
#define WATERS list(WATER, HOLYWATER)
|
||||
#define WATERS list(WATER, HOLYWATER, ICE)
|
||||
#define CORES list(SOFTCORES, MEDCORES)
|
||||
#define ALLNANITES list(NANITES, AUTISTNANITES)
|
||||
#define SUGARS list(SUGAR, CORNSYRUP)
|
||||
|
||||
@@ -4,28 +4,13 @@
|
||||
icon = 'icons/obj/fish_items.dmi'
|
||||
icon_state = "eggs"
|
||||
w_class = W_CLASS_SMALL
|
||||
var/fish_type = "dud" //Holds the name of the fish that the egg is for
|
||||
var/fish_type = "dud"
|
||||
var/acidic = FALSE
|
||||
var/hatching = TRUE
|
||||
|
||||
/obj/item/fish_eggs/New()
|
||||
..()
|
||||
|
||||
var/list/fish_eggs_list = list("dud" = /obj/item/fish_eggs,
|
||||
"goldfish" = /obj/item/fish_eggs/goldfish,
|
||||
"clownfish" = /obj/item/fish_eggs/clownfish,
|
||||
"shark" = /obj/item/fish_eggs/shark,
|
||||
//"baby space carp" = /obj/item/fish_eggs/babycarp,
|
||||
"catfish" = /obj/item/fish_eggs/catfish,
|
||||
"feederfish" = /obj/item/fish_eggs/feederfish,
|
||||
"salmon" = /obj/item/fish_eggs/salmon,
|
||||
"shrimp" = /obj/item/fish_eggs/shrimp,
|
||||
"electric eel" = /obj/item/fish_eggs/electric_eel,
|
||||
"glofish" = /obj/item/fish_eggs/glofish,
|
||||
"sea devil" = /obj/item/fish_eggs/seadevil,
|
||||
"lobster" = /obj/item/fish_eggs/lobster
|
||||
)
|
||||
|
||||
var/list/nonhatching_types = list("sea devil") //If you ever want to create another no-egg fish, add it here.
|
||||
|
||||
/obj/item/fish_eggs/goldfish
|
||||
name = "goldfish eggs"
|
||||
desc = "Goldfish eggs, surprisingly, don't contain actual gold."
|
||||
@@ -91,6 +76,7 @@ var/list/nonhatching_types = list("sea devil") //If you ever want to create anot
|
||||
desc = "An aquatic offshoot of gremlins that engage in the peculiar behavior of hatching fish eggs to eat mature adults."
|
||||
icon_state = "seadevil"
|
||||
fish_type = "sea devil"
|
||||
hatching = FALSE
|
||||
|
||||
/obj/item/fish_eggs/lobster
|
||||
name = "lobster eggs"
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
|
||||
|
||||
var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
|
||||
"clownfish" = /obj/item/weapon/bananapeel/clownfish,
|
||||
"shark" = /obj/item/weapon/fish/shark,
|
||||
//"baby space carp" = /obj/item/weapon/fish/babycarp,
|
||||
"catfish" = /obj/item/weapon/fish/catfish,
|
||||
"feederfish" = /obj/item/weapon/reagent_containers/food/snacks/feederfish,
|
||||
"salmon" = /obj/item/weapon/fish/salmon,
|
||||
"shrimp" = /obj/item/weapon/reagent_containers/food/snacks/shrimp,
|
||||
"electric eel" = /obj/item/weapon/fish/electric_eel,
|
||||
"glofish" = /obj/item/weapon/fish/glofish,
|
||||
, "sea devil" = /obj/item/fish_eggs/seadevil, //You can fish a sea devil straight back out and stick it in another tank.
|
||||
"lobster" = /obj/item/weapon/lobster
|
||||
)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Aquarium Supplies //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/obj/item/weapon/fishtools/fish_egg_scoop
|
||||
name = "fish egg scoop"
|
||||
desc = "A small scoop to collect fish eggs with."
|
||||
@@ -77,11 +57,6 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
|
||||
icon_state = "cyborg_upgrade"
|
||||
w_class = W_CLASS_SMALL
|
||||
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Fish Items //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/shrimp
|
||||
name = "shrimp"
|
||||
desc = "A single raw shrimp."
|
||||
|
||||
@@ -43,15 +43,16 @@
|
||||
var/lid_switch = FALSE // FALSE = open, TRUE = closed (open by default)
|
||||
var/max_fish = 0 // How many fish the tank can support (varies with tank type, 1 fish per 50 units sounds reasonable)
|
||||
var/food_level = 0 // Amount of fishfood floating in the tank (max 10)
|
||||
var/list/fish_list = list() // Tracks the current types of fish in the tank
|
||||
var/list/egg_list = list() // Tracks the current types of harvestable eggs in the tank
|
||||
var/list/fish_list_water = list() // Tracks the current types of fish in the tank
|
||||
var/list/fish_list_acidic = list()
|
||||
var/list/fish_list = list()
|
||||
var/list/egg_list = list() // Strings containing egg.fish_type
|
||||
|
||||
var/has_lid = FALSE // FALSE if the tank doesn't have a lid/light, TRUE if it does
|
||||
var/max_health = 0 // Can handle a couple hits
|
||||
var/cur_health = 0 // Current health, starts at max_health
|
||||
var/leaking = NO_LEAK
|
||||
var/shard_count = 0 // Number of glass shards to salvage when broken (1 less than the number of sheets to build the tank)
|
||||
var/automated = 0 // Cleans the aquarium on its own
|
||||
var/acidic = FALSE
|
||||
|
||||
/obj/machinery/fishtank/bowl
|
||||
name = "fish bowl"
|
||||
@@ -67,8 +68,8 @@
|
||||
max_fish = 1 // What a lonely fish
|
||||
|
||||
has_lid = FALSE
|
||||
max_health = 15 // Not very sturdy
|
||||
cur_health = 15
|
||||
maxHealth = 15 // Not very sturdy
|
||||
health = 15
|
||||
shard_count = 0 // No salvageable shards
|
||||
|
||||
/obj/machinery/fishtank/bowl/full
|
||||
@@ -94,8 +95,8 @@
|
||||
max_fish = 4 // Room for a few fish
|
||||
|
||||
has_lid = TRUE
|
||||
max_health = 50 // Average strength, will take a couple hits from a toolbox.
|
||||
cur_health = 50
|
||||
maxHealth = 50 // Average strength, will take a couple hits from a toolbox.
|
||||
health = 50
|
||||
shard_count = 4
|
||||
|
||||
/obj/machinery/fishtank/tank/full
|
||||
@@ -116,8 +117,8 @@
|
||||
max_fish = 10 // Plenty of room for a lot of fish
|
||||
|
||||
has_lid = TRUE
|
||||
max_health = 100 // This thing is a freaking wall, it can handle abuse.
|
||||
cur_health = 100
|
||||
maxHealth = 100 // This thing is a freaking wall, it can handle abuse.
|
||||
health = 100
|
||||
shard_count = 9
|
||||
|
||||
/obj/machinery/fishtank/wall/full
|
||||
@@ -182,8 +183,8 @@
|
||||
/obj/machinery/fishtank/update_icon()
|
||||
overlays.Cut()
|
||||
//Update Alert Lights
|
||||
if(has_lid) //Skip the alert lights for aquariums that don't have lids (fishbowls)
|
||||
if(egg_list.len) //There is at least 1 egg to harvest
|
||||
if(has_lid)
|
||||
if(egg_list.len)
|
||||
overlays += "over_egg"
|
||||
if(lid_switch == TRUE) //Lid is closed, lid status light is red
|
||||
overlays += "over_lid_1"
|
||||
@@ -234,58 +235,63 @@
|
||||
water_type = "clean"
|
||||
if (FILTH_THRESHOLD to MAX_FILTH)
|
||||
water_type = "dirty"
|
||||
|
||||
switch (water_level/water_capacity)
|
||||
if (0.01 to 0.85) // Lest there can be fish in waterless environements
|
||||
// Lest there can be fish in waterless environments
|
||||
if(!acidic)
|
||||
if(water_level/water_capacity < 0.85 && water_level/water_capacity > 0.01)
|
||||
overlays += icon('icons/obj/fish_items.dmi', "over_[tank_type]_half_[water_type]", WATER_LAYER)
|
||||
if (0.85 to 1)
|
||||
else if(water_level/water_capacity > 0.85)
|
||||
overlays += icon('icons/obj/fish_items.dmi', "over_[tank_type]_full_[water_type]", WATER_LAYER)
|
||||
|
||||
//////////////////////////////
|
||||
// PROCESS PROC //
|
||||
//////////////////////////////
|
||||
|
||||
else
|
||||
if(water_level/water_capacity < 0.85 && water_level/water_capacity > 0.01)
|
||||
overlays += icon('icons/obj/fish_items.dmi', "over_[tank_type]_half_[water_type]_acidic", WATER_LAYER)
|
||||
else if(water_level/water_capacity > 0.85)
|
||||
overlays += icon('icons/obj/fish_items.dmi', "over_[tank_type]_full_[water_type]_acidic", WATER_LAYER)
|
||||
|
||||
/obj/machinery/fishtank/process()
|
||||
|
||||
//Check if the water level can support the current number of fish
|
||||
if((fish_list.len * 50) > water_level)
|
||||
if(prob(50)) //Not enough water for all the fish, chance to kill one
|
||||
kill_fish() //Chance passed, kill a random fish
|
||||
add_filth(2) //Dead fish raise the filth level quite a bit, reflect this
|
||||
if(prob(50))
|
||||
remove_fish()
|
||||
add_filth(2)
|
||||
|
||||
//Check filth_level
|
||||
if(filth_level == MAX_FILTH && fish_list.len > 0) //This tank is nasty and possibly unsuitable for fish if any are in it
|
||||
if(prob(30)) //Chance for a fish to die each cycle while the tank is this nasty
|
||||
kill_fish() //Kill a random fish, don't raise filth level since we're at cap already
|
||||
if(filth_level == MAX_FILTH && fish_list.len > 0)
|
||||
if(prob(30))
|
||||
remove_fish()
|
||||
|
||||
//Check breeding conditions
|
||||
if(fish_list.len >=2 && egg_list.len < max_fish) //Need at least 2 fish to breed, but won't breed if there are as many eggs as max_fish
|
||||
if(food_level > 2 && filth_level <=5) //Breeding is going to use extra food, and the filth_level shouldn't be too high
|
||||
if(prob(((fish_list.len - 2) * 5)+10)) //Chances increase with each additional fish, 10% base + 5% per additional fish
|
||||
egg_list.Add(select_egg_type()) //Add the new egg to the egg_list for storage
|
||||
remove_food(2) //Remove extra food for the breeding process
|
||||
if(fish_list.len >=2 && egg_list.len < max_fish)
|
||||
if(food_level > 2 && filth_level <=5)
|
||||
if(prob(((fish_list.len - 2) * 5)+8))
|
||||
egg_list.Add(pick(fish_list))
|
||||
remove_food(2)
|
||||
|
||||
//Handle standard food and filth adjustments
|
||||
var/ate_food = FALSE
|
||||
if(food_level > 0 && prob(50)) //Chance for the fish to eat some food
|
||||
if(food_level >= (fish_list.len * 0.01)) //If there is at least enough food to go around, feed all the fish
|
||||
if(food_level > 0 && prob(50))
|
||||
if(food_level >= (fish_list.len * 0.01))
|
||||
remove_food(fish_list.len * 0.01)
|
||||
else //Use up the last of the food
|
||||
else
|
||||
food_level = 0
|
||||
ate_food = TRUE
|
||||
|
||||
if(water_level > 0) //Don't dirty the tank if it has no water
|
||||
if(fish_list.len == 0) //If the tank has no fish, algae growth can occur
|
||||
if(filth_level < ALGAE_THRESHOLD && prob(15)) //Algae growth is a low chance and cannot exceed filth_level of 7.5
|
||||
add_filth(0.05) //Algae growth is slower than fish filth build-up
|
||||
else if(filth_level < MAX_FILTH && prob(10)) //Chance for the tank to get dirtier if the filth_level isn't 10
|
||||
if(ate_food && prob(25)) //If they ate this cycle, there is an additional chance they make a bigger mess
|
||||
if(water_level > 0)
|
||||
if(!fish_list.len)
|
||||
//If the tank has no fish, algae growth can occur
|
||||
if(filth_level < ALGAE_THRESHOLD && prob(15))
|
||||
add_filth(0.05)
|
||||
//Chance for the tank to get dirtier if the filth_level isn't max
|
||||
else
|
||||
if(acidic && fish_list_water.len)
|
||||
remove_fish(pick(fish_list_water))
|
||||
else if(!acidic && fish_list_acidic.len)
|
||||
remove_fish(pick(fish_list_acidic))
|
||||
if(filth_level < MAX_FILTH && prob(10))
|
||||
if(ate_food && prob(25))
|
||||
add_filth(fish_list.len * 0.1)
|
||||
else //If they didn't make the big mess, make a little one
|
||||
else
|
||||
add_filth(0.1)
|
||||
|
||||
//Handle special interactions
|
||||
handle_special_interactions()
|
||||
|
||||
//Handle water leakage from damage
|
||||
@@ -300,24 +306,21 @@
|
||||
if(filth_level > 0)
|
||||
remove_filth(0.05)
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// SUPPORT PROCS //
|
||||
//////////////////////////////
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_special_interactions()
|
||||
var/glo_light = 0
|
||||
for(var/fish in fish_list)
|
||||
switch(fish)
|
||||
if("catfish") //Catfish have a small chance of cleaning some filth since they are a bottom-feeder
|
||||
//Catfish have a small chance of cleaning some filth since they are a bottom-feeder
|
||||
if("catfish")
|
||||
if(filth_level > 0 && prob(30))
|
||||
remove_filth(0.1)
|
||||
if("feederfish") //Feeder fish have a small chance of sacrificing themselves to produce some food
|
||||
if(fish_list.len < 2) //Don't sacrifice the last fish, there's nothing to eat it
|
||||
if("feederfish")
|
||||
//only feederfish left
|
||||
if(fish_list.len < 2)
|
||||
continue
|
||||
if(food_level <= FOOD_OK && prob(25))
|
||||
kill_fish("feederfish") //Kill the fish to reflect it's sacrifice, but don't increase the filth_level
|
||||
add_food(1) //The corpse became food for the other fish, ecology at it's finest
|
||||
remove_fish("feederfish")
|
||||
add_food(1)
|
||||
if("glofish")
|
||||
glo_light++
|
||||
if("clownfish")
|
||||
@@ -327,15 +330,13 @@
|
||||
if(fish_list.len > 1 && prob(5))
|
||||
//Small chance to eat a random fish that isn't itself.
|
||||
seadevil_eat()
|
||||
|
||||
if(fish_list.len < max_fish && egg_list.len)
|
||||
add_fish(get_key_by_element(fish_eggs_list,egg_list[1])) //add_fish takes a string. egg_list gives a path. fish_eggs_list is an associative list keyed with strings. get_key_by_index returns that string key by matching the path
|
||||
add_fish(egg_list[1])
|
||||
egg_list -= egg_list[1]
|
||||
|
||||
if(!light_switch && (glo_light > 0))
|
||||
set_light(2,glo_light,"#99FF66")
|
||||
|
||||
|
||||
/obj/machinery/fishtank/proc/remove_water(var/amount)
|
||||
water_level = max(0, water_level - amount)
|
||||
update_icon()
|
||||
@@ -360,27 +361,33 @@
|
||||
food_level = min(MAX_FOOD, food_level + amount)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/fishtank/proc/check_health()
|
||||
//Max value check
|
||||
if(cur_health > max_health) //Cur_health cannot exceed max_health, set it to max_health if it does
|
||||
cur_health = max_health
|
||||
//Leaking status check
|
||||
if(cur_health <= (max_health * 0.25)) //Major leak at or below 25% health (-10 water/cycle)
|
||||
/obj/machinery/fishtank/proc/add_health(var/amount)
|
||||
if(amount > 0)
|
||||
health = min(health + amount, maxHealth)
|
||||
else
|
||||
health = max(0, health + amount)
|
||||
playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1)
|
||||
if(health <= (maxHealth * 0.25))
|
||||
leaking = MAJOR_LEAK
|
||||
else if(cur_health <= (max_health * 0.5)) //Minor leak at or below 50% health (-1 water/cycle)
|
||||
else if(health <= (maxHealth * 0.5))
|
||||
leaking = MINOR_LEAK
|
||||
else //Not leaking above 50% health
|
||||
else
|
||||
leaking = NO_LEAK
|
||||
//Destruction check
|
||||
if(cur_health <= 0) //The tank is broken, destroy it
|
||||
|
||||
if(health < 1)
|
||||
playsound(loc, 'sound/effects/Glassbr2.ogg', 100, 1)
|
||||
destroy()
|
||||
|
||||
/obj/machinery/fishtank/proc/kill_fish(var/type = null)
|
||||
//Check if we were passed a fish to kill, otherwise kill a random one
|
||||
/obj/machinery/fishtank/proc/remove_fish(var/type = null)
|
||||
if(type)
|
||||
fish_list.Remove(type) //Kill a fish of the specified type
|
||||
fish_list.Remove(type)
|
||||
fish_list_water.Remove(type)
|
||||
fish_list_acidic.Remove(type)
|
||||
else
|
||||
fish_list.Remove(pick(fish_list)) //Kill a random fish
|
||||
var/fish = pick(fish_list)
|
||||
fish_list.Remove(fish)
|
||||
fish_list_water.Remove(fish)
|
||||
fish_list_acidic.Remove(fish)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/fishtank/proc/seadevil_eat()
|
||||
@@ -388,81 +395,70 @@
|
||||
fish_to_eat.Remove("sea devil")
|
||||
var/eat_target = pick(fish_to_eat)
|
||||
visible_message("<span class='notice'>The sea devil devours \an [eat_target].</span>")
|
||||
kill_fish(eat_target)
|
||||
remove_fish(eat_target)
|
||||
|
||||
/obj/machinery/fishtank/proc/add_fish(var/type)
|
||||
if(!type || type == "dud")
|
||||
/obj/machinery/fishtank/proc/add_fish(var/fish_type)
|
||||
if(!fish_type || fish_type == "dud")
|
||||
return
|
||||
//Check if we were passed a fish type
|
||||
fish_list.Add("[type]") //Add a fish of the specified type
|
||||
//Announce the new fish
|
||||
update_icon()
|
||||
if(nonhatching_types.Find(type))
|
||||
visible_message("The [type] has been placed in \the [src]!")
|
||||
else
|
||||
visible_message("A new [type] has hatched in \the [src]!")
|
||||
|
||||
/obj/machinery/fishtank/proc/select_egg_type()
|
||||
var/fish = null
|
||||
if(prob(10)) //Small chance for infertility
|
||||
fish = "dud"
|
||||
else
|
||||
fish = recursive_valid_egg(fish_list)
|
||||
var/obj/item/fish_eggs/egg_path = fish_eggs_list[fish] //Locate the corresponding path from fish_eggs_list that matches the fish
|
||||
return egg_path
|
||||
|
||||
/obj/machinery/fishtank/proc/recursive_valid_egg(var/list/pick_egg_from)
|
||||
var/fish = pick(pick_egg_from)
|
||||
if(!fish || nonhatching_types.Find(fish))
|
||||
var/list/new_list = pick_egg_from.Copy()
|
||||
return recursive_valid_egg(new_list.Remove(fish))
|
||||
//If it's a nonvalid type, let's try again without it.
|
||||
else
|
||||
return fish
|
||||
//If it's valid, return this.
|
||||
for (var/egg_path in subtypesof(/obj/item/fish_eggs/))
|
||||
var/obj/item/fish_eggs/egg = new egg_path
|
||||
if(egg.fish_type != fish_type)
|
||||
continue
|
||||
if(egg.acidic)
|
||||
fish_list_acidic.Add(egg.fish_type)
|
||||
else
|
||||
fish_list_water.Add(egg.fish_type)
|
||||
fish_list.Add(egg.fish_type)
|
||||
//Announce the new fish
|
||||
update_icon()
|
||||
if(egg.hatching)
|
||||
visible_message("A new [egg.fish_type] has hatched in \the [src]!")
|
||||
else
|
||||
visible_message("The [egg.fish_type] has been placed in \the [src]!")
|
||||
|
||||
/obj/machinery/fishtank/proc/harvest_eggs(var/mob/user)
|
||||
if(!egg_list.len) //Can't harvest non-existant eggs
|
||||
if(!egg_list.len)
|
||||
return
|
||||
|
||||
for(var/i = 1 to egg_list.len) //Loop until you've harvested all the eggs
|
||||
var/obj/item/fish_eggs/egg = egg_list[i] //Go through the eggs
|
||||
new egg(get_turf(user)) //Spawn the egg at the user's feet
|
||||
|
||||
egg_list = list() //Destroy any excess eggs, clearing the egg_list
|
||||
for(var/fish_type in egg_list)
|
||||
for (var/egg_path in subtypesof(/obj/item/fish_eggs/))
|
||||
var/obj/item/fish_eggs/egg = new egg_path
|
||||
if(egg.fish_type == fish_type)
|
||||
egg = new egg_path(get_turf(user))
|
||||
egg_list.len = 0
|
||||
|
||||
/obj/machinery/fishtank/proc/harvest_fish(var/mob/user)
|
||||
if(!fish_list.len) //Can't catch non-existant fish!
|
||||
if(!fish_list.len)
|
||||
to_chat(user, "There are no fish in \the [src] to catch!")
|
||||
return
|
||||
|
||||
var/caught_fish = input("Select a fish to catch.", "Fishing") as null|anything in fish_list //Select a fish from the tank
|
||||
var/caught_fish = pick(fish_list)
|
||||
if(caught_fish)
|
||||
var/dead_fish = fish_items_list[caught_fish] //Locate the appropriate fish_item for the caught fish
|
||||
if(!dead_fish) //No fish_item found, possibly due to typo or not being listed. Do nothing.
|
||||
return
|
||||
kill_fish(caught_fish) //Kill the caught fish from the tank
|
||||
remove_fish(caught_fish)
|
||||
user.visible_message("[user.name] harvests \a [caught_fish] from \the [src].", "You scoop \a [caught_fish] out of \the [src].")
|
||||
new dead_fish(get_turf(user)) //Spawn the appropriate fish_item at the user's feet.
|
||||
for(var/fish_path in subtypesof(/obj/item/weapon/fish/))
|
||||
var/obj/item/weapon/fish = new fish_path
|
||||
if(fish.name == caught_fish)
|
||||
new fish(get_turf(user))
|
||||
|
||||
/obj/machinery/fishtank/proc/destroy(var/deconstruct = FALSE)
|
||||
if(!deconstruct) //Check if we are deconstructing or breaking the tank
|
||||
for(var/i = 0 to shard_count) //Produce the appropriate number of glass shards
|
||||
if(!deconstruct)
|
||||
for(var/i = 0 to shard_count)
|
||||
new /obj/item/weapon/shard(get_turf(src))
|
||||
if(water_level) //Spill any water that was left in the tank when it broke
|
||||
if(water_level)
|
||||
spill_water()
|
||||
else //We are deconstructing, make glass sheets instead of shards
|
||||
var/sheets = shard_count + 1 //Deconstructing it salvages all the glass used to build the tank
|
||||
else
|
||||
var/sheets = shard_count + 1
|
||||
var/cur_turf = get_turf(src)
|
||||
new /obj/item/stack/sheet/glass/glass(cur_turf, sheets) //Produce the appropriate number of glass sheets, in a single stack (/glass/glass)
|
||||
new /obj/item/stack/sheet/glass/glass(cur_turf, sheets)
|
||||
if(circuitboard)
|
||||
new circuitboard(cur_turf) //Eject the circuitboard
|
||||
qdel(src) //qdel the tank and it's contents
|
||||
|
||||
new circuitboard(cur_turf)
|
||||
new /obj/item/stack/sheet/metal(cur_turf, 5)
|
||||
new /obj/item/stack/cable_coil(cur_turf, 5)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/fishtank/proc/spill_water()
|
||||
switch(tank_type)
|
||||
if(FISH_BOWL) //Fishbowl: Wets it's own tile
|
||||
if(FISH_BOWL)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T, /turf/simulated))
|
||||
return
|
||||
@@ -479,11 +475,6 @@
|
||||
for(var/turf/simulated/S in view(src, 1))
|
||||
S.wet(10 SECONDS, TURF_WET_WATER)
|
||||
|
||||
|
||||
////////////////////////////// Note from FalseIncarnate:
|
||||
// EXAMINE PROC // This proc is massive, messy, and probably could be handled better.
|
||||
////////////////////////////// Feel free to try cleaning it up if you think of a better way to do it.
|
||||
|
||||
/obj/machinery/fishtank/examine(var/mob/user)
|
||||
..()
|
||||
var/examine_message = list()
|
||||
@@ -596,7 +587,6 @@
|
||||
if(MAJOR_LEAK)
|
||||
examine_message += "<span class = 'warning'>\The [src] is nearly shattered!</span>"
|
||||
|
||||
//Finally, report the full examine_message constructed from the above reports
|
||||
to_chat(user, jointext(examine_message, ""))
|
||||
|
||||
//////////////////////////////
|
||||
@@ -608,7 +598,6 @@
|
||||
return
|
||||
attack_generic(user, 15)
|
||||
|
||||
|
||||
/obj/machinery/fishtank/attack_hand(var/mob/user)
|
||||
|
||||
if (!Adjacent(user) || user.incapacitated())
|
||||
@@ -623,153 +612,43 @@
|
||||
user.visible_message("\The [user] taps on \the [src].", \
|
||||
"You tap on \the [src].", \
|
||||
"You hear a knocking sound.")
|
||||
|
||||
user.delayNextAttack(0.8 SECONDS)
|
||||
|
||||
|
||||
/obj/machinery/fishtank/proc/hit(var/obj/O, var/mob/user)
|
||||
user.delayNextAttack(0.8 SECONDS)
|
||||
user.do_attack_animation(src, O)
|
||||
playsound(src, 'sound/effects/glassknock.ogg', 80, 1)
|
||||
cur_health = max(0, cur_health - O.force)
|
||||
check_health()
|
||||
add_health(-O.force)
|
||||
|
||||
/obj/machinery/fishtank/proc/attack_generic(var/mob/living/user, var/damage = 0) //used by attack_alien, attack_animal, and attack_slime
|
||||
cur_health = max(0, cur_health - damage)
|
||||
if(cur_health <= 0)
|
||||
user.visible_message("<span class='danger'>\The [user] smashes through \the [src]!</span>")
|
||||
destroy()
|
||||
else //for nicer text
|
||||
user.visible_message("<span class='danger'>\The [user] smashes into \the [src]!</span>")
|
||||
playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1)
|
||||
check_health()
|
||||
//used by attack_alien, attack_animal, and attack_slime
|
||||
/obj/machinery/fishtank/proc/attack_generic(var/mob/living/user, var/damage = 0)
|
||||
add_health(-damage)
|
||||
|
||||
/obj/machinery/fishtank/attackby(var/obj/item/O, var/mob/user as mob)
|
||||
//Silicate sprayers repair damaged tanks on help intent
|
||||
if(issilicatesprayer(O))
|
||||
var/obj/item/device/silicate_sprayer/S = O
|
||||
if(user.a_intent == I_HELP)
|
||||
if (S.get_amount() >= 2)
|
||||
if(cur_health < max_health)
|
||||
to_chat(user, "<span class='notice'>You repair some of the cracks on \the [src].</span>")
|
||||
cur_health += 20
|
||||
S.remove_silicate(2)
|
||||
check_health()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is no damage to fix!</span>")
|
||||
else if (cur_health < max_health)
|
||||
to_chat(user, "<span class='notice'>You require more silicate to fix the damage on \the [src].</span>")
|
||||
return TRUE
|
||||
return handle_silicate_sprayer(O, user)
|
||||
//Open reagent containers add and remove water
|
||||
if(O.is_open_container())
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
if(lid_switch)
|
||||
to_chat(user, "<span class='notice'>Open the lid on \the [src] first!</span>")
|
||||
return TRUE
|
||||
var/obj/item/weapon/reagent_containers/glass/C = O
|
||||
//Containers with any reagents will get dumped in
|
||||
if(C.reagents.total_volume)
|
||||
var/water_value = 0
|
||||
water_value += C.reagents.get_reagent_amount(WATER) //Water is full value
|
||||
water_value += C.reagents.get_reagent_amount(HOLYWATER) *1.1 //Holywater is (somehow) better. Who said religion had to make sense?
|
||||
|
||||
water_value += C.reagents.get_reagent_amount(ICE) * 0.80 //Ice is 80% value
|
||||
var/message = ""
|
||||
if(!water_value) //The container has no water value, clear everything in it
|
||||
message = "<span class='warning'>The filtration process removes everything, leaving the water level unchanged.</span>"
|
||||
C.reagents.clear_reagents()
|
||||
else
|
||||
if(water_level == water_capacity)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already full!</span>")
|
||||
return TRUE
|
||||
else
|
||||
message = "The filtration process purifies the water, raising the water level."
|
||||
add_water(water_value)
|
||||
if(water_level == water_capacity)
|
||||
message += "You filled \the [src] to the brim!"
|
||||
if(water_level > water_capacity)
|
||||
message += "You overfilled \the [src] and some water runs down the side, wasted."
|
||||
C.reagents.clear_reagents()
|
||||
user.visible_message("\The [user] pours the contents of \the [C] into \the [src].", "<span class = 'notice'>[message]</span>")
|
||||
return TRUE
|
||||
//Empty containers will scoop out water, filling the container as much as possible from the water_level
|
||||
else
|
||||
if(water_level == 0)
|
||||
to_chat(user, "<span class='notice'>\The [src] is empty!</span>")
|
||||
else
|
||||
C.reagents.add_reagent(WATER, water_level)
|
||||
remove_water(C.volume)
|
||||
if(water_level >= C.volume) //Enough to fill the container completely
|
||||
user.visible_message("\The [user] scoops out some water from \the [src].", "<span class = 'notice'>You completely fill [C.name] from \the [src].</span>")
|
||||
else //Fill the container as much as possible with the water_level
|
||||
user.visible_message("\The [user] scoops out some water from \the [src].", "<span class = 'notice'>You fill [C.name] with the last of the water in \the [src].</span>")
|
||||
|
||||
return TRUE
|
||||
//Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process
|
||||
return handle_containers(O, user)
|
||||
//Wrenches can deconstruct empty tanks, but not tanks with any water
|
||||
if(O.is_wrench(user))
|
||||
if (water_level == 0)
|
||||
to_chat(user, "<span class='notice'>Now disassembling \the [src].</span>")
|
||||
O.playtoolsound(loc, 50)
|
||||
if(do_after(user,50, target = src))
|
||||
destroy(1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] must be empty before you disassemble it!</span>")
|
||||
return TRUE
|
||||
return handle_wrench(O, user)
|
||||
//Fish eggs
|
||||
else if(istype(O, /obj/item/fish_eggs))
|
||||
var/obj/item/fish_eggs/egg = O
|
||||
//Don't add eggs if there is no water (they kinda need that to live)
|
||||
if(water_level == 0)
|
||||
to_chat(user, "<span class='warning'>\The [src] has no water; [egg.name] won't hatch without water!</span>")
|
||||
return FALSE
|
||||
//Don't add eggs if the tank already has the max number of fish
|
||||
if(fish_list.len >= max_fish)
|
||||
to_chat(user, "<span class='warning'>\The [src] can't hold any more fish.</span>")
|
||||
return FALSE
|
||||
if (egg.fish_type == "dud") // Fugging duds
|
||||
to_chat(user, "<span class='warning'>The eggs didn't hatch. They were duds!</span>")
|
||||
qdel(egg)
|
||||
return FALSE
|
||||
add_fish(egg.fish_type)
|
||||
qdel(egg)
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/fish_eggs))
|
||||
return handle_eggs(O, user)
|
||||
//Fish food
|
||||
else if(istype(O, /obj/item/weapon/fishtools/fish_food))
|
||||
//Only add food if there is water and it isn't already full of food
|
||||
if(!water_level)
|
||||
to_chat(user, "<span class='warning'>\The [src] doesn't have any water in it. You should fill it with water first.</span>")
|
||||
return FALSE
|
||||
if(food_level >= MAX_FOOD)
|
||||
to_chat(user, "<span class='notice'>\The [src] already has plenty of food in it. You decide to not add more.<span>")
|
||||
return FALSE
|
||||
|
||||
if(fish_list.len == 0)
|
||||
user.visible_message("\The [user] shakes some fish food into the empty [src]... How sad.", "<span class='notice'>You shake some fish food into the empty [src]... If only it had fish.</span>")
|
||||
else
|
||||
user.visible_message("\The [user] feeds the fish in \the [src]. The fish look excited!", "<span class='notice'>You feed the fish in \the [src]. They look excited!</span>")
|
||||
add_food(MAX_FOOD)
|
||||
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/weapon/fishtools/fish_food))
|
||||
return handle_food(O, user)
|
||||
//Fish egg scoop
|
||||
else if(istype(O, /obj/item/weapon/fishtools/fish_egg_scoop))
|
||||
if(egg_list.len)
|
||||
user.visible_message("\The [user] harvests some fish eggs from \the [src].", "<span class='notice'>You scoop the fish eggs out of \the [src].</span>")
|
||||
harvest_eggs(user)
|
||||
else
|
||||
user.visible_message("\The [user] fails to harvest any fish eggs from \the [src].", "<span class='notice'>There are no fish eggs in \the [src] to scoop out.</span>")
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/weapon/fishtools/fish_egg_scoop))
|
||||
return handle_fish_scoop(O, user)
|
||||
//Fish net
|
||||
if(istype(O, /obj/item/weapon/fishtools/fish_net))
|
||||
harvest_fish(user)
|
||||
return TRUE
|
||||
return harvest_fish(user)
|
||||
//Tank brush
|
||||
if(istype(O, /obj/item/weapon/fishtools/fish_tank_brush))
|
||||
if(filth_level == 0)
|
||||
to_chat(user, "\The [src] is already spotless!")
|
||||
return TRUE
|
||||
filth_level = 0
|
||||
user.visible_message("\The [user] scrubs the inside of \the [src], cleaning the filth.", "<span class='notice'>You scrub the inside of \the [src], cleaning the filth.</span>")
|
||||
return TRUE
|
||||
return handle_brush(O, user)
|
||||
//Installing the automation module
|
||||
if(istype(O, /obj/item/weapon/fishtools/fishtank_helper))
|
||||
if(automated)
|
||||
@@ -785,6 +664,110 @@
|
||||
hit(O, user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_silicate_sprayer(var/obj/item/O, var/mob/user as mob)
|
||||
var/obj/item/device/silicate_sprayer/S = O
|
||||
if(user.a_intent == I_HELP)
|
||||
if (S.get_amount() >= 2)
|
||||
add_health(20)
|
||||
S.remove_silicate(2)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_containers(var/obj/item/O, var/mob/user as mob)
|
||||
if(!istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
return FALSE
|
||||
if(lid_switch)
|
||||
to_chat(user, "<span class='notice'>Open the lid on \the [src] first!</span>")
|
||||
return FALSE
|
||||
|
||||
var/obj/item/weapon/reagent_containers/glass/C = O
|
||||
if(water_level && !C.reagents.total_volume)
|
||||
//Empty containers will scoop out water, filling the container as much as possible from the water_level
|
||||
if(acidic)
|
||||
C.reagents.add_reagent(SACID, water_level)
|
||||
remove_water(C.volume)
|
||||
else
|
||||
C.reagents.add_reagent(WATER, water_level)
|
||||
remove_water(C.volume)
|
||||
update_icon()
|
||||
return TRUE
|
||||
else if(water_level == water_capacity)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already full!</span>")
|
||||
return TRUE
|
||||
|
||||
var/water_value = 0
|
||||
if(!C.reagents.has_any_reagents(PETRITRICINCURES) && C.reagents.has_any_reagents(WATERS))
|
||||
acidic = FALSE
|
||||
water_value += C.reagents.get_reagent_amount(WATER)
|
||||
water_value += C.reagents.get_reagent_amount(HOLYWATER) *1.1
|
||||
water_value += C.reagents.get_reagent_amount(ICE) * 0.80
|
||||
else if(C.reagents.has_any_reagents(PETRITRICINCURES) && !C.reagents.has_any_reagents(WATERS))
|
||||
acidic = TRUE
|
||||
water_value += C.reagents.get_reagent_amount(PACID) * 2
|
||||
water_value += C.reagents.get_reagent_amount(SACID)
|
||||
water_value += C.reagents.get_reagent_amount(PHENOL)
|
||||
water_value += C.reagents.get_reagent_amount(FORMIC_ACID)
|
||||
else
|
||||
water_value += C.reagents.get_reagent_amount(WATER)
|
||||
water_value += C.reagents.get_reagent_amount(HOLYWATER) *1.1
|
||||
water_value += C.reagents.get_reagent_amount(ICE) * 0.80
|
||||
var/message = ""
|
||||
if(water_value)
|
||||
add_water(water_value)
|
||||
C.reagents.clear_reagents()
|
||||
if(water_level == water_capacity)
|
||||
message += "You filled \the [src] to the brim!"
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_wrench(var/obj/item/O, var/mob/user as mob)
|
||||
if (water_level == 0)
|
||||
O.playtoolsound(loc, 50)
|
||||
if(do_after(user,50, target = src))
|
||||
destroy(1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] must be empty before you disassemble it!</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_eggs(var/obj/item/O, var/mob/user as mob)
|
||||
var/obj/item/fish_eggs/egg = O
|
||||
if(water_level == 0)
|
||||
to_chat(user, "<span class='warning'>\The [src] has no water; [egg.name] won't hatch without water!</span>")
|
||||
return FALSE
|
||||
//Don't add eggs if the tank already has the max number of fish
|
||||
if(fish_list.len >= max_fish)
|
||||
to_chat(user, "<span class='warning'>\The [src] can't hold any more fish.</span>")
|
||||
return FALSE
|
||||
if (egg.fish_type == "dud")
|
||||
to_chat(user, "<span class='warning'>The eggs didn't hatch.</span>")
|
||||
qdel(egg)
|
||||
return FALSE
|
||||
add_fish(egg.fish_type)
|
||||
qdel(egg)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_food(var/obj/item/O, var/mob/user as mob)
|
||||
//Only add food if there is water and it isn't already full of food
|
||||
if(!water_level)
|
||||
to_chat(user, "<span class='warning'>\The [src] doesn't have any water in it. You should fill it with water first.</span>")
|
||||
return FALSE
|
||||
if(food_level >= MAX_FOOD)
|
||||
to_chat(user, "<span class='notice'>\The [src] already has plenty of food in it. You decide to not add more.<span>")
|
||||
return FALSE
|
||||
add_food(MAX_FOOD)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_fish_scoop(var/obj/item/O, var/mob/user as mob)
|
||||
harvest_eggs(user)
|
||||
|
||||
/obj/machinery/fishtank/proc/handle_brush(var/obj/item/O, var/mob/user as mob)
|
||||
if(filth_level == 0)
|
||||
to_chat(user, "\The [src] is already spotless!")
|
||||
return TRUE
|
||||
filth_level = 0
|
||||
user.visible_message("\The [user] scrubs the inside of \the [src], cleaning the filth.", "<span class='notice'>You scrub the inside of \the [src], cleaning the filth.</span>")
|
||||
return TRUE
|
||||
|
||||
//Conduction plate for electric eels
|
||||
|
||||
/obj/machinery/power/conduction_plate
|
||||
@@ -825,15 +808,10 @@
|
||||
add_avail(power)
|
||||
|
||||
/obj/machinery/power/conduction_plate/proc/check_tank()
|
||||
//Are we anchored?
|
||||
if(!anchored)
|
||||
return 0
|
||||
|
||||
//Is our old tank is still valid?
|
||||
if(attached_tank && attached_tank.loc == loc)
|
||||
return 1
|
||||
|
||||
//No? Let's look for a new one.
|
||||
attached_tank = locate(/obj/machinery/fishtank/) in loc
|
||||
if(attached_tank)
|
||||
return 1
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Reference in New Issue
Block a user