diff --git a/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm b/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm index f2d1f05e13..2a16a3e091 100644 --- a/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm +++ b/code/modules/ai/aI_holder_subtypes/simple_mob_ai.dm @@ -16,9 +16,9 @@ can_flee = TRUE violent_breakthrough = FALSE -// Won't wander away, ideal for event-spawned mobs like carp or drones. +// Won't wander away as quickly, ideal for event-spawned mobs like carp or drones. /datum/ai_holder/simple_mob/event - wander = FALSE + base_wander_delay = 8 // Doesn't really act until told to by something on the outside. /datum/ai_holder/simple_mob/inert @@ -60,7 +60,7 @@ // For event-spawned malf drones. /datum/ai_holder/simple_mob/ranged/kiting/threatening/event - wander = FALSE + base_wander_delay = 8 /datum/ai_holder/simple_mob/ranged/kiting/no_moonwalk moonwalk = FALSE @@ -96,6 +96,11 @@ /datum/ai_holder/simple_mob/restrained violent_breakthrough = FALSE conserve_ammo = TRUE + destructive = FALSE + +// This does the opposite of the above subtype. +/datum/ai_holder/simple_mob/destructive + destructive = TRUE // Melee mobs. diff --git a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm index c859a523cc..059adfb849 100644 --- a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm +++ b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm @@ -12,13 +12,16 @@ var/always_stun = FALSE // If true, the slime will elect to attempt to permastun the target. + var/last_discipline_decay = null // Last world.time discipline was reduced from decay. + var/discipline_decay_time = 5 SECONDS // Earliest that one discipline can decay. + /datum/ai_holder/simple_mob/xenobio_slime/sapphire always_stun = TRUE // They know that stuns are godly. intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death. /datum/ai_holder/simple_mob/xenobio_slime/light_pink - discipline = 5 - obedience = 5 + discipline = 10 + obedience = 10 /datum/ai_holder/simple_mob/xenobio_slime/passive/New() // For Kendrick. ..() @@ -89,9 +92,10 @@ // Handles decay of discipline. /datum/ai_holder/simple_mob/xenobio_slime/proc/discipline_decay() - if(discipline > 0) + if(discipline > 0 && last_discipline_decay + discipline_decay_time < world.time) if(!prob(75 + (obedience * 5))) adjust_discipline(-1) + last_discipline_decay = world.time /datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic() evolve_and_reproduce() diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm index acb3da2309..37f064f8c0 100644 --- a/code/modules/ai/ai_holder_targeting.dm +++ b/code/modules/ai/ai_holder_targeting.dm @@ -15,8 +15,9 @@ var/lose_target_time = 0 // world.time when a target was lost. var/lose_target_timeout = 5 SECONDS // How long until a mob 'times out' and stops trying to find the mob that disappeared. - var/list/attackers = list() // List of strings of names of people who attacked us before in our life. - // This uses strings and not refs to allow for disguises, and to avoid needing to use weakrefs. + var/list/attackers = list() // List of strings of names of people who attacked us before in our life. + // This uses strings and not refs to allow for disguises, and to avoid needing to use weakrefs. + var/destructive = FALSE // Will target 'neutral' structures/objects and not just 'hostile' ones. // A lot of this is based off of /TG/'s AI code. @@ -111,6 +112,7 @@ var/obj/mecha/M = the_target if(M.occupant) return can_attack(M.occupant) + return destructive // Empty mechs are 'neutral'. if(istype(the_target, /obj/machinery/porta_turret)) var/obj/machinery/porta_turret/P = the_target diff --git a/code/modules/mob/living/simple_mob/combat.dm b/code/modules/mob/living/simple_mob/combat.dm index e0cf980cc3..ae1fa4ad3b 100644 --- a/code/modules/mob/living/simple_mob/combat.dm +++ b/code/modules/mob/living/simple_mob/combat.dm @@ -102,7 +102,7 @@ return FALSE visible_message("\The [src] fires at \the [A]!") - shoot(A, src.loc, src) + shoot(A) if(casingtype) new casingtype(loc) @@ -112,21 +112,22 @@ return TRUE -//Shoot a bullet at someone (idk why user is an argument when src would fit???) -/mob/living/simple_mob/proc/shoot(atom/A, turf/start, mob/living/user, bullet = 0) - if(A == start) +// Shoot a bullet at something. +/mob/living/simple_mob/proc/shoot(atom/A) + if(A == get_turf(src)) return face_atom(A) - var/obj/item/projectile/P = new projectiletype(user.loc) + var/obj/item/projectile/P = new projectiletype(src.loc) if(!P) return // If the projectile has its own sound, use it. // Otherwise default to the mob's firing sound. - playsound(user, P.fire_sound ? P.fire_sound : projectilesound, 80, 1) + playsound(src, P.fire_sound ? P.fire_sound : projectilesound, 80, 1) + P.firer = src // So we can't shoot ourselves. P.launch(A) if(needs_reload) reload_count++ diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/xenobio.dm b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/xenobio.dm index f7f594f139..6cae7dd6e7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/xenobio.dm +++ b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/xenobio.dm @@ -20,17 +20,40 @@ var/number = 0 // This is used to make the slime semi-unique for indentification. var/harmless = FALSE // Set to true when pacified. Makes the slime harmless, not get hungry, and not be able to grow/reproduce. -/mob/living/simple_mob/slime/xenobio/initialize() +/mob/living/simple_mob/slime/xenobio/initialize(mapload, var/mob/living/simple_mob/slime/xenobio/my_predecessor) ASSERT(ispath(ai_holder_type, /datum/ai_holder/simple_mob/xenobio_slime)) number = rand(1, 1000) update_name() - return ..() + + . = ..() // This will make the AI and do the other mob constructor things. It will also return the default hint at the end. + + if(my_predecessor) + inherit_information(my_predecessor) + /mob/living/simple_mob/slime/xenobio/Destroy() if(victim) stop_consumption() // Unbuckle us from our victim. return ..() +// Called when a slime makes another slime by splitting. The predecessor slime will be deleted shortly afterwards. +/mob/living/simple_mob/slime/xenobio/proc/inherit_information(var/mob/living/simple_mob/slime/xenobio/predecessor) + if(!predecessor) + return + + var/datum/ai_holder/simple_mob/xenobio_slime/AI = ai_holder + var/datum/ai_holder/simple_mob/xenobio_slime/previous_AI = predecessor.ai_holder + ASSERT(istype(AI)) + ASSERT(istype(previous_AI)) + + // Now to transfer the information. + // Newly made slimes are bit more rebellious than their predecessors, but they also somewhat forget the atrocities the xenobiologist may have done. + AI.discipline = max(previous_AI.discipline - 1, 0) + AI.obedience = max(previous_AI.obedience - 1, 0) + AI.resentment = max(previous_AI.resentment - 1, 0) + AI.rabid = previous_AI.rabid + + /mob/living/simple_mob/slime/xenobio/update_icon() icon_living = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"][victim ? " eating" : ""]" icon_dead = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"] dead" @@ -212,14 +235,12 @@ t = /mob/living/simple_mob/slime/xenobio/rainbow else if(prob(mutation_chance) && slime_mutation.len) t = slime_mutation[rand(1, slime_mutation.len)] - var/mob/living/simple_mob/slime/xenobio/baby = new t(loc) + var/mob/living/simple_mob/slime/xenobio/baby = new t(loc, src) // Handle 'inheriting' from parent slime. baby.mutation_chance = mutation_chance baby.power_charge = round(power_charge / 4) - pass_on_data(baby) // Transfer the AI stuff slowly, sadly. - if(!istype(baby, /mob/living/simple_mob/slime/xenobio/rainbow)) baby.unity = unity baby.faction = faction @@ -228,33 +249,6 @@ step_away(baby, src) return baby -/mob/living/simple_mob/slime/xenobio/proc/pass_on_data(mob/living/simple_mob/slime/xenobio/baby) - // This is superdumb but the AI datum won't exist until the new slime's initialize() finishes. - var/new_discipline = 0 - var/new_obedience = 0 - var/new_resentment = 0 - var/new_rabid = FALSE - - // First, get this slime's AI values since they are likely to be deleted in a moment. - if(src && src.has_AI()) - var/datum/ai_holder/simple_mob/xenobio_slime/our_AI = ai_holder - new_discipline = max(our_AI.discipline - 1, 0) - new_obedience = max(our_AI.obedience - 1, 0) - new_resentment = max(our_AI.resentment - 1, 0) - new_rabid = our_AI.rabid - - spawn(2) // Race conditions are fun, but with the first two letters capitalized. - if(istype(baby) && baby.has_AI()) - var/datum/ai_holder/simple_mob/xenobio_slime/their_AI = baby.ai_holder - - if(!istype(baby, /mob/living/simple_mob/slime/xenobio/light_pink)) - their_AI.discipline = new_discipline - their_AI.obedience = new_obedience - - their_AI.resentment = new_resentment - - their_AI.rabid = new_rabid - /mob/living/simple_mob/slime/xenobio/get_description_interaction() var/list/results = list() @@ -281,4 +275,4 @@ lines.Add(null) lines.Add(description_info) - return lines.Join("\n") \ No newline at end of file + return lines.Join("\n")