mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-31 04:31:41 +00:00
Changes instances of \red and \blue to use spans as per suggestions in glass.dm and fishtank.dm Fixed a mistake preventing the building of one direction windows and fishbowls (whoops!) Fixes grammar concerns in multiple messages Holy water is now (magically?) worth 110% of it's reagent amount when filling aquariums. - This is a rather small boost to having the chaplain bless the water you are going to dump into a filtration system anyways. Moves the fishwater ingestion method out of the on_mob_life proc to prevent spam, now will display when initially ingested Updates the CritterCare vendor's sprite to include the pug and fox, as well as adjusting the "static" between displays to give it a slight variety.
702 lines
30 KiB
Plaintext
702 lines
30 KiB
Plaintext
|
|
//////////////////////////////
|
|
// Fish Tanks! //
|
|
//////////////////////////////
|
|
|
|
|
|
/obj/machinery/fishtank
|
|
name = "placeholder tank"
|
|
desc = "So generic, it might as well have no description at all."
|
|
icon = 'icons/obj/fish_items.dmi'
|
|
icon_state = "tank1"
|
|
density = 0
|
|
anchored = 0
|
|
throwpass = 0
|
|
|
|
var/tank_type = "" // Type of aquarium, used for icon updating
|
|
var/water_capacity = 0 // Number of units the tank holds (varies with tank type)
|
|
var/water_level = 0 // Number of units currently in the tank (new tanks start empty)
|
|
var/light_switch = 0 // 0 = off, 1 = on (off by default)
|
|
var/filth_level = 0.0 // How dirty the tank is (max 10)
|
|
var/lid_switch = 0 // 0 = open, 1 = 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/fish_count = 0 // Number of fish in the tank
|
|
var/list/fish_list = null // Tracks the current types of fish in the tank
|
|
var/egg_count = 0 // How many fish eggs can be harvested from the tank (capped at the max_fish value)
|
|
var/list/egg_list = null // Tracks the current types of harvestable eggs in the tank
|
|
|
|
var/has_lid = 0 // 0 if the tank doesn't have a lid/light, 1 if it does
|
|
var/max_health = 0 // Can handle a couple hits
|
|
var/cur_health = 0 // Current health, starts at max_health
|
|
var/leaking = 0 // 0 if not leaking, 1 if minor leak, 2 if major leak (not leaking by default)
|
|
var/shard_count = 0 // Number of glass shards to salvage when broken (1 less than the number of sheets to build the tank)
|
|
|
|
/obj/machinery/fishtank/bowl
|
|
name = "fish bowl"
|
|
desc = "A small bowl capable of housing a single fish, commonly found on desks. This one has a tiny treasure chest in it!"
|
|
icon_state = "bowl1"
|
|
density = 0 // Small enough to not block stuff
|
|
anchored = 0 // Small enough to move even when filled
|
|
throwpass = 1 // Just like at the county fair, you can't seem to throw the ball in to win the goldfish
|
|
pass_flags = PASSTABLE // Small enough to pull onto a table
|
|
|
|
tank_type = "bowl"
|
|
water_capacity = 50 // Not very big, therefore it can't hold much
|
|
max_fish = 1 // What a lonely fish
|
|
|
|
has_lid = 0
|
|
max_health = 15 // Not very sturdy
|
|
cur_health = 15
|
|
shard_count = 0 // No salvageable shards
|
|
|
|
/obj/machinery/fishtank/tank
|
|
name = "fish tank"
|
|
desc = "A large glass tank designed to house aquatic creatures. Contains an integrated water circulation system."
|
|
icon = 'icons/obj/fish_items.dmi'
|
|
icon_state = "tank1"
|
|
density = 1
|
|
anchored = 1
|
|
throwpass = 1 // You can throw objects over this, despite it's density, because it's short enough.
|
|
|
|
tank_type = "tank"
|
|
water_capacity = 200 // Decent sized, holds almost 2 full buckets
|
|
max_fish = 4 // Room for a few fish
|
|
|
|
has_lid = 1
|
|
max_health = 50 // Average strength, will take a couple hits from a toolbox.
|
|
cur_health = 50
|
|
shard_count = 2
|
|
|
|
|
|
/obj/machinery/fishtank/wall
|
|
name = "wall aquarium"
|
|
desc = "This aquarium is massive! It completely occupies the same space as a wall, and looks very sturdy too!"
|
|
icon_state = "wall1"
|
|
density = 1
|
|
anchored = 1
|
|
throwpass = 0 // This thing is the size of a wall, you can't throw past it.
|
|
|
|
tank_type = "wall"
|
|
water_capacity = 500 // This thing fills an entire tile, it holds a lot.
|
|
max_fish = 10 // Plenty of room for a lot of fish
|
|
|
|
has_lid = 1
|
|
max_health = 100 // This thing is a freaking wall, it can handle abuse.
|
|
cur_health = 100
|
|
shard_count = 3
|
|
|
|
|
|
//////////////////////////////
|
|
// VERBS & PROCS //
|
|
//////////////////////////////
|
|
|
|
/obj/machinery/fishtank/verb/toggle_lid_verb()
|
|
set name = "Toggle Tank Lid"
|
|
set category = "Object"
|
|
set src in view(1)
|
|
toggle_lid(usr)
|
|
|
|
/obj/machinery/fishtank/proc/toggle_lid(var/mob/living/user)
|
|
lid_switch = !lid_switch
|
|
update_icon()
|
|
|
|
/obj/machinery/fishtank/verb/toggle_light_verb()
|
|
set name = "Toggle Tank Light"
|
|
set category = "Object"
|
|
set src in view(1)
|
|
toggle_light(usr)
|
|
|
|
/obj/machinery/fishtank/proc/toggle_light(var/mob/living/user)
|
|
light_switch = !light_switch
|
|
if(light_switch)
|
|
set_light(2,2,"#a0a080")
|
|
else
|
|
set_light(0)
|
|
|
|
//////////////////////////////
|
|
// NEW() PROCS //
|
|
//////////////////////////////
|
|
|
|
/obj/machinery/fishtank/New()
|
|
..()
|
|
fish_list = new/list()
|
|
egg_list = new/list()
|
|
if(!has_lid) //Tank doesn't have a lid/light, remove the verbs for then
|
|
verbs -= /obj/machinery/fishtank/verb/toggle_lid_verb
|
|
verbs -= /obj/machinery/fishtank/verb/toggle_light_verb
|
|
|
|
/obj/machinery/fishtank/tank/New()
|
|
..()
|
|
if(prob(5)) //5% chance to get the castle decoration
|
|
icon_state = "tank2"
|
|
|
|
//////////////////////////////
|
|
// ICON PROCS //
|
|
//////////////////////////////
|
|
|
|
/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_count > 0) //There is at least 1 egg to harvest
|
|
overlays += "over_egg"
|
|
if(lid_switch == 1) //Lid is closed, lid status light is red
|
|
overlays += "over_lid_1"
|
|
else //Lid is open, lid status light is green
|
|
overlays += "over_lid_0"
|
|
if(food_level > 5) //Food_level is high and isn't a concern yet
|
|
overlays += "over_food_0"
|
|
else if(food_level > 2) //Food_level is starting to get low, but still above the breeding threshold
|
|
overlays += "over_food_1"
|
|
else //Food_level is below breeding threshold, or fully consumed, feed the fish!
|
|
overlays += "over_food_2"
|
|
overlays += "over_leak_[leaking]" //Green if we aren't leaking, light blue and slow blink if minor link, dark blue and rapid flashing for major leak
|
|
|
|
//Update water overlay
|
|
if(water_level == 0) return //Skip the rest of this if there is no water in the aquarium
|
|
var/water_type = "_clean" //Default to clean water
|
|
if(filth_level > 5) water_type = "_dirty" //Show dirty water above filth_level 5 (breeding threshold)
|
|
if(water_level > (water_capacity * 0.85)) //Show full if the water_level is over 85% of water_capacity
|
|
overlays += "over_[tank_type]_full[water_type]"
|
|
else if(water_level > (water_capacity * 0.35)) //Show half-full if the water_level is over 35% of water_capacity
|
|
overlays += "over_[tank_type]_half[water_type]"
|
|
|
|
return
|
|
|
|
//////////////////////////////
|
|
// PROCESS PROC //
|
|
//////////////////////////////
|
|
|
|
//Stops atmos from passing wall tanks, since they are effectively full-windows.
|
|
/obj/machinery/fishtank/wall/CanAtmosPass(var/turf/T)
|
|
return 0
|
|
|
|
/obj/machinery/fishtank/process()
|
|
//Start by counting fish in the tank
|
|
fish_count = 0
|
|
for(var/fish in fish_list)
|
|
if(fish)
|
|
fish_count ++
|
|
|
|
//Check if the water level can support the current number of fish
|
|
if((fish_count * 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
|
|
filth_level += 2 //Dead fish raise the filth level quite a bit, reflect this
|
|
|
|
//Check filth_level
|
|
check_filth_level()
|
|
if(filth_level == 10 && fish_count > 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
|
|
|
|
//Check breeding conditions
|
|
if(fish_count >=2 && egg_count < 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_count - 2) * 5)+10)) //Chances increase with each additional fish, 10% base + 5% per additional fish
|
|
egg_count ++ //A new set of eggs were laid, increase egg_count
|
|
egg_list.Add(select_egg_type()) //Add the new egg to the egg_list for storage
|
|
food_level -= 2 //Remove extra food for the breeding process
|
|
|
|
//Handle standard food and filth adjustments
|
|
check_food_level()
|
|
var/ate_food = 0
|
|
if(food_level > 0 && prob(50)) //Chance for the fish to eat some food
|
|
if(food_level >= (fish_count * 0.1)) //If there is at least enough food to go around, feed all the fish
|
|
food_level -= fish_count * 0.1
|
|
else //Use up the last of the food
|
|
food_level = 0
|
|
ate_food = 1
|
|
check_food_level()
|
|
|
|
if(water_level > 0) //Don't dirty the tank if it has no water
|
|
if(filth_level < 10 && prob(25)) //Chance for the tank to get dirtier if the filth_level isn't 10
|
|
if(ate_food && prob(30)) //If they ate this cycle, there is an additional chance they make a bigger mess
|
|
filth_level += fish_count * 0.1
|
|
else //If they didn't make the big mess, make a little one
|
|
filth_level += 0.1
|
|
check_filth_level()
|
|
|
|
//Handle special interactions
|
|
handle_special_interactions()
|
|
|
|
//Handle water leakage from damage
|
|
if(water_level > 0) //Can't leak water if there is no water in the tank
|
|
if(leaking == 2) //At or below 25% health, the tank will lose 10 water_level per cycle (major leak)
|
|
water_level -= 10
|
|
else if(leaking == 1) //At or below 50% health, the tank will lose 1 water_level per cycle (minor leak)
|
|
water_level -= 1
|
|
check_water_level()
|
|
|
|
//////////////////////////////
|
|
// SUPPORT PROCS //
|
|
//////////////////////////////
|
|
|
|
/obj/machinery/fishtank/proc/handle_special_interactions()
|
|
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
|
|
if((filth_level > 0) && prob(25))
|
|
filth_level -= 0.1
|
|
if("feederfish") //Feeder fish have a small chance of sacrificing themselves to produce some food
|
|
if(fish_count < 2) //Don't sacrifice the last fish, there's nothing to eat it
|
|
continue
|
|
if(food_level <= 7.5 && prob(25))
|
|
kill_fish("feederfish") //Kill the fish to reflect it's sacrifice, but don't increase the filth_level
|
|
food_level += 1 //The corpse became food for the other fish, ecology at it's finest
|
|
check_food_level()
|
|
check_filth_level()
|
|
check_water_level()
|
|
|
|
/obj/machinery/fishtank/proc/check_water_level()
|
|
if(water_level < 0) //Water_level cannot be negative, set it to 0 if it is
|
|
water_level = 0
|
|
if(water_level > water_capacity) //Water_level cannot exceed capacity, set it to capacity if it does
|
|
water_level = water_capacity
|
|
update_icon()
|
|
|
|
/obj/machinery/fishtank/proc/check_filth_level()
|
|
if(filth_level < 0) //Filth_level cannot be negative, set it to 0 if it is
|
|
filth_level = 0
|
|
if(filth_level > 10) //Filth_level cannot exceed 10 (cap), set it to 10 if it does
|
|
filth_level = 10
|
|
|
|
/obj/machinery/fishtank/proc/check_food_level()
|
|
if(food_level < 0) //Food_level cannot be negative, set it to 0 if it is
|
|
food_level = 0
|
|
if(food_level > 10) //Food_level cannot exceed 10 (cap), set it to 10 if it does
|
|
food_level = 10
|
|
|
|
/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)
|
|
leaking = 2
|
|
else if(cur_health <= (max_health * 0.5)) //Minor leak at or below 50% health (-1 water/cycle)
|
|
leaking = 1
|
|
else //Not leaking above 50% health
|
|
leaking = 0
|
|
//Destruction check
|
|
if(cur_health <= 0) //The tank is broken, destroy it
|
|
destroy()
|
|
|
|
/obj/machinery/fishtank/proc/kill_fish(var/type = null)
|
|
//Check if we were passed a fish to kill, otherwise kill a random one
|
|
if(type)
|
|
fish_list.Remove(type) //Kill a fish of the specified type
|
|
fish_count -- //Lower fish_count to reflect the death of a fish, so the everything else works fine
|
|
else
|
|
fish_list.Remove(pick(fish_list)) //Kill a random fish
|
|
fish_count -- //Lower fish_count to reflect the death of a fish, so the everything else works fine
|
|
|
|
/obj/machinery/fishtank/proc/add_fish(var/type = null)
|
|
//Check if we were passed a fish type
|
|
if(type)
|
|
fish_list.Add("[type]") //Add a fish of the specified type
|
|
fish_count ++ //Increase fish_count to reflect the introduction of a fish, so the everything else works fine
|
|
//Announce the new fish
|
|
src.visible_message("A new [type] has hatched in \the [src]!")
|
|
//Null type fish are dud eggs, give a message to inform the player
|
|
else
|
|
usr << "The eggs disolve in the water. They were duds!"
|
|
|
|
/obj/machinery/fishtank/proc/select_egg_type()
|
|
var/fish = pick(fish_list) //Select a fish from the fish in the tank
|
|
if(prob(25)) //25% chance to be a dud (blank) egg
|
|
fish = "dud"
|
|
var/obj/item/fish_eggs/egg_path = null //Create empty variable to receive the egg_path
|
|
egg_path = fish_eggs_list[fish] //Locate the corresponding path from fish_eggs_list that matches the fish
|
|
if(!egg_path) //The fish wasn't located in the fish_eggs_list, potentially due to a typo, so return a dud egg
|
|
return /obj/item/fish_eggs
|
|
else //The fish was located in the fish_eggs_list, so return the proper egg
|
|
return egg_path
|
|
|
|
/obj/machinery/fishtank/proc/harvest_eggs(var/mob/user)
|
|
if(!egg_count) //Can't harvest non-existant eggs
|
|
return
|
|
|
|
if(egg_count > max_fish) //Make sure the number of eggs doesn't exceed the max_fish for the tank
|
|
egg_count = max_fish //If you somehow exceeded the cap, set the egg_count to max, destroy the excess later
|
|
|
|
while(egg_count > 0) //Loop until you've harvested all the eggs
|
|
var/obj/item/fish_eggs/egg = pick(egg_list) //Select an egg at random
|
|
egg = new egg(get_turf(user)) //Spawn the egg at the user's feet
|
|
egg_list.Remove(egg) //Remove the egg from the egg_list
|
|
egg_count -- //Decrease the egg_count and begin again
|
|
|
|
egg_list.Cut() //Destroy any excess eggs, clearing the egg_list
|
|
|
|
/obj/machinery/fishtank/proc/destroy(var/deconstruct = 0)
|
|
var/turf/T = get_turf(src) //Store the tank's turf for atmos updating after deletion of tank
|
|
if(!deconstruct) //Check if we are deconstructing or breaking the tank
|
|
var/shards_left = shard_count
|
|
while(shards_left > 0) //Produce the appropriate number of glass shards
|
|
new /obj/item/weapon/shard(get_turf(src))
|
|
shards_left --
|
|
if(water_level) //Spill any water that was left in the tank when it broke
|
|
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
|
|
new /obj/item/stack/sheet/glass(get_turf(src), sheets) //Produce the appropriate number of glass sheets, in a single stack
|
|
qdel(src) //QDel the tank and it's contents
|
|
T.air_update_turf(1) //Update the air for the turf, to avoid permanent atmos sealing with wall tanks
|
|
|
|
/obj/machinery/fishtank/proc/spill_water()
|
|
switch(tank_type)
|
|
if("bowl") //Fishbowl: Wets it's own tile
|
|
var/turf/T = get_turf(src)
|
|
if(!istype(T, /turf/simulated)) return
|
|
var/turf/simulated/S = T
|
|
S.MakeSlippery()
|
|
if("tank") //Fishtank: Wets it's own tile and the 4 adjacent tiles (cardinal directions)
|
|
var/turf/ST = get_turf(src)
|
|
if(istype(ST, /turf/simulated))
|
|
var/turf/simulated/ST2 = ST
|
|
ST2.MakeSlippery()
|
|
var/list/L = ST.CardinalTurfs()
|
|
for(var/turf/T in L)
|
|
if(!istype(T, /turf/simulated)) continue
|
|
var/turf/simulated/S = T
|
|
S.MakeSlippery()
|
|
if("wall") //Wall-tank: Wets it's own tile and the surrounding 8 tiles (3x3 square)
|
|
for(var/turf/T in trange(1, src.loc))
|
|
if(!istype(T, /turf/simulated)) continue
|
|
var/turf/simulated/S = T
|
|
S.MakeSlippery()
|
|
|
|
////////////////////////////// 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/examine_message = ""
|
|
//Approximate water level
|
|
if(water_level == 0)
|
|
examine_message += "\The [src] is empty! "
|
|
else if(water_level < water_capacity * 0.1)
|
|
examine_message += "\The [src] is nearly empty! "
|
|
else if(water_level <= water_capacity * 0.25)
|
|
examine_message += "\The [src] is about one-quarter filled. "
|
|
else if(water_level <= water_capacity * 0.5)
|
|
examine_message += "\The [src] is about half filled. "
|
|
else if(water_level <= water_capacity * 0.75)
|
|
examine_message += "\The [src] is about three-quarters filled. "
|
|
else if(water_level < water_capacity)
|
|
examine_message += "\The [src] is nearly full! "
|
|
else if (water_level == water_capacity)
|
|
examine_message += "\The [src] is full! "
|
|
|
|
//Approximate filth level
|
|
if(filth_level == 0)
|
|
examine_message += "[src] is spotless! "
|
|
else if(filth_level <= 2.5)
|
|
examine_message += "[src] looks like the glass has been smudged. "
|
|
else if(filth_level <= 5) //This is the breeding threshold
|
|
examine_message += "[src] has some algae growth in it. "
|
|
else if(filth_level <= 7.5)
|
|
examine_message += "[src] has a lot of algae growth in it. "
|
|
else if(filth_level < 10)
|
|
examine_message += "[src] is getting hard to see into! Someone should clean it soon! "
|
|
else if(filth_level == 10)
|
|
examine_message += "[src] is absolutely disgusting! Someone should clean it NOW! "
|
|
|
|
//Approximate food level
|
|
if(!fish_count) //Check if there are fish in the tank
|
|
if(food_level > 0) //Don't report a tank that has neither fish nor food in it
|
|
examine_message += "There's some food in [src], but no fish! "
|
|
else //We've got fish, report the food level
|
|
if(food_level == 0)
|
|
examine_message += "The fish look very hungry! "
|
|
else if(food_level < 2)
|
|
examine_message += "The fish are nibbling on the last of their food. "
|
|
else if(food_level < 10) //Breeding is possible
|
|
examine_message += "The fish seem happy! "
|
|
else if(food_level == 10)
|
|
examine_message += "There is a solid layer of fish food at the top. "
|
|
|
|
//Report the number of harvestable eggs
|
|
if(egg_count) //Don't bother if there isn't any eggs
|
|
examine_message += "There are [egg_count] eggs able to be harvested! "
|
|
|
|
//Report the number and types of live fish if there is water in the tank
|
|
if(fish_count == 0)
|
|
examine_message += "\The [src] doesn't contain any live fish. "
|
|
else
|
|
//Build a message reporting the types of fish
|
|
var/fish_num = fish_count
|
|
var/message = "You spot "
|
|
while(fish_num > 0)
|
|
if(fish_count > 1 && fish_num == 1) //If there were at least 2 fish, and this is the last one, add "and" to the message
|
|
message += "and "
|
|
message += "a [fish_list[fish_num]]"
|
|
fish_num --
|
|
if(fish_num > 0) //There's more fish, add a comma to the message
|
|
message +=", "
|
|
message +="." //No more fish, end the message with a period
|
|
//Display the number of fish and previously constructed message
|
|
examine_message += "\The [src] contains [fish_count] live fish. [message] "
|
|
|
|
//Report lid state for tanks and wall-tanks
|
|
if(has_lid) //Only report if the tank actually has a lid
|
|
//Report lid state
|
|
if(lid_switch)
|
|
examine_message += "The lid is closed. "
|
|
else
|
|
examine_message += "The lid is open. "
|
|
|
|
//Report if the tank is leaking/cracked
|
|
if(water_level > 0) //Tank has water, so it's actually leaking
|
|
if(leaking == 1) examine_message += "\The [src] is leaking."
|
|
if(leaking == 2) examine_message += "\The [src] is leaking profusely!"
|
|
else //No water, report the cracks instead
|
|
if(leaking == 1) examine_message += "\The [src] is cracked."
|
|
if(leaking == 2) examine_message += "\The [src] is nearly shattered!"
|
|
|
|
|
|
//Finally, report the full examine_message constructed from the above reports
|
|
usr << "[examine_message]"
|
|
|
|
//////////////////////////////
|
|
// ATACK PROCS //
|
|
//////////////////////////////
|
|
|
|
/obj/machinery/fishtank/attack_animal(mob/living/simple_animal/M as mob)
|
|
if(istype(M, /mob/living/simple_animal/pet/cat))
|
|
if(M.a_intent == "help") //Cats can try to fish in open tanks on help intent
|
|
if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open.
|
|
M.visible_message("[M.name] stares at into \the [src] while sitting perfectly still.", "The lid is closed, so you stare into \the [src] intently.")
|
|
else
|
|
if(fish_count) //Tank must actually have fish to try catching one
|
|
M.visible_message("[M.name] leaps up onto \the[src] and attempts to fish through the opening!", "You jump up onto \the [src] and begin fishing through the opening!")
|
|
spawn(10)
|
|
if(water_level && prob(45)) //If there is water, there is a chance the cat will slip, Syndicat will spark like E-N when this happens
|
|
M.visible_message("[M.name] slipped and got soaked!", "You slipped and got soaked!")
|
|
if(istype(M, /mob/living/simple_animal/pet/cat/Syndi))
|
|
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
|
s.set_up(3, 1, src)
|
|
s.start()
|
|
else //No water or didn't slip, get that fish!
|
|
M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!")
|
|
kill_fish() //Kill a random fish
|
|
M.health = M.maxHealth //Eating fish heals the predator
|
|
else
|
|
usr << "There are no fish in [src]!"
|
|
else
|
|
attack_generic(M, M.harm_intent_damage)
|
|
else if(istype(M, /mob/living/simple_animal/hostile/bear))
|
|
if(M.a_intent == "help") //Bears can try to fish in open tanks on help intent
|
|
if(lid_switch) //Can't fish in a closed tank. Fishbowls are ALWAYS open.
|
|
M.visible_message("[M.name] scrapes it's claws along \the [src]'s lid.", "The lid is closed, so you scrape your claws against \the [src]'s lid.")
|
|
else
|
|
if(fish_count) //Tank must actually have fish to try catching one
|
|
M.visible_message("[M.name] reaches into \the[src] and attempts to fish through the opening!", "You reach into \the [src] and begin fishing through the opening!")
|
|
spawn(5)
|
|
if(water_level && prob(5)) //Bears are good at catching fish, only a 5% chance to fail
|
|
M.visible_message("[M.name] swipes at the water!", "You just barely missed that fish!")
|
|
else //No water or didn't slip, get that fish!
|
|
M.visible_message("[M.name] catches and devours a live fish!", "You catch and devour a live fish, yum!")
|
|
kill_fish() //Kill a random fish
|
|
M.health = M.maxHealth //Eating fish heals the predator
|
|
else
|
|
usr << "There are no fish in [src]!"
|
|
else
|
|
attack_generic(M, M.harm_intent_damage)
|
|
else
|
|
if(M.melee_damage_upper > 0) //If the simple_animal has a melee_damage_upper defined, use that for the damage
|
|
attack_generic(M, M.melee_damage_upper)
|
|
else if(M.a_intent == "harm") //Let any simple_animal try to break tanks when on harm intent
|
|
if(M.harm_intent_damage <= 0) return //If it doesn't do damage, don't bother with the attack
|
|
attack_generic(M, M.harm_intent_damage)
|
|
check_health()
|
|
|
|
/obj/machinery/fishtank/attack_alien(mob/living/user as mob)
|
|
if(islarva(user)) return
|
|
attack_generic(user, 15)
|
|
|
|
/obj/machinery/fishtank/attack_slime(mob/living/user as mob)
|
|
var/mob/living/carbon/slime/S = user
|
|
if (!S.is_adult)
|
|
return
|
|
attack_generic(user, rand(10, 15))
|
|
|
|
/obj/machinery/fishtank/attack_hand(mob/user as mob)
|
|
if(HULK in user.mutations)
|
|
user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!"))
|
|
user.visible_message("<span class='danger'>[user] smashes through [src]!</span>")
|
|
destroy()
|
|
else if (usr.a_intent == "harm")
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
playsound(get_turf(src), 'sound/effects/glassknock.ogg', 80, 1)
|
|
usr.visible_message("<span class='danger'>[usr.name] bangs against the [src.name]!</span>", \
|
|
"<span class='danger'>You bang against the [src.name]!</span>", \
|
|
"You hear a banging sound.")
|
|
else
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
|
|
usr.visible_message("[usr.name] taps on the [src.name].", \
|
|
"You tap on the [src.name].", \
|
|
"You hear a knocking sound.")
|
|
return
|
|
|
|
/obj/machinery/fishtank/proc/hit(var/damage, var/sound_effect = 1)
|
|
cur_health = max(0, cur_health - damage)
|
|
if(sound_effect)
|
|
playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
|
|
check_health()
|
|
|
|
/obj/machinery/fishtank/proc/attack_generic(mob/living/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
user.do_attack_animation(src)
|
|
cur_health -= damage
|
|
if(cur_health <= 0)
|
|
user.visible_message("<span class='danger'>[user] smashes through \the [src]!</span>")
|
|
destroy()
|
|
else //for nicer text~
|
|
user.visible_message("<span class='danger'>[user] smashes into \the [src]!</span>")
|
|
playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1)
|
|
check_health()
|
|
|
|
/obj/machinery/fishtank/attackby(var/obj/item/O, var/mob/user as mob)
|
|
//Welders repair damaged tanks on help intent, damage on all others
|
|
if(istype(O, /obj/item/weapon/weldingtool))
|
|
var/obj/item/weapon/weldingtool/W = O
|
|
if(user.a_intent == "help")
|
|
if(W.isOn())
|
|
if(cur_health < max_health)
|
|
usr << "You repair some of the cracks on \the [src]."
|
|
cur_health += 20
|
|
check_health()
|
|
else
|
|
usr << "There is no damage to fix!"
|
|
else
|
|
if(cur_health < max_health)
|
|
usr << "[W.name] must on to repair this damage."
|
|
else
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
hit(W.force)
|
|
return
|
|
//Open reagent containers add and remove water
|
|
if(O.is_open_container())
|
|
if(istype(O, /obj/item/weapon/reagent_containers/glass))
|
|
if(lid_switch)
|
|
usr << "Open the lid on \the [src] first!"
|
|
return
|
|
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("tonic") * 0.25 //Tonic water is 25% value
|
|
water_value += C.reagents.get_reagent_amount("sodawater") * 0.50 //Sodawater is 50% value
|
|
water_value += C.reagents.get_reagent_amount("fishwater") * 0.75 //Fishwater is 75% value, to account for the fish poo
|
|
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 = "The filtration process removes everything, leaving the water level unchanged."
|
|
C.reagents.clear_reagents()
|
|
else
|
|
if(water_level == water_capacity)
|
|
usr << "[src] is already full!"
|
|
return
|
|
else
|
|
message = "The filtration process purifies the water, raising the water level."
|
|
water_level += 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()
|
|
check_water_level()
|
|
user.visible_message("[user.name] pours the contents of [C.name] into \the [src].", "[message]")
|
|
return
|
|
//Empty containers will scoop out water, filling the container as much as possible from the water_level
|
|
else
|
|
if(water_level == 0)
|
|
usr << "[src] is empty!"
|
|
else
|
|
if(water_level >= C.volume) //Enough to fill the container completely
|
|
C.reagents.add_reagent("fishwater", C.volume)
|
|
water_level -= C.volume
|
|
user.visible_message("[user.name] scoops out some water from \the [src].", "You completely fill [C.name] from \the [src].")
|
|
else //Fill the container as much as possible with the water_level
|
|
C.reagents.add_reagent("fishwater", water_level)
|
|
water_level = 0
|
|
user.visible_message("[user.name] scoops out some water from \the [src].", "You fill [C.name] with the last of the water in \the [src].")
|
|
check_water_level()
|
|
return
|
|
//Wrenches can deconstruct empty tanks, but not tanks with any water. Kills any fish left inside and destroys any unharvested eggs in the process
|
|
if(istype(O, /obj/item/weapon/wrench))
|
|
if(water_level == 0)
|
|
usr << "<span class='notice'>Now disassembling [src].</span>"
|
|
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
|
if(do_after(user,50))
|
|
destroy(1)
|
|
else
|
|
usr << "[src] must be empty before you disassemble it!"
|
|
return
|
|
//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)
|
|
usr << "[src] has no water; [egg.name] won't hatch without water!"
|
|
else
|
|
//Don't add eggs if the tank already has the max number of fish
|
|
if(fish_count >= max_fish)
|
|
usr << "[src] can't hold any more fish."
|
|
else
|
|
add_fish(egg.fish_type)
|
|
qdel(egg)
|
|
return
|
|
//Fish food
|
|
else if(istype(O, /obj/item/weapon/fishfood))
|
|
//Only add food if there is water and it isn't already full of food
|
|
if(water_level)
|
|
if(food_level < 10)
|
|
if(fish_count == 0)
|
|
user.visible_message("[user.name] shakes some fish food into the empty [src]... How sad.", "You shake some fish food into the empty [src]... If only it had fish.")
|
|
else
|
|
user.visible_message("[user.name] feeds the fish in \the [src]. The fish look excited!", "You feed the fish in \the [src]. They look excited!")
|
|
food_level += 10
|
|
else
|
|
usr << "[src] already has plenty of food in it. You decide to not add more."
|
|
else
|
|
usr << "[src] doesn't have any water in it. You should fill it with water first."
|
|
check_food_level()
|
|
return
|
|
//Fish egg scoop
|
|
else if(istype(O, /obj/item/weapon/egg_scoop))
|
|
if(egg_count)
|
|
user.visible_message("[user.name] harvests some fish eggs from \the [src].", "You scoop the fish eggs out of \the [src].")
|
|
harvest_eggs(user)
|
|
else
|
|
user.visible_message("[user.name] fails to harvest any fish eggs from \the [src].", "There are no fish eggs in \the [src] to scoop out.")
|
|
return
|
|
//Fish net
|
|
if(istype(O, /obj/item/weapon/fish_net))
|
|
if(fish_count > 0)
|
|
var/caught_fish = pick(fish_list)
|
|
usr << "You catch and remove a [caught_fish] from \the [src]."
|
|
kill_fish(caught_fish)
|
|
//TODO: Fish object spawning, need to get sprites before I can code the fish objects
|
|
else
|
|
usr << "There are no fish in \the [src] to catch!"
|
|
return
|
|
//Tank brush
|
|
if(istype(O, /obj/item/weapon/tank_brush))
|
|
if(filth_level == 0)
|
|
usr << "[src] is already spotless!"
|
|
else
|
|
filth_level = 0
|
|
user.visible_message("[user.name] scrubs the inside of \the [src], cleaning the filth.", "You scrub the inside of \the [src], cleaning the filth.")
|
|
else if(O && O.force)
|
|
user.visible_message("<span class='danger'>\The [src] has been attacked by [user.name] with \the [O]!</span>")
|
|
hit(O.force)
|
|
return
|