Merge remote-tracking branch 'upstream/master' into universal-damage

This commit is contained in:
Fox McCloud
2019-09-14 21:15:31 -04:00
212 changed files with 2977 additions and 1726 deletions
@@ -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)
@@ -99,7 +99,7 @@
var/blocked = 0
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK))
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
blocked = 1
if(!blocked)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
@@ -14,8 +14,6 @@
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
pass_flags = PASSTABLE
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
@@ -8,6 +8,7 @@
heal_rate = 5
large = 1
ventcrawler = 0
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
/mob/living/carbon/alien/humanoid/queen/New()
create_reagents(100)
@@ -1,5 +1,6 @@
/mob/living/carbon
gender = MALE
pressure_resistance = 15
var/list/stomach_contents = list()
var/list/internal_organs = list()
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
@@ -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"))
@@ -34,7 +34,7 @@ emp_act
return -1 // complete projectile permutation
//Shields
if(check_shields(P.damage, "the [P.name]", P, PROJECTILE_ATTACK, P.armour_penetration))
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
@@ -136,24 +136,24 @@ emp_act
//End Here
/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, attack_type = MELEE_ATTACK, armour_penetration = 0)
/mob/living/carbon/human/proc/check_shields(atom/AM, var/damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
if(l_hand && !istype(l_hand, /obj/item/clothing))
var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
if(l_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
if(r_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
if(w_uniform.hit_reaction(src, attack_text, final_block_chance, damage, attack_type, AM))
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
@@ -363,7 +363,7 @@ emp_act
if(user != src)
user.do_attack_animation(src)
if(check_shields(I.force, "the [I.name]", I, MELEE_ATTACK, I.armour_penetration))
if(check_shields(I, I.force, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return 0
if(check_block())
@@ -457,7 +457,7 @@ emp_act
throwpower = I.throwforce
if(I.thrownby == src) //No throwing stuff at yourself to trigger reactions
return ..()
if(check_shields(throwpower, "\the [AM.name]", AM, THROWN_PROJECTILE_ATTACK))
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
hitpush = 0
skipcatch = 1
blocked = 1
@@ -538,7 +538,7 @@ emp_act
updatehealth("larva attack")
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
if(check_shields(0, M.name))
if(check_shields(M, 0, M.name))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return 0
@@ -583,16 +583,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(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")
@@ -646,11 +647,12 @@ emp_act
return
/mob/living/carbon/human/experience_pressure_difference(pressure_difference, direction)
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
if(shoes)
if(istype(shoes,/obj/item/clothing/shoes/magboots) && (shoes.flags & NOSLIP)) //TODO: Make a not-shit shoe var system to negate airflow.
return 0
..()
playsound(src, 'sound/effects/space_wind.ogg', 50, TRUE)
if(shoes && istype(shoes, /obj/item/clothing))
var/obj/item/clothing/S = shoes
if (S.flags & NOSLIP)
return FALSE
return ..()
/mob/living/carbon/human/water_act(volume, temperature, source, method = TOUCH)
. = ..()
@@ -2,7 +2,7 @@ var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,GLAND_HUD)
pressure_resistance = 25
//Marking colour and style
var/list/m_colours = DEFAULT_MARKING_COLOURS //All colours set to #000000.
var/list/m_styles = DEFAULT_MARKING_STYLES //All markings set to None.
@@ -522,7 +522,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)
+30
View File
@@ -608,6 +608,34 @@
else
return pick("trails_1", "trails_2")
/mob/living/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
if(buckled)
return
if(client && client.move_delay >= world.time + world.tick_lag * 2)
pressure_resistance_prob_delta -= 30
var/list/turfs_to_check = list()
if(has_limbs)
var/turf/T = get_step(src, angle2dir(dir2angle(direction) + 90))
if (T)
turfs_to_check += T
T = get_step(src, angle2dir(dir2angle(direction) - 90))
if(T)
turfs_to_check += T
for(var/t in turfs_to_check)
T = t
if(T.density)
pressure_resistance_prob_delta -= 20
continue
for(var/atom/movable/AM in T)
if(AM.density && AM.anchored)
pressure_resistance_prob_delta -= 20
break
..(pressure_difference, direction, pressure_resistance_prob_delta)
/*//////////////////////
START RESIST PROCS
@@ -621,6 +649,8 @@
return
changeNext_move(CLICK_CD_RESIST)
SEND_SIGNAL(src, COMSIG_LIVING_RESIST, src)
if(!restrained())
if(resist_grab())
return
+9 -9
View File
@@ -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)
+2 -1
View File
@@ -1,5 +1,6 @@
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
pressure_resistance = 10
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
@@ -65,7 +66,7 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD)
var/list/status_effects //a list of all status effects the mob has
var/deathgasp_on_death = FALSE
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
+2 -8
View File
@@ -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)
@@ -252,7 +252,7 @@
modules += new /obj/item/soap/nanotrasen(src)
modules += new /obj/item/storage/bag/trash/cyborg(src)
modules += new /obj/item/mop/advanced/cyborg(src)
modules += new /obj/item/lightreplacer(src)
modules += new /obj/item/lightreplacer/cyborg(src)
modules += new /obj/item/holosign_creator(src)
emag = new /obj/item/reagent_containers/spray(src)
@@ -544,7 +544,7 @@
modules += new /obj/item/crowbar/cyborg(src)
modules += new /obj/item/wirecutters/cyborg(src)
modules += new /obj/item/multitool/cyborg(src)
modules += new /obj/item/lightreplacer(src)
modules += new /obj/item/lightreplacer/cyborg(src)
modules += new /obj/item/gripper(src)
modules += new /obj/item/matter_decompiler(src)
modules += new /obj/item/reagent_containers/spray/cleaner/drone(src)
@@ -562,10 +562,6 @@
/obj/item/robot_module/drone/respawn_consumable(mob/living/silicon/robot/R)
var/obj/item/reagent_containers/spray/cleaner/C = locate() in modules
C.reagents.add_reagent("cleaner", 3)
var/obj/item/lightreplacer/LR = locate() in modules
LR.Charge(R)
..()
@@ -9,7 +9,6 @@
modtype = "Syndicate"
req_access = list(access_syndicate)
ionpulse = 1
magpulse = 1
lawchannel = "State"
var/playstyle_string = "<span class='userdanger'>You are a Syndicate assault cyborg!</span><br>\
<b>You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
@@ -80,7 +79,7 @@
var/datum/action/thermals = new /datum/action/innate/robot_sight/thermal()
thermals.Grant(src)
/mob/living/silicon/robot/syndicate/saboteur/verb/modify_name()
set name = "Modify Name"
set desc = "Change your systems' registered name to fool Nanotrasen systems. No cost."
@@ -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)
..()
@@ -16,8 +16,6 @@
faction = list("syndicate")
shoot_sound = 'sound/weapons/wave.ogg'
anchored = 1
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120
window_id = "syndiebot"
window_name = "Syndicate Bot Interface"
var/turf/saved_turf
@@ -18,6 +18,7 @@
minbodytemp = 0
faction = list("cult")
flying = 1
pressure_resistance = 100
universal_speak = 1
AIStatus = AI_OFF //normal constructs don't have AI
var/const_type = "shade"
@@ -79,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()
@@ -24,8 +24,6 @@
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)
unsuitable_atmos_damage = 15
heat_damage_per_tick = 20
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
faction = list("alien")
status_flags = CANPUSH
minbodytemp = 0
@@ -30,6 +30,7 @@
faction = list("carp")
flying = 1
pressure_resistance = 200
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
var/carp_color = "carp" //holder for icon set
@@ -18,7 +18,7 @@
attack_sound = 'sound/creatures/headcrab_attack.ogg'
speak_emote = list("hisses")
var/is_zombie = 0
stat_attack = UNCONSCIOUS //so they continue to attack when they are on the ground.
stat_attack = DEAD //so they continue to attack when they are on the ground.
var/host_species = ""
var/list/human_overlays = list()
@@ -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
@@ -132,7 +132,7 @@
. = ..()
if(.)
var/mob/living/L = target
if (istype(L))
if(istype(L))
L.adjust_fire_stacks(0.1)
L.IgniteMob()
@@ -141,5 +141,12 @@
damage_type = BURN
nodamage = FALSE
/obj/item/projectile/temp/basilisk/icewing/on_hit(atom/target, blocked = FALSE)
. = ..()
if(.)
var/mob/living/L = target
if(istype(L))
L.apply_status_effect(/datum/status_effect/freon/watcher)
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
fromtendril = TRUE
@@ -46,7 +46,7 @@
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)
minbodytemp = 0
pressure_resistance = 300
faction = list("undead") // did I mention ghost
loot = list(/obj/item/reagent_containers/food/snacks/ectoplasm)
del_on_death = 1
@@ -49,10 +49,6 @@ var/global/list/ts_spiderling_list = list()
// '1' (default for most simple_mobs, including terror spiders) converts to 3.5, or 2.8 tiles/sec.
// '2' converts to 4.5, or 2.2 tiles/sec.
// Atmos
pressure_resistance = 50 //50 kPa difference required to push
throw_pressure_limit = 100 //100 kPa difference required to throw
// Ventcrawling
ventcrawler = 1 // allows player ventcrawling
var/ai_ventcrawls = TRUE
+5
View File
@@ -556,6 +556,11 @@
genemutcheck(src, block,null, MUTCHK_FORCED)
dna.UpdateSE()
///////////////////////////////// FROZEN /////////////////////////////////////
/mob/living/proc/IsFrozen()
return has_status_effect(/datum/status_effect/freon)
///////////////////////////////////// STUN ABSORPTION /////////////////////////////////////
/mob/living/proc/add_stun_absorption(key, duration, priority, message, self_message, examine_message)
+1 -1
View File
@@ -89,7 +89,7 @@
else if((fall_over || resting) && !lying)
fall(fall_over)
canmove = !(fall_over || resting || stunned || buckled)
canmove = !(fall_over || resting || stunned || IsFrozen() || buckled)
density = !lying
if(lying)
if(layer == initial(layer))