Enhances AI some more.

This commit is contained in:
Neerti
2018-09-14 12:55:12 -04:00
parent 16b40f0dcd
commit 1b6ccdabf7
25 changed files with 738 additions and 122 deletions
+1 -1
View File
@@ -48,7 +48,7 @@
#define STANCE_MOVE 7 // Similar to above but for out of combat. If a baddie is seen, they'll cancel and fight them.
#define STANCE_FOLLOW 8 // Following somone, without trying to murder them.
#define STANCE_FLEE 9 // Run away from the target because they're too spooky/we're dying/some other reason.
#define STANCE_STUNNED 10 // Do nothing, because the mob is unable to act in some form. Can be applied by other disabling effects besides stuns.
#define STANCE_DISABLED 10 // Used when the holder is afflicted with certain status effects, such as stuns or confusion.
#define STANCES_COMBAT list(STANCE_ALERT, STANCE_APPROACH, STANCE_FIGHT, STANCE_BLINDFIGHT, STANCE_REPOSITION)
+4
View File
@@ -152,3 +152,7 @@ var/list/shoreline_icon_cache = list()
shoreline_icon_cache[cache_string] = final
add_overlay(shoreline_icon_cache[cache_string])
/turf/simulated/floor/water/is_safe_to_enter(mob/living/L)
if(L.get_water_protection() < 1)
return FALSE
return ..()
+4
View File
@@ -318,3 +318,7 @@ var/const/enterloopsanity = 100
/turf/AllowDrop()
return TRUE
// Returns false if stepping into a tile would cause harm (e.g. open space while unable to fly, water tile while a slime, lava, etc).
/turf/proc/is_safe_to_enter(mob/living/L)
return TRUE
+1 -19
View File
@@ -84,25 +84,7 @@
// Some apply to those within zap range, others if they were a bit farther away.
for(var/mob/living/L in view(5, T))
if(get_dist(L, T) <= LIGHTNING_ZAP_RANGE) // They probably got zapped.
// The actual damage/electrocution is handled by tesla_zap().
L.Paralyse(5)
L.stuttering += 20
L.make_jittery(150)
L.emp_act(1)
to_chat(L, span("critical", "You've been struck by lightning!"))
// If a non-player simplemob was struck, inflict huge damage.
// If the damage is fatal, the SA is turned to ash.
if(istype(L, /mob/living/simple_animal) && !L.key)
var/mob/living/simple_animal/SA = L
SA.adjustFireLoss(200)
SA.updatehealth()
if(SA.health <= 0) // Might be best to check/give simple_mobs siemens when this gets ported to new mobs.
SA.visible_message(span("critical", "\The [SA] disintegrates into ash!"))
SA.ash()
continue // No point deafening something that wont exist.
if(istype(L, /mob/living/simple
L.lightning_act()
// Deafen them.
if(L.get_ear_protection() < 2)
@@ -15,6 +15,9 @@
/datum/ai_holder/simple_mob/xenobio_slime/sapphire
always_stun = TRUE // They know that stuns are godly.
/datum/ai_holder/simple_mob/xenobio_slime/light_pink
discipline = 5
obedience = 5
/datum/ai_holder/simple_mob/xenobio_slime/New()
..()
@@ -69,6 +72,13 @@
discipline = between(0, discipline + amount, 10)
my_slime.update_mood()
// This slime always enrages if disciplined.
/datum/ai_holder/simple_mob/xenobio_slime/red/adjust_discipline(amount, silent)
if(amount > 0 && !rabid)
holder.say("Grrr...")
holder.add_modifier(/datum/modifier/berserk, 30 SECONDS)
enrage()
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_strategical()
discipline_decay()
+9 -18
View File
@@ -150,9 +150,9 @@
if(target && can_see_target(target))
track_target_position()
if(!can_act())
ai_log("handle_stance_tactical() : Stunned.", AI_LOG_TRACE)
set_stance(STANCE_STUNNED)
if(is_disabled()) // Stunned/confused/etc
ai_log("handle_stance_tactical() : Disabled.", AI_LOG_TRACE)
set_stance(STANCE_DISABLED)
return
if(stance in STANCES_COMBAT)
@@ -217,11 +217,13 @@
ai_log("handle_stance_tactical() : STANCE_FLEE, going to flee_from_target().", AI_LOG_TRACE)
flee_from_target()
if(STANCE_STUNNED)
ai_log("handle_stance_tactical() : STANCE_STUNNED.", AI_LOG_TRACE)
if(can_act())
ai_log("handle_stance_tactical() : No longer stunned.", AI_LOG_TRACE)
if(STANCE_DISABLED)
ai_log("handle_stance_tactical() : STANCE_DISABLED.", AI_LOG_TRACE)
if(!is_disabled())
ai_log("handle_stance_tactical() : No longer disabled.", AI_LOG_TRACE)
set_stance(STANCE_IDLE)
else
handle_disabled()
ai_log("handle_stance_tactical() : Exiting.", AI_LOG_TRACE)
ai_log("========= Fast Process Ending ==========", AI_LOG_TRACE)
@@ -314,17 +316,6 @@
AttackTarget()
*/
// If our holder is able to do anything.
/datum/ai_holder/proc/can_act()
if(holder.stat) // Dead or unconscious.
ai_log("can_act() : Stat was non-zero ([holder.stat]).", AI_LOG_TRACE)
return FALSE
if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned in some form.
ai_log("can_act() : Incapacited.", AI_LOG_TRACE)
return FALSE
return TRUE
// Helper proc to turn AI 'busy' mode on or off without having to check if there is an AI, to simplify writing code.
/mob/living/proc/set_AI_busy(value)
if(ai_holder)
+1 -1
View File
@@ -74,7 +74,7 @@
new_color = "#00FFFF" // Cyan
if(STANCE_FLEE)
new_color = "#666666" // Grey
if(STANCE_STUNNED)
if(STANCE_DISABLED)
new_color = "#000000" // Black
holder.color = new_color
+72
View File
@@ -0,0 +1,72 @@
// Handles AI while stunned or otherwise disabled.
/datum/ai_holder
var/respect_confusion = TRUE // If false, the mob won't wander around recklessly.
// If our holder is able to do anything.
/datum/ai_holder/proc/can_act()
if(holder.stat) // Dead or unconscious.
ai_log("can_act() : Stat was non-zero ([holder.stat]).", AI_LOG_TRACE)
return FALSE
if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned in some form.
ai_log("can_act() : Incapacited.", AI_LOG_TRACE)
return FALSE
return TRUE
// Test if we should switch to STANCE_DISABLE.
// Currently tests for death, stuns, and confusion.
/datum/ai_holder/proc/is_disabled()
if(!can_act())
return TRUE
if(is_confused())
return TRUE
return FALSE
/datum/ai_holder/proc/is_confused()
return holder.confused > 0 && respect_confusion
// Called by the main loop.
/datum/ai_holder/proc/handle_disabled()
if(!can_act())
return // Just sit there and take it.
else if(is_confused())
dangerous_wander() // Let's bump into allies and hit them.
// Similar to normal wander, but will walk into tiles that are harmful, and attack anything they bump into, including allies.
// Occurs when confused.
/datum/ai_holder/proc/dangerous_wander()
ai_log("dangerous_wander() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
var/moving_to = 0
moving_to = pick(cardinal)
var/turf/T = get_step(holder, moving_to)
holder.set_dir(moving_to)
var/mob/living/L = locate() in T
if(L)
// Attack whoever's on the tile. Even if it's an ally.
melee_attack(L)
else
// Move to the tile. Even if it's unsafe.
holder.IMove(T, safety = FALSE)
ai_log("dangerous_wander() : Exited.", AI_LOG_DEBUG)
/*
// Wanders randomly in cardinal directions.
/datum/ai_holder/proc/handle_wander_movement()
ai_log("handle_wander_movement() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
wander_delay--
if(wander_delay <= 0)
if(!wander_when_pulled && holder.pulledby)
ai_log("handle_wander_movement() : Being pulled and cannot wander. Exiting.", AI_LOG_DEBUG)
return
var/moving_to = 0 // Apparently this is required or it always picks 4, according to the previous developer for simplemob AI.
moving_to = pick(cardinal)
holder.set_dir(moving_to)
holder.IMove(get_step(holder,moving_to))
wander_delay = base_wander_delay
ai_log("handle_wander_movement() : Exited.", AI_LOG_DEBUG)
*/
+6 -2
View File
@@ -65,11 +65,15 @@
return myid.GetID()
// Respects move cooldowns as if it had a client.
/mob/living/proc/IMove(newloc)
// Also tries to avoid being superdumb with moving into certain tiles (unless that's desired).
/mob/living/proc/IMove(turf/newloc, safety = TRUE)
if(check_move_cooldown())
// if(!newdir)
// newdir = get_dir(get_turf(src), newloc)
// Check to make sure moving to newloc won't actually kill us. e.g. we're a slime and trying to walk onto water.
if(istype(newloc))
if(safety && !newloc.is_safe_to_enter(src))
return MOVEMENT_FAILED
// Move()ing to another tile successfully returns 32 because BYOND. Would rather deal with TRUE/FALSE-esque terms.
// Note that moving to the same tile will be 'successful'.
var/turf/old_T = get_turf(src)
@@ -200,9 +200,9 @@ the artifact triggers the rage.
holder.adjustFireLoss(damage_per_tick)
// Applied when subjected to a cold attack.
// Applied when near something very cold.
// Reduces mobility, attack speed.
/datum/modifier/chilled
/datum/modifier/aura/chilled
name = "chilled"
desc = "You feel yourself freezing up. Its hard to move."
mob_overlay_state = "chilled"
@@ -446,6 +446,15 @@
//lower limit of 700 K, same as matches and roughly the temperature of a cool flame.
return max(2.25*round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*(fire_stacks/FIRE_MAX_FIRESUIT_STACKS)**2), 700)
// Called when struck by lightning.
/mob/living/proc/lightning_act()
// The actual damage/electrocution is handled by the tesla_zap() that accompanies this.
Paralyse(5)
stuttering += 20
make_jittery(150)
emp_act(1)
to_chat(src, span("critical", "You've been struck by lightning!"))
/mob/living/proc/reagent_permeability()
return 1
return round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*(fire_stacks/FIRE_MAX_FIRESUIT_STACKS)**2)
+1 -1
View File
@@ -145,7 +145,7 @@
return FALSE
// Charge check.
if(!special_attack_charges)
if(!isnull(special_attack_charges) && special_attack_charges <= 0)
return FALSE
return TRUE
@@ -199,3 +199,16 @@
else
return armorval
// Lightning
/mob/living/simple_mob/lightning_act()
..()
// If a non-player simple_mob was struck, inflict huge damage.
// If the damage is fatal, it is turned to ash.
if(!client)
inflict_shock_damage(200) // Mobs that are very beefy or resistant to shock may survive getting struck.
updatehealth()
if(health <= 0)
visible_message(span("critical", "\The [src] disintegrates into ash!"))
ash()
return // No point deafening something that wont exist.
@@ -23,6 +23,8 @@
poison_per_bite = 3
poison_type = "stimm"
shock_resist = 0.75
player_msg = "You can fire a taser-like ranged attack by clicking on an enemy or tile at a distance."
ai_holder_type = /datum/ai_holder/simple_mob/ranged/electric_spider
@@ -11,6 +11,8 @@
poison_per_bite = 5
poison_type = "cryotoxin"
heat_resist = -0.50
cold_resist = 0.75
// Sif variant with a somewhat different desc.
/mob/living/simple_mob/animal/giant_spider/frost/sif
@@ -12,6 +12,9 @@
melee_damage_lower = 10
melee_damage_upper = 25
heat_resist = 0.75
cold_resist = -0.50
poison_chance = 30
poison_per_bite = 1
poison_type = "thermite_v"
@@ -1,3 +1,5 @@
// Mobs intended to be on Sif. As such, they won't die to the cold.
/mob/living/simple_mob/animal/sif
minbodytemp = 175
minbodytemp = 175
cold_resist = 0.75
heat_resist = -0.5
@@ -38,8 +38,9 @@
min_n2 = 0
max_n2 = 0
unsuitable_atoms_damage = 0
shock_resist = 1 // Slimes are immune to electricity, and it actually charges them.
shock_resist = 0.5 // Slimes are resistant to electricity, and it actually charges them.
taser_kill = FALSE
water_resist = 0 // Slimes are very weak to water.
melee_damage_lower = 10
melee_damage_upper = 15
@@ -80,6 +81,18 @@
drop_hat()
return ..()
/mob/living/simple_mob/slime/death()
// Make dead slimes stop glowing.
glow_toggle = FALSE
handle_light()
..()
/mob/living/simple_mob/slime/revive()
// Make revived slimes resume glowing.
glow_toggle = initial(glow_toggle)
handle_light()
..()
/mob/living/simple_mob/slime/update_icon()
..() // Do the regular stuff first.
@@ -140,9 +153,6 @@
adjustCloneLoss(-1)
adjustBruteLoss(-1)
/mob/living/simple_mob/slime/water_act(amount) // This is called if a slime enters a water tile.
adjustBruteLoss(40 * amount)
// Clicked on by empty hand.
/mob/living/simple_mob/slime/attack_hand(mob/living/L)
@@ -52,37 +52,3 @@
/mob/living/simple_mob/slime/xenobio/slimebatoned(mob/living/user, amount)
Weaken(amount)
adjust_discipline(round(amount/2))
/*
/mob/living/simple_animal/slime/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
..()
if(!stat)
if(O.force > 0 && discipline && !rabid) // wow, buddy, why am I getting attacked??
adjust_discipline(1)
return
if(O.force >= 3)
if(victim || target_mob) // We've been a bad slime.
if(is_adult)
if(prob(5 + round(O.force / 2)) )
if(prob(80) && !client)
adjust_discipline(2)
if(user)
step_away(src, user)
else
if(prob(10 + O.force * 2))
if(prob(80) && !client)
adjust_discipline(2)
if(user)
step_away(src, user)
else
if(user in friends) // Friend attacking us for no reason.
if(prob(25))
friends -= user
say("[user]... not friend...")
// Shocked grilles don't hurt slimes, and in fact give them charge.
/mob/living/simple_animal/slime/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
power_charge = between(0, power_charge + round(shock_damage / 10), 10)
to_chat(src, "<span class='notice'>\The [source] shocks you, and it charges you.</span>")
*/
@@ -1,4 +1,5 @@
// Handles the subjugation of slimes by force.
// Mostly a way for things to talk to the AI indirectly.
/mob/living/simple_mob/slime/xenobio/proc/adjust_discipline(amount, silent)
if(amount > 0)
@@ -14,10 +14,10 @@
player_msg = "You <b>inject a harmful toxin</b> when attacking."
slime_mutation = list(
// /mob/living/simple_animal/slime/dark_purple,
// /mob/living/simple_animal/slime/dark_blue,
// /mob/living/simple_animal/slime/green,
// /mob/living/simple_animal/slime
/mob/living/simple_mob/slime/xenobio/dark_purple,
/mob/living/simple_mob/slime/xenobio/dark_blue,
/mob/living/simple_mob/slime/xenobio/green,
/mob/living/simple_mob/slime/xenobio
)
/mob/living/simple_mob/slime/xenobio/orange
@@ -27,15 +27,18 @@
coretype = /obj/item/slime_extract/orange
melee_damage_lower = 5
melee_damage_upper = 5
heat_resist = 1
description_info = "Attacks from this slime will burn you, and can ignite you. A firesuit can protect from the burning attacks of this slime."
player_msg = "You <b>inflict burning attacks</b>, which causes additional damage, makes the target more flammable, and has a chance to ignite them."
description_info = "The slime is immune to burning attacks, and attacks from this slime will burn you, and can ignite you. \
A firesuit can protect from the burning attacks of this slime."
player_msg = "You <b>inflict burning attacks</b>, which causes additional damage, makes the target more flammable, and has a chance to ignite them.<br>\
You are also immune to burning attacks."
slime_mutation = list(
// /mob/living/simple_animal/slime/dark_purple,
// /mob/living/simple_animal/slime/yellow,
// /mob/living/simple_animal/slime/red,
// /mob/living/simple_animal/slime
/mob/living/simple_mob/slime/xenobio/dark_purple,
/mob/living/simple_mob/slime/xenobio/yellow,
/mob/living/simple_mob/slime/xenobio/red,
/mob/living/simple_mob/slime/xenobio
)
/mob/living/simple_mob/slime/xenobio/orange/apply_melee_effects(atom/A)
@@ -49,6 +52,26 @@
if(prob(12))
L.IgniteMob()
/mob/living/simple_mob/slime/xenobio/blue
desc = "This slime produces 'cryotoxin' and uses it against their foes. Very deadly to other slimes."
color = "#19FFFF"
slime_color = "blue"
coretype = /obj/item/slime_extract/blue
reagent_injected = "cryotoxin"
cold_resist = 0.50 // Not as strong as dark blue, which has immunity.
description_info = "The slime is resistant to the cold, and attacks from this slime can inject cryotoxin into you. \
A biosuit or other thick armor can protect from the injection."
player_msg = "You <b>inject cryotoxin on attack</b>, which causes them to get very cold, slowing them down and harming them over time.<br>\
You are also resistant to cold attacks."
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/dark_blue,
/mob/living/simple_mob/slime/xenobio/silver,
/mob/living/simple_mob/slime/xenobio/pink,
/mob/living/simple_mob/slime/xenobio
)
/mob/living/simple_mob/slime/xenobio/metal
desc = "This slime is a lot more resilient than the others, due to having a metamorphic metallic and sloped surface."
@@ -86,10 +109,10 @@
)
slime_mutation = list(
// /mob/living/simple_animal/slime/silver,
// /mob/living/simple_animal/slime/yellow,
// /mob/living/simple_animal/slime/gold,
// /mob/living/simple_animal/slime
/mob/living/simple_mob/slime/xenobio/silver,
/mob/living/simple_mob/slime/xenobio/yellow,
/mob/living/simple_mob/slime/xenobio/gold,
/mob/living/simple_mob/slime/xenobio
)
/mob/living/simple_mob/slime/xenobio/metal/apply_melee_effects(atom/A)
@@ -107,20 +130,23 @@
coretype = /obj/item/slime_extract/yellow
melee_damage_lower = 5
melee_damage_upper = 5
shock_resist = 1
projectiletype = /obj/item/projectile/beam/lightning/slime
projectilesound = 'sound/weapons/gauss_shoot.ogg' // Closest thing to a 'thunderstrike' sound we have.
glow_toggle = TRUE
description_info = "This slime will fire ranged lightning attacks at enemies if they are at range, inflict shocks upon entities they attack, \
and generate electricity for their stun attack faster than usual. Insulative or reflective armor can protect from these attacks."
player_msg = "You have a <b>ranged electric attack</b>. You also <b>shock enemies you attack</b>, and your electric stun attack charges passively."
description_info = "In addition to being immune to electrical shocks, this slime will fire ranged lightning attacks at \
enemies if they are at range, inflict shocks upon entities they attack, and generate electricity for their stun \
attack faster than usual. Insulative or reflective armor can protect from these attacks."
player_msg = "You have a <b>ranged electric attack</b>. You also <b>shock enemies you attack</b>, and your electric stun attack charges passively.<br>\
You are also immune to shocking attacks."
slime_mutation = list(
// /mob/living/simple_animal/slime/bluespace,
// /mob/living/simple_animal/slime/bluespace,
// /mob/living/simple_animal/slime/metal,
// /mob/living/simple_animal/slime/orange
/mob/living/simple_mob/slime/xenobio/bluespace,
/mob/living/simple_mob/slime/xenobio/bluespace,
/mob/living/simple_mob/slime/xenobio/metal,
/mob/living/simple_mob/slime/xenobio/orange
)
/mob/living/simple_mob/slime/xenobio/yellow/apply_melee_effects(atom/A)
@@ -195,11 +221,12 @@
/mob/living/simple_mob/slime/xenobio/dark_blue
desc = "This slime makes other entities near it feel much colder, and is more resilient to the cold. It tends to kill other slimes rather quickly."
color = "#2398FF"
glows = TRUE
glow_toggle = TRUE
slime_color = "dark blue"
coretype = /obj/item/slime_extract/dark_blue
melee_damage_lower = 5
melee_damage_upper = 5
cold_resist = 1
description_info = "This slime is immune to the cold, however water will still kill it. Its attacks will \
@@ -207,15 +234,14 @@
player_msg = "You are <b>immune to the cold</b>, inflict additional cold damage on attack, and cause nearby entities to become colder."
slime_mutation = list(
// /mob/living/simple_animal/slime/purple,
// /mob/living/simple_animal/slime/blue,
// /mob/living/simple_animal/slime/cerulean,
// /mob/living/simple_animal/slime/cerulean
/mob/living/simple_mob/slime/xenobio/purple,
/mob/living/simple_mob/slime/xenobio/blue,
/mob/living/simple_mob/slime/xenobio/cerulean,
/mob/living/simple_mob/slime/xenobio/cerulean
)
minbodytemp = 0
cold_damage_per_tick = 0
cold_resist = 1
/mob/living/simple_mob/slime/xenobio/dark_blue/handle_special()
if(stat != DEAD)
@@ -244,9 +270,510 @@
/mob/living/simple_mob/slime/xenobio/dark_blue/proc/chill(mob/living/L)
L.inflict_cold_damage(is_adult ? 20 : 10)
if(!L.get_cold_protection() * 100) // Having complete protection always saves you, otherwise there's a chance to get this modifier.
add_modifier(/datum/modifier/chilled, 10 SECONDS)
if(L.get_cold_protection() < 1)
L.add_modifier(/datum/modifier/aura/chilled, null, src)
/*
*/
/mob/living/simple_mob/slime/xenobio/silver
desc = "This slime is shiny, and can deflect lasers or other energy weapons directed at it."
color = "#AAAAAA"
slime_color = "silver"
coretype = /obj/item/slime_extract/silver
shiny = TRUE
description_info = "Tasers, including the slime version, are ineffective against this slime. The slimebation still works."
player_msg = "You <b>automatically reflect</b> lasers, beams, and tasers that hit you."
slime_mutation = list(
// /mob/living/simple_animal/slime/metal,
// /mob/living/simple_animal/slime/blue,
// /mob/living/simple_animal/slime/amber,
// /mob/living/simple_animal/slime/amber
)
/mob/living/simple_mob/slime/xenobio/silver/bullet_act(var/obj/item/projectile/P, var/def_zone)
if(istype(P,/obj/item/projectile/beam) || istype(P, /obj/item/projectile/energy))
visible_message(span("danger", "\The [src] reflects \the [P]!"))
// Find a turf near or on the original location to bounce to
var/new_x = P.starting.x + pick(0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = TRUE
return PROJECTILE_CONTINUE // complete projectile permutation
else
..()
// Tier 3
/mob/living/simple_mob/slime/xenobio/bluespace
desc = "Trapping this slime in a cell is generally futile, as it can teleport at will."
color = null
slime_color = "bluespace"
icon_state_override = "bluespace"
coretype = /obj/item/slime_extract/bluespace
description_info = "This slime will teleport to attack something if it is within a range of seven tiles. The teleport has a cooldown of five seconds."
player_msg = "You can <b>teleport at will</b> to a specific tile by clicking on it at range. This has a five second cooldown."
slime_mutation = list(
// /mob/living/simple_animal/slime/bluespace,
// /mob/living/simple_animal/slime/bluespace,
// /mob/living/simple_animal/slime/yellow,
// /mob/living/simple_animal/slime/yellow
)
special_attack_min_range = 3
special_attack_max_range = 7
special_attack_cooldown = 5 SECONDS
/mob/living/simple_mob/slime/xenobio/bluespace/do_special_attack(atom/A)
// Teleport attack.
if(!A)
to_chat(src, span("warning", "There's nothing to teleport to."))
return FALSE
var/list/nearby_things = range(1, A)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
var/turf/T = get_turf(src)
var/turf/target_turf = pick(valid_turfs)
if(!target_turf)
to_chat(src, span("warning", "There wasn't an unoccupied spot to teleport to."))
return FALSE
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
s1.set_up(5, 1, T)
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s2.set_up(5, 1, target_turf)
T.visible_message(span("notice", "\The [src] vanishes!"))
s1.start()
forceMove(target_turf)
playsound(target_turf, 'sound/effects/phasein.ogg', 50, 1)
to_chat(src, span("notice", "You teleport to \the [target_turf]."))
target_turf.visible_message(span("warning", "\The [src] appears!"))
s2.start()
if(Adjacent(A))
attack_target(A)
/mob/living/simple_mob/slime/xenobio/ruby
desc = "This slime has great physical strength."
color = "#FF3333"
slime_color = "ruby"
shiny = TRUE
glow_toggle = TRUE
coretype = /obj/item/slime_extract/ruby
description_info = "This slime is unnaturally stronger, allowing it to hit much harder, take less damage, and be stunned for less time. \
Their glomp attacks also send the victim flying."
player_msg = "Your <b>attacks knock back the target</b> a fair distance.<br>\
You also hit harder, take less damage, and stuns affect you for less time."
attack_delay = 1 SECOND
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/dark_purple,
/mob/living/simple_mob/slime/xenobio/dark_purple,
/mob/living/simple_mob/slime/xenobio/ruby,
/mob/living/simple_mob/slime/xenobio/ruby
)
/mob/living/simple_mob/slime/xenobio/ruby/initialize()
add_modifier(/datum/modifier/slime_strength, null, src) // Slime is always swole.
return ..()
/mob/living/simple_mob/slime/xenobio/ruby/apply_melee_effects(atom/A)
..()
if(isliving(A) && a_intent == I_HURT)
var/mob/living/L = A
if(L.mob_size <= MOB_MEDIUM)
visible_message(span("danger", "\The [src] sends \the [L] flying with the impact!"))
playsound(src, "punch", 50, 1)
L.Weaken(1)
var/throwdir = get_dir(src, L)
L.throw_at(get_edge_target_turf(L, throwdir), 3, 1, src)
else
to_chat(L, span("warning", "\The [src] hits you with incredible force, but you remain in place."))
/mob/living/simple_mob/slime/xenobio/amber
desc = "This slime seems to be an expert in the culinary arts, as they create their own food to share with others. \
They would probably be very important to other slimes, if the other colors didn't try to kill them."
color = "#FFBB00"
slime_color = "amber"
shiny = TRUE
glow_toggle = TRUE
coretype = /obj/item/slime_extract/amber
description_info = "This slime feeds nearby entities passively while it is alive. This can cause uncontrollable \
slime growth and reproduction if not kept in check. The amber slime cannot feed itself, but can be fed by other amber slimes."
player_msg = "You <b>passively provide nutrition</b> to nearby entities."
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/silver,
/mob/living/simple_mob/slime/xenobio/silver,
/mob/living/simple_mob/slime/xenobio/amber,
/mob/living/simple_mob/slime/xenobio/amber
)
/mob/living/simple_mob/slime/xenobio/amber/handle_special()
if(stat != DEAD)
feed_aura()
..()
/mob/living/simple_mob/slime/xenobio/amber/proc/feed_aura()
for(var/mob/living/L in view(2, src))
if(L == src) // Don't feed themselves, or it is impossible to stop infinite slimes without killing all of the ambers.
continue
if(istype(L, /mob/living/simple_mob/slime/xenobio))
var/mob/living/simple_mob/slime/xenobio/X = L
X.adjust_nutrition(rand(15, 25))
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.isSynthetic())
continue
H.nutrition = between(0, H.nutrition + rand(15, 25), 800)
/mob/living/simple_mob/slime/xenobio/cerulean
desc = "This slime is generally superior in a wide range of attributes, compared to the common slime. The jack of all trades, but master of none."
color = "#4F7EAA"
slime_color = "cerulean"
coretype = /obj/item/slime_extract/cerulean
// Less than the specialized slimes, but higher than the rest.
maxHealth = 200
maxHealth_adult = 250
melee_damage_lower = 10
melee_damage_upper = 30
movement_cooldown = 0 // This actually isn't any faster due to AI limitations that hopefully the timer subsystem can fix in the future.
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/dark_blue,
/mob/living/simple_mob/slime/xenobio/dark_blue,
/mob/living/simple_mob/slime/xenobio/cerulean,
/mob/living/simple_mob/slime/xenobio/cerulean
)
// Tier 4
/mob/living/simple_mob/slime/xenobio/red
desc = "This slime is full of energy, and very aggressive. 'The red ones go faster.' seems to apply here."
color = "#FF3333"
slime_color = "red"
coretype = /obj/item/slime_extract/red
movement_cooldown = 0 // See above.
description_info = "This slime is faster than the others. Attempting to discipline this slime will always cause it to go rabid and berserk."
slime_mutation = list(
// /mob/living/simple_animal/slime/red,
// /mob/living/simple_animal/slime/oil,
// /mob/living/simple_animal/slime/oil,
// /mob/living/simple_animal/slime/orange
)
ai_holder_type = /datum/ai_holder/simple_mob/xenobio_slime/red // Will enrage if disciplined.
/mob/living/simple_mob/slime/xenobio/green
desc = "This slime is radioactive."
color = "#14FF20"
slime_color = "green"
coretype = /obj/item/slime_extract/green
glow_toggle = TRUE
reagent_injected = "radium"
var/rads = 25
description_info = "This slime will irradiate anything nearby passively, and will inject radium on attack. \
A radsuit or other thick and radiation-hardened armor can protect from this. It will only radiate while alive."
player_msg = "You <b>passively irradiate your surroundings</b>.<br>\
You also inject radium on attack."
slime_mutation = list(
// /mob/living/simple_animal/slime/purple,
// /mob/living/simple_animal/slime/green,
// /mob/living/simple_animal/slime/emerald,
// /mob/living/simple_animal/slime/emerald
)
/mob/living/simple_mob/slime/xenobio/green/handle_special()
if(stat != DEAD)
irradiate()
..()
/mob/living/simple_mob/slime/xenobio/green/proc/irradiate()
radiation_repository.radiate(src, rads)
/mob/living/simple_mob/slime/xenobio/pink
desc = "This slime has regenerative properties."
color = "#FF0080"
slime_color = "pink"
coretype = /obj/item/slime_extract/pink
glow_toggle = TRUE
description_info = "This slime will passively heal nearby entities within two tiles, including itself. It will only do this while alive."
player_msg = "You <b>passively heal yourself and nearby allies</b>."
slime_mutation = list(
// /mob/living/simple_animal/slime/blue,
// /mob/living/simple_animal/slime/light_pink,
// /mob/living/simple_animal/slime/light_pink,
// /mob/living/simple_animal/slime/pink
)
/mob/living/simple_mob/slime/xenobio/pink/handle_special()
if(stat != DEAD)
heal_aura()
..()
/mob/living/simple_mob/slime/xenobio/pink/proc/heal_aura()
for(var/mob/living/L in view(src, 2))
if(L.stat == DEAD || !IIsAlly(L))
continue
L.add_modifier(/datum/modifier/aura/slime_heal, null, src)
/datum/modifier/aura/slime_heal
name = "slime mending"
desc = "You feel somewhat gooy."
mob_overlay_state = "pink_sparkles"
stacks = MODIFIER_STACK_FORBID
aura_max_distance = 2
on_created_text = "<span class='warning'>Twinkling spores of goo surround you. It makes you feel healthier.</span>"
on_expired_text = "<span class='notice'>The spores of goo have faded, although you feel much healthier than before.</span>"
/datum/modifier/aura/slime_heal/tick()
if(holder.stat == DEAD)
expire()
if(ishuman(holder)) // Robolimbs need this code sadly.
var/mob/living/carbon/human/H = holder
for(var/obj/item/organ/external/E in H.organs)
var/obj/item/organ/external/O = E
O.heal_damage(2, 2, 0, 1)
else
holder.adjustBruteLoss(-2)
holder.adjustFireLoss(-2)
holder.adjustToxLoss(-2)
holder.adjustOxyLoss(-2)
holder.adjustCloneLoss(-1)
/mob/living/simple_mob/slime/xenobio/gold
desc = "This slime absorbs energy, and cannot be stunned by normal means."
color = "#EEAA00"
shiny = TRUE
slime_color = "gold"
coretype = /obj/item/slime_extract/gold
description_info = "This slime is immune to the slimebaton and taser, and will actually charge the slime, however it will still discipline the slime."
slime_mutation = list(
// /mob/living/simple_animal/slime/metal,
// /mob/living/simple_animal/slime/gold,
// /mob/living/simple_animal/slime/sapphire,
// /mob/living/simple_animal/slime/sapphire
)
/mob/living/simple_mob/slime/xenobio/gold/slimebatoned(mob/living/user, amount)
power_charge = between(0, power_charge + amount, 10)
/mob/living/simple_mob/slime/xenobio/gold/get_description_interaction() // So it doesn't say to use a baton on them.
return list()
// Tier 5
/mob/living/simple_mob/slime/xenobio/oil
desc = "This slime is explosive and volatile. Smoking near it is probably a bad idea."
color = "#333333"
slime_color = "oil"
shiny = TRUE
coretype = /obj/item/slime_extract/oil
description_info = "If this slime suffers damage from a fire or heat based source, or if it is caught inside \
an explosion, it will explode. Oil slimes will also suicide-bomb themselves when fighting something that is not a monkey or slime."
player_msg = "You <b>will explode if struck by a burning attack</b>, or if you hit an enemy with a melee attack that is not a monkey or another slime."
slime_mutation = list(
// /mob/living/simple_animal/slime/oil,
// /mob/living/simple_animal/slime/oil,
// /mob/living/simple_animal/slime/red,
// /mob/living/simple_animal/slime/red
)
/mob/living/simple_mob/slime/xenobio/oil/proc/explode()
if(stat != DEAD)
explosion(src.loc, 0, 2, 4) // A bit weaker since the suicide charger tended to gib the poor sod being targeted.
if(src) // Delete ourselves if the explosion didn't do it.
qdel(src)
/mob/living/simple_mob/slime/xenobio/oil/apply_melee_effects(atom/A)
if(isliving(A))
var/mob/living/L = A
if(ishuman(L))
var/mob/living/carbon/human/H = A
if(istype(H.species, /datum/species/monkey))
return ..()// Don't blow up when just eatting monkeys.
else if(isslime(L))
return ..()
// Otherwise blow ourselves up.
say(pick("Sacrifice...!", "Sssss...", "Boom...!"))
set_AI_busy(TRUE)
sleep(2 SECONDS)
log_and_message_admins("[src] has suicide-bombed themselves while trying to kill \the [L].")
explode()
return ..()
/mob/living/simple_mob/slime/xenobio/oil/ex_act(severity)
log_and_message_admins("[src] exploded due to a chain reaction with another explosion.")
explode()
/mob/living/simple_mob/slime/xenobio/oil/fire_act(datum/gas_mixture/air, temperature, volume)
log_and_message_admins("[src] exploded due to exposure to fire.")
explode()
/mob/living/simple_mob/slime/xenobio/oil/bullet_act(obj/item/projectile/P, def_zone)
if(P.damage_type && P.damage_type == BURN && P.damage) // Most bullets won't trigger the explosion, as a mercy towards Security.
log_and_message_admins("[src] exploded due to bring hit by a burning projectile[P.firer ? " by [key_name(P.firer)]" : ""].")
explode()
else
..()
/mob/living/simple_mob/slime/xenobio/oil/attackby(obj/item/weapon/W, mob/living/user)
if(istype(W) && W.force && W.damtype == BURN)
log_and_message_admins("[src] exploded due to being hit with a burning weapon ([W]) by [key_name(user)].")
explode()
else
..()
/mob/living/simple_mob/slime/xenobio/sapphire
desc = "This slime seems a bit brighter than the rest, both figuratively and literally."
color = "#2398FF"
slime_color = "sapphire"
shiny = TRUE
glow_toggle = TRUE
coretype = /obj/item/slime_extract/sapphire
ai_holder_type = /datum/ai_holder/simple_mob/xenobio_slime/sapphire
description_info = "This slime uses more robust tactics when fighting and won't hold back, so it is dangerous to be alone \
with one if hostile, and especially dangerous if they outnumber you."
slime_mutation = list(
// /mob/living/simple_animal/slime/sapphire,
// /mob/living/simple_animal/slime/sapphire,
// /mob/living/simple_animal/slime/gold,
// /mob/living/simple_animal/slime/gold
)
/mob/living/simple_mob/slime/xenobio/emerald
desc = "This slime is faster than usual, even more so than the red slimes."
color = "#22FF22"
shiny = TRUE
glow_toggle = TRUE
slime_color = "emerald"
coretype = /obj/item/slime_extract/emerald
description_info = "This slime will make everything around it, and itself, faster for a few seconds, if close by."
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/green,
/mob/living/simple_mob/slime/xenobio/green,
/mob/living/simple_mob/slime/xenobio/emerald,
/mob/living/simple_mob/slime/xenobio/emerald
)
/mob/living/simple_mob/slime/xenobio/emerald/handle_special()
if(stat != DEAD)
zoom_aura()
..()
/mob/living/simple_mob/slime/xenobio/emerald/proc/zoom_aura()
for(var/mob/living/L in view(src, 2))
if(L.stat == DEAD || !IIsAlly(L))
continue
L.add_modifier(/datum/modifier/technomancer/haste, 5 SECONDS, src)
/mob/living/simple_mob/slime/xenobio/light_pink
desc = "This slime seems a lot more peaceful than the others."
color = "#FF8888"
slime_color = "light pink"
coretype = /obj/item/slime_extract/light_pink
description_info = "This slime is effectively always disciplined initially."
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/pink,
/mob/living/simple_mob/slime/xenobio/pink,
/mob/living/simple_mob/slime/xenobio/light_pink,
/mob/living/simple_mob/slime/xenobio/light_pink
)
// Special
/mob/living/simple_mob/slime/xenobio/rainbow
desc = "This slime changes colors constantly."
color = null // Uses a special icon_state.
slime_color = "rainbow"
coretype = /obj/item/slime_extract/rainbow
icon_state_override = "rainbow"
unity = TRUE
description_info = "This slime is considered to be the same color as all other slime colors at the same time for the purposes of \
other slimes being friendly to them, and therefore will never be harmed by another slime. \
Attacking this slime will provoke the wrath of all slimes within range."
player_msg = "You are <b>considered to be the same color as every slime</b>, \
meaning that you are considered an ally to all slimes."
slime_mutation = list(
/mob/living/simple_mob/slime/xenobio/rainbow,
/mob/living/simple_mob/slime/xenobio/rainbow,
/mob/living/simple_mob/slime/xenobio/rainbow,
/mob/living/simple_mob/slime/xenobio/rainbow
)
/mob/living/simple_mob/slime/xenobio/rainbow/initialize()
unify()
return ..()
// The RD's pet slime.
/mob/living/simple_mob/slime/xenobio/rainbow/kendrick
name = "Kendrick"
desc = "The Research Director's pet slime. It shifts colors constantly."
rainbow_core_candidate = FALSE
/mob/living/simple_mob/slime/xenobio/rainbow/initialize()
pacify()
return ..()
@@ -123,6 +123,8 @@
var/datum/ai_holder/simple_mob/xenobio_slime/AI = ai_holder
AI.pacify()
faction = "neutral"
// If for whatever reason the mob AI (or player) decides to try to attack something anyways.
melee_damage_upper = 0
melee_damage_lower = 0
+5
View File
@@ -208,6 +208,11 @@
if((locate(/obj/structure/disposalpipe/up) in below) || locate(/obj/machinery/atmospherics/pipe/zpipe/up in below))
return FALSE
/mob/living/can_fall()
if(hovering)
return FALSE
return ..()
/mob/living/carbon/human/can_fall()
if(..())
return species.can_fall(src)
+7 -1
View File
@@ -147,4 +147,10 @@
/turf/simulated/open/is_space()
var/turf/below = GetBelow(src)
return !below || below.is_space()
return !below || below.is_space()
/turf/simulated/open/is_safe_to_enter(mob/living/L)
if(L.can_fall())
if(!locate(/obj/structure/stairs) in GetBelow(src))
return FALSE
return ..()
+8 -7
View File
@@ -18,6 +18,7 @@
#include "code\names.dm"
#include "code\stylesheet.dm"
#include "code\world.dm"
#include "code\modules\ai\ai_holder_disabled.dm"
#include "code\__datastructures\globals.dm"
#include "code\__defines\_compile_options.dm"
#include "code\__defines\_planes+layers.dm"
@@ -1957,13 +1958,6 @@
#include "code\modules\mob\living\simple_mob\on_click.dm"
#include "code\modules\mob\living\simple_mob\simple_hud.dm"
#include "code\modules\mob\living\simple_mob\simple_mob.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\slime.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\combat.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\consumption.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\defense.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\discipline.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\subtypes.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\xenobio.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\animal.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\farm animals\chicken.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\farm animals\cow.dm"
@@ -2022,6 +2016,13 @@
#include "code\modules\mob\living\simple_mob\subtypes\occult\constructs\wraith.dm"
#include "code\modules\mob\living\simple_mob\subtypes\plant\tomato.dm"
#include "code\modules\mob\living\simple_mob\subtypes\plant\tree.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\slime.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\combat.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\consumption.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\defense.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\discipline.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\subtypes.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\xenobio.dm"
#include "code\modules\mob\living\voice\voice.dm"
#include "code\modules\mob\new_player\login.dm"
#include "code\modules\mob\new_player\logout.dm"