Merge remote-tracking branch 'upstream/master' into too-many-monkeys-jumping-on-the-bed
@@ -34,17 +34,28 @@ actual development.
|
||||
* Pull requests should be atomic; Make one commit for each distinct change, so if a part
|
||||
of a pull request needs to be removed/changed, you may simply modify that single commit.
|
||||
Due to limitations of the engine, this may not always be possible; but do try your best.
|
||||
* Document and explain your pull requests thoroughly. Detail what each commit changes,
|
||||
and why it changes it. We do not want to have to read all of you commit names to figure
|
||||
out what your pull request is about.
|
||||
|
||||
* Document and explain your pull requests thoroughly. Failure to do so will delay a PR as
|
||||
we question why changes were made. This is especially important if you're porting a PR
|
||||
from another codebase (i.e. TG) and divert from the original. Explaining with single
|
||||
comment on why you've made changes will help us review the PR faster and understand your
|
||||
decision making process.
|
||||
|
||||
* Any pull request must have a changelog, this is to allow us to know when a PR is deployed
|
||||
on the live server. Inline changelogs are supported through the format described
|
||||
[here](https://github.com/ParadiseSS13/Paradise/pull/3291#issuecomment-172950466)
|
||||
and should be used rather than manually edited .yml file changelogs.
|
||||
|
||||
* Pull requests should not have any merge commits except in the case of fixing merge
|
||||
conflicts for an existing pull request. New pull requests should not have any merge
|
||||
commits. Use `git rebase` or `git reset` to update your branches, not `git pull`.
|
||||
|
||||
* Please explain why you are submitting the pull request, and how you think your change will be beneficial to the game. Failure to do so will be grounds for rejecting the PR.
|
||||
|
||||
* If your pull request is not finished make sure it is at least testable in a live environment. Pull requests that do not at least meet this requirement may be closed at maintainer discretion. You may request a maintainer reopen the pull request when you're ready, or make a new one.
|
||||
|
||||
* While we have no issue helping contributors (and especially new contributors) bring reasonably sized contributions up to standards via the pull request review process, larger contributions are expected to pass a higher bar of completeness and code quality *before* you open a pull request. Maintainers may close such pull requests that are deemed to be substantially flawed. You should take some time to discuss with maintainers or other contributors on how to improve the changes.
|
||||
|
||||
#### Using Changelog
|
||||
* Tags used in changelog include add/rscadd, del/rscdel, fix/fixes, typo/spellcheck.
|
||||
* Without specifying a name it will default to using your GitHub name.
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
**What does this PR do:**
|
||||
Include a small to medium description of what your PR changes. Feel free to give it a little flourish if you want to show off a new feature more completely.
|
||||
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may not be viewable. -->
|
||||
<!-- You can view Contributing.MD for a detailed description of the pull request process. -->
|
||||
|
||||
**Images of sprite/map changes (IF APPLICABLE):**
|
||||
If you did not make a map or sprite edit, you may leave this section blank. You may include a gif of your feature if you want
|
||||
## What Does This PR Do
|
||||
<!-- Include a small to medium description of what your PR changes. Document every changes or this may delay review or even discourage maintainers from merging your PR! -->
|
||||
|
||||
**Changelog:**
|
||||
*Remove this line, and appropriate fields from the changelog*
|
||||
## Why It's Good For The Game
|
||||
<!-- Please add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
|
||||
|
||||
## Images of changes
|
||||
<!-- If you did not make a map or sprite edit, you may delete this section. You may include a gif of your feature if you want -->
|
||||
|
||||
## Changelog
|
||||
:cl:
|
||||
add: Added new things
|
||||
del: Removed old things
|
||||
@@ -21,3 +26,5 @@ spellcheck: fixed a few typos
|
||||
experiment: added an experimental thingy
|
||||
/:cl:
|
||||
|
||||
<!-- Both :cl:'s are required for the changelog to work! You can put your name to the right of the first :cl: if you want to overwrite your GitHub username as author ingame. -->
|
||||
<!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. -->
|
||||
|
||||
@@ -298,7 +298,7 @@ This is always put in the attack log.
|
||||
loglevel = ATKLOG_FEW
|
||||
else if(istype(user) && !user.ckey && !target.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL
|
||||
loglevel = ATKLOG_ALL
|
||||
else if(!user.ckey || !target.ckey) // Player v NPC combat is de-prioritized.
|
||||
else if(!user.ckey || !target.ckey || (user.ckey == target.ckey)) // Player v NPC combat is de-prioritized. Also no self-harm, nobody cares
|
||||
loglevel = ATKLOG_ALMOSTALL
|
||||
else
|
||||
var/area/A = get_area(target)
|
||||
|
||||
@@ -244,6 +244,9 @@
|
||||
|
||||
//cube monkey limit
|
||||
var/cubemonkeycap = 20
|
||||
|
||||
// Makes gamemodes respect player limits
|
||||
var/enable_gamemode_player_limit = 0
|
||||
|
||||
/datum/configuration/New()
|
||||
for(var/T in subtypesof(/datum/game_mode))
|
||||
@@ -723,6 +726,8 @@
|
||||
config.developer_express_start = 1
|
||||
if("disable_localhost_admin")
|
||||
config.disable_localhost_admin = 1
|
||||
if("enable_gamemode_player_limit")
|
||||
config.enable_gamemode_player_limit = 1
|
||||
else
|
||||
log_config("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire
|
||||
name = "Toggle Friendly Fire \[ON\]"
|
||||
desc = "Toggles if the staff causes friendly fire."
|
||||
desc = "Toggles if the club's blasts cause friendly fire."
|
||||
button_icon_state = "vortex_ff_on"
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/Trigger()
|
||||
@@ -220,8 +220,8 @@
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon()
|
||||
if(istype(target, /obj/item/hierophant_staff))
|
||||
var/obj/item/hierophant_staff/H = target
|
||||
if(istype(target, /obj/item/hierophant_club))
|
||||
var/obj/item/hierophant_club/H = target
|
||||
if(H.friendly_fire_check)
|
||||
button_icon_state = "vortex_ff_off"
|
||||
name = "Toggle Friendly Fire \[OFF\]"
|
||||
@@ -247,12 +247,12 @@
|
||||
|
||||
/datum/action/item_action/vortex_recall
|
||||
name = "Vortex Recall"
|
||||
desc = "Recall yourself, and anyone nearby, to an attuned hierophant rune at any time.<br>If no such rune exists, will produce a rune at your location."
|
||||
desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.<br>If the beacon is still attached, will detach it."
|
||||
button_icon_state = "vortex_recall"
|
||||
|
||||
/datum/action/item_action/vortex_recall/IsAvailable()
|
||||
if(istype(target, /obj/item/hierophant_staff))
|
||||
var/obj/item/hierophant_staff/H = target
|
||||
if(istype(target, /obj/item/hierophant_club))
|
||||
var/obj/item/hierophant_club/H = target
|
||||
if(H.teleporting)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
@@ -124,8 +124,8 @@ datum/map_template/ruin/lavaland/ash_walker
|
||||
id = "hierophant"
|
||||
description = "A strange, square chunk of metal of massive size. Inside awaits only death and many, many squares."
|
||||
suffix = "lavaland_surface_hierophant.dmm"
|
||||
allow_duplicates = FALSE
|
||||
always_place = TRUE
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/blood_drunk_miner
|
||||
name = "Blood-Drunk Miner"
|
||||
|
||||
@@ -383,18 +383,18 @@
|
||||
name = "Repulse"
|
||||
desc = "This spell throws everything around the user away."
|
||||
charge_max = 400
|
||||
clothes_req = 1
|
||||
clothes_req = TRUE
|
||||
invocation = "GITTAH WEIGH"
|
||||
invocation_type = "shout"
|
||||
range = 5
|
||||
cooldown_min = 150
|
||||
selection_type = "view"
|
||||
sound = 'sound/magic/repulse.ogg'
|
||||
var/maxthrow = 5
|
||||
var/sparkle_path = /obj/effect/temp_visual/gravpush
|
||||
action_icon_state = "repulse"
|
||||
sound = 'sound/magic/repulse.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets, mob/user = usr, stun_amt = 2)
|
||||
var/list/thrownatoms = list()
|
||||
var/atom/throwtarget
|
||||
var/distfromcaster
|
||||
@@ -411,16 +411,16 @@
|
||||
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
|
||||
distfromcaster = get_dist(user, AM)
|
||||
if(distfromcaster == 0)
|
||||
if(istype(AM, /mob/living))
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
M.Weaken(5)
|
||||
M.adjustBruteLoss(5)
|
||||
to_chat(M, "<span class='userdanger'>You're slammed into the floor by a mystical force!</span>")
|
||||
else
|
||||
new sparkle_path(get_turf(AM), get_dir(user, AM)) //created sparkles will disappear on their own
|
||||
if(istype(AM, /mob/living))
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
M.Weaken(2)
|
||||
M.Weaken(stun_amt)
|
||||
to_chat(M, "<span class='userdanger'>You're thrown back by a mystical force!</span>")
|
||||
spawn(0)
|
||||
AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
|
||||
|
||||
@@ -1037,7 +1037,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
|
||||
/datum/uplink_item/explosives/grenadier
|
||||
name = "Grenadier's belt"
|
||||
desc = "A belt containing 25 lethally dangerous and destructive grenades."
|
||||
desc = "A belt containing 26 lethally dangerous and destructive grenades."
|
||||
item = /obj/item/storage/belt/grenade/full
|
||||
cost = 30
|
||||
surplus = 0
|
||||
@@ -1052,15 +1052,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
gamemodes = list(/datum/game_mode/nuclear)
|
||||
surplus = 35
|
||||
|
||||
/datum/uplink_item/explosives/saringrenades
|
||||
name = "Sarin Gas Grenades"
|
||||
desc = "A box of four (4) grenades filled with Sarin, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintained with team to avoid accidental gassings."
|
||||
reference = "TGG"
|
||||
item = /obj/item/storage/box/syndie_kit/sarin
|
||||
cost = 12
|
||||
gamemodes = list(/datum/game_mode/nuclear)
|
||||
surplus = 0
|
||||
|
||||
/datum/uplink_item/explosives/atmosn2ogrenades
|
||||
name = "Knockout Gas Grenades"
|
||||
desc = "A box of two (2) grenades that spread knockout gas over a large area. Equip internals before using one of these."
|
||||
@@ -1651,10 +1642,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
|
||||
/datum/uplink_item/bundles_TC/c20r
|
||||
name = "C-20r Bundle"
|
||||
desc = "Old Faithful: The classic C-20r, bundled with two magazines and a (surplus) suppressor at discount price."
|
||||
desc = "Old Faithful: The classic C-20r, bundled with three magazines and a (surplus) suppressor at discount price."
|
||||
reference = "C20B"
|
||||
item = /obj/item/storage/backpack/duffel/syndie/c20rbundle
|
||||
cost = 14 // normally 17
|
||||
cost = 18 // normally 21
|
||||
gamemodes = list(/datum/game_mode/nuclear)
|
||||
|
||||
/datum/uplink_item/bundles_TC/cyber_implants
|
||||
@@ -1669,10 +1660,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
/datum/uplink_item/bundles_TC/medical
|
||||
name = "Medical Bundle"
|
||||
desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a tactical medkit, \
|
||||
a Donksoft LMG and a box of riot darts."
|
||||
a medical beam gun and a pair of syndicate magboots."
|
||||
reference = "MEDB"
|
||||
item = /obj/item/storage/backpack/duffel/syndie/med/medicalbundle
|
||||
cost = 15 // normally 20
|
||||
cost = 20 // normally 24
|
||||
gamemodes = list(/datum/game_mode/nuclear)
|
||||
|
||||
/datum/uplink_item/bundles_TC/sniper
|
||||
|
||||
@@ -104,6 +104,7 @@ var/list/blob_nodes = list()
|
||||
to_chat(blob.current, "<b>Find a good location to spawn the core and then take control and overwhelm the station!</b>")
|
||||
to_chat(blob.current, "<b>When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.</b>")
|
||||
to_chat(blob.current, "<b>If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover.</b>")
|
||||
SEND_SOUND(blob.current, 'sound/magic/mutate.ogg')
|
||||
return
|
||||
|
||||
/datum/game_mode/blob/proc/show_message(var/message)
|
||||
@@ -207,4 +208,4 @@ var/list/blob_nodes = list()
|
||||
/datum/game_mode/proc/update_blob_icons_removed(datum/mind/mob_mind)
|
||||
var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB]
|
||||
antaghud.leave_hud(mob_mind.current)
|
||||
set_antag_hud(mob_mind.current, null)
|
||||
set_antag_hud(mob_mind.current, null)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
if((player.client)&&(player.ready))
|
||||
playerC++
|
||||
|
||||
if(playerC >= required_players)
|
||||
if(!config.enable_gamemode_player_limit || (playerC >= required_players))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
DeactivateStealth()
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/IsReflect()
|
||||
DeactivateStealth()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
armour_penetration = 0
|
||||
damage_transfer = 0.6
|
||||
playstyle_string = "As an <b>Assassin</b> type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage."
|
||||
magic_fluff_string = "..And draw the Space Ninja, a lethal, invisible assassin."
|
||||
tech_fluff_string = "Boot sequence complete. Assassin modules loaded. Holoparasite swarm online."
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
if(!drownee)
|
||||
return
|
||||
|
||||
if(drownee && (drownee.lying || deep_water)) //Mob lying down or water is deep (determined by controller)
|
||||
if(drownee && ((drownee.lying && !drownee.player_logged) || deep_water)) //Mob lying down and not SSD or water is deep (determined by controller)
|
||||
if(drownee.internal)
|
||||
return //Has internals, no drowning
|
||||
if((NO_BREATHE in drownee.dna.species.species_traits) || (BREATHLESS in drownee.mutations))
|
||||
|
||||
@@ -121,9 +121,10 @@
|
||||
product_records = list()
|
||||
hidden_records = list()
|
||||
coin_records = list()
|
||||
build_inventory(products, product_records, start_empty = TRUE)
|
||||
build_inventory(contraband, hidden_records, start_empty = TRUE)
|
||||
build_inventory(premium, coin_records, start_empty = TRUE)
|
||||
if(refill_canister)
|
||||
build_inventory(products, product_records, start_empty = TRUE)
|
||||
build_inventory(contraband, hidden_records, start_empty = TRUE)
|
||||
build_inventory(premium, coin_records, start_empty = TRUE)
|
||||
for(var/obj/item/vending_refill/VR in component_parts)
|
||||
restock(VR)
|
||||
|
||||
@@ -1275,16 +1276,57 @@
|
||||
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
|
||||
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
|
||||
icon_state = "seeds"
|
||||
products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/cotton = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3,
|
||||
/obj/item/seeds/cabbage = 3, /obj/item/seeds/carrot = 3, /obj/item/seeds/cherry = 3, /obj/item/seeds/chanter = 3,
|
||||
/obj/item/seeds/chili = 3, /obj/item/seeds/cocoapod = 3, /obj/item/seeds/coffee = 3, /obj/item/seeds/comfrey =3, /obj/item/seeds/corn = 3,
|
||||
/obj/item/seeds/nymph =3, /obj/item/seeds/eggplant = 3, /obj/item/seeds/grape = 3, /obj/item/seeds/grass = 3, /obj/item/seeds/lemon = 3,
|
||||
/obj/item/seeds/lime = 3, /obj/item/seeds/onion = 3, /obj/item/seeds/orange = 3, /obj/item/seeds/peanuts = 3, /obj/item/seeds/pineapple = 3, /obj/item/seeds/potato = 3, /obj/item/seeds/poppy = 3,
|
||||
/obj/item/seeds/pumpkin = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/wheat/rice = 3, /obj/item/seeds/soya = 3, /obj/item/seeds/sunflower = 3, /obj/item/seeds/sugarcane = 3,
|
||||
/obj/item/seeds/tea = 3, /obj/item/seeds/tobacco = 3, /obj/item/seeds/tomato = 3,
|
||||
/obj/item/seeds/tower = 3, /obj/item/seeds/watermelon = 3, /obj/item/seeds/wheat = 3, /obj/item/seeds/whitebeet = 3)
|
||||
contraband = list(/obj/item/seeds/amanita = 2, /obj/item/seeds/glowshroom = 2, /obj/item/seeds/liberty = 2, /obj/item/seeds/nettle = 2,
|
||||
/obj/item/seeds/plump = 2, /obj/item/seeds/reishi = 2, /obj/item/seeds/cannabis = 3, /obj/item/seeds/starthistle = 2, /obj/item/seeds/fungus = 3, /obj/item/seeds/random = 2)
|
||||
products = list(/obj/item/seeds/aloe =3,
|
||||
/obj/item/seeds/ambrosia = 3,
|
||||
/obj/item/seeds/apple = 3,
|
||||
/obj/item/seeds/cotton = 3,
|
||||
/obj/item/seeds/banana = 3,
|
||||
/obj/item/seeds/berry = 3,
|
||||
/obj/item/seeds/cabbage = 3,
|
||||
/obj/item/seeds/carrot = 3,
|
||||
/obj/item/seeds/cherry = 3,
|
||||
/obj/item/seeds/chanter = 3,
|
||||
/obj/item/seeds/chili = 3,
|
||||
/obj/item/seeds/cocoapod = 3,
|
||||
/obj/item/seeds/coffee = 3,
|
||||
/obj/item/seeds/comfrey =3,
|
||||
/obj/item/seeds/corn = 3,
|
||||
/obj/item/seeds/nymph =3,
|
||||
/obj/item/seeds/eggplant = 3,
|
||||
/obj/item/seeds/garlic = 3,
|
||||
/obj/item/seeds/grape = 3,
|
||||
/obj/item/seeds/grass = 3,
|
||||
/obj/item/seeds/lemon = 3,
|
||||
/obj/item/seeds/lime = 3,
|
||||
/obj/item/seeds/onion = 3,
|
||||
/obj/item/seeds/orange = 3,
|
||||
/obj/item/seeds/peanuts = 3,
|
||||
/obj/item/seeds/pineapple = 3,
|
||||
/obj/item/seeds/potato = 3,
|
||||
/obj/item/seeds/poppy = 3,
|
||||
/obj/item/seeds/pumpkin = 3,
|
||||
/obj/item/seeds/replicapod = 3,
|
||||
/obj/item/seeds/wheat/rice = 3,
|
||||
/obj/item/seeds/soya = 3,
|
||||
/obj/item/seeds/sunflower = 3,
|
||||
/obj/item/seeds/sugarcane = 3,
|
||||
/obj/item/seeds/tea = 3,
|
||||
/obj/item/seeds/tobacco = 3,
|
||||
/obj/item/seeds/tomato = 3,
|
||||
/obj/item/seeds/tower = 3,
|
||||
/obj/item/seeds/watermelon = 3,
|
||||
/obj/item/seeds/wheat = 3,
|
||||
/obj/item/seeds/whitebeet = 3)
|
||||
contraband = list(/obj/item/seeds/amanita = 2,
|
||||
/obj/item/seeds/glowshroom = 2,
|
||||
/obj/item/seeds/liberty = 2,
|
||||
/obj/item/seeds/nettle = 2,
|
||||
/obj/item/seeds/plump = 2,
|
||||
/obj/item/seeds/reishi = 2,
|
||||
/obj/item/seeds/cannabis = 3,
|
||||
/obj/item/seeds/starthistle = 2,
|
||||
/obj/item/seeds/fungus = 3,
|
||||
/obj/item/seeds/random = 2)
|
||||
premium = list(/obj/item/reagent_containers/spray/waterflower = 1)
|
||||
refill_canister = /obj/item/vending_refill/hydroseeds
|
||||
|
||||
@@ -1326,41 +1368,129 @@
|
||||
product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!"
|
||||
vend_delay = 15
|
||||
vend_reply = "Thank you for using AutoDrobe!"
|
||||
products = list(/obj/item/clothing/suit/chickensuit = 1,/obj/item/clothing/head/chicken = 1,/obj/item/clothing/under/gladiator = 1,
|
||||
/obj/item/clothing/head/helmet/gladiator = 1,/obj/item/clothing/under/gimmick/rank/captain/suit = 1,/obj/item/clothing/head/flatcap = 1,
|
||||
/obj/item/clothing/suit/storage/labcoat/mad = 1,/obj/item/clothing/glasses/gglasses = 1,/obj/item/clothing/shoes/jackboots = 1,
|
||||
/obj/item/clothing/under/schoolgirl = 1,/obj/item/clothing/head/kitty = 1,/obj/item/clothing/under/blackskirt = 1,
|
||||
/obj/item/clothing/suit/toggle/owlwings = 1, /obj/item/clothing/under/owl = 1,/obj/item/clothing/mask/gas/owl_mask = 1,
|
||||
/obj/item/clothing/suit/toggle/owlwings/griffinwings = 1, /obj/item/clothing/under/griffin = 1, /obj/item/clothing/shoes/griffin = 1, /obj/item/clothing/head/griffin = 1,
|
||||
/obj/item/clothing/accessory/waistcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/accessory/waistcoat = 1,
|
||||
/obj/item/clothing/glasses/monocle =1,/obj/item/clothing/head/bowlerhat = 1,/obj/item/cane = 1,/obj/item/clothing/under/sl_suit = 1,
|
||||
/obj/item/clothing/mask/fakemoustache = 1,/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,/obj/item/clothing/head/plaguedoctorhat = 1,/obj/item/clothing/mask/gas/plaguedoctor = 1,
|
||||
/obj/item/clothing/suit/apron = 1,/obj/item/clothing/under/waiter = 1,/obj/item/clothing/suit/jacket/miljacket = 1,
|
||||
/obj/item/clothing/suit/jacket/miljacket/white = 1, /obj/item/clothing/suit/jacket/miljacket/desert = 1, /obj/item/clothing/suit/jacket/miljacket/navy = 1,
|
||||
/obj/item/clothing/under/pirate = 1,/obj/item/clothing/suit/pirate_brown = 1,/obj/item/clothing/suit/pirate_black =1,/obj/item/clothing/under/pirate_rags =1,/obj/item/clothing/head/pirate = 1,/obj/item/clothing/head/bandana = 1,
|
||||
/obj/item/clothing/head/bandana = 1,/obj/item/clothing/under/soviet = 1,/obj/item/clothing/head/ushanka = 1,/obj/item/clothing/suit/imperium_monk = 1,
|
||||
/obj/item/clothing/mask/gas/cyborg = 1,/obj/item/clothing/suit/holidaypriest = 1,/obj/item/clothing/head/wizard/marisa/fake = 1,
|
||||
/obj/item/clothing/suit/wizrobe/marisa/fake = 1,/obj/item/clothing/under/sundress = 1,/obj/item/clothing/head/witchwig = 1,/obj/item/twohanded/staff/broom = 1,
|
||||
/obj/item/clothing/suit/wizrobe/fake = 1,/obj/item/clothing/head/wizard/fake = 1,/obj/item/twohanded/staff = 3,/obj/item/clothing/mask/gas/clown_hat/sexy = 1,
|
||||
/obj/item/clothing/under/rank/clown/sexy = 1,/obj/item/clothing/mask/gas/sexymime = 1,/obj/item/clothing/under/sexymime = 1,
|
||||
/obj/item/clothing/mask/face/bat = 1,/obj/item/clothing/mask/face/bee = 1,/obj/item/clothing/mask/face/bear = 1,/obj/item/clothing/mask/face/raven = 1,/obj/item/clothing/mask/face/jackal = 1,/obj/item/clothing/mask/face/fox = 1,/obj/item/clothing/mask/face/tribal = 1,/obj/item/clothing/mask/face/rat = 1,
|
||||
products = list(/obj/item/clothing/suit/chickensuit = 1,
|
||||
/obj/item/clothing/head/chicken = 1,
|
||||
/obj/item/clothing/under/gladiator = 1,
|
||||
/obj/item/clothing/head/helmet/gladiator = 1,
|
||||
/obj/item/clothing/under/gimmick/rank/captain/suit = 1,
|
||||
/obj/item/clothing/head/flatcap = 1,
|
||||
/obj/item/clothing/suit/storage/labcoat/mad = 1,
|
||||
/obj/item/clothing/glasses/gglasses = 1,
|
||||
/obj/item/clothing/shoes/jackboots = 1,
|
||||
/obj/item/clothing/under/schoolgirl = 1,
|
||||
/obj/item/clothing/head/kitty = 1,
|
||||
/obj/item/clothing/under/blackskirt = 1,
|
||||
/obj/item/clothing/suit/toggle/owlwings = 1,
|
||||
/obj/item/clothing/under/owl = 1,
|
||||
/obj/item/clothing/mask/gas/owl_mask = 1,
|
||||
/obj/item/clothing/suit/toggle/owlwings/griffinwings = 1,
|
||||
/obj/item/clothing/under/griffin = 1,
|
||||
/obj/item/clothing/shoes/griffin = 1,
|
||||
/obj/item/clothing/head/griffin = 1,
|
||||
/obj/item/clothing/accessory/waistcoat = 1,
|
||||
/obj/item/clothing/under/suit_jacket = 1,
|
||||
/obj/item/clothing/head/that =1,
|
||||
/obj/item/clothing/under/kilt = 1,
|
||||
/obj/item/clothing/accessory/waistcoat = 1,
|
||||
/obj/item/clothing/glasses/monocle =1,
|
||||
/obj/item/clothing/head/bowlerhat = 1,
|
||||
/obj/item/cane = 1,
|
||||
/obj/item/clothing/under/sl_suit = 1,
|
||||
/obj/item/clothing/mask/fakemoustache = 1,
|
||||
/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,
|
||||
/obj/item/clothing/head/plaguedoctorhat = 1,
|
||||
/obj/item/clothing/mask/gas/plaguedoctor = 1,
|
||||
/obj/item/clothing/suit/apron = 1,
|
||||
/obj/item/clothing/under/waiter = 1,
|
||||
/obj/item/clothing/suit/jacket/miljacket = 1,
|
||||
/obj/item/clothing/suit/jacket/miljacket/white = 1,
|
||||
/obj/item/clothing/suit/jacket/miljacket/desert = 1,
|
||||
/obj/item/clothing/suit/jacket/miljacket/navy = 1,
|
||||
/obj/item/clothing/under/pirate = 1,
|
||||
/obj/item/clothing/suit/pirate_brown = 1,
|
||||
/obj/item/clothing/suit/pirate_black =1,
|
||||
/obj/item/clothing/under/pirate_rags =1,
|
||||
/obj/item/clothing/head/pirate = 1,
|
||||
/obj/item/clothing/head/bandana = 1,
|
||||
/obj/item/clothing/head/bandana = 1,
|
||||
/obj/item/clothing/under/soviet = 1,
|
||||
/obj/item/clothing/head/ushanka = 1,
|
||||
/obj/item/clothing/suit/imperium_monk = 1,
|
||||
/obj/item/clothing/mask/gas/cyborg = 1,
|
||||
/obj/item/clothing/suit/holidaypriest = 1,
|
||||
/obj/item/clothing/head/wizard/marisa/fake = 1,
|
||||
/obj/item/clothing/suit/wizrobe/marisa/fake = 1,
|
||||
/obj/item/clothing/under/sundress = 1,
|
||||
/obj/item/clothing/head/witchwig = 1,
|
||||
/obj/item/twohanded/staff/broom = 1,
|
||||
/obj/item/clothing/suit/wizrobe/fake = 1,
|
||||
/obj/item/clothing/head/wizard/fake = 1,
|
||||
/obj/item/twohanded/staff = 3,
|
||||
/obj/item/clothing/mask/gas/clown_hat/sexy = 1,
|
||||
/obj/item/clothing/under/rank/clown/sexy = 1,
|
||||
/obj/item/clothing/mask/gas/sexymime = 1,
|
||||
/obj/item/clothing/under/sexymime = 1,
|
||||
/obj/item/clothing/mask/face/bat = 1,
|
||||
/obj/item/clothing/mask/face/bee = 1,
|
||||
/obj/item/clothing/mask/face/bear = 1,
|
||||
/obj/item/clothing/mask/face/raven = 1,
|
||||
/obj/item/clothing/mask/face/jackal = 1,
|
||||
/obj/item/clothing/mask/face/fox = 1,
|
||||
/obj/item/clothing/mask/face/tribal = 1,
|
||||
/obj/item/clothing/mask/face/rat = 1,
|
||||
/obj/item/clothing/suit/apron/overalls = 1,
|
||||
/obj/item/clothing/head/rabbitears =1, /obj/item/clothing/head/sombrero = 1, /obj/item/clothing/suit/poncho = 1,
|
||||
/obj/item/clothing/suit/poncho/green = 1, /obj/item/clothing/suit/poncho/red = 1, /obj/item/clothing/accessory/blue = 1, /obj/item/clothing/accessory/red = 1, /obj/item/clothing/accessory/black = 1, /obj/item/clothing/accessory/horrible = 1,
|
||||
/obj/item/clothing/under/maid = 1, /obj/item/clothing/under/janimaid = 1,
|
||||
/obj/item/clothing/under/jester = 1, /obj/item/clothing/head/jester = 1,
|
||||
/obj/item/clothing/under/pants/camo = 1, /obj/item/clothing/mask/bandana = 1, /obj/item/clothing/mask/bandana/black = 1,
|
||||
/obj/item/clothing/shoes/singery = 1,/obj/item/clothing/under/singery = 1,
|
||||
/obj/item/clothing/shoes/singerb = 1,/obj/item/clothing/under/singerb = 1,
|
||||
/obj/item/clothing/suit/hooded/carp_costume = 1,/obj/item/clothing/suit/hooded/bee_costume = 1,
|
||||
/obj/item/clothing/suit/snowman = 1,/obj/item/clothing/head/snowman = 1,
|
||||
/obj/item/clothing/head/cueball = 1,/obj/item/clothing/under/scratch = 1,
|
||||
/obj/item/clothing/under/victdress = 1, /obj/item/clothing/under/victdress/red = 1, /obj/item/clothing/suit/victcoat = 1, /obj/item/clothing/suit/victcoat/red = 1,
|
||||
/obj/item/clothing/under/victsuit = 1, /obj/item/clothing/under/victsuit/redblk = 1, /obj/item/clothing/under/victsuit/red = 1, /obj/item/clothing/suit/tailcoat = 1,
|
||||
/obj/item/clothing/suit/draculacoat = 1, /obj/item/clothing/head/zepelli = 1,
|
||||
/obj/item/clothing/under/redhawaiianshirt = 1, /obj/item/clothing/under/pinkhawaiianshirt = 1, /obj/item/clothing/under/bluehawaiianshirt = 1, /obj/item/clothing/under/orangehawaiianshirt = 1)
|
||||
contraband = list(/obj/item/clothing/suit/judgerobe = 1,/obj/item/clothing/head/powdered_wig = 1,/obj/item/gun/magic/wand = 1, /obj/item/clothing/mask/balaclava=1, /obj/item/clothing/mask/horsehead = 2)
|
||||
premium = list(/obj/item/clothing/suit/hgpirate = 1, /obj/item/clothing/head/hgpiratecap = 1, /obj/item/clothing/head/helmet/roman = 1, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/roman = 1, /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman = 1)
|
||||
/obj/item/clothing/head/rabbitears =1,
|
||||
/obj/item/clothing/head/sombrero = 1,
|
||||
/obj/item/clothing/suit/poncho = 1,
|
||||
/obj/item/clothing/suit/poncho/green = 1,
|
||||
/obj/item/clothing/suit/poncho/red = 1,
|
||||
/obj/item/clothing/accessory/blue = 1,
|
||||
/obj/item/clothing/accessory/red = 1,
|
||||
/obj/item/clothing/accessory/black = 1,
|
||||
/obj/item/clothing/accessory/horrible = 1,
|
||||
/obj/item/clothing/under/maid = 1,
|
||||
/obj/item/clothing/under/janimaid = 1,
|
||||
/obj/item/clothing/under/jester = 1,
|
||||
/obj/item/clothing/head/jester = 1,
|
||||
/obj/item/clothing/under/pants/camo = 1,
|
||||
/obj/item/clothing/mask/bandana = 1,
|
||||
/obj/item/clothing/mask/bandana/black = 1,
|
||||
/obj/item/clothing/shoes/singery = 1,
|
||||
/obj/item/clothing/under/singery = 1,
|
||||
/obj/item/clothing/shoes/singerb = 1,
|
||||
/obj/item/clothing/under/singerb = 1,
|
||||
/obj/item/clothing/suit/hooded/carp_costume = 1,
|
||||
/obj/item/clothing/suit/hooded/bee_costume = 1,
|
||||
/obj/item/clothing/suit/snowman = 1,
|
||||
/obj/item/clothing/head/snowman = 1,
|
||||
/obj/item/clothing/head/cueball = 1,
|
||||
/obj/item/clothing/under/scratch = 1,
|
||||
/obj/item/clothing/under/victdress = 1,
|
||||
/obj/item/clothing/under/victdress/red = 1,
|
||||
/obj/item/clothing/suit/victcoat = 1,
|
||||
/obj/item/clothing/suit/victcoat/red = 1,
|
||||
/obj/item/clothing/under/victsuit = 1,
|
||||
/obj/item/clothing/under/victsuit/redblk = 1,
|
||||
/obj/item/clothing/under/victsuit/red = 1,
|
||||
/obj/item/clothing/suit/tailcoat = 1,
|
||||
/obj/item/clothing/suit/draculacoat = 1,
|
||||
/obj/item/clothing/head/zepelli = 1,
|
||||
/obj/item/clothing/under/redhawaiianshirt = 1,
|
||||
/obj/item/clothing/under/pinkhawaiianshirt = 1,
|
||||
/obj/item/clothing/under/bluehawaiianshirt = 1,
|
||||
/obj/item/clothing/under/orangehawaiianshirt = 1)
|
||||
contraband = list(/obj/item/clothing/suit/judgerobe = 1,
|
||||
/obj/item/clothing/head/powdered_wig = 1,
|
||||
/obj/item/gun/magic/wand = 1,
|
||||
/obj/item/clothing/mask/balaclava=1,
|
||||
/obj/item/clothing/mask/horsehead = 2)
|
||||
premium = list(/obj/item/clothing/suit/hgpirate = 1,
|
||||
/obj/item/clothing/head/hgpiratecap = 1,
|
||||
/obj/item/clothing/head/helmet/roman/fake = 1,
|
||||
/obj/item/clothing/head/helmet/roman/legionaire/fake = 1,
|
||||
/obj/item/clothing/under/roman = 1,
|
||||
/obj/item/clothing/shoes/roman = 1,
|
||||
/obj/item/shield/riot/roman/fake = 1)
|
||||
refill_canister = /obj/item/vending_refill/autodrobe
|
||||
|
||||
/obj/machinery/vending/autodrobe/Initialize(mapload)
|
||||
|
||||
@@ -90,6 +90,10 @@
|
||||
/obj/effect/temp_visual/dir_setting/wraith/out
|
||||
icon_state = "phase_shift"
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/tailsweep
|
||||
icon_state = "tailsweep"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/temp_visual/wizard
|
||||
name = "water"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
|
||||
@@ -231,7 +231,8 @@
|
||||
create_with_tank = TRUE
|
||||
|
||||
/obj/item/flamethrower/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(ptank && damage && attack_type == PROJECTILE_ATTACK && prob(15))
|
||||
var/obj/item/projectile/P = hitby
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15))
|
||||
owner.visible_message("<span class='danger'>[attack_text] hits the fueltank on [owner]'s [src], rupturing it! What a shot!</span>")
|
||||
var/turf/target_turf = get_turf(owner)
|
||||
log_game("A projectile ([hitby]) detonated a flamethrower tank held by [key_name(owner)] at [COORD(target_turf)]")
|
||||
|
||||
@@ -114,7 +114,8 @@
|
||||
prime()
|
||||
|
||||
/obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && prob(15))
|
||||
var/obj/item/projectile/P = hitby
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15))
|
||||
owner.visible_message("<span class='danger'>[attack_text] hits [owner]'s [src], setting it off! What a shot!</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
log_game("A projectile ([hitby]) detonated a grenade held by [key_name(owner)] at [COORD(T)]")
|
||||
@@ -566,7 +567,7 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/grenade/chem_grenade/saringas
|
||||
payload_name = "saringas"
|
||||
payload_name = "sarin gas"
|
||||
desc = "Contains sarin gas; extremely deadly and fast acting; use with extreme caution."
|
||||
stage = READY
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>."
|
||||
icon_state = "roman_shield"
|
||||
item_state = "roman_shield"
|
||||
materials = list(MAT_METAL=8500)
|
||||
|
||||
/obj/item/shield/riot/roman/fake
|
||||
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
|
||||
block_chance = 0
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
|
||||
|
||||
/obj/item/shield/riot/buckler
|
||||
name = "wooden buckler"
|
||||
|
||||
@@ -389,6 +389,7 @@
|
||||
..()
|
||||
new /obj/item/ammo_box/magazine/smgm45(src)
|
||||
new /obj/item/ammo_box/magazine/smgm45(src)
|
||||
new /obj/item/ammo_box/magazine/smgm45(src)
|
||||
new /obj/item/gun/projectile/automatic/c20r(src)
|
||||
new /obj/item/suppressor/specialoffer(src)
|
||||
|
||||
@@ -403,13 +404,13 @@
|
||||
new /obj/item/clothing/glasses/chameleon/thermal(src)
|
||||
|
||||
/obj/item/storage/backpack/duffel/syndie/med/medicalbundle
|
||||
desc = "A large duffel bag containing a tactical medkit, a Donksoft machine gun and a big jumbo box of riot darts."
|
||||
desc = "A large duffel bag containing a tactical medkit, a medical beam gun and a pair of syndicate magboots."
|
||||
|
||||
/obj/item/storage/backpack/duffel/syndie/med/medicalbundle/New()
|
||||
..()
|
||||
new /obj/item/storage/firstaid/tactical(src)
|
||||
new /obj/item/gun/projectile/automatic/l6_saw/toy(src)
|
||||
new /obj/item/ammo_box/foambox/riot(src)
|
||||
new /obj/item/clothing/shoes/magboots/syndie(src)
|
||||
new /obj/item/gun/medbeam(src)
|
||||
|
||||
/obj/item/storage/backpack/duffel/syndie/c4/New()
|
||||
..()
|
||||
|
||||
@@ -332,6 +332,7 @@
|
||||
new /obj/item/grenade/gluon(src)
|
||||
new /obj/item/grenade/gluon(src)
|
||||
new /obj/item/grenade/chem_grenade/facid(src) //1
|
||||
new /obj/item/grenade/chem_grenade/saringas(src) //1
|
||||
new /obj/item/grenade/gas/plasma(src) //2
|
||||
new /obj/item/grenade/gas/plasma(src)
|
||||
new /obj/item/grenade/frag(src) //10
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return
|
||||
|
||||
|
||||
@@ -74,15 +74,16 @@
|
||||
temperature = T20C
|
||||
|
||||
/turf/simulated/floor/indestructible/hierophant
|
||||
icon_state = "hierophant1"
|
||||
name = "floor"
|
||||
icon = 'icons/turf/floors/hierophant_floor.dmi'
|
||||
icon_state = "floor"
|
||||
oxygen = 14
|
||||
nitrogen = 23
|
||||
temperature = 300
|
||||
planetary_atmos = TRUE
|
||||
desc = "A floor with a square pattern. It's faintly cool to the touch."
|
||||
smooth = SMOOTH_TRUE
|
||||
|
||||
/turf/simulated/floor/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
|
||||
return FALSE
|
||||
|
||||
/turf/simulated/floor/indestructible/hierophant/two
|
||||
icon_state = "hierophant2"
|
||||
/turf/simulated/floor/indestructible/hierophant/two
|
||||
@@ -29,17 +29,17 @@
|
||||
return
|
||||
|
||||
/turf/simulated/wall/indestructible/attackby(obj/item/I, mob/user, params)
|
||||
return
|
||||
return
|
||||
|
||||
/turf/simulated/wall/indestructible/attack_hand(mob/user)
|
||||
return
|
||||
return
|
||||
|
||||
/turf/simulated/wall/indestructible/attack_hulk(mob/user, does_attack_animation = FALSE)
|
||||
return
|
||||
|
||||
/turf/simulated/wall/indestructible/attack_animal(mob/living/simple_animal/M)
|
||||
return
|
||||
|
||||
|
||||
/turf/simulated/wall/indestructible/mech_melee_attack(obj/mecha/M)
|
||||
return
|
||||
|
||||
@@ -66,9 +66,9 @@
|
||||
|
||||
/turf/simulated/wall/indestructible/hierophant
|
||||
name = "wall"
|
||||
desc = "A wall made out of smooth, cold stone."
|
||||
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
|
||||
icon = 'icons/turf/walls/hierophant_wall.dmi'
|
||||
icon_state = "hierophant"
|
||||
icon_state = "wall"
|
||||
smooth = SMOOTH_TRUE
|
||||
|
||||
/turf/simulated/wall/indestructible/uranium
|
||||
|
||||
@@ -163,12 +163,20 @@
|
||||
strip_delay = 100
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/fake
|
||||
desc = "An ancient helmet made of plastic and leather."
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/legionaire
|
||||
name = "roman legionaire helmet"
|
||||
desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it."
|
||||
icon_state = "roman_c"
|
||||
item_state = "roman_c"
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/legionaire/fake
|
||||
desc = "An ancient helmet made of plastic and leather. Has a red crest on top of it."
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
|
||||
|
||||
/obj/item/clothing/head/helmet/gladiator
|
||||
name = "gladiator helmet"
|
||||
desc = "Ave, Imperator, morituri te salutant."
|
||||
|
||||
@@ -269,51 +269,59 @@ Gunshots/explosions/opening doors/less rare audio (done)
|
||||
px = -32
|
||||
|
||||
/obj/effect/hallucination/oh_yeah
|
||||
var/turf/simulated/wall/wall
|
||||
var/obj/effect/hallucination/simple/bubblegum/bubblegum = null
|
||||
var/obj/effect/hallucination/simple/bubblegum/bubblegum
|
||||
var/image/fakebroken
|
||||
var/image/fakerune
|
||||
|
||||
/obj/effect/hallucination/oh_yeah/New(loc, mob/living/carbon/T)
|
||||
/obj/effect/hallucination/oh_yeah/New(loc, mob/living/carbon/C)
|
||||
set waitfor = FALSE
|
||||
..()
|
||||
target = T
|
||||
for(var/turf/simulated/wall/W in range(7,target))
|
||||
target = C
|
||||
var/turf/simulated/wall/wall
|
||||
for(var/turf/simulated/wall/W in range(7, target))
|
||||
wall = W
|
||||
break
|
||||
if(wall)
|
||||
fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
|
||||
var/turf/landing = get_turf(target)
|
||||
var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3
|
||||
fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER)
|
||||
fakebroken.override = TRUE
|
||||
if(target.client)
|
||||
target.client.images |= fakebroken
|
||||
target.client.images |= fakerune
|
||||
target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1)
|
||||
bubblegum = new(wall, target)
|
||||
sleep(10) //ominous wait
|
||||
var/charged = FALSE //only get hit once
|
||||
while(get_turf(bubblegum) != landing && target)
|
||||
bubblegum.forceMove(get_step_towards(bubblegum, landing))
|
||||
bubblegum.setDir(get_dir(bubblegum, landing))
|
||||
target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1)
|
||||
shake_camera(target, 2, 1)
|
||||
if(bubblegum.Adjacent(target) && !charged)
|
||||
charged = TRUE
|
||||
target.Weaken(4)
|
||||
target.adjustStaminaLoss(40)
|
||||
step_away(target, bubblegum)
|
||||
shake_camera(target, 4, 3)
|
||||
target.visible_message("<span class='warning'>[target] jumps backwards, falling on the ground!</span>","<span class='userdanger'>[bubblegum] slams into you!</span>")
|
||||
sleep(2)
|
||||
sleep(30)
|
||||
qdel(bubblegum)
|
||||
if(!wall)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
|
||||
var/turf/landing = get_turf(target)
|
||||
var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3
|
||||
fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER)
|
||||
fakebroken.override = TRUE
|
||||
if(target.client)
|
||||
target.client.images |= fakebroken
|
||||
target.client.images |= fakerune
|
||||
target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1)
|
||||
bubblegum = new(wall, target)
|
||||
addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10)
|
||||
|
||||
/obj/effect/hallucination/oh_yeah/proc/bubble_attack(turf/landing)
|
||||
var/charged = FALSE //only get hit once
|
||||
while(get_turf(bubblegum) != landing && target && target.stat != DEAD)
|
||||
bubblegum.forceMove(get_step_towards(bubblegum, landing))
|
||||
bubblegum.setDir(get_dir(bubblegum, landing))
|
||||
target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1)
|
||||
shake_camera(target, 2, 1)
|
||||
if(bubblegum.Adjacent(target) && !charged)
|
||||
charged = TRUE
|
||||
target.Weaken(4)
|
||||
target.adjustStaminaLoss(40)
|
||||
step_away(target, bubblegum)
|
||||
shake_camera(target, 4, 3)
|
||||
target.visible_message("<span class='warning'>[target] jumps backwards, falling on the ground!</span>", "<span class='userdanger'>[bubblegum] slams into you!</span>")
|
||||
sleep(2)
|
||||
sleep(30)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/hallucination/oh_yeah/Destroy()
|
||||
if(target.client)
|
||||
target.client.images.Remove(fakebroken)
|
||||
target.client.images.Remove(fakerune)
|
||||
QDEL_NULL(fakebroken)
|
||||
QDEL_NULL(fakerune)
|
||||
QDEL_NULL(bubblegum)
|
||||
return ..()
|
||||
|
||||
/obj/effect/hallucination/singularity_scare
|
||||
|
||||
@@ -334,14 +334,6 @@
|
||||
icon_state = "britcup"
|
||||
volume = 30
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/mushroom_bowl
|
||||
name = "mushroom bowl"
|
||||
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_bowl"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/bag
|
||||
name = "drink bag"
|
||||
desc = "Normally put in wine boxes, or down pants at stadium events."
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
seed.genes += disk.gene.Copy()
|
||||
if(istype(disk.gene, /datum/plant_gene/reagent))
|
||||
seed.reagents_from_genes()
|
||||
disk.gene.apply_vars(seed)
|
||||
repaint_seed()
|
||||
|
||||
update_genes()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
icon_dead = "soybean-dead"
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
mutatelist = list(/obj/item/seeds/soya/koi)
|
||||
reagents_add = list("soybeanoil" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.05)
|
||||
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05, "soybeanoil" = 0.03)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/soybeans
|
||||
seed = /obj/item/seeds/soya
|
||||
@@ -25,7 +25,7 @@
|
||||
icon_state = "soybeans"
|
||||
filling_color = "#F0E68C"
|
||||
bitesize_mod = 2
|
||||
tastes = list("soybean" = 1)
|
||||
tastes = list("soy" = 1)
|
||||
wine_power = 0.2
|
||||
|
||||
// Koibean
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
desc = "Taste so good, you could die!"
|
||||
icon_state = "poisonberrypile"
|
||||
filling_color = "#C71585"
|
||||
distill_reagent = null
|
||||
tastes = list("poison-berry" = 1)
|
||||
distill_reagent = null
|
||||
wine_power = 0.35
|
||||
|
||||
// Death Berries
|
||||
@@ -70,8 +70,8 @@
|
||||
desc = "Taste so good, you could die!"
|
||||
icon_state = "deathberrypile"
|
||||
filling_color = "#708090"
|
||||
distill_reagent = null
|
||||
tastes = list("death-berry" = 1)
|
||||
distill_reagent = null
|
||||
wine_power = 0.5
|
||||
|
||||
// Glow Berries
|
||||
@@ -130,8 +130,8 @@
|
||||
gender = PLURAL
|
||||
filling_color = "#FF0000"
|
||||
bitesize_mod = 2
|
||||
wine_power = 0.3
|
||||
tastes = list("cherry" = 1)
|
||||
wine_power = 0.3
|
||||
|
||||
// Blue Cherries
|
||||
/obj/item/seeds/cherry/blue
|
||||
@@ -152,8 +152,8 @@
|
||||
icon_state = "bluecherry"
|
||||
filling_color = "#6495ED"
|
||||
bitesize_mod = 2
|
||||
wine_power = 0.5
|
||||
tastes = list("blue cherry" = 1)
|
||||
wine_power = 0.5
|
||||
|
||||
// Grapes
|
||||
/obj/item/seeds/grape
|
||||
@@ -184,8 +184,8 @@
|
||||
dried_type = /obj/item/reagent_containers/food/snacks/no_raisin
|
||||
filling_color = "#FF1493"
|
||||
bitesize_mod = 2
|
||||
distill_reagent = "wine"
|
||||
tastes = list("grapes" = 1)
|
||||
distill_reagent = "wine"
|
||||
|
||||
// Green Grapes
|
||||
/obj/item/seeds/grape/green
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
filling_color = "#0000CD"
|
||||
bitesize_mod = 2
|
||||
origin_tech = "biotech=4"
|
||||
tastes = list("chilli" = 1)
|
||||
tastes = list("chilly" = 1)
|
||||
wine_power = 0.3
|
||||
|
||||
// Ghost Chili
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
icon_state = "lime"
|
||||
filling_color = "#00FF00"
|
||||
tastes = list("lime" = 1)
|
||||
distill_reagent = "triple_sec"
|
||||
|
||||
// Orange
|
||||
/obj/item/seeds/orange
|
||||
@@ -59,6 +58,7 @@
|
||||
icon_state = "orange"
|
||||
tastes = list("orange" = 1)
|
||||
filling_color = "#FFA500"
|
||||
distill_reagent = "triple_sec"
|
||||
|
||||
// Lemon
|
||||
/obj/item/seeds/lemon
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/obj/item/grown/snapcorn
|
||||
seed = /obj/item/seeds/corn/snapcorn
|
||||
name = "snap corn"
|
||||
desc = "A cob with snap pops"
|
||||
desc = "A cob with snap pops."
|
||||
icon_state = "snapcorn"
|
||||
item_state = "corncob"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
|
||||
// Egg-Plant
|
||||
/obj/item/seeds/eggplant/eggy
|
||||
name = "pack of egg-plant seeds"
|
||||
desc = "These seeds grow to produce berries that look a lot like eggs."
|
||||
icon_state = "seed-eggy"
|
||||
species = "eggy"
|
||||
plantname = "Egg-Plants"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/shell/eggy
|
||||
lifespan = 75
|
||||
production = 12
|
||||
|
||||
@@ -138,6 +138,8 @@
|
||||
icon_state = "seed-moonflower"
|
||||
species = "moonflower"
|
||||
plantname = "Moonflowers"
|
||||
icon_grow = "moonflower-grow"
|
||||
icon_dead = "sunflower-dead"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/moonflower
|
||||
mutatelist = list()
|
||||
reagents_add = list("moonshine" = 0.2, "vitamin" = 0.02, "plantmatter" = 0.02)
|
||||
@@ -152,7 +154,7 @@
|
||||
filling_color = "#E6E6FA"
|
||||
bitesize_mod = 2
|
||||
tastes = list("moonflower" = 1)
|
||||
distill_reagent = "absinthe"
|
||||
distill_reagent = "absinthe" //It's made from flowers.
|
||||
|
||||
// Novaflower
|
||||
/obj/item/seeds/sunflower/novaflower
|
||||
@@ -161,6 +163,8 @@
|
||||
icon_state = "seed-novaflower"
|
||||
species = "novaflower"
|
||||
plantname = "Novaflowers"
|
||||
icon_grow = "novaflower-grow"
|
||||
icon_dead = "sunflower-dead"
|
||||
product = /obj/item/grown/novaflower
|
||||
mutatelist = list()
|
||||
reagents_add = list("condensedcapsaicin" = 0.25, "capsaicin" = 0.3, "plantmatter" = 0)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/obj/item/seeds/garlic
|
||||
name = "pack of garlic seeds"
|
||||
desc = "A packet of extremely pungent seeds."
|
||||
icon_state = "seed-garlic"
|
||||
species = "garlic"
|
||||
plantname = "Garlic Sprouts"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/garlic
|
||||
yield = 6
|
||||
potency = 25
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
|
||||
reagents_add = list("garlic" = 0.15, "plantmatter" = 0.1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/garlic
|
||||
seed = /obj/item/seeds/garlic
|
||||
name = "garlic"
|
||||
desc = "Delicious, but with a potentially overwhelming odor."
|
||||
icon_state = "garlic"
|
||||
filling_color = "#C0C9A0"
|
||||
bitesize_mod = 2
|
||||
tastes = list("garlic" = 1)
|
||||
wine_power = 0.1
|
||||
@@ -38,17 +38,8 @@
|
||||
continue
|
||||
grassAmt += 1 + round(G.seed.potency * tile_coefficient)
|
||||
qdel(G)
|
||||
var/obj/item/stack/tile/GT = new stacktype(user.loc)
|
||||
while(grassAmt > GT.max_amount)
|
||||
GT.amount = GT.max_amount
|
||||
grassAmt -= GT.max_amount
|
||||
GT = new stacktype(user.loc)
|
||||
GT.amount = grassAmt
|
||||
for(var/obj/item/stack/tile/T in user.loc)
|
||||
if((T.type == stacktype) && (T.amount < T.max_amount) && (T != GT))
|
||||
T.attackby(GT, user)
|
||||
new stacktype(user.drop_location(), grassAmt)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// Carpet
|
||||
/obj/item/seeds/grass/carpet
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
mutatelist = list(/obj/item/seeds/watermelon/holy)
|
||||
reagents_add = list("water" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.2)
|
||||
|
||||
/obj/item/seeds/watermelon/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is swallowing [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
user.gib()
|
||||
new product(drop_location())
|
||||
qdel(src)
|
||||
return OBLITERATION
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/watermelon
|
||||
seed = /obj/item/seeds/watermelon
|
||||
name = "watermelon"
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
|
||||
genes = list(/datum/plant_gene/trait/plant_type/weed_hardy)
|
||||
mutatelist = list(/obj/item/seeds/harebell)
|
||||
|
||||
/obj/item/seeds/starthistle/harvest(mob/user)
|
||||
var/obj/machinery/hydroponics/parent = loc
|
||||
var/seed_count = yield
|
||||
if(prob(getYield() * 20))
|
||||
seed_count++
|
||||
var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc
|
||||
for(var/i in 1 to yield+1)
|
||||
for(var/i in 1 to seed_count)
|
||||
var/obj/item/seeds/starthistle/harvestseeds = Copy()
|
||||
harvestseeds.forceMove(output_loc)
|
||||
|
||||
parent.update_tray()
|
||||
|
||||
|
||||
// Cabbage
|
||||
/obj/item/seeds/cabbage
|
||||
name = "pack of cabbage seeds"
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
can_distill = FALSE
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/mushroom/walkingmushroom/attack_self(mob/user)
|
||||
if(istype(user.loc, /turf/space))
|
||||
if(isspaceturf(user.loc))
|
||||
return
|
||||
var/mob/living/simple_animal/hostile/mushroom/M = new /mob/living/simple_animal/hostile/mushroom(user.loc)
|
||||
M.maxHealth += round(seed.endurance / 4)
|
||||
@@ -277,8 +277,7 @@
|
||||
desc = "This mycelium -powers- into mushrooms!"
|
||||
icon_state = "mycelium-glowcap"
|
||||
species = "glowcap"
|
||||
icon_grow = "glowshroom-grow"
|
||||
icon_dead = "glowshroom-dead"
|
||||
icon_harvest = "glowcap-harvest"
|
||||
plantname = "Glowcaps"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom/glowcap
|
||||
genes = list(/datum/plant_gene/trait/glow/red, /datum/plant_gene/trait/cell_charge, /datum/plant_gene/trait/plant_type/fungal_metabolism)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/onion_slice
|
||||
tastes = list("onion" = 1, "pungentness" = 1)
|
||||
slices_num = 2
|
||||
wine_power = 0.2
|
||||
wine_power = 0.3
|
||||
wine_flavor = "pungentness"
|
||||
|
||||
/obj/item/seeds/onion/red
|
||||
|
||||
@@ -1,29 +1,33 @@
|
||||
// Pineapple!
|
||||
/obj/item/seeds/pineapple
|
||||
name = "pack of pineapple seeds"
|
||||
desc = "These seeds grow into pineapple plants."
|
||||
icon_state = "seed-pineapple" //NEEDED
|
||||
species = "pineapple"
|
||||
plantname = "Pineapple Plant"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/pineapple
|
||||
maturation = 6
|
||||
lifespan = 55
|
||||
endurance = 35
|
||||
growthstages = 4
|
||||
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
|
||||
icon_grow = "pineapple-grow" //NEEDED
|
||||
icon_dead = "pineapple-dead" //NEEDED
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
reagents_add = list("water" = 0.1, "vitamin" = 0.03, "sugar" = 0.02, "plantmatter" = 0.2)
|
||||
name = "pack of pineapple seeds"
|
||||
desc = "Oooooooooooooh!"
|
||||
icon_state = "seed-pineapple"
|
||||
species = "pineapple"
|
||||
plantname = "Pineapple Plant"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/pineapple
|
||||
lifespan = 40
|
||||
endurance = 30
|
||||
growthstages = 3
|
||||
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
mutatelist = list(/obj/item/seeds/apple)
|
||||
reagents_add = list("vitamin" = 0.02, "plantmatter" = 0.2, "water" = 0.04)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/pineapple
|
||||
seed = /obj/item/seeds/pineapple
|
||||
name = "pineapple"
|
||||
desc = "A soft sweet interior surrounded by a spiky skin."
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/pineappleslice
|
||||
slices_num = 4
|
||||
icon_state = "pineapple"
|
||||
filling_color = "#e5b437"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
bitesize_mod = 3
|
||||
tastes = list("pineapple" = 1)
|
||||
wine_power = 0.4
|
||||
seed = /obj/item/seeds/pineapple
|
||||
name = "pineapple"
|
||||
desc = "A soft sweet interior surrounded by a spiky skin."
|
||||
icon_state = "pineapple"
|
||||
force = 4
|
||||
throwforce = 8
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("stung", "pined")
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/pineappleslice
|
||||
slices_num = 3
|
||||
filling_color = "#F6CB0B"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
tastes = list("pineapple" = 1)
|
||||
wine_power = 0.4
|
||||
@@ -98,8 +98,6 @@
|
||||
podman.ckey = ckey_holder
|
||||
podman.gender = blood_gender
|
||||
podman.faction |= factions
|
||||
podman.faction |= "plants"
|
||||
podman.faction |= "vines" //Pod grown Diona are allied with plants and vines alike.
|
||||
|
||||
else //else, one packet of seeds. maybe two
|
||||
var/seed_count = 1
|
||||
|
||||
@@ -44,15 +44,11 @@
|
||||
attack_verb = list("bashed", "battered", "bludgeoned", "whacked")
|
||||
var/plank_type = /obj/item/stack/sheet/wood
|
||||
var/plank_name = "wooden planks"
|
||||
var/list/accepted = list(/obj/item/reagent_containers/food/snacks/grown/tobacco,
|
||||
var/static/list/accepted = typecacheof(list(/obj/item/reagent_containers/food/snacks/grown/tobacco,
|
||||
/obj/item/reagent_containers/food/snacks/grown/tea,
|
||||
/obj/item/reagent_containers/food/snacks/grown/ambrosia/vulgaris,
|
||||
/obj/item/reagent_containers/food/snacks/grown/ambrosia/deus,
|
||||
/obj/item/reagent_containers/food/snacks/grown/wheat)
|
||||
|
||||
/obj/item/grown/log/New()
|
||||
..()
|
||||
accepted = typecacheof(accepted)
|
||||
/obj/item/reagent_containers/food/snacks/grown/wheat))
|
||||
|
||||
/obj/item/grown/log/attackby(obj/item/W, mob/user, params)
|
||||
if(is_sharp(W))
|
||||
@@ -69,7 +65,7 @@
|
||||
to_chat(user, "<span class='notice'>You add the newly-formed [plank_name] to the stack. It now contains [plank.amount] [plank_name].</span>")
|
||||
qdel(src)
|
||||
|
||||
if(is_type_in_typecache(W, accepted))
|
||||
if(CheckAccepted(W))
|
||||
var/obj/item/reagent_containers/food/snacks/grown/leaf = W
|
||||
if(leaf.dry)
|
||||
user.show_message("<span class='notice'>You wrap \the [W] around the log, turning it into a torch!</span>")
|
||||
@@ -84,6 +80,9 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/grown/log/proc/CheckAccepted(obj/item/I)
|
||||
return is_type_in_typecache(I, accepted)
|
||||
|
||||
/obj/item/grown/log/tree
|
||||
seed = null
|
||||
name = "wood log"
|
||||
@@ -94,10 +93,11 @@
|
||||
name = "steel-cap log"
|
||||
desc = "It's made of metal."
|
||||
icon_state = "steellogs"
|
||||
accepted = list()
|
||||
plank_type = /obj/item/stack/rods
|
||||
plank_name = "rods"
|
||||
|
||||
/obj/item/grown/log/steel/CheckAccepted(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/////////BONFIRES//////////
|
||||
|
||||
|
||||
@@ -636,9 +636,10 @@
|
||||
|
||||
// why, just why
|
||||
if(S.has_reagent("napalm", 1))
|
||||
adjustHealth(-round(S.get_reagent_amount("napalm") * 6))
|
||||
adjustToxic(round(S.get_reagent_amount("napalm") * 7))
|
||||
adjustWeeds(-rand(5,9))
|
||||
if(!(myseed.resistance_flags & FIRE_PROOF))
|
||||
adjustHealth(-round(S.get_reagent_amount("napalm") * 6))
|
||||
adjustToxic(round(S.get_reagent_amount("napalm") * 7))
|
||||
adjustWeeds(-rand(5, 9)) //At least give them a small reward if they bother
|
||||
|
||||
//Weed Spray
|
||||
if(S.has_reagent("atrazine", 1))
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
/datum/plant_gene/proc/Copy()
|
||||
return new type
|
||||
|
||||
|
||||
/datum/plant_gene/proc/apply_vars(obj/item/seeds/S) // currently used for fire resist, can prob. be further refactored
|
||||
return
|
||||
|
||||
|
||||
// Core plant genes store 5 main variables: lifespan, endurance, production, yield, potency
|
||||
@@ -412,6 +413,17 @@
|
||||
S.set_up(G.reagents, splat_location)
|
||||
S.start(smoke_amount)
|
||||
|
||||
/datum/plant_gene/trait/fire_resistance // Lavaland
|
||||
name = "Fire Resistance"
|
||||
|
||||
/datum/plant_gene/trait/fire_resistance/apply_vars(obj/item/seeds/S)
|
||||
if(!(S.resistance_flags & FIRE_PROOF))
|
||||
S.resistance_flags |= FIRE_PROOF
|
||||
|
||||
/datum/plant_gene/trait/fire_resistance/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc)
|
||||
if(!(G.resistance_flags & FIRE_PROOF))
|
||||
G.resistance_flags |= FIRE_PROOF
|
||||
|
||||
/datum/plant_gene/trait/plant_type // Parent type
|
||||
name = "you shouldn't see this"
|
||||
trait_id = "plant_type"
|
||||
|
||||
@@ -164,7 +164,6 @@
|
||||
name = "survival pod medical supply"
|
||||
desc = "Wall-mounted Medical Equipment dispenser. This one seems just a tiny bit smaller."
|
||||
req_access = list()
|
||||
refill_canister = null
|
||||
|
||||
products = list(/obj/item/reagent_containers/food/pill/patch/styptic = 5,
|
||||
/obj/item/reagent_containers/food/pill/patch/silver_sulf = 5,
|
||||
@@ -342,7 +341,7 @@
|
||||
/obj/item/shield/changeling,
|
||||
/obj/item/lava_staff,
|
||||
/obj/item/katana/energy,
|
||||
/obj/item/hierophant_staff,
|
||||
/obj/item/hierophant_club,
|
||||
/obj/item/storage/toolbox/green/memetic,
|
||||
/obj/item/gun/projectile/automatic/l6_saw,
|
||||
/obj/item/gun/magic/staff/chaos,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/obj/structure/flora/ash
|
||||
gender = PLURAL
|
||||
layer = PROJECTILE_HIT_THRESHHOLD_LAYER //sporangiums up don't shoot
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "l_mushroom"
|
||||
name = "large mushrooms"
|
||||
@@ -17,42 +18,41 @@
|
||||
var/harvest_message_high = "You harvest and collect shavings from several mushroom caps."
|
||||
var/harvested = FALSE
|
||||
var/base_icon
|
||||
var/regrowth_time_low = 4800
|
||||
var/regrowth_time_high = 8400
|
||||
var/regrowth_time_low = 8 MINUTES
|
||||
var/regrowth_time_high = 16 MINUTES
|
||||
|
||||
/obj/structure/flora/ash/New()
|
||||
..()
|
||||
/obj/structure/flora/ash/Initialize(mapload)
|
||||
. = ..()
|
||||
base_icon = "[icon_state][rand(1, 4)]"
|
||||
icon_state = base_icon
|
||||
if(prob(15))
|
||||
harvest(null, TRUE)
|
||||
|
||||
/obj/structure/flora/ash/ex_act(severity, target)
|
||||
switch(severity)
|
||||
if(1)
|
||||
qdel(src)
|
||||
if(2)
|
||||
if(prob(80))
|
||||
qdel(src)
|
||||
if(3)
|
||||
if(prob(50))
|
||||
/obj/structure/flora/ash/ex_act(severity, target)
|
||||
switch(severity)
|
||||
if(1)
|
||||
qdel(src)
|
||||
if(2)
|
||||
if(prob(80))
|
||||
qdel(src)
|
||||
if(3)
|
||||
if(prob(50))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/flora/ash/proc/harvest(user, no_drop)
|
||||
/obj/structure/flora/ash/proc/harvest(user)
|
||||
if(harvested)
|
||||
return 0
|
||||
if(!no_drop)
|
||||
var/rand_harvested = rand(harvest_amount_low, harvest_amount_high)
|
||||
if(rand_harvested)
|
||||
if(user)
|
||||
var/msg = harvest_message_med
|
||||
if(rand_harvested == harvest_amount_low)
|
||||
msg = harvest_message_low
|
||||
else if(rand_harvested == harvest_amount_high)
|
||||
msg = harvest_message_high
|
||||
to_chat(user, "<span class='notice'>[msg]</span>")
|
||||
for(var/i in 1 to rand_harvested)
|
||||
new harvest(get_turf(src))
|
||||
|
||||
var/rand_harvested = rand(harvest_amount_low, harvest_amount_high)
|
||||
if(rand_harvested)
|
||||
if(user)
|
||||
var/msg = harvest_message_med
|
||||
if(rand_harvested == harvest_amount_low)
|
||||
msg = harvest_message_low
|
||||
else if(rand_harvested == harvest_amount_high)
|
||||
msg = harvest_message_high
|
||||
to_chat(user, "<span class='notice'>[msg]</span>")
|
||||
for(var/i in 1 to rand_harvested)
|
||||
new harvest(get_turf(src))
|
||||
|
||||
icon_state = "[base_icon]p"
|
||||
name = harvested_name
|
||||
desc = harvested_desc
|
||||
@@ -120,7 +120,8 @@
|
||||
icon_state = "t_mushroom"
|
||||
name = "numerous mushrooms"
|
||||
desc = "A large number of mushrooms, some of which have long, fleshy stems. They're radiating light!"
|
||||
luminosity = 1
|
||||
light_range = 1.5
|
||||
light_power = 2.1
|
||||
harvested_name = "tiny mushrooms"
|
||||
harvested_desc = "A few tiny mushrooms around larger stumps. You can already see them growing back."
|
||||
harvest = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
|
||||
@@ -166,12 +167,12 @@
|
||||
desc = "Some shavings from a tall mushroom. With enough, might serve as a bowl."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_shavings"
|
||||
list_reagents = list("sugar" = 3, "ethanol" = 2, "stabilizing_agent" = 3, "minttoxin" = 2)
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
seed = /obj/item/seeds/lavaland/polypore
|
||||
wine_power = 0.2
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/New()
|
||||
..()
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/Initialize(mapload)
|
||||
. = ..()
|
||||
pixel_x = rand(-4, 4)
|
||||
pixel_y = rand(-4, 4)
|
||||
|
||||
@@ -180,39 +181,105 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_leaf
|
||||
name = "mushroom leaf"
|
||||
desc = "A leaf, from a mushroom."
|
||||
list_reagents = list("nutriment" = 3, "vitfro" = 2, "nicotine" = 2)
|
||||
icon_state = "mushroom_leaf"
|
||||
seed = /obj/item/seeds/lavaland/porcini
|
||||
wine_power = 0.4
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_cap
|
||||
name = "mushroom cap"
|
||||
desc = "The cap of a large mushroom."
|
||||
list_reagents = list("lsd" = 2, "entpoly" = 4, "psilocybin" = 2)
|
||||
icon_state = "mushroom_cap"
|
||||
seed = /obj/item/seeds/lavaland/inocybe
|
||||
wine_power = 0.7
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
|
||||
name = "mushroom stem"
|
||||
desc = "A long mushroom stem. It's slightly glowing."
|
||||
list_reagents = list("tinlux" = 2, "vitamin" = 1, "space_drugs" = 1)
|
||||
icon_state = "mushroom_stem"
|
||||
luminosity = 1
|
||||
seed = /obj/item/seeds/lavaland/ember
|
||||
wine_power = 0.6
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
|
||||
name = "cactus fruit"
|
||||
list_reagents = list("vitamin" = 2, "nutriment" = 2, "vitfro" = 4)
|
||||
desc = "A cactus fruit covered in a thick, reddish skin. And some ash."
|
||||
icon_state = "cactus_fruit"
|
||||
seed = /obj/item/seeds/lavaland/cactus
|
||||
wine_power = 0.5
|
||||
|
||||
/obj/item/mushroom_bowl
|
||||
name = "mushroom bowl"
|
||||
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_bowl"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
//SEEDS
|
||||
|
||||
/obj/item/seeds/lavaland
|
||||
name = "lavaland seeds"
|
||||
desc = "You should never see this."
|
||||
lifespan = 50
|
||||
endurance = 25
|
||||
maturation = 7
|
||||
production = 4
|
||||
yield = 4
|
||||
potency = 15
|
||||
growthstages = 3
|
||||
rarity = 20
|
||||
reagents_add = list("nutriment" = 0.1)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/seeds/lavaland/cactus
|
||||
name = "pack of fruiting cactus seeds"
|
||||
desc = "These seeds grow into fruiting cacti."
|
||||
icon_state = "seed-cactus"
|
||||
species = "cactus"
|
||||
plantname = "Fruiting Cactus"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
|
||||
genes = list(/datum/plant_gene/trait/fire_resistance)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
|
||||
growthstages = 2
|
||||
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.04, "vitfro" = 0.08)
|
||||
|
||||
/obj/item/seeds/lavaland/polypore
|
||||
name = "pack of polypore mycelium"
|
||||
desc = "This mycelium grows into bracket mushrooms, also known as polypores. Woody and firm, shaft miners often use them for makeshift crafts."
|
||||
icon_state = "mycelium-polypore"
|
||||
species = "polypore"
|
||||
plantname = "Polypore Mushrooms"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/shavings
|
||||
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/fire_resistance)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
reagents_add = list("sugar" = 0.06, "ethanol" = 0.04, "stabilizing_agent" = 0.06, "minttoxin" = 0.02)
|
||||
|
||||
/obj/item/seeds/lavaland/porcini
|
||||
name = "pack of porcini mycelium"
|
||||
desc = "This mycelium grows into Boletus edulus, also known as porcini. Native to the late Earth, but discovered on Lavaland. Has culinary, medicinal and relaxant effects."
|
||||
icon_state = "mycelium-porcini"
|
||||
species = "porcini"
|
||||
plantname = "Porcini Mushrooms"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_leaf
|
||||
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/fire_resistance)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
reagents_add = list("nutriment" = 0.06, "vitfro" = 0.04, "nicotine" = 0.04)
|
||||
|
||||
|
||||
/obj/item/seeds/lavaland/inocybe
|
||||
name = "pack of inocybe mycelium"
|
||||
desc = "This mycelium grows into an inocybe mushroom, a species of Lavaland origin with hallucinatory and toxic effects."
|
||||
icon_state = "mycelium-inocybe"
|
||||
species = "inocybe"
|
||||
plantname = "Inocybe Mushrooms"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_cap
|
||||
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/fire_resistance)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
reagents_add = list("lsd" = 0.04, "entpoly" = 0.08, "psilocybin" = 0.04)
|
||||
|
||||
/obj/item/seeds/lavaland/ember
|
||||
name = "pack of embershroom mycelium"
|
||||
desc = "This mycelium grows into embershrooms, a species of bioluminescent mushrooms native to Lavaland."
|
||||
icon_state = "mycelium-ember"
|
||||
species = "ember"
|
||||
plantname = "Embershroom Mushrooms"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/mushroom_stem
|
||||
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/glow, /datum/plant_gene/trait/fire_resistance)
|
||||
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
reagents_add = list("tinlux" = 0.04, "vitamin" = 0.02, "space_drugs" = 0.02)
|
||||
|
||||
//CRAFTING
|
||||
|
||||
//what you can craft with these things
|
||||
/datum/crafting_recipe/mushroom_bowl
|
||||
@@ -221,3 +288,10 @@
|
||||
reqs = list(/obj/item/reagent_containers/food/snacks/grown/ash_flora/shavings = 5)
|
||||
time = 30
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/mushroom_bowl
|
||||
name = "mushroom bowl"
|
||||
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
|
||||
icon = 'icons/obj/lavaland/ash_flora.dmi'
|
||||
icon_state = "mushroom_bowl"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -1,115 +1,190 @@
|
||||
/obj/item/hierophant_staff
|
||||
name = "Hierophant's staff"
|
||||
desc = "A large club with intense magic power infused into it."
|
||||
icon_state = "hierophant_staff"
|
||||
item_state = "hierophant_staff"
|
||||
icon = 'icons/obj/guns/magic.dmi'
|
||||
#define HIEROPHANT_CLUB_CARDINAL_DAMAGE 30
|
||||
|
||||
/obj/item/hierophant_club
|
||||
name = "hierophant club"
|
||||
desc = "The strange technology of this large club allows various nigh-magical feats. It used to beat you, but now you can set the beat."
|
||||
icon_state = "hierophant_club_ready_beacon"
|
||||
item_state = "hierophant_club_ready_beacon"
|
||||
icon = 'icons/obj/lavaland/artefacts.dmi'
|
||||
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
|
||||
inhand_x_dimension = 64
|
||||
inhand_y_dimension = 64
|
||||
slot_flags = SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 20
|
||||
hitsound = "swing_hit"
|
||||
//hitsound = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
force = 15
|
||||
attack_verb = list("clubbed", "beat", "pummeled")
|
||||
hitsound = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire)
|
||||
var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is
|
||||
var/chaser_cooldown = 101 //how long the cooldown between firing chasers at mobs is
|
||||
var/chaser_cooldown = 81 //how long the cooldown between firing chasers at mobs is
|
||||
var/chaser_timer = 0 //what our current chaser cooldown is
|
||||
var/chaser_speed = 0.8 //how fast our chasers are
|
||||
var/timer = 0 //what our current cooldown is
|
||||
var/blast_range = 3 //how long the cardinal blast's walls are
|
||||
var/obj/effect/hierophant/rune //the associated rune we teleport to
|
||||
var/blast_range = 13 //how long the cardinal blast's walls are
|
||||
var/obj/effect/hierophant/beacon //the associated beacon we teleport to
|
||||
var/teleporting = FALSE //if we ARE teleporting
|
||||
var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets
|
||||
|
||||
/obj/item/hierophant_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
/obj/item/hierophant_club/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='hierophant_warning'>The[beacon ? " beacon is not currently":"re is a beacon"] attached.</span>")
|
||||
|
||||
/obj/item/hierophant_club/suicide_act(mob/living/user)
|
||||
atom_say("Xverwpsgexmrk...")
|
||||
user.visible_message("<span class='suicide'>[user] holds [src] into the air! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
new/obj/effect/temp_visual/hierophant/telegraph(get_turf(user))
|
||||
playsound(user,'sound/machines/airlock_open.ogg', 75, TRUE)
|
||||
user.visible_message("<span class='hierophant_warning'>[user] fades out, leaving [user.p_their()] belongings behind!</span>")
|
||||
for(var/obj/item/I in user)
|
||||
if(I != src)
|
||||
user.unEquip(I)
|
||||
for(var/turf/T in RANGE_TURFS(1, user))
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(T, user, TRUE)
|
||||
B.damage = 0
|
||||
user.unEquip(src) //Drop us last, so it goes on top of their stuff
|
||||
qdel(user)
|
||||
return OBLITERATION
|
||||
|
||||
|
||||
/obj/item/hierophant_club/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
..()
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T || timer > world.time)
|
||||
return
|
||||
calculate_anger_mod(user)
|
||||
timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown
|
||||
if(proximity_flag)
|
||||
spawn(0)
|
||||
aoe_burst(T, user)
|
||||
INVOKE_ASYNC(src, .proc/aoe_burst, T, user)
|
||||
add_attack_logs(user, target, "Fired 3x3 blast at [src]")
|
||||
else
|
||||
if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it)
|
||||
spawn(0)
|
||||
cardinal_blasts(T, user)
|
||||
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user)
|
||||
timer = world.time + cooldown_time
|
||||
else if(target in view(5, get_turf(user))) //if the target is in view, hit it
|
||||
timer = world.time + cooldown_time
|
||||
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
|
||||
chaser_timer = world.time + chaser_cooldown
|
||||
new /obj/effect/temp_visual/hierophant/chaser(get_turf(user), user, target, 1.5, friendly_fire_check)
|
||||
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check)
|
||||
C.damage = 30
|
||||
C.monster_damage_boost = FALSE
|
||||
add_attack_logs(user, target, "Fired a chaser at [src]")
|
||||
else
|
||||
spawn(0)
|
||||
cardinal_blasts(T, user) //otherwise, just do cardinal blast
|
||||
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
|
||||
add_attack_logs(user, target, "Fired cardinal blast at [src]")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>That target is out of range!</span>") //too far away
|
||||
to_chat(user, "<span class='warning'>That target is out of range!</span>" )
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
|
||||
/obj/item/hierophant_staff/ui_action_click(mob/user, actiontype)
|
||||
/obj/item/hierophant_club/proc/calculate_anger_mod(mob/user) //we get stronger as the user loses health
|
||||
chaser_cooldown = initial(chaser_cooldown)
|
||||
cooldown_time = initial(cooldown_time)
|
||||
chaser_speed = initial(chaser_speed)
|
||||
blast_range = initial(blast_range)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
var/health_percent = L.health / L.maxHealth
|
||||
chaser_cooldown += round(health_percent * 20) //two tenths of a second for each missing 10% of health
|
||||
cooldown_time += round(health_percent * 10) //one tenth of a second for each missing 10% of health
|
||||
chaser_speed = max(chaser_speed + health_percent, 0.5) //one tenth of a second faster for each missing 10% of health
|
||||
blast_range -= round(health_percent * 10) //one additional range for each missing 10% of health
|
||||
|
||||
/obj/item/hierophant_club/update_icon()
|
||||
icon_state = "hierophant_club[timer <= world.time ? "_ready":""][(beacon && !QDELETED(beacon)) ? "":"_beacon"]"
|
||||
item_state = icon_state
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.update_inv_l_hand()
|
||||
M.update_inv_r_hand()
|
||||
M.update_inv_back()
|
||||
|
||||
/obj/item/hierophant_club/proc/prepare_icon_update()
|
||||
update_icon()
|
||||
sleep(timer - world.time)
|
||||
update_icon()
|
||||
|
||||
/obj/item/hierophant_club/ui_action_click(mob/user, actiontype)
|
||||
if(actiontype == /datum/action/item_action/toggle_unfriendly_fire) //toggle friendly fire...
|
||||
friendly_fire_check = !friendly_fire_check
|
||||
to_chat(user, "<span class='warning'>You toggle friendly fire [friendly_fire_check ? "off":"on"]!</span>")
|
||||
return
|
||||
if(user.is_in_active_hand(src) && user.is_in_inactive_hand(src)) //you need to hold the staff to teleport
|
||||
to_chat(user, "<span class='warning'>You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!</span>")
|
||||
if(timer > world.time)
|
||||
return
|
||||
if(!rune)
|
||||
if(user.is_in_active_hand(src) && user.is_in_inactive_hand(src)) //you need to hold the staff to teleport
|
||||
to_chat(user, "<span class='warning'>You need to hold the club in your hands to [beacon ? "teleport with it":"detach the beacon"]!</span>")
|
||||
return
|
||||
if(!beacon || QDELETED(beacon))
|
||||
if(isturf(user.loc))
|
||||
user.visible_message("<span class='hierophant_warning'>[user] holds [src] carefully in front of [user.p_them()], moving it in a strange pattern...</span>", \
|
||||
"<span class='notice'>You start creating a hierophant rune to teleport to...</span>")
|
||||
user.visible_message("<span class='hierophant_warning'>[user] starts fiddling with [src]'s pommel...</span>", \
|
||||
"<span class='notice'>You start detaching the hierophant beacon...</span>")
|
||||
timer = world.time + 51
|
||||
if(do_after(user, 50, target = user))
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
if(do_after(user, 50, target = user) && !beacon)
|
||||
var/turf/T = get_turf(user)
|
||||
playsound(T,'sound/magic/blind.ogg', 200, 1, -4)
|
||||
playsound(T,'sound/magic/blind.ogg', 200, TRUE, -4)
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user)
|
||||
var/obj/effect/hierophant/H = new/obj/effect/hierophant(T)
|
||||
rune = H
|
||||
beacon = new/obj/effect/hierophant(T)
|
||||
user.update_action_buttons_icon()
|
||||
user.visible_message("<span class='hierophant_warning'>[user] creates a strange rune beneath [user.p_them()]!</span>", \
|
||||
"<span class='hierophant'>You create a hierophant rune, which you can teleport yourself and any allies to at any time!</span>\n\
|
||||
<span class='notice'>You can remove the rune to place a new one by striking it with the staff.</span>")
|
||||
user.visible_message("<span class='hierophant_warning'>[user] places a strange machine beneath [user.p_their()] feet!</span>", \
|
||||
"<span class='hierophant'>You detach the hierophant beacon, allowing you to teleport yourself and any allies to it at any time!</span>\n\
|
||||
<span class='notice'>You can remove the beacon to place it again by striking it with the club.</span>")
|
||||
else
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to be on solid ground to produce a rune!</span>")
|
||||
to_chat(user, "<span class='warning'>You need to be on solid ground to detach the beacon!</span>")
|
||||
return
|
||||
if(get_dist(user, rune) <= 2) //rune too close abort
|
||||
to_chat(user, "<span class='warning'>You are too close to the rune to teleport to it!</span>")
|
||||
if(get_dist(user, beacon) <= 2) //beacon too close abort
|
||||
to_chat(user, "<span class='warning'>You are too close to the beacon to teleport to it!</span>")
|
||||
return
|
||||
if(is_blocked_turf(get_turf(rune)))
|
||||
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
|
||||
if(is_blocked_turf(get_turf(beacon), TRUE))
|
||||
to_chat(user, "<span class='warning'>The beacon is blocked by something, preventing teleportation!</span>")
|
||||
return
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "<span class='warning'>You don't have enough space to teleport from here!</span>")
|
||||
return
|
||||
teleporting = TRUE //start channel
|
||||
user.update_action_buttons_icon()
|
||||
user.visible_message("<span class='hierophant_warning'>[user] starts to glow faintly...</span>")
|
||||
timer = world.time + 50
|
||||
if(do_after(user, 40, target = user) && rune)
|
||||
var/turf/T = get_turf(rune)
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
beacon.icon_state = "hierophant_tele_on"
|
||||
var/obj/effect/temp_visual/hierophant/telegraph/edge/TE1 = new /obj/effect/temp_visual/hierophant/telegraph/edge(user.loc)
|
||||
var/obj/effect/temp_visual/hierophant/telegraph/edge/TE2 = new /obj/effect/temp_visual/hierophant/telegraph/edge(beacon.loc)
|
||||
if(do_after(user, 40, target = user) && user && beacon)
|
||||
var/turf/T = get_turf(beacon)
|
||||
var/turf/source = get_turf(user)
|
||||
if(is_blocked_turf(T))
|
||||
if(is_blocked_turf(T, TRUE))
|
||||
teleporting = FALSE
|
||||
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
|
||||
to_chat(user, "<span class='warning'>The beacon is blocked by something, preventing teleportation!</span>")
|
||||
user.update_action_buttons_icon()
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
beacon.icon_state = "hierophant_tele_off"
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/telegraph(T, user)
|
||||
new /obj/effect/temp_visual/hierophant/telegraph(source, user)
|
||||
playsound(T,'sound/magic/blink.ogg', 200, 1)
|
||||
//playsound(T,'sound/magic/wand_teleport.ogg', 200, 1)
|
||||
playsound(source,'sound/magic/blink.ogg', 200, 1)
|
||||
//playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1)
|
||||
if(!do_after(user, 3, target = user) || !rune) //no walking away shitlord
|
||||
playsound(T,'sound/magic/wand_teleport.ogg', 200, TRUE)
|
||||
playsound(source,'sound/machines/airlock_open.ogg', 200, TRUE)
|
||||
if(!do_after(user, 3, target = user) || !user || !beacon || QDELETED(beacon)) //no walking away shitlord
|
||||
teleporting = FALSE
|
||||
if(user)
|
||||
user.update_action_buttons_icon()
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
if(beacon)
|
||||
beacon.icon_state = "hierophant_tele_off"
|
||||
return
|
||||
if(is_blocked_turf(T))
|
||||
if(is_blocked_turf(T, TRUE))
|
||||
teleporting = FALSE
|
||||
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
|
||||
to_chat(user, "<span class='warning'>The beacon is blocked by something, preventing teleportation!</span>")
|
||||
user.update_action_buttons_icon()
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
beacon.icon_state = "hierophant_tele_off"
|
||||
return
|
||||
add_attack_logs(user, rune, "Teleported self from ([source.x],[source.y],[source.z]) to ([T.x],[T.y],[T.z])")
|
||||
add_attack_logs(user, beacon, "Teleported self from ([AREACOORD(source)]) to ([AREACOORD(beacon)])")
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user)
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, user)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
@@ -119,18 +194,24 @@
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
|
||||
B.damage = 30
|
||||
for(var/mob/living/L in range(1, source))
|
||||
spawn(0)
|
||||
teleport_mob(source, L, T, user) //regardless, take all mobs near us along
|
||||
INVOKE_ASYNC(src, .proc/teleport_mob, source, L, T, user) //regardless, take all mobs near us along
|
||||
sleep(6) //at this point the blasts detonate
|
||||
if(beacon)
|
||||
beacon.icon_state = "hierophant_tele_off"
|
||||
else
|
||||
qdel(TE1)
|
||||
qdel(TE2)
|
||||
timer = world.time
|
||||
INVOKE_ASYNC(src, .proc/prepare_icon_update)
|
||||
if(beacon)
|
||||
beacon.icon_state = "hierophant_tele_off"
|
||||
teleporting = FALSE
|
||||
if(user)
|
||||
user.update_action_buttons_icon()
|
||||
|
||||
/obj/item/hierophant_staff/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
|
||||
/obj/item/hierophant_club/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
|
||||
var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster
|
||||
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to))
|
||||
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to, TRUE))
|
||||
return
|
||||
animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out
|
||||
sleep(1)
|
||||
@@ -152,19 +233,19 @@
|
||||
if(user != M)
|
||||
add_attack_logs(user, M, "Teleported from ([source.x],[source.y],[source.z])")
|
||||
|
||||
/obj/item/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay
|
||||
/obj/item/hierophant_club/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay
|
||||
if(!T)
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/cardinal(T, user)
|
||||
playsound(T,'sound/magic/blink.ogg', 200, 1)
|
||||
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
|
||||
playsound(T,'sound/effects/bin_close.ogg', 200, TRUE)
|
||||
sleep(2)
|
||||
new /obj/effect/temp_visual/hierophant/blast(T, user, friendly_fire_check)
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(T, user, friendly_fire_check)
|
||||
B.damage = HIEROPHANT_CLUB_CARDINAL_DAMAGE
|
||||
B.monster_damage_boost = FALSE
|
||||
for(var/d in cardinal)
|
||||
spawn(0)
|
||||
blast_wall(T, d, user)
|
||||
INVOKE_ASYNC(src, .proc/blast_wall, T, d, user)
|
||||
|
||||
/obj/item/hierophant_staff/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long
|
||||
/obj/item/hierophant_club/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long
|
||||
if(!T)
|
||||
return
|
||||
var/range = blast_range
|
||||
@@ -173,16 +254,20 @@
|
||||
for(var/i in 1 to range)
|
||||
if(!J)
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/blast(J, user, friendly_fire_check)
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(J, user, friendly_fire_check)
|
||||
B.damage = HIEROPHANT_CLUB_CARDINAL_DAMAGE
|
||||
B.monster_damage_boost = FALSE
|
||||
previousturf = J
|
||||
J = get_step(previousturf, dir)
|
||||
|
||||
/obj/item/hierophant_staff/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target
|
||||
/obj/item/hierophant_club/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target
|
||||
if(!T)
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/telegraph(T, user)
|
||||
playsound(T,'sound/magic/blink.ogg', 200, 1)
|
||||
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
|
||||
playsound(T,'sound/effects/bin_close.ogg', 200, TRUE)
|
||||
sleep(2)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
new /obj/effect/temp_visual/hierophant/blast(t, user, friendly_fire_check)
|
||||
var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check)
|
||||
B.damage = 15 //keeps monster damage boost due to lower damage
|
||||
|
||||
#undef HIEROPHANT_CLUB_CARDINAL_DAMAGE
|
||||
@@ -126,7 +126,6 @@
|
||||
modkit_design = /datum/design/unique_modkit/bounty
|
||||
|
||||
/datum/design/unique_modkit
|
||||
category = list("Mining", "Cyborg Upgrade Modules") //can't be normally obtained
|
||||
build_type = PROTOLATHE | MECHFAB
|
||||
|
||||
/datum/design/unique_modkit/offensive_turf_aoe
|
||||
@@ -135,6 +134,7 @@
|
||||
id = "hyperaoemod"
|
||||
materials = list(MAT_METAL = 7000, MAT_GLASS = 3000, MAT_SILVER= 3000, MAT_GOLD = 3000, MAT_DIAMOND = 4000)
|
||||
build_path = /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs
|
||||
category = list("Mining", "Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/unique_modkit/rapid_repeater
|
||||
name = "Kinetic Accelerator Rapid Repeater Mod"
|
||||
@@ -142,6 +142,7 @@
|
||||
id = "repeatermod"
|
||||
materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_URANIUM = 8000, MAT_BLUESPACE = 2000)
|
||||
build_path = /obj/item/borg/upgrade/modkit/cooldown/repeater
|
||||
category = list("Mining", "Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/unique_modkit/resonator_blast
|
||||
name = "Kinetic Accelerator Resonator Blast Mod"
|
||||
@@ -149,6 +150,7 @@
|
||||
id = "resonatormod"
|
||||
materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_SILVER= 5000, MAT_URANIUM = 5000)
|
||||
build_path = /obj/item/borg/upgrade/modkit/resonator_blasts
|
||||
category = list("Mining", "Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/unique_modkit/bounty
|
||||
name = "Kinetic Accelerator Death Syphon Mod"
|
||||
@@ -156,4 +158,5 @@
|
||||
id = "bountymod"
|
||||
materials = list(MAT_METAL = 4000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_BLUESPACE = 4000)
|
||||
reagents_list = list("blood" = 40)
|
||||
build_path = /obj/item/borg/upgrade/modkit/bounty
|
||||
build_path = /obj/item/borg/upgrade/modkit/bounty
|
||||
category = list("Mining", "Cyborg Upgrade Modules")
|
||||
|
||||
@@ -59,7 +59,8 @@ In all, this is a lot like the monkey code. /N
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
switch(M.melee_damage_type)
|
||||
if(BRUTE)
|
||||
|
||||
@@ -328,7 +328,7 @@ This function restores all organs.
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/get_organ(zone)
|
||||
/mob/living/carbon/human/get_organ(zone)
|
||||
if(!zone)
|
||||
zone = "chest"
|
||||
if(zone in list("eyes", "mouth"))
|
||||
|
||||
@@ -437,16 +437,17 @@ emp_act
|
||||
visible_message("<span class='danger'>[M] has tried to disarm [src]!</span>")
|
||||
|
||||
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(check_shields(M, damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
|
||||
return 0
|
||||
if(check_shields(M, damage, "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
return FALSE
|
||||
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
|
||||
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_organ("chest")
|
||||
affecting.add_autopsy_data(M.name, damage) // Add the mob's name to the autopsy data
|
||||
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
|
||||
var/obj/item/organ/external/affected = src.get_organ(dam_zone)
|
||||
if(affected)
|
||||
affected.add_autopsy_data(M.name, damage) // Add the mob's name to the autopsy data
|
||||
apply_damage(damage, M.melee_damage_type, affecting, armor)
|
||||
updatehealth("animal attack")
|
||||
|
||||
|
||||
@@ -519,7 +519,7 @@
|
||||
to_chat(M, "<span class='warning'>You can't use your hand.</span>")
|
||||
return
|
||||
|
||||
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(0, M.name, attack_type = UNARMED_ATTACK))
|
||||
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
|
||||
add_attack_logs(M, H, "Melee attacked with fists (miss/block)")
|
||||
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -258,7 +258,8 @@
|
||||
M.updatehealth()
|
||||
|
||||
/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
attacked += 10
|
||||
adjustBruteLoss(damage)
|
||||
|
||||
@@ -303,17 +303,17 @@
|
||||
return
|
||||
|
||||
/mob/living/attack_animal(mob/living/simple_animal/M)
|
||||
M.face_atom(src)
|
||||
if((M.a_intent == INTENT_HELP && M.ckey) || M.melee_damage_upper == 0)
|
||||
M.custom_emote(1, "[M.friendly] [src].")
|
||||
return 0
|
||||
else
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
|
||||
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>")
|
||||
add_attack_logs(M, src, "Animal attacked")
|
||||
return 1
|
||||
return FALSE
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
|
||||
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>")
|
||||
add_attack_logs(M, src, "Animal attacked")
|
||||
return TRUE
|
||||
|
||||
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
switch(L.a_intent)
|
||||
|
||||
@@ -227,14 +227,8 @@
|
||||
// See software.dm for Topic()
|
||||
|
||||
/mob/living/silicon/pai/attack_animal(mob/living/simple_animal/M)
|
||||
if((M.a_intent == INTENT_HELP && M.ckey) || M.melee_damage_upper == 0)
|
||||
M.custom_emote(1, "[M.friendly] [src].")
|
||||
else
|
||||
M.do_attack_animation(src)
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message("<span class='danger'>[M]</span> [M.attacktext] [src]!", 1)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
add_attack_logs(M, src, "Animal attacked for [damage] damage")
|
||||
adjustBruteLoss(damage)
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
return
|
||||
|
||||
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
switch(M.melee_damage_type)
|
||||
if(BRUTE)
|
||||
|
||||
@@ -53,9 +53,10 @@
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
|
||||
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
attack_threshold_check(damage, M.melee_damage_type)
|
||||
return attack_threshold_check(damage, M.melee_damage_type)
|
||||
|
||||
/mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M)
|
||||
..()
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
else
|
||||
to_chat(M, "<span class='cult'>You cannot repair your own dents, as you have none!</span>")
|
||||
else if(src != M)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/narsie_act()
|
||||
|
||||
@@ -30,7 +30,7 @@ Difficulty: Medium
|
||||
icon = 'icons/mob/alienqueen.dmi'
|
||||
light_color = "#E4C7C5"
|
||||
speak_emote = list("roars")
|
||||
speed = 1
|
||||
speed = 3
|
||||
move_to_delay = 3
|
||||
projectiletype = /obj/item/projectile/kinetic/miner
|
||||
projectilesound = 'sound/weapons/kenetic_accel.ogg'
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#define BUBBLEGUM_SMASH (health <= maxHealth * 0.5) // angery
|
||||
#define BUBBLEGUM_CAN_ENRAGE (enrage_till + (enrage_time * 2) <= world.time)
|
||||
#define BUBBLEGUM_IS_ENRAGED (enrage_till > world.time)
|
||||
|
||||
|
||||
/*
|
||||
|
||||
BUBBLEGUM
|
||||
@@ -5,14 +10,16 @@ BUBBLEGUM
|
||||
Bubblegum spawns randomly wherever a lavaland creature is able to spawn. It is the most powerful slaughter demon in existence.
|
||||
Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size.
|
||||
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power
|
||||
|
||||
It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
|
||||
If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
|
||||
If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
|
||||
At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
|
||||
It leaves blood trails behind wherever it goes, its clones do as well.
|
||||
It tries to strike at its target through any bloodpools under them; if it fails to do that.
|
||||
If it does warp it will enter an enraged state, becoming immune to all projectiles, becoming much faster, and dealing damage and knockback to anything that gets in the cloud around it.
|
||||
It may summon clones charging from all sides, one of these charges being bubblegum himself.
|
||||
It can charge at its target, and also heavily damaging anything directly hit in the charge.
|
||||
If at half health it will start to charge from all sides with clones.
|
||||
|
||||
When Bubblegum dies, it leaves behind a chest that can contain three things:
|
||||
When Bubblegum dies, it leaves behind a H.E.C.K. mining suit as well as a chest that can contain three things:
|
||||
1. A bottle that, when activated, drives everyone nearby into a frenzy
|
||||
2. A contract that marks for death the chosen target
|
||||
3. A spellblade that can slice off limbs at range
|
||||
@@ -37,19 +44,31 @@ Difficulty: Hard
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 40
|
||||
melee_damage_upper = 40
|
||||
speed = 1
|
||||
move_to_delay = 10
|
||||
ranged = 1
|
||||
speed = 5
|
||||
move_to_delay = 5
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
rapid_melee = 8 // every 1/4 second
|
||||
melee_queue_distance = 20 // as far as possible really, need this because of blood warp
|
||||
ranged = TRUE
|
||||
pixel_x = -32
|
||||
del_on_death = 1
|
||||
del_on_death = TRUE
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
|
||||
var/charging = 0
|
||||
blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
|
||||
var/charging = FALSE
|
||||
var/enrage_till = 0
|
||||
var/enrage_time = 70
|
||||
var/revving_charge = FALSE
|
||||
internal_type = /obj/item/gps/internal/bubblegum
|
||||
medal_type = BOSS_MEDAL_BUBBLEGUM
|
||||
score_type = BUBBLEGUM_SCORE
|
||||
deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... "
|
||||
death_sound = 'sound/misc/enter_blood.ogg'
|
||||
attack_action_types = list(/datum/action/innate/megafauna_attack/triple_charge,
|
||||
/datum/action/innate/megafauna_attack/hallucination_charge,
|
||||
/datum/action/innate/megafauna_attack/hallucination_surround,
|
||||
/datum/action/innate/megafauna_attack/blood_warp)
|
||||
|
||||
/obj/item/gps/internal/bubblegum
|
||||
icon_state = null
|
||||
@@ -57,54 +76,6 @@ Difficulty: Hard
|
||||
desc = "You're not quite sure how a signal can be bloody."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount)
|
||||
if(amount > 0 && prob(25))
|
||||
var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
|
||||
if(prob(40))
|
||||
step(B, pick(cardinal))
|
||||
else
|
||||
B.dir = pick(cardinal)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum
|
||||
name = "thick blood"
|
||||
desc = "Thick, splattered blood."
|
||||
random_icon_states = list("gib3", "gib5", "gib6")
|
||||
amount = 20
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life(seconds, times_fired)
|
||||
..()
|
||||
move_to_delay = Clamp((health/maxHealth) * 10, 5, 10)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
|
||||
anger_modifier = Clamp(((maxHealth - health)/60),0,20)
|
||||
if(charging)
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
|
||||
var/warped = FALSE
|
||||
if(!try_bloodattack())
|
||||
spawn(0)
|
||||
blood_spray()
|
||||
warped = blood_warp()
|
||||
if(warped && prob(100 - anger_modifier))
|
||||
return
|
||||
|
||||
if(prob(90 - anger_modifier) || slaughterlings())
|
||||
if(health > maxHealth * 0.5)
|
||||
spawn(0)
|
||||
charge()
|
||||
else
|
||||
if(prob(70) || warped)
|
||||
spawn(0)
|
||||
triple_charge()
|
||||
else
|
||||
spawn(0)
|
||||
warp_charge()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Initialize(mapload)
|
||||
. = ..()
|
||||
if(true_spawn)
|
||||
@@ -112,88 +83,118 @@ Difficulty: Hard
|
||||
if(B != src)
|
||||
qdel(src) //There can be only one
|
||||
return
|
||||
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
|
||||
AddSpell(bloodspell)
|
||||
if(istype(loc, /obj/effect/dummy/slaughter))
|
||||
bloodspell.phased = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
|
||||
if(!charging)
|
||||
..()
|
||||
/datum/action/innate/megafauna_attack/triple_charge
|
||||
name = "Triple Charge"
|
||||
icon_icon = 'icons/mob/actions/actions.dmi'
|
||||
button_icon_state = "sniper_zoom"
|
||||
chosen_message = "<span class='colossus'>You are now triple charging at the target you click on.</span>"
|
||||
chosen_attack_num = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget()
|
||||
if(!charging)
|
||||
return ..()
|
||||
/datum/action/innate/megafauna_attack/hallucination_charge
|
||||
name = "Hallucination Charge"
|
||||
icon_icon = 'icons/effects/bubblegum.dmi'
|
||||
button_icon_state = "smack ya one"
|
||||
chosen_message = "<span class='colossus'>You are now charging with hallucinations at the target you click on.</span>"
|
||||
chosen_attack_num = 2
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
|
||||
if(!charging)
|
||||
..()
|
||||
/datum/action/innate/megafauna_attack/hallucination_surround
|
||||
name = "Surround Target"
|
||||
icon_icon = 'icons/turf/walls/wall.dmi'
|
||||
button_icon_state = "wall"
|
||||
chosen_message = "<span class='colossus'>You are now surrounding the target you click on with hallucinations.</span>"
|
||||
chosen_attack_num = 3
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/MoveToTarget(list/possible_targets)
|
||||
if(!charging)
|
||||
..()
|
||||
/datum/action/innate/megafauna_attack/blood_warp
|
||||
name = "Blood Warp"
|
||||
icon_icon = 'icons/effects/blood.dmi'
|
||||
button_icon_state = "floor1"
|
||||
chosen_message = "<span class='colossus'>You are now warping to blood around your clicked position.</span>"
|
||||
chosen_attack_num = 4
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
|
||||
if(charging)
|
||||
new /obj/effect/temp_visual/decoy/fading(loc, src)
|
||||
DestroySurroundings()
|
||||
. = ..()
|
||||
if(!stat && .)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
|
||||
blood_warp()
|
||||
charge()
|
||||
anger_modifier = Clamp(((maxHealth - health)/60),0,20)
|
||||
enrage_time = initial(enrage_time) * Clamp(anger_modifier / 20, 0.5, 1)
|
||||
ranged_cooldown = world.time + 50
|
||||
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(1)
|
||||
triple_charge()
|
||||
if(2)
|
||||
hallucination_charge()
|
||||
if(3)
|
||||
surround_with_hallucinations()
|
||||
if(4)
|
||||
blood_warp()
|
||||
return
|
||||
|
||||
if(!try_bloodattack() || prob(25 + anger_modifier))
|
||||
blood_warp()
|
||||
|
||||
if(!BUBBLEGUM_SMASH)
|
||||
triple_charge()
|
||||
else
|
||||
if(prob(50 + anger_modifier))
|
||||
hallucination_charge()
|
||||
else
|
||||
surround_with_hallucinations()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
|
||||
charge()
|
||||
charge()
|
||||
charge()
|
||||
charge(delay = 6)
|
||||
charge(delay = 4)
|
||||
charge(delay = 2)
|
||||
SetRecoveryTime(15)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T || T == loc)
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/hallucination_charge()
|
||||
if(!BUBBLEGUM_SMASH || prob(33))
|
||||
hallucination_charge_around(times = 6, delay = 8)
|
||||
SetRecoveryTime(10)
|
||||
else
|
||||
hallucination_charge_around(times = 4, delay = 9)
|
||||
hallucination_charge_around(times = 4, delay = 8)
|
||||
hallucination_charge_around(times = 4, delay = 7)
|
||||
triple_charge()
|
||||
SetRecoveryTime(20)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/surround_with_hallucinations()
|
||||
for(var/i = 1 to 5)
|
||||
INVOKE_ASYNC(src, .proc/hallucination_charge_around, 2, 8, 2, 0, 4)
|
||||
if(ismob(target))
|
||||
charge(delay = 6)
|
||||
else
|
||||
SLEEP_CHECK_DEATH(6)
|
||||
SetRecoveryTime(20)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge(atom/chargeat = target, delay = 3, chargepast = 2)
|
||||
if(!chargeat)
|
||||
return
|
||||
new /obj/effect/temp_visual/dragon_swoop(T)
|
||||
charging = 1
|
||||
var/chargeturf = get_turf(chargeat)
|
||||
if(!chargeturf)
|
||||
return
|
||||
var/dir = get_dir(src, chargeturf)
|
||||
var/turf/T = get_ranged_target_turf(chargeturf, dir, chargepast)
|
||||
if(!T)
|
||||
return
|
||||
new /obj/effect/temp_visual/dragon_swoop/bubblegum(T)
|
||||
charging = TRUE
|
||||
revving_charge = TRUE
|
||||
DestroySurroundings()
|
||||
walk(src, 0)
|
||||
dir = get_dir(src, T)
|
||||
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc, src)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
|
||||
sleep(5)
|
||||
throw_at(T, get_dist(src, T), 1, src, 0)
|
||||
charging = 0
|
||||
setDir(dir)
|
||||
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 3)
|
||||
SLEEP_CHECK_DEATH(delay)
|
||||
revving_charge = FALSE
|
||||
var/movespeed = 0.7
|
||||
walk_towards(src, T, movespeed)
|
||||
SLEEP_CHECK_DEATH(get_dist(src, T) * movespeed)
|
||||
walk(src, 0) // cancel the movement
|
||||
try_bloodattack()
|
||||
if(target)
|
||||
Goto(target, move_to_delay, minimum_distance)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
|
||||
if(charging)
|
||||
if(isturf(A) || isobj(A) && A.density)
|
||||
A.ex_act(2)
|
||||
DestroySurroundings()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/A)
|
||||
if(!charging)
|
||||
return ..()
|
||||
|
||||
else if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
|
||||
L.apply_damage(40, BRUTE)
|
||||
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
|
||||
L.throw_at(throwtarget, 3)
|
||||
|
||||
charging = 0
|
||||
|
||||
charging = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
|
||||
var/list/targets = ListTargets()
|
||||
@@ -206,9 +207,7 @@ Difficulty: Hard
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
|
||||
var/list/targets = get_mobs_on_blood()
|
||||
if(targets.len)
|
||||
spawn(0)
|
||||
bloodattack(targets, prob(50))
|
||||
|
||||
INVOKE_ASYNC(src, .proc/bloodattack, targets, prob(50))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -249,14 +248,14 @@ Difficulty: Hard
|
||||
new /obj/effect/temp_visual/bubblegum_hands/rightsmack(T)
|
||||
else
|
||||
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T)
|
||||
sleep(2.5)
|
||||
SLEEP_CHECK_DEATH(4)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check_mob(L))
|
||||
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
|
||||
playsound(T, attack_sound, 100, 1, -1)
|
||||
var/limb_to_hit = pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg")
|
||||
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
|
||||
sleep(3)
|
||||
playsound(T, attack_sound, 100, TRUE, -1)
|
||||
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
L.apply_damage(10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
|
||||
SLEEP_CHECK_DEATH(3)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T, handedness)
|
||||
if(handedness)
|
||||
@@ -265,18 +264,221 @@ Difficulty: Hard
|
||||
else
|
||||
new /obj/effect/temp_visual/bubblegum_hands/leftpaw(T)
|
||||
new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T)
|
||||
sleep(6)
|
||||
SLEEP_CHECK_DEATH(6)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check_mob(L))
|
||||
to_chat(L, "<span class='userdanger'>[src] drags you through the blood!</span>")
|
||||
playsound(T, 'sound/misc/enter_blood.ogg', 100, 1, -1)
|
||||
var/turf/targetturf = get_step(src, dir)
|
||||
L.forceMove(targetturf)
|
||||
playsound(targetturf, 'sound/misc/exit_blood.ogg', 100, 1, -1)
|
||||
if(L.stat != CONSCIOUS)
|
||||
spawn(2)
|
||||
devour(L)
|
||||
sleep(1)
|
||||
to_chat(L, "<span class='userdanger'>[src] drags you through the blood!</span>")
|
||||
playsound(T, 'sound/misc/enter_blood.ogg', 100, TRUE, -1)
|
||||
var/turf/targetturf = get_step(src, dir)
|
||||
L.forceMove(targetturf)
|
||||
playsound(targetturf, 'sound/misc/exit_blood.ogg', 100, TRUE, -1)
|
||||
addtimer(CALLBACK(src, .proc/devour, L), 2)
|
||||
SLEEP_CHECK_DEATH(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
|
||||
if(Adjacent(target))
|
||||
return FALSE
|
||||
var/list/can_jaunt = get_pools(get_turf(src), 1)
|
||||
if(!can_jaunt.len)
|
||||
return FALSE
|
||||
|
||||
var/list/pools = get_pools(get_turf(target), 5)
|
||||
var/list/pools_to_remove = get_pools(get_turf(target), 4)
|
||||
pools -= pools_to_remove
|
||||
if(!pools.len)
|
||||
return FALSE
|
||||
|
||||
var/obj/effect/temp_visual/decoy/DA = new /obj/effect/temp_visual/decoy(loc,src)
|
||||
DA.color = "#FF0000"
|
||||
var/oldtransform = DA.transform
|
||||
DA.transform = matrix()*2
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 3)
|
||||
SLEEP_CHECK_DEATH(3)
|
||||
qdel(DA)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
pools = get_pools(get_turf(target), 5)
|
||||
pools_to_remove = get_pools(get_turf(target), 4)
|
||||
pools -= pools_to_remove
|
||||
if(pools.len)
|
||||
shuffle_inplace(pools)
|
||||
found_bloodpool = pick(pools)
|
||||
if(found_bloodpool)
|
||||
visible_message("<span class='danger'>[src] sinks into the blood...</span>")
|
||||
playsound(get_turf(src), 'sound/misc/enter_blood.ogg', 100, TRUE, -1)
|
||||
forceMove(get_turf(found_bloodpool))
|
||||
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, TRUE, -1)
|
||||
visible_message("<span class='danger'>And springs back out!</span>")
|
||||
blood_enrage()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/be_aggressive()
|
||||
if(BUBBLEGUM_IS_ENRAGED)
|
||||
return TRUE
|
||||
if(isliving(target))
|
||||
var/mob/living/livingtarget = target
|
||||
return (livingtarget.stat != CONSCIOUS || livingtarget.lying)
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_retreat_distance()
|
||||
return (be_aggressive() ? null : initial(retreat_distance))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_minimum_distance()
|
||||
return (be_aggressive() ? 1 : initial(minimum_distance))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/update_approach()
|
||||
retreat_distance = get_retreat_distance()
|
||||
minimum_distance = get_minimum_distance()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_enrage()
|
||||
if(!BUBBLEGUM_CAN_ENRAGE)
|
||||
return FALSE
|
||||
enrage_till = world.time + enrage_time
|
||||
update_approach()
|
||||
change_move_delay(3.75)
|
||||
var/newcolor = rgb(149, 10, 10)
|
||||
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
|
||||
var/datum/callback/cb = CALLBACK(src, .proc/blood_enrage_end)
|
||||
addtimer(cb, enrage_time)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_enrage_end(newcolor = rgb(149, 10, 10))
|
||||
update_approach()
|
||||
change_move_delay()
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, newcolor)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/change_move_delay(newmove = initial(move_to_delay))
|
||||
move_to_delay = newmove
|
||||
speed = move_to_delay
|
||||
handle_automated_action() // need to recheck movement otherwise move_to_delay won't update until the next checking aka will be wrong speed for a bit
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
|
||||
. = list()
|
||||
for(var/obj/effect/decal/cleanable/nearby in view(T, range))
|
||||
if(nearby.can_bloodcrawl_in())
|
||||
. += nearby
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegum
|
||||
bloodiness = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/hallucination_charge_around(times = 4, delay = 6, chargepast = 0, useoriginal = 1, radius)
|
||||
var/startingangle = rand(1, 360)
|
||||
if(!target)
|
||||
return
|
||||
var/turf/chargeat = get_turf(target)
|
||||
var/srcplaced = FALSE
|
||||
if(!radius)
|
||||
radius = times
|
||||
for(var/i = 1 to times)
|
||||
var/ang = (startingangle + 360/times * i)
|
||||
if(!chargeat)
|
||||
return
|
||||
var/turf/place = locate(chargeat.x + cos(ang) * radius, chargeat.y + sin(ang) * radius, chargeat.z)
|
||||
if(!place)
|
||||
continue
|
||||
if(!nest || nest && nest.parent && get_dist(nest.parent, place) <= nest_range)
|
||||
if(!srcplaced && useoriginal)
|
||||
forceMove(place)
|
||||
srcplaced = TRUE
|
||||
continue
|
||||
var/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/B = new /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination(loc)
|
||||
B.forceMove(place)
|
||||
INVOKE_ASYNC(B, .proc/charge, chargeat, delay, chargepast)
|
||||
if(useoriginal)
|
||||
charge(chargeat, delay, chargepast)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount, updating_health = TRUE)
|
||||
. = ..()
|
||||
if(. > 0 && prob(25))
|
||||
var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
|
||||
if(prob(40))
|
||||
step(B, pick(cardinal))
|
||||
else
|
||||
B.setDir(pick(cardinal))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum
|
||||
name = "thick blood"
|
||||
desc = "Thick, splattered blood."
|
||||
random_icon_states = list("gib3", "gib5", "gib6")
|
||||
bloodiness = 20
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget()
|
||||
if(!charging)
|
||||
. = ..()
|
||||
if(.)
|
||||
recovery_time = world.time + 20 // can only attack melee once every 2 seconds but rapid_melee gives higher priority
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/bullet_act(obj/item/projectile/P)
|
||||
if(BUBBLEGUM_IS_ENRAGED)
|
||||
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons while enraged!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 300, TRUE)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/ex_act(severity, target)
|
||||
if(severity >= EXPLODE_LIGHT)
|
||||
return
|
||||
severity = EXPLODE_LIGHT // puny mortals
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/MoveToTarget(list/possible_targets)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
|
||||
update_approach()
|
||||
if(revving_charge)
|
||||
return FALSE
|
||||
if(charging)
|
||||
new /obj/effect/temp_visual/decoy/fading(loc,src)
|
||||
DestroySurroundings()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Moved(atom/OldLoc, Dir, Forced = FALSE)
|
||||
if(Dir)
|
||||
new /obj/effect/decal/cleanable/blood/bubblegum(loc)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 200, TRUE, 2, TRUE)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
|
||||
if(charging)
|
||||
if(isturf(A) || isobj(A) && A.density)
|
||||
A.ex_act(EXPLODE_HEAVY)
|
||||
DestroySurroundings()
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] tramples you into the ground!</span>")
|
||||
forceMove(get_turf(L))
|
||||
L.apply_damage(istype(src, /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination) ? 15 : 30, BRUTE)
|
||||
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
..()
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/bubblegum
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands
|
||||
icon = 'icons/effects/bubblegum.dmi'
|
||||
@@ -290,11 +492,11 @@ Difficulty: Hard
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/rightpaw
|
||||
icon_state = "rightpawgrab"
|
||||
layer = MOB_LAYER - 0.1
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/leftpaw
|
||||
icon_state = "leftpawgrab"
|
||||
layer = MOB_LAYER - 0.1
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/rightsmack
|
||||
icon_state = "rightsmack"
|
||||
@@ -302,94 +504,48 @@ Difficulty: Hard
|
||||
/obj/effect/temp_visual/bubblegum_hands/leftsmack
|
||||
icon_state = "leftsmack"
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
|
||||
if(Adjacent(target))
|
||||
return FALSE
|
||||
var/list/can_jaunt = get_pools(get_turf(src), 1)
|
||||
if(!can_jaunt.len)
|
||||
return FALSE
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination
|
||||
name = "bubblegum's hallucination"
|
||||
desc = "Is that really just a hallucination?"
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
alpha = 127.5
|
||||
crusher_loot = null
|
||||
loot = null
|
||||
medal_type = null
|
||||
score_type = null
|
||||
deathmessage = "Explodes into a pool of blood!"
|
||||
death_sound = 'sound/effects/splat.ogg'
|
||||
true_spawn = FALSE
|
||||
|
||||
var/list/pools = get_pools(get_turf(target), 2)
|
||||
var/list/pools_to_remove = get_pools(get_turf(target), 1)
|
||||
pools -= pools_to_remove
|
||||
if(!pools.len)
|
||||
return FALSE
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Initialize(mapload)
|
||||
. = ..()
|
||||
toggle_ai(AI_OFF)
|
||||
|
||||
var/obj/effect/temp_visual/decoy/DA = new /obj/effect/temp_visual/decoy(loc, src)
|
||||
DA.color = "#FF0000"
|
||||
var/oldtransform = DA.transform
|
||||
DA.transform = matrix()*2
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
|
||||
sleep(5)
|
||||
qdel(DA)
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/charge(atom/chargeat = target, delay = 3, chargepast = 2)
|
||||
..()
|
||||
qdel(src)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
pools = get_pools(get_turf(target), 2)
|
||||
pools_to_remove = get_pools(get_turf(target), 1)
|
||||
pools -= pools_to_remove
|
||||
if(pools.len)
|
||||
shuffle(pools)
|
||||
found_bloodpool = pick(pools)
|
||||
if(found_bloodpool)
|
||||
visible_message("<span class='danger'>[src] sinks into the blood...</span>")
|
||||
playsound(get_turf(src), 'sound/misc/enter_blood.ogg', 100, 1, -1)
|
||||
forceMove(get_turf(found_bloodpool))
|
||||
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1)
|
||||
visible_message("<span class='danger'>And springs back out!</span>")
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Destroy()
|
||||
new /obj/effect/decal/cleanable/blood(get_turf(src))
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum)) // hallucinations should not be stopping bubblegum or eachother
|
||||
return TRUE
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
|
||||
. = list()
|
||||
for(var/obj/effect/decal/cleanable/nearby in view(T, range))
|
||||
if(nearby.can_bloodcrawl_in())
|
||||
. += nearby
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Life()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
|
||||
visible_message("<span class='danger'>[src] sprays a stream of gore!</span>")
|
||||
var/range = 6 + round(anger_modifier * 0.4)
|
||||
var/turf/previousturf = get_turf(src)
|
||||
var/turf/J = previousturf
|
||||
var/targetdir = get_dir(src, target)
|
||||
if(target.loc == loc)
|
||||
targetdir = dir
|
||||
face_atom(target)
|
||||
new /obj/effect/decal/cleanable/blood/bubblegum(J)
|
||||
for(var/i in 1 to range)
|
||||
J = get_step(previousturf, targetdir)
|
||||
new /obj/effect/temp_visual/dir_setting/bloodsplatter(previousturf, get_dir(previousturf, J))
|
||||
playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
|
||||
if(!J || !previousturf.CanAtmosPass(J))
|
||||
break
|
||||
new /obj/effect/decal/cleanable/blood/bubblegum(J)
|
||||
previousturf = J
|
||||
sleep(1)
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/adjustBruteLoss(amount, updating_health = TRUE)
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegum
|
||||
amount = 0
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/OpenFire()
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/AttackingTarget()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
|
||||
visible_message("<span class='danger'>[src] summons a shoal of slaughterlings!</span>")
|
||||
var/max_amount = 6
|
||||
for(var/H in get_pools(get_turf(src), 1))
|
||||
if(!max_amount)
|
||||
break
|
||||
max_amount--
|
||||
var/obj/effect/decal/cleanable/blood/B = H
|
||||
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(B.loc)
|
||||
return max_amount
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter
|
||||
name = "slaughterling"
|
||||
desc = "Though not yet strong enough to create a true physical form, it's nonetheless determined to murder you."
|
||||
density = 0
|
||||
faction = list("mining", "boss")
|
||||
weather_immunities = list("lava","ash")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter/CanPass(atom/movable/mover, turf/target, height = 0)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
|
||||
return 1
|
||||
return 0
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/try_bloodattack()
|
||||
return
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
|
||||
COLOSSUS
|
||||
@@ -31,35 +30,74 @@ Difficulty: Very Hard
|
||||
attack_sound = 'sound/magic/ratvar_attack.ogg'
|
||||
icon_state = "eva"
|
||||
icon_living = "eva"
|
||||
icon_dead = "dragon_dead"
|
||||
icon_dead = ""
|
||||
friendly = "stares down"
|
||||
icon = 'icons/mob/lavaland/96x96megafauna.dmi'
|
||||
speak_emote = list("roars")
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 40
|
||||
melee_damage_upper = 40
|
||||
speed = 1
|
||||
speed = 10
|
||||
move_to_delay = 10
|
||||
ranged = 1
|
||||
ranged = TRUE
|
||||
pixel_x = -32
|
||||
del_on_death = 1
|
||||
del_on_death = TRUE
|
||||
internal_type = /obj/item/gps/internal/colossus
|
||||
medal_type = BOSS_MEDAL_COLOSSUS
|
||||
score_type = COLOSSUS_SCORE
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/colossus)
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
|
||||
deathmessage = "disintegrates, leaving a glowing core in its wake."
|
||||
death_sound = 'sound/misc/demon_dies.ogg'
|
||||
attack_action_types = list(/datum/action/innate/megafauna_attack/spiral_attack,
|
||||
/datum/action/innate/megafauna_attack/aoe_attack,
|
||||
/datum/action/innate/megafauna_attack/shotgun,
|
||||
/datum/action/innate/megafauna_attack/alternating_cardinals)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/devour(mob/living/L)
|
||||
visible_message("<span class='colossus'>[src] disintegrates [L]!</span>")
|
||||
L.dust()
|
||||
/datum/action/innate/megafauna_attack/spiral_attack
|
||||
name = "Spiral Shots"
|
||||
icon_icon = 'icons/mob/actions/actions.dmi'
|
||||
button_icon_state = "sniper_zoom"
|
||||
chosen_message = "<span class='colossus'>You are now firing in a spiral.</span>"
|
||||
chosen_attack_num = 1
|
||||
|
||||
/datum/action/innate/megafauna_attack/aoe_attack
|
||||
name = "All Directions"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "at_shield2"
|
||||
chosen_message = "<span class='colossus'>You are now firing in all directions.</span>"
|
||||
chosen_attack_num = 2
|
||||
|
||||
/datum/action/innate/megafauna_attack/shotgun
|
||||
name = "Shotgun Fire"
|
||||
icon_icon = 'icons/obj/guns/projectile.dmi'
|
||||
button_icon_state = "shotgun"
|
||||
chosen_message = "<span class='colossus'>You are now firing shotgun shots where you aim.</span>"
|
||||
chosen_attack_num = 3
|
||||
|
||||
/datum/action/innate/megafauna_attack/alternating_cardinals
|
||||
name = "Alternating Shots"
|
||||
icon_icon = 'icons/obj/guns/projectile.dmi'
|
||||
button_icon_state = "pistol"
|
||||
chosen_message = "<span class='colossus'>You are now firing in alternating cardinal directions.</span>"
|
||||
chosen_attack_num = 4
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/OpenFire()
|
||||
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
|
||||
ranged_cooldown = world.time + 120
|
||||
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(1)
|
||||
select_spiral_attack()
|
||||
if(2)
|
||||
random_shots()
|
||||
if(3)
|
||||
blast()
|
||||
if(4)
|
||||
alternating_dir_shots()
|
||||
return
|
||||
|
||||
if(enrage(target))
|
||||
if(move_to_delay == initial(move_to_delay))
|
||||
visible_message("<span class='colossus'>\"<b>You can't dodge.</b>\"</span>")
|
||||
@@ -72,26 +110,111 @@ Difficulty: Very Hard
|
||||
move_to_delay = initial(move_to_delay)
|
||||
|
||||
if(prob(20+anger_modifier)) //Major attack
|
||||
telegraph()
|
||||
|
||||
if(health < maxHealth/3)
|
||||
double_spiral()
|
||||
else
|
||||
visible_message("<span class='colossus'>\"<b>Judgement.</b>\"</span>")
|
||||
spawn(0)
|
||||
spiral_shoot(rand(0, 1))
|
||||
|
||||
select_spiral_attack()
|
||||
else if(prob(20))
|
||||
ranged_cooldown = world.time + 30
|
||||
random_shots()
|
||||
else
|
||||
if(prob(70))
|
||||
ranged_cooldown = world.time + 20
|
||||
blast()
|
||||
else
|
||||
ranged_cooldown = world.time + 40
|
||||
spawn(0)
|
||||
alternating_dir_shots()
|
||||
alternating_dir_shots()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.martial_art && prob(H.martial_art.deflection_chance))
|
||||
. = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
|
||||
ranged_cooldown = world.time + 40
|
||||
dir_shots(diagonals)
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
dir_shots(cardinal)
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
dir_shots(diagonals)
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
dir_shots(cardinal)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/select_spiral_attack()
|
||||
telegraph()
|
||||
if(health < maxHealth/3)
|
||||
return double_spiral()
|
||||
visible_message("<span class='colossus'>\"<b>Judgement.</b>\"</span>")
|
||||
return spiral_shoot()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/double_spiral()
|
||||
visible_message("<span class='colossus'>\"<b>Die.</b>\"</span>")
|
||||
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
INVOKE_ASYNC(src, .proc/spiral_shoot, FALSE)
|
||||
INVOKE_ASYNC(src, .proc/spiral_shoot, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/spiral_shoot(negative = pick(TRUE, FALSE), counter_start = 8)
|
||||
var/turf/start_turf = get_step(src, pick(alldirs))
|
||||
var/counter = counter_start
|
||||
for(var/i in 1 to 80)
|
||||
if(negative)
|
||||
counter--
|
||||
else
|
||||
counter++
|
||||
if(counter > 16)
|
||||
counter = 1
|
||||
if(counter < 1)
|
||||
counter = 16
|
||||
shoot_projectile(start_turf, counter * 22.5)
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
SLEEP_CHECK_DEATH(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker, set_angle)
|
||||
if(!isnum(set_angle) && (!marker || marker == loc))
|
||||
return
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
|
||||
P.preparePixelProjectile(marker, marker, startloc)
|
||||
P.firer = src
|
||||
if(target)
|
||||
P.original = target
|
||||
P.fire(set_angle)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/random_shots()
|
||||
ranged_cooldown = world.time + 30
|
||||
var/turf/U = get_turf(src)
|
||||
playsound(U, 'sound/magic/clockwork/invoke_general.ogg', 300, TRUE, 5)
|
||||
for(var/T in RANGE_TURFS(12, U) - U)
|
||||
if(prob(5))
|
||||
shoot_projectile(T)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/blast(set_angle)
|
||||
ranged_cooldown = world.time + 20
|
||||
var/turf/target_turf = get_turf(target)
|
||||
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 2)
|
||||
newtonian_move(get_dir(target_turf, src))
|
||||
var/angle_to_target = Get_Angle(src, target_turf)
|
||||
if(isnum(set_angle))
|
||||
angle_to_target = set_angle
|
||||
var/static/list/colossus_shotgun_shot_angles = list(12.5, 7.5, 2.5, -2.5, -7.5, -12.5)
|
||||
for(var/i in colossus_shotgun_shot_angles)
|
||||
shoot_projectile(target_turf, angle_to_target + i)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs)
|
||||
if(!islist(dirs))
|
||||
dirs = alldirs.Copy()
|
||||
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 2)
|
||||
for(var/d in dirs)
|
||||
var/turf/E = get_step(src, d)
|
||||
shoot_projectile(E)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/telegraph()
|
||||
for(var/mob/M in range(10,src))
|
||||
if(M.client)
|
||||
flash_color(M.client, "#C80000", 1)
|
||||
shake_camera(M, 4, 3)
|
||||
playsound(src, 'sound/magic/narsie_attack.ogg', 200, TRUE)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/devour(mob/living/L)
|
||||
visible_message("<span class='colossus'>[src] disintegrates [L]!</span>")
|
||||
L.dust()
|
||||
|
||||
/obj/effect/temp_visual/at_shield
|
||||
name = "anti-toolbox field"
|
||||
@@ -99,15 +222,14 @@ Difficulty: Very Hard
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "at_shield2"
|
||||
layer = FLY_LAYER
|
||||
luminosity = 2
|
||||
light_range = 2
|
||||
duration = 8
|
||||
var/target
|
||||
|
||||
/obj/effect/temp_visual/at_shield/New(new_loc, new_target)
|
||||
..()
|
||||
/obj/effect/temp_visual/at_shield/Initialize(mapload, new_target)
|
||||
. = ..()
|
||||
target = new_target
|
||||
spawn(0)
|
||||
orbit(target, 0, FALSE, 0, 0, FALSE, TRUE)
|
||||
INVOKE_ASYNC(src, /atom/movable/proc/orbit, target, 0, FALSE, 0, 0, FALSE, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/bullet_act(obj/item/projectile/P)
|
||||
if(!stat)
|
||||
@@ -117,126 +239,7 @@ Difficulty: Very Hard
|
||||
|
||||
var/random_y = rand(0, 72)
|
||||
AT.pixel_y += random_y
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.martial_art && prob(H.martial_art.deflection_chance))
|
||||
. = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
|
||||
dir_shots(diagonals)
|
||||
sleep(10)
|
||||
dir_shots(cardinal)
|
||||
sleep(10)
|
||||
dir_shots(diagonals)
|
||||
sleep(10)
|
||||
dir_shots(cardinal)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/double_spiral()
|
||||
visible_message("<span class='colossus'>\"<b>Die.</b>\"</span>")
|
||||
|
||||
sleep(10)
|
||||
spawn(0)
|
||||
spiral_shoot()
|
||||
spawn(0)
|
||||
spiral_shoot(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/spiral_shoot(negative = 0, counter_start = 1)
|
||||
var/counter = counter_start
|
||||
var/turf/marker
|
||||
for(var/i in 1 to 80)
|
||||
switch(counter)
|
||||
if(1)
|
||||
marker = locate(x, y - 2, z)
|
||||
if(2)
|
||||
marker = locate(x - 1, y - 2, z)
|
||||
if(3)
|
||||
marker = locate(x - 2, y - 2, z)
|
||||
if(4)
|
||||
marker = locate(x - 2, y - 1, z)
|
||||
if(5)
|
||||
marker = locate(x - 2, y, z)
|
||||
if(6)
|
||||
marker = locate(x - 2, y + 1, z)
|
||||
if(7)
|
||||
marker = locate(x - 2, y + 2, z)
|
||||
if(8)
|
||||
marker = locate(x - 1, y + 2, z)
|
||||
if(9)
|
||||
marker = locate(x, y + 2, z)
|
||||
if(10)
|
||||
marker = locate(x + 1, y + 2, z)
|
||||
if(11)
|
||||
marker = locate(x + 2, y + 2, z)
|
||||
if(12)
|
||||
marker = locate(x + 2, y + 1, z)
|
||||
if(13)
|
||||
marker = locate(x + 2, y, z)
|
||||
if(14)
|
||||
marker = locate(x + 2, y - 1, z)
|
||||
if(15)
|
||||
marker = locate(x + 2, y - 2, z)
|
||||
if(16)
|
||||
marker = locate(x + 1, y - 2, z)
|
||||
|
||||
if(negative)
|
||||
counter--
|
||||
else
|
||||
counter++
|
||||
if(counter > 16)
|
||||
counter = 1
|
||||
if(counter < 1)
|
||||
counter = 16
|
||||
shoot_projectile(marker)
|
||||
playsound(get_turf(src), 'sound/magic/invoke_general.ogg', 20, 1)
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker)
|
||||
if(!marker || marker == loc)
|
||||
return
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
|
||||
P.current = startloc
|
||||
P.starting = startloc
|
||||
P.firer = src
|
||||
P.yo = marker.y - startloc.y
|
||||
P.xo = marker.x - startloc.x
|
||||
if(target)
|
||||
P.original = target
|
||||
else
|
||||
P.original = marker
|
||||
P.fire()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/random_shots()
|
||||
var/turf/U = get_turf(src)
|
||||
playsound(U, 'sound/magic/invoke_general.ogg', 300, 1, 5)
|
||||
for(var/T in RANGE_TURFS(12, U) - U)
|
||||
if(prob(5))
|
||||
shoot_projectile(T)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/blast()
|
||||
playsound(get_turf(src), 'sound/magic/invoke_general.ogg', 200, 1, 2)
|
||||
var/turf/T = get_turf(target)
|
||||
newtonian_move(get_dir(T, targets_from))
|
||||
for(var/turf/turf in range(1, T))
|
||||
shoot_projectile(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs)
|
||||
if(!islist(dirs))
|
||||
dirs = alldirs.Copy()
|
||||
playsound(get_turf(src), 'sound/magic/invoke_general.ogg', 200, 1, 2)
|
||||
for(var/d in dirs)
|
||||
var/turf/E = get_step(src, d)
|
||||
shoot_projectile(E)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/telegraph()
|
||||
for(var/mob/M in range(10,src))
|
||||
if(M.client)
|
||||
flash_color(M.client, rgb(200, 0, 0), 1)
|
||||
shake_camera(M, 4, 3)
|
||||
playsound(get_turf(src),'sound/magic/narsie_attack.ogg', 200, 1)
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/colossus
|
||||
name ="death bolt"
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#define DRAKE_SWOOP_HEIGHT 270 //how high up drakes go, in pixels
|
||||
#define DRAKE_SWOOP_DIRECTION_CHANGE_RANGE 5 //the range our x has to be within to not change the direction we slam from
|
||||
|
||||
#define SWOOP_DAMAGEABLE 1
|
||||
#define SWOOP_INVULNERABLE 2
|
||||
|
||||
/*
|
||||
|
||||
ASH DRAKE
|
||||
@@ -6,10 +12,11 @@ Ash drakes spawn randomly wherever a lavaland creature is able to spawn. They ar
|
||||
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
|
||||
|
||||
Whenever possible, the drake will breathe fire in the four cardinal directions, igniting and heavily damaging anything caught in the blast.
|
||||
It also often causes fire to rain from the sky - many nearby turfs will flash red as a fireball crashes into them, dealing damage to anything on the turfs.
|
||||
The drake also utilizes its wings to fly into the sky and crash down onto a specified point. Anything on this point takes tremendous damage.
|
||||
Whenever possible, the drake will breathe fire directly at it's target, igniting and heavily damaging anything caught in the blast.
|
||||
It also often causes lava to pool from the ground around you - many nearby turfs will temporarily turn into lava, dealing damage to anything on the turfs.
|
||||
The drake also utilizes its wings to fly into the sky, flying after its target and attempting to slam down on them. Anything near when it slams down takes huge damage.
|
||||
- Sometimes it will chain these swooping attacks over and over, making swiftness a necessity.
|
||||
- Sometimes, it will encase its target in an arena of lava
|
||||
|
||||
When an ash drake dies, it leaves behind a chest that can contain four things:
|
||||
1. A spectral blade that allows its wielder to call ghosts to it, enhancing its power
|
||||
@@ -39,31 +46,358 @@ Difficulty: Medium
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 40
|
||||
melee_damage_upper = 40
|
||||
speed = 1
|
||||
move_to_delay = 10
|
||||
ranged = 1
|
||||
speed = 5
|
||||
move_to_delay = 5
|
||||
ranged = TRUE
|
||||
pixel_x = -16
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/dragon)
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
|
||||
var/swooping = 0
|
||||
var/swoop_cooldown = 0
|
||||
var/swooping = NONE
|
||||
var/player_cooldown = 0
|
||||
internal_type = /obj/item/gps/internal/dragon
|
||||
medal_type = BOSS_MEDAL_DRAKE
|
||||
score_type = DRAKE_SCORE
|
||||
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
|
||||
death_sound = 'sound/misc/demon_dies.ogg'
|
||||
attack_action_types = list(/datum/action/innate/megafauna_attack/fire_cone,
|
||||
/datum/action/innate/megafauna_attack/fire_cone_meteors,
|
||||
/datum/action/innate/megafauna_attack/mass_fire,
|
||||
/datum/action/innate/megafauna_attack/lava_swoop)
|
||||
|
||||
/datum/action/innate/megafauna_attack/fire_cone
|
||||
name = "Fire Cone"
|
||||
icon_icon = 'icons/obj/wizard.dmi'
|
||||
button_icon_state = "fireball"
|
||||
chosen_message = "<span class='colossus'>You are now shooting fire at your target.</span>"
|
||||
chosen_attack_num = 1
|
||||
|
||||
/datum/action/innate/megafauna_attack/fire_cone_meteors
|
||||
name = "Fire Cone With Meteors"
|
||||
icon_icon = 'icons/mob/actions/actions.dmi'
|
||||
button_icon_state = "sniper_zoom"
|
||||
chosen_message = "<span class='colossus'>You are now shooting fire at your target and raining fire around you.</span>"
|
||||
chosen_attack_num = 2
|
||||
|
||||
/datum/action/innate/megafauna_attack/mass_fire
|
||||
name = "Mass Fire Attack"
|
||||
icon_icon = 'icons/effects/fire.dmi'
|
||||
button_icon_state = "1"
|
||||
chosen_message = "<span class='colossus'>You are now shooting mass fire at your target.</span>"
|
||||
chosen_attack_num = 3
|
||||
|
||||
/datum/action/innate/megafauna_attack/lava_swoop
|
||||
name = "Lava Swoop"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "lavastaff_warn"
|
||||
chosen_message = "<span class='colossus'>You are now swooping and raining lava at your target.</span>"
|
||||
chosen_attack_num = 4
|
||||
|
||||
/obj/item/gps/internal/dragon
|
||||
icon_state = null
|
||||
gpstag = "Fiery Signal"
|
||||
desc = "Here there be dragons."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
|
||||
if(swooping)
|
||||
return
|
||||
|
||||
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(1)
|
||||
fire_cone(meteors = FALSE)
|
||||
if(2)
|
||||
fire_cone()
|
||||
if(3)
|
||||
mass_fire()
|
||||
if(4)
|
||||
lava_swoop()
|
||||
return
|
||||
|
||||
if(prob(15 + anger_modifier))
|
||||
lava_swoop()
|
||||
|
||||
else if(prob(10+anger_modifier))
|
||||
shoot_fire_attack()
|
||||
else
|
||||
fire_cone()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/shoot_fire_attack()
|
||||
if(health < maxHealth*0.5)
|
||||
mass_fire()
|
||||
else
|
||||
fire_cone()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_rain()
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>Fire rains from the sky!</span>")
|
||||
for(var/turf/turf in range(9,get_turf(target)))
|
||||
if(prob(11))
|
||||
new /obj/effect/temp_visual/target(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_pools(var/amount, var/delay = 0.8)
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>Lava starts to pool up around you!</span>")
|
||||
while(amount > 0)
|
||||
if(QDELETED(target))
|
||||
break
|
||||
var/turf/T = pick(RANGE_TURFS(1, target))
|
||||
new /obj/effect/temp_visual/lava_warning(T, 60) // longer reset time for the lava
|
||||
amount--
|
||||
SLEEP_CHECK_DEATH(delay)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_swoop(var/amount = 30)
|
||||
if(health < maxHealth * 0.5)
|
||||
return swoop_attack(lava_arena = TRUE, swoop_cooldown = 60)
|
||||
INVOKE_ASYNC(src, .proc/lava_pools, amount)
|
||||
swoop_attack(FALSE, target, 1000) // longer cooldown until it gets reset below
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
fire_cone()
|
||||
if(health < maxHealth*0.5)
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
fire_cone()
|
||||
SLEEP_CHECK_DEATH(10)
|
||||
fire_cone()
|
||||
SetRecoveryTime(40)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/mass_fire(var/spiral_count = 12, var/range = 15, var/times = 3)
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
for(var/i = 1 to times)
|
||||
SetRecoveryTime(50)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
var/increment = 360 / spiral_count
|
||||
for(var/j = 1 to spiral_count)
|
||||
var/list/turfs = line_target(j * increment + i * increment / 2, range, src)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
SLEEP_CHECK_DEATH(25)
|
||||
SetRecoveryTime(30)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_arena()
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>[src] encases you in an arena of fire!</span>")
|
||||
var/amount = 3
|
||||
var/turf/center = get_turf(target)
|
||||
var/list/walled = RANGE_TURFS(3, center) - RANGE_TURFS(2, center)
|
||||
var/list/drakewalls = list()
|
||||
for(var/turf/T in walled)
|
||||
drakewalls += new /obj/effect/temp_visual/drakewall(T) // no people with lava immunity can just run away from the attack for free
|
||||
var/list/indestructible_turfs = list()
|
||||
for(var/turf/T in RANGE_TURFS(2, center))
|
||||
if(istype(T, /turf/simulated/floor/indestructible))
|
||||
continue
|
||||
if(!istype(T, /turf/simulated/wall/indestructible))
|
||||
T.ChangeTurf(/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface)
|
||||
else
|
||||
indestructible_turfs += T
|
||||
SLEEP_CHECK_DEATH(10) // give them a bit of time to realize what attack is actually happening
|
||||
|
||||
var/list/turfs = RANGE_TURFS(2, center)
|
||||
while(amount > 0)
|
||||
var/list/empty = indestructible_turfs.Copy() // can't place safe turfs on turfs that weren't changed to be open
|
||||
var/any_attack = 0
|
||||
for(var/turf/T in turfs)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L.client)
|
||||
empty += pick(((RANGE_TURFS(2, L) - RANGE_TURFS(1, L)) & turfs) - empty) // picks a turf within 2 of the creature not outside or in the shield
|
||||
any_attack = 1
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
empty += pick(((RANGE_TURFS(2, M) - RANGE_TURFS(1, M)) & turfs) - empty)
|
||||
any_attack = 1
|
||||
if(!any_attack)
|
||||
for(var/obj/effect/temp_visual/drakewall/D in drakewalls)
|
||||
qdel(D)
|
||||
return 0 // nothing to attack in the arena time for enraged attack if we still have a target
|
||||
for(var/turf/T in turfs)
|
||||
if(!(T in empty))
|
||||
new /obj/effect/temp_visual/lava_warning(T)
|
||||
else if(!istype(T, /turf/simulated/wall/indestructible))
|
||||
new /obj/effect/temp_visual/lava_safe(T)
|
||||
amount--
|
||||
SLEEP_CHECK_DEATH(24)
|
||||
return 1 // attack finished completely
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/arena_escape_enrage() // you ran somehow / teleported away from my arena attack now i'm mad fucker
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
SetRecoveryTime(80)
|
||||
visible_message("<span class='boldwarning'>[src] starts to glow vibrantly as its wounds close up!</span>")
|
||||
adjustBruteLoss(-250) // yeah you're gonna pay for that, don't run nerd
|
||||
add_atom_colour(rgb(255, 255, 0), TEMPORARY_COLOUR_PRIORITY)
|
||||
move_to_delay = move_to_delay / 2
|
||||
light_range = 10
|
||||
SLEEP_CHECK_DEATH(10) // run.
|
||||
mass_fire(20, 15, 3)
|
||||
move_to_delay = initial(move_to_delay)
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
|
||||
light_range = initial(light_range)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_cone(var/atom/at = target, var/meteors = TRUE)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
if(prob(50) && meteors)
|
||||
INVOKE_ASYNC(src, .proc/fire_rain)
|
||||
var/range = 15
|
||||
var/list/turfs = list()
|
||||
turfs = line_target(-40, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
turfs = line_target(0, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
turfs = line_target(40, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/line_target(var/offset, var/range, var/atom/at = target)
|
||||
if(!at)
|
||||
return
|
||||
var/angle = Atan2(at.x - src.x, at.y - src.y) + offset
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i in 1 to range)
|
||||
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
|
||||
if(!check)
|
||||
break
|
||||
T = check
|
||||
return (getline(src, T) - get_turf(src))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_line(var/list/turfs)
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
dragon_fire_line(src, turfs)
|
||||
|
||||
//fire line keeps going even if dragon is deleted
|
||||
/proc/dragon_fire_line(var/source, var/list/turfs)
|
||||
var/list/hit_list = list()
|
||||
for(var/turf/T in turfs)
|
||||
if(T.density)
|
||||
break
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L in hit_list || L == source)
|
||||
continue
|
||||
hit_list += L
|
||||
L.adjustFireLoss(20)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by [source]'s fire breath!</span>")
|
||||
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
if(M in hit_list)
|
||||
continue
|
||||
hit_list += M
|
||||
M.take_damage(45, BRUTE, "melee", 1)
|
||||
sleep(1.5)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/swoop_attack(lava_arena = FALSE, atom/movable/manual_target, var/swoop_cooldown = 30)
|
||||
if(stat || swooping)
|
||||
return
|
||||
if(manual_target)
|
||||
target = manual_target
|
||||
if(!target)
|
||||
return
|
||||
stop_automated_movement = TRUE
|
||||
swooping |= SWOOP_DAMAGEABLE
|
||||
density = FALSE
|
||||
icon_state = "shadow"
|
||||
visible_message("<span class='boldwarning'>[src] swoops up high!</span>")
|
||||
|
||||
var/negative
|
||||
var/initial_x = x
|
||||
if(target.x < initial_x) //if the target's x is lower than ours, swoop to the left
|
||||
negative = TRUE
|
||||
else if(target.x > initial_x)
|
||||
negative = FALSE
|
||||
else if(target.x == initial_x) //if their x is the same, pick a direction
|
||||
negative = prob(50)
|
||||
var/obj/effect/temp_visual/dragon_flight/F = new /obj/effect/temp_visual/dragon_flight(loc, negative)
|
||||
|
||||
negative = !negative //invert it for the swoop down later
|
||||
|
||||
var/oldtransform = transform
|
||||
alpha = 255
|
||||
animate(src, alpha = 204, transform = matrix()*0.9, time = 3, easing = BOUNCE_EASING)
|
||||
for(var/i in 1 to 3)
|
||||
sleep(1)
|
||||
if(QDELETED(src) || stat == DEAD) //we got hit and died, rip us
|
||||
qdel(F)
|
||||
if(stat == DEAD)
|
||||
swooping &= ~SWOOP_DAMAGEABLE
|
||||
animate(src, alpha = 255, transform = oldtransform, time = 0, flags = ANIMATION_END_NOW) //reset immediately
|
||||
return
|
||||
animate(src, alpha = 100, transform = matrix()*0.7, time = 7)
|
||||
swooping |= SWOOP_INVULNERABLE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
SLEEP_CHECK_DEATH(7)
|
||||
|
||||
while(target && loc != get_turf(target))
|
||||
forceMove(get_step(src, get_dir(src, target)))
|
||||
SLEEP_CHECK_DEATH(0.5)
|
||||
|
||||
// Ash drake flies onto its target and rains fire down upon them
|
||||
var/descentTime = 10
|
||||
var/lava_success = TRUE
|
||||
if(lava_arena)
|
||||
lava_success = lava_arena()
|
||||
|
||||
|
||||
//ensure swoop direction continuity.
|
||||
if(negative)
|
||||
if(IsInRange(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
|
||||
negative = FALSE
|
||||
else
|
||||
if(IsInRange(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
|
||||
negative = TRUE
|
||||
new /obj/effect/temp_visual/dragon_flight/end(loc, negative)
|
||||
new /obj/effect/temp_visual/dragon_swoop(loc)
|
||||
animate(src, alpha = 255, transform = oldtransform, descentTime)
|
||||
SLEEP_CHECK_DEATH(descentTime)
|
||||
swooping &= ~SWOOP_INVULNERABLE
|
||||
mouse_opacity = initial(mouse_opacity)
|
||||
icon_state = "dragon"
|
||||
playsound(loc, 'sound/effects/meteorimpact.ogg', 200, TRUE)
|
||||
for(var/mob/living/L in orange(1, src))
|
||||
if(L.stat)
|
||||
visible_message("<span class='warning'>[src] slams down on [L], crushing [L.p_them()]!</span>")
|
||||
L.gib()
|
||||
else
|
||||
L.adjustBruteLoss(75)
|
||||
if(L && !QDELETED(L)) // Some mobs are deleted on death
|
||||
var/throw_dir = get_dir(src, L)
|
||||
if(L.loc == loc)
|
||||
throw_dir = pick(alldirs)
|
||||
var/throwtarget = get_edge_target_turf(src, throw_dir)
|
||||
L.throw_at(throwtarget, 3)
|
||||
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
|
||||
for(var/obj/mecha/M in orange(1, src))
|
||||
M.take_damage(75, BRUTE, "melee", 1)
|
||||
|
||||
for(var/mob/M in range(7, src))
|
||||
shake_camera(M, 15, 1)
|
||||
|
||||
density = TRUE
|
||||
SLEEP_CHECK_DEATH(1)
|
||||
swooping &= ~SWOOP_DAMAGEABLE
|
||||
SetRecoveryTime(swoop_cooldown)
|
||||
if(!lava_success)
|
||||
arena_escape_enrage()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/ex_act(severity, target)
|
||||
if(severity == 3)
|
||||
if(severity == EXPLODE_LIGHT)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount, updating_health = TRUE)
|
||||
if(swooping)
|
||||
if(swooping & SWOOP_INVULNERABLE)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/visible_message()
|
||||
if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/AttackingTarget()
|
||||
if(!swooping)
|
||||
return ..()
|
||||
@@ -83,181 +417,161 @@ Difficulty: Medium
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
/obj/effect/temp_visual/fireball
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "fireball"
|
||||
name = "fireball"
|
||||
desc = "Get out of the way!"
|
||||
layer = 6
|
||||
randomdir = 0
|
||||
duration = 12
|
||||
pixel_z = 500
|
||||
/obj/effect/temp_visual/lava_warning
|
||||
icon_state = "lavastaff_warn"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/fireball/New(loc)
|
||||
..()
|
||||
animate(src, pixel_z = 0, time = 12)
|
||||
/obj/effect/temp_visual/lava_warning/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/target
|
||||
icon = 'icons/mob/actions/actions.dmi'
|
||||
icon_state = "sniper_zoom"
|
||||
layer = MOB_LAYER - 0.1
|
||||
luminosity = 2
|
||||
duration = 12
|
||||
/obj/effect/temp_visual/lava_warning/Initialize(mapload, var/reset_time = 10)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/fall, reset_time)
|
||||
src.alpha = 63.75
|
||||
animate(src, alpha = 255, time = duration)
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/proc/fall(var/reset_time)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
sleep(duration)
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
|
||||
continue
|
||||
L.adjustFireLoss(10)
|
||||
to_chat(L, "<span class='userdanger'>You fall directly into the pool of lava!</span>")
|
||||
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
M.take_damage(45, BRUTE, "melee", 1)
|
||||
|
||||
// changes turf to lava temporarily
|
||||
if(!T.density && !istype(T, /turf/simulated/floor/plating/lava))
|
||||
var/lava_turf = /turf/simulated/floor/plating/lava/smooth
|
||||
var/reset_turf = T.type
|
||||
T.ChangeTurf(lava_turf)
|
||||
sleep(reset_time)
|
||||
T.ChangeTurf(reset_turf)
|
||||
|
||||
/obj/effect/temp_visual/drakewall
|
||||
desc = "An ash drakes true flame."
|
||||
name = "Fire Barrier"
|
||||
icon = 'icons/effects/fire.dmi'
|
||||
icon_state = "1"
|
||||
anchored = TRUE
|
||||
opacity = 0
|
||||
density = TRUE
|
||||
duration = 82
|
||||
color = COLOR_DARK_ORANGE
|
||||
|
||||
/obj/effect/temp_visual/drakewall/CanAtmosPass()
|
||||
return !density
|
||||
|
||||
/obj/effect/temp_visual/lava_safe
|
||||
icon = 'icons/obj/hand_of_god_structures.dmi'
|
||||
icon_state = "trap-earth"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop
|
||||
name = "certain death"
|
||||
desc = "Don't just stand there, move!"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "landing"
|
||||
layer = MOB_LAYER - 0.1
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
color = "#FF0000"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight
|
||||
icon = 'icons/mob/lavaland/64x64megafauna.dmi'
|
||||
icon_state = "dragon"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
pixel_x = -16
|
||||
duration = 10
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/Initialize(mapload, negative)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/flight, negative)
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/proc/flight(negative)
|
||||
if(negative)
|
||||
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
|
||||
else
|
||||
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
|
||||
sleep(3)
|
||||
icon_state = "swoop"
|
||||
if(negative)
|
||||
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT, pixel_z = DRAKE_SWOOP_HEIGHT, time = 7)
|
||||
else
|
||||
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT, pixel_z = DRAKE_SWOOP_HEIGHT, time = 7)
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/end
|
||||
pixel_x = DRAKE_SWOOP_HEIGHT
|
||||
pixel_z = DRAKE_SWOOP_HEIGHT
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/end/flight(negative)
|
||||
if(negative)
|
||||
pixel_x = -DRAKE_SWOOP_HEIGHT
|
||||
animate(src, pixel_x = -16, pixel_z = 0, time = 5)
|
||||
else
|
||||
animate(src, pixel_x = -16, pixel_z = 0, time = 5)
|
||||
|
||||
obj/effect/temp_visual/fireball
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "fireball"
|
||||
name = "fireball"
|
||||
desc = "Get out of the way!"
|
||||
layer = FLY_LAYER
|
||||
randomdir = FALSE
|
||||
duration = 9
|
||||
pixel_z = 270
|
||||
|
||||
/obj/effect/temp_visual/fireball/Initialize()
|
||||
. = ..()
|
||||
animate(src, pixel_z = 0, time = duration)
|
||||
|
||||
/obj/effect/temp_visual/target
|
||||
icon = 'icons/mob/actions/actions.dmi'
|
||||
icon_state = "sniper_zoom"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 9
|
||||
|
||||
/obj/effect/temp_visual/target/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/target/New(loc)
|
||||
..()
|
||||
spawn(0)
|
||||
fall()
|
||||
/obj/effect/temp_visual/target/Initialize(mapload, list/flame_hit)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/fall, flame_hit)
|
||||
|
||||
/obj/effect/temp_visual/target/proc/fall()
|
||||
/obj/effect/temp_visual/target/proc/fall(list/flame_hit)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, 1)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
new /obj/effect/temp_visual/fireball(T)
|
||||
sleep(12)
|
||||
explosion(T, 0, 0, 1, 0, 0, 0, 1, 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
|
||||
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
if(swooping)
|
||||
fire_rain()
|
||||
return
|
||||
|
||||
if(prob(15 + anger_modifier) && !client)
|
||||
if(health < maxHealth/2)
|
||||
spawn(0)
|
||||
swoop_attack(1)
|
||||
else
|
||||
fire_rain()
|
||||
|
||||
else if(prob(10+anger_modifier) && !client)
|
||||
if(health > maxHealth/2)
|
||||
spawn(0)
|
||||
swoop_attack(0)
|
||||
else
|
||||
spawn(0)
|
||||
triple_swoop(0)
|
||||
else
|
||||
fire_walls()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_rain()
|
||||
visible_message("<span class='boldwarning'>Fire rains from the sky!</span>")
|
||||
for(var/turf/turf in range(12,get_turf(src)))
|
||||
if(prob(10))
|
||||
new /obj/effect/temp_visual/target(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_walls()
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, 1)
|
||||
|
||||
for(var/d in cardinal)
|
||||
spawn(0)
|
||||
fire_wall(d)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(dir)
|
||||
var/list/hit_things = list(src)
|
||||
var/turf/E = get_edge_target_turf(src, dir)
|
||||
var/range = 10
|
||||
var/turf/previousturf = get_turf(src)
|
||||
for(var/turf/J in getline(src,E))
|
||||
if(!range || !previousturf.CanAtmosPass(J))
|
||||
break
|
||||
range--
|
||||
new /obj/effect/hotspot(J)
|
||||
J.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/L in J.contents - hit_things)
|
||||
L.adjustFireLoss(20)
|
||||
sleep(duration)
|
||||
if(ismineralturf(T))
|
||||
var/turf/simulated/mineral/M = T
|
||||
M.gets_drilled()
|
||||
playsound(T, "explosion", 80, TRUE)
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700, 50, 1)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
|
||||
continue
|
||||
if(islist(flame_hit) && !flame_hit[L])
|
||||
L.adjustFireLoss(40)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by the drake's fire breath!</span>")
|
||||
hit_things += L
|
||||
previousturf = J
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/triple_swoop()
|
||||
swoop_attack()
|
||||
swoop_attack()
|
||||
swoop_attack()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/swoop_attack(fire_rain = 0, atom/movable/manual_target)
|
||||
if(stat || swooping)
|
||||
return
|
||||
swoop_cooldown = world.time + 200
|
||||
var/atom/swoop_target
|
||||
if(manual_target)
|
||||
swoop_target = manual_target
|
||||
else
|
||||
swoop_target = target
|
||||
stop_automated_movement = TRUE
|
||||
swooping = 1
|
||||
density = 0
|
||||
icon_state = "swoop"
|
||||
visible_message("<span class='boldwarning'>[src] swoops up high!</span>")
|
||||
if(prob(50))
|
||||
animate(src, pixel_x = 500, pixel_z = 500, time = 10)
|
||||
else
|
||||
animate(src, pixel_x = -500, pixel_z = 500, time = 10)
|
||||
sleep(30)
|
||||
|
||||
var/turf/tturf
|
||||
if(fire_rain)
|
||||
fire_rain()
|
||||
|
||||
icon_state = "dragon"
|
||||
if(swoop_target && !QDELETED(swoop_target) && swoop_target.z == src.z)
|
||||
tturf = get_turf(swoop_target)
|
||||
else
|
||||
tturf = get_turf(src)
|
||||
forceMove(tturf)
|
||||
new /obj/effect/temp_visual/dragon_swoop(tturf)
|
||||
animate(src, pixel_x = initial(pixel_x), pixel_z = 0, time = 10)
|
||||
sleep(10)
|
||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1)
|
||||
for(var/mob/living/L in orange(1, src))
|
||||
if(L.stat)
|
||||
visible_message("<span class='warning'>[src] slams down on [L], crushing [L.p_them()]!</span>")
|
||||
L.gib()
|
||||
flame_hit[L] = TRUE
|
||||
else
|
||||
L.adjustBruteLoss(75)
|
||||
if(L && !QDELETED(L)) // Some mobs are deleted on death
|
||||
var/throw_dir = get_dir(src, L)
|
||||
if(L.loc == loc)
|
||||
throw_dir = pick(alldirs)
|
||||
var/throwtarget = get_edge_target_turf(src, throw_dir)
|
||||
L.throw_at(throwtarget, 3)
|
||||
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
|
||||
|
||||
for(var/mob/M in range(7, src))
|
||||
shake_camera(M, 15, 1)
|
||||
|
||||
stop_automated_movement = FALSE
|
||||
swooping = 0
|
||||
density = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/AltClickOn(atom/movable/A)
|
||||
if(!istype(A))
|
||||
return
|
||||
if(swoop_cooldown >= world.time)
|
||||
to_chat(src, "<span class='warning'>You need to wait 20 seconds between swoop attacks!</span>")
|
||||
return
|
||||
swoop_attack(1, A)
|
||||
|
||||
/obj/item/gps/internal/dragon
|
||||
icon_state = null
|
||||
gpstag = "Fiery Signal"
|
||||
desc = "Here there be dragons."
|
||||
invisibility = 100
|
||||
L.adjustFireLoss(10) //if we've already hit them, do way less damage
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser
|
||||
name = "lesser ash drake"
|
||||
@@ -267,9 +581,92 @@ Difficulty: Medium
|
||||
obj_damage = 80
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 30
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
|
||||
loot = list()
|
||||
crusher_loot = list()
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
|
||||
attack_action_types = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/AltClickOn(atom/movable/A)
|
||||
if(!istype(A))
|
||||
return
|
||||
if(player_cooldown >= world.time)
|
||||
to_chat(src, "<span class='warning'>You need to wait [(player_cooldown - world.time) / 10] seconds before swooping again!</span>")
|
||||
return
|
||||
swoop_attack(FALSE, A)
|
||||
lava_pools(10, 2) // less pools but longer delay before spawns
|
||||
player_cooldown = world.time + 200 // needs seperate cooldown or cant use fire attacks
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon
|
||||
name = "space dragon"
|
||||
maxHealth = 250
|
||||
health = 250
|
||||
faction = list("neutral")
|
||||
desc = "A space carp turned dragon by vile magic. Has the same ferocity of a space carp, but also a much more enabling body."
|
||||
icon = 'icons/mob/spacedragon.dmi'
|
||||
icon_state = "spacedragon"
|
||||
icon_living = "spacedragon"
|
||||
icon_dead = "spacedragon_dead"
|
||||
obj_damage = 80
|
||||
melee_damage_upper = 35
|
||||
melee_damage_lower = 35
|
||||
speed = 0
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
loot = list()
|
||||
crusher_loot = list()
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
|
||||
move_force = MOVE_FORCE_NORMAL
|
||||
move_resist = MOVE_FORCE_NORMAL
|
||||
pull_force = MOVE_FORCE_NORMAL
|
||||
deathmessage = "screeches as its wings turn to dust and it collapses on the floor, life estinguished."
|
||||
attack_action_types = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/grant_achievement(medaltype, scoretype)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/Initialize(mapload)
|
||||
var/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon/repulse_action = new /obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon(src)
|
||||
repulse_action.action.Grant(src)
|
||||
mob_spell_list += repulse_action
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/proc/fire_stream(var/atom/at = target)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
SLEEP_CHECK_DEATH(0)
|
||||
var/range = 20
|
||||
var/list/turfs = list()
|
||||
turfs = line_target(0, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/OpenFire()
|
||||
if(swooping)
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
fire_stream()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon
|
||||
name = "Tail Sweep"
|
||||
desc = "Throw back attackers with a sweep of your tail."
|
||||
sound = 'sound/magic/tail_swing.ogg'
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
range = 1
|
||||
cooldown_min = 150
|
||||
invocation_type = "none"
|
||||
sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep
|
||||
action_icon_state = "tailsweep"
|
||||
action_background_icon_state = "bg_alien"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon/cast(list/targets, mob/user = usr)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
playsound(C.loc, 'sound/effects/hit_punch.ogg', 80, TRUE, TRUE)
|
||||
C.spin(6, 1)
|
||||
..(targets, user, 3)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/AltClickOn(atom/movable/A)
|
||||
return
|
||||
@@ -7,11 +7,11 @@
|
||||
sentience_type = SENTIENCE_BOSS
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
obj_damage = 400
|
||||
luminosity = 3
|
||||
light_range = 3
|
||||
faction = list("mining", "boss")
|
||||
weather_immunities = list("lava","ash")
|
||||
flying = 1
|
||||
robust_searching = 1
|
||||
flying = TRUE
|
||||
robust_searching = TRUE
|
||||
ranged_ignores_vision = TRUE
|
||||
stat_attack = DEAD
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
@@ -20,6 +20,12 @@
|
||||
maxbodytemp = INFINITY
|
||||
vision_range = 5
|
||||
aggro_vision_range = 18
|
||||
move_force = MOVE_FORCE_OVERPOWERING
|
||||
move_resist = MOVE_FORCE_OVERPOWERING
|
||||
pull_force = MOVE_FORCE_OVERPOWERING
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||
var/list/crusher_loot
|
||||
var/medal_type
|
||||
var/score_type = BOSS_SCORE
|
||||
@@ -27,13 +33,9 @@
|
||||
var/anger_modifier = 0
|
||||
var/obj/item/gps/internal_gps
|
||||
var/internal_type
|
||||
move_force = MOVE_FORCE_OVERPOWERING
|
||||
move_resist = MOVE_FORCE_OVERPOWERING
|
||||
pull_force = MOVE_FORCE_OVERPOWERING
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||
var/recovery_time = 0
|
||||
var/true_spawn = TRUE // if this is a megafauna that should grant achievements, or have a gps signal
|
||||
var/nest_range = 10
|
||||
var/chosen_attack = 1 // chosen attack num
|
||||
var/list/attack_action_types = list()
|
||||
|
||||
@@ -50,6 +52,16 @@
|
||||
QDEL_NULL(internal_gps)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/Moved()
|
||||
if(nest && nest.parent && get_dist(nest.parent, src) > nest_range)
|
||||
var/turf/closest = get_turf(nest.parent)
|
||||
for(var/i = 1 to nest_range)
|
||||
closest = get_step(closest, get_dir(closest, src))
|
||||
forceMove(closest) // someone teleported out probably and the megafauna kept chasing them
|
||||
target = null
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/can_die()
|
||||
return ..() && health <= 0
|
||||
|
||||
@@ -68,6 +80,8 @@
|
||||
loot = crusher_loot
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/AttackingTarget()
|
||||
if(recovery_time >= world.time)
|
||||
return
|
||||
. = ..()
|
||||
if(. && isliving(target))
|
||||
var/mob/living/L = target
|
||||
@@ -90,13 +104,14 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L)
|
||||
if(!L)
|
||||
return
|
||||
return FALSE
|
||||
visible_message(
|
||||
"<span class='danger'>[src] devours [L]!</span>",
|
||||
"<span class='userdanger'>You feast on [L], restoring your health!</span>")
|
||||
if(!is_station_level(z) && !client) //NPC monsters won't heal while on station
|
||||
if(!is_station_level(z) || client) //NPC monsters won't heal while on station
|
||||
adjustBruteLoss(-L.maxHealth/2)
|
||||
L.gib()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ex_act(severity, target)
|
||||
switch(severity)
|
||||
@@ -109,6 +124,10 @@
|
||||
if(3)
|
||||
adjustBruteLoss(50)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/proc/SetRecoveryTime(buffer_time)
|
||||
recovery_time = world.time + buffer_time
|
||||
ranged_cooldown = world.time + buffer_time
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill)
|
||||
if(!medal_type || admin_spawned || !SSmedals.hub_enabled) //Don't award medals if the medal type isn't set
|
||||
return FALSE
|
||||
|
||||
@@ -336,6 +336,31 @@
|
||||
M.bodytemperature = min(310, M.bodytemperature + (5 * TEMPERATURE_DAMAGE_COEFFICIENT))
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/garlic
|
||||
name = "Garlic Juice"
|
||||
id = "garlic"
|
||||
description = "Crushed garlic. Chefs love it, but it can make you smell bad."
|
||||
color = "#FEFEFE"
|
||||
taste_description = "garlic"
|
||||
metabolization_rate = 0.15 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/consumable/garlic/on_mob_life(mob/living/carbon/M)
|
||||
var/update_flags = STATUS_UPDATE_NONE
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.mind && H.mind.vampire && !H.mind.vampire.get_ability(/datum/vampire_passive/full)) //incapacitating but not lethal.
|
||||
if(prob(min(25, current_cycle)))
|
||||
to_chat(H, "<span class='danger'>You can't get the scent of garlic out of your nose! You can barely think...</span>")
|
||||
H.Weaken(1)
|
||||
H.Jitter(10)
|
||||
H.fakevomit()
|
||||
else
|
||||
if(H.job == "Chef")
|
||||
if(prob(20)) //stays in the system much longer than sprinkles/banana juice, so heals slower to partially compensate
|
||||
update_flags |= H.adjustBruteLoss(-1, FALSE)
|
||||
update_flags |= H.adjustFireLoss(-1, FALSE)
|
||||
return ..() | update_flags
|
||||
|
||||
/datum/reagent/consumable/sprinkles
|
||||
name = "Sprinkles"
|
||||
id = "sprinkles"
|
||||
@@ -941,7 +966,7 @@
|
||||
id = "entpoly"
|
||||
description = "An ichor, derived from a certain mushroom, makes for a bad time."
|
||||
color = "#1d043d"
|
||||
taste_description = "mold"
|
||||
taste_description = "bitter mushroom"
|
||||
|
||||
/datum/reagent/consumable/entpoly/on_mob_life(mob/living/M)
|
||||
var/update_flags = STATUS_UPDATE_NONE
|
||||
@@ -960,13 +985,13 @@
|
||||
id = "tinlux"
|
||||
description = "A stimulating ichor which causes luminescent fungi to grow on the skin. "
|
||||
color = "#b5a213"
|
||||
var/light_activated = 0
|
||||
taste_description = "mold"
|
||||
var/light_activated = FALSE
|
||||
taste_description = "tingling mushroom"
|
||||
|
||||
/datum/reagent/consumable/tinlux/on_mob_life(mob/living/M)
|
||||
if(!light_activated)
|
||||
M.set_light(2)
|
||||
light_activated = 1
|
||||
light_activated = TRUE
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/tinlux/on_mob_delete(mob/living/M)
|
||||
@@ -978,11 +1003,11 @@
|
||||
description = "A bubbly paste that heals wounds of the skin."
|
||||
color = "#d3a308"
|
||||
nutriment_factor = 3 * REAGENTS_METABOLISM
|
||||
taste_description = "sweetness"
|
||||
taste_description = "fruity mushroom"
|
||||
|
||||
/datum/reagent/consumable/vitfro/on_mob_life(mob/living/M)
|
||||
var/update_flags = STATUS_UPDATE_NONE
|
||||
if(prob(80))
|
||||
update_flags |= M.adjustBruteLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE)
|
||||
update_flags |= M.adjustFireLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE)
|
||||
return ..() | update_flags
|
||||
return ..() | update_flags
|
||||
@@ -82,12 +82,12 @@
|
||||
/obj/item/reagent_containers/hypospray/combat
|
||||
name = "combat stimulant injector"
|
||||
desc = "A modified air-needle autoinjector, used by support operatives to quickly heal injuries in combat."
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(10)
|
||||
amount_per_transfer_from_this = 15
|
||||
possible_transfer_amounts = list(15)
|
||||
icon_state = "combat_hypo"
|
||||
volume = 75
|
||||
volume = 90
|
||||
ignore_flags = 1 // So they can heal their comrades.
|
||||
list_reagents = list("epinephrine" = 30, "omnizine" = 30, "teporone" = 15)
|
||||
list_reagents = list("epinephrine" = 30, "weak_omnizine" = 30, "salglu_solution" = 30)
|
||||
|
||||
/obj/item/reagent_containers/hypospray/combat/nanites
|
||||
desc = "A modified air-needle autoinjector for use in combat situations. Prefilled with expensive medical nanites for rapid healing."
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
list_reagents = list("silver_sulfadiazine" = 40)
|
||||
|
||||
/obj/item/reagent_containers/food/pill/patch/synthflesh
|
||||
name = "syntheflesh patch"
|
||||
desc = "Helps with burn injuries."
|
||||
name = "synthflesh patch"
|
||||
desc = "Helps with brute and burn injuries."
|
||||
icon_state = "bandaid_med"
|
||||
instant_application = 1
|
||||
list_reagents = list("synthflesh" = 20)
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
/mob/proc/get_int_organ_tag(tag) //is it a brain, is it a brain_tumor?
|
||||
return
|
||||
|
||||
/mob/living/proc/get_organ(zone)
|
||||
return
|
||||
|
||||
/mob/living/carbon/get_int_organ(typepath)
|
||||
return (locate(typepath) in internal_organs)
|
||||
|
||||
|
||||
@@ -439,6 +439,8 @@ HIGH_POP_MC_MODE_AMOUNT 65
|
||||
##Disengage high pop mode if player count drops below this
|
||||
DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
|
||||
|
||||
##Developer options
|
||||
|
||||
##Uncomment to enable developer start. Auto starts the server after initialization
|
||||
##DEVELOPER_EXPRESS_START
|
||||
|
||||
@@ -447,3 +449,6 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
|
||||
|
||||
## Uncomment to give a confirmation before hitting start now
|
||||
#START_NOW_CONFIRMATION
|
||||
|
||||
## If uncommented, all gamemodes will respect the number of required players. Defaults to no.
|
||||
#ENABLE_GAMEMODE_PLAYER_LIMIT
|
||||
@@ -404,8 +404,8 @@ h1.alert, h2.alert {color: #FFF;}
|
||||
|
||||
/* MEGAFAUNA */
|
||||
.colossus {color: #7F282A; font-size: 175%;}
|
||||
.hierophant {color: #660099; font-weight: bold; font-size: 150%;}
|
||||
.hierophant_warning {color: #660099; font-weight: bold; font-style: italic;}
|
||||
.hierophant {color: #660099; font-weight: bold; font-style: italic;}
|
||||
.hierophant_warning {color: #660099; font-style: italic;}
|
||||
|
||||
/* EMOJI STUFF */
|
||||
.emoji {max-height: 16px; max-width: 16px}
|
||||
|
||||
@@ -401,8 +401,8 @@ h1.alert, h2.alert {color: #000000;}
|
||||
|
||||
/* MEGAFAUNA */
|
||||
.colossus {color: #7F282A; font-size: 175%;}
|
||||
.hierophant {color: #660099; font-weight: bold; font-size: 150%;}
|
||||
.hierophant_warning {color: #660099; font-weight: bold; font-style: italic;}
|
||||
.hierophant {color: #660099; font-weight: bold; font-style: italic;}
|
||||
.hierophant_warning {color: #660099; font-style: italic;}
|
||||
|
||||
/* EMOJI STUFF */
|
||||
.emoji {max-height: 16px; max-width: 16px}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "variableundefined"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Config option to let gamemode ignore the number of required players."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "variableundefined"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Contribution guideline has been updated. No in game changes."
|
||||
@@ -0,0 +1,9 @@
|
||||
author: "Fox McCloud"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Updates moonflower, sunflower, novaflower, and pineapple sprites"
|
||||
- rscadd: "Adds in Garlic"
|
||||
- bugfix: "Fixes a few issues with incorrect values from the wine PR"
|
||||
- rscadd: "Can now grow and extract the reagents/traits of Lavaland flora"
|
||||
- tweak: "Slightly tweaks soybean oil production on soybeans"
|
||||
- rscadd: "Adds amusing garlic suicide"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "variableundefined"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Github pull request template has been changed"
|
||||
@@ -0,0 +1,8 @@
|
||||
author: "Fox McCloud"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Ash Drake reworked; it's much more powerful now and has a diverse set of attacks--its fire breath is more random, it moves faster, it can turn the ground into lava, and once it's lower on health, will seal you into an arena and make you play the \"only one turf is safe; stand on it or suffer\" mini-game"
|
||||
- rscadd: "Bubblegum is now much more difficult; instead of just spraying blood at you and attempting to endlessly charge you (walking backwards essentially counters it), it's now faster, engages in zig-zag attacks, uses a hallucination multi-attack, and can rapidly melee attack you in range"
|
||||
- bugfix: "Fixes megafauana endlessly attacking dead mobs"
|
||||
- tweak: "Blood drunk Colossus, and Ash Drake made to be more player friendly if they control the fauna"
|
||||
- rscadd: "Adds in Space dragon; a very weak version of the Ash drake which can't swoop, but can still breathe fire--has a spell that whips you back with its tail, too (not currently used anywhere)"
|
||||
@@ -0,0 +1,9 @@
|
||||
author: "AzuleUtama"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscdel: "Sarin gas grenades no longer purchasable for nuke ops.
|
||||
balance: Grenadier belt now contains a sarin gas grenade.
|
||||
balance: Tactical medkit's hypospray tweaked to contain chems better for dealing with newcrit.
|
||||
balance: C20 bundle increased in price to 18TC, contains an additional clip of ammo.
|
||||
balance: Medical bundle increased in price to 20TC, Donk LMG removed, replaced with medbeam gun and magboots."
|
||||
- spellcheck: "Fixed some minor spelling/grammar errors with synthflesh patches and sarin gas grenades."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Fox McCloud"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "The real Roman shield and real Roman helmets in the Autodrobe have been replaced by fake, armorless, varieties"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Shadow-Quill"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Blobs now get a audio notification roundstart (like traitors do.)"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Dave-TH"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixes some vending machines (namely miner nanomeds) from adding all of their product twice."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Couls"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "hotkey menu option in the dropdown works correctly now"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "TDSSS"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "lowered attack log level of self-harm"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "AzuleUtama"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "R&D Console no longer has a default design called 'Name' show up in the mining category."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Ty-Omaha"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "SSD players no longer drown in shallow water"
|
||||
@@ -0,0 +1,6 @@
|
||||
author: "Fox McCloud"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Hierophant has been updated--it'll be a bit tougher and will attempt to trap you if you run for it."
|
||||
- tweak: "Heirophant is no longer a weird bird thing, but a massive, indecipherable piece of machinery that will make you dance to ITS tune"
|
||||
- tweak: "Hierophant club is weaker up front, but becomes stronger the lower health you are"
|
||||
|
Before Width: | Height: | Size: 412 KiB After Width: | Height: | Size: 423 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 949 B After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 849 B After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |