From 86dfb4c823af0c22486aeffc919e4b678bc369b8 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Fri, 30 Aug 2019 20:32:08 -0400 Subject: [PATCH 01/13] Simple Mob Update --- code/__DEFINES/components.dm | 4 + code/__DEFINES/flags.dm | 1 + code/__DEFINES/is_helpers.dm | 2 + code/_onclick/click.dm | 31 +- code/game/gamemodes/miniantags/morph/morph.dm | 6 +- code/game/machinery/doors/door.dm | 1 + code/game/objects/structures/window.dm | 3 + code/modules/mining/equipment/survival_pod.dm | 3 +- code/modules/mining/minebot.dm | 5 +- .../living/simple_animal/animal_defense.dm | 87 ++++- .../mob/living/simple_animal/damage_procs.dm | 37 ++ .../mob/living/simple_animal/friendly/cat.dm | 43 +-- .../simple_animal/friendly/farm_animals.dm | 25 +- .../living/simple_animal/friendly/mouse.dm | 6 +- .../simple_animal/hostile/giant_spider.dm | 27 +- .../living/simple_animal/hostile/hostile.dm | 316 ++++++++++------ .../simple_animal/hostile/megafauna/legion.dm | 1 - .../hostile/megafauna/megafauna.dm | 13 +- .../simple_animal/hostile/mining/basilisk.dm | 2 +- .../simple_animal/hostile/mining/goldgrub.dm | 4 +- .../simple_animal/hostile/mining/goliath.dm | 2 +- .../simple_animal/hostile/mining/gutlunch.dm | 2 +- .../simple_animal/hostile/mining/hivelord.dm | 2 +- .../living/simple_animal/hostile/statue.dm | 1 - .../hostile/terror_spiders/gray.dm | 4 +- .../hostile/terror_spiders/terror_spiders.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 342 +++++++----------- code/modules/mob/login.dm | 3 - icons/mob/screen_gen.dmi | Bin 141329 -> 141348 bytes paradise.dme | 1 + 30 files changed, 562 insertions(+), 414 deletions(-) create mode 100644 code/modules/mob/living/simple_animal/damage_procs.dm diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 02b36614cb5..aa4b49ff6fc 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -155,6 +155,10 @@ // /mob/living/carbon signals #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) +// /mob/living/simple_animal/hostile signals +#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" + #define COMPONENT_HOSTILE_NO_ATTACK 1 + // /obj signals #define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) #define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 14b712754fb..edc77bae4c3 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -13,6 +13,7 @@ #define CONDUCT 32 // conducts electricity (metal etc.) #define ABSTRACT 64 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way #define ON_BORDER 128 // item has priority to check when entering or leaving +#define PREVENT_CLICK_UNDER 256 #define EARBANGPROTECT 1024 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index c4478f62837..d9f4eff3e43 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -17,6 +17,8 @@ #define ismecha(A) (istype(A, /obj/mecha)) +#define isspacepod(A) (istype(A, /obj/spacepod)) + #define iseffect(A) (istype(A, /obj/effect)) #define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index b823efe2563..7695b8b5851 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -107,6 +107,9 @@ if(next_move > world.time) // in the year 2000... return + if(!modifiers["catcher"] && A.IsObscured()) + return + if(istype(loc,/obj/mecha)) if(!locate(/turf) in list(A,A.loc)) // Prevents inventory from being drilled return @@ -172,6 +175,24 @@ return +//Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it +/atom/proc/IsObscured() + if(!isturf(loc)) //This only makes sense for things directly on turfs for now + return FALSE + var/turf/T = get_turf_pixel(src) + if(!T) + return FALSE + for(var/atom/movable/AM in T) + if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer) + return TRUE + return FALSE + +/turf/IsObscured() + for(var/atom/movable/AM in src) + if(AM.flags & PREVENT_CLICK_UNDER && AM.density) + return TRUE + return FALSE + // Default behavior: ignore double clicks, consider them normal clicks instead /mob/proc/DblClickOn(var/atom/A, var/params) return @@ -399,8 +420,8 @@ dir = direction /obj/screen/click_catcher - icon = 'icons/mob/screen_full.dmi' - icon_state = "passage0" + icon = 'icons/mob/screen_gen.dmi' + icon_state = "catcher" plane = CLICKCATCHER_PLANE mouse_opacity = MOUSE_OPACITY_OPAQUE screen_loc = "CENTER" @@ -430,5 +451,7 @@ C.swap_hand() else var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr)) - T.Click(location, control, params) - return 1 + params += "&catcher=1" + if(T) + T.Click(location, control, params) + . = 1 \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 81e052a85d8..e774e893851 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -28,7 +28,7 @@ melee_damage_upper = 20 see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - idle_vision_range = 1 // Only attack when target is close + vision_range = 1 // Only attack when target is close wander = 0 attacktext = "glomps" attack_sound = 'sound/effects/blobattack.ogg' @@ -54,7 +54,7 @@ . = ..() AddSpell(new /obj/effect/proc_holder/spell/targeted/smoke) AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall) - + /mob/living/simple_animal/hostile/morph/examine(mob/user) if(morphed) if(form) @@ -153,7 +153,7 @@ restore() /mob/living/simple_animal/hostile/morph/LoseAggro() - vision_range = idle_vision_range + vision_range = initial(vision_range) /mob/living/simple_animal/hostile/morph/AIShouldSleep(var/list/possible_targets) . = ..() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 65854bb1412..89321f2e1a8 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -10,6 +10,7 @@ power_channel = ENVIRON max_integrity = 350 armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100) + flags = PREVENT_CLICK_UNDER var/closingLayer = CLOSED_DOOR_LAYER var/visible = 1 var/operating = FALSE diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 16851097844..4090420525d 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -579,6 +579,7 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f dir = FULLTILE_WINDOW_DIR level = 3 fulltile = TRUE + flags = PREVENT_CLICK_UNDER /obj/structure/window/full/basic desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." @@ -675,6 +676,7 @@ obj/structure/window/full/reinforced/ice dir = FULLTILE_WINDOW_DIR max_integrity = 200 fulltile = TRUE + flags = PREVENT_CLICK_UNDER reinf = TRUE heat_resistance = 1600 armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) @@ -734,6 +736,7 @@ obj/structure/window/full/reinforced/ice smooth = SMOOTH_TRUE canSmoothWith = null fulltile = TRUE + flags = PREVENT_CLICK_UNDER dir = FULLTILE_WINDOW_DIR max_integrity = 120 level = 3 diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index 9a88dd50259..015921634fe 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -77,6 +77,7 @@ dir = FULLTILE_WINDOW_DIR max_integrity = 100 fulltile = TRUE + flags = PREVENT_CLICK_UNDER reinf = TRUE heat_resistance = 1600 armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100) @@ -296,7 +297,7 @@ name = "air flow blocker" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF unacidable = TRUE - invisibility = INVISIBILITY_ABSTRACT + invisibility = INVISIBILITY_ABSTRACT //Signs /obj/structure/sign/mining diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index e7036ad4f2f..7e55a60d387 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -15,7 +15,6 @@ a_intent = INTENT_HARM 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 - idle_vision_range = 5 move_to_delay = 10 health = 125 maxHealth = 125 @@ -145,7 +144,7 @@ /mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior() mode = MINEDRONE_COLLECT - idle_vision_range = 9 + vision_range = 9 search_objects = 2 wander = TRUE ranged = FALSE @@ -156,7 +155,7 @@ /mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior() mode = MINEDRONE_ATTACK - idle_vision_range = 7 + vision_range = 7 search_objects = 0 wander = FALSE ranged = TRUE diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 636df89885d..20f6155ba0f 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -1,10 +1,26 @@ +/mob/living/simple_animal/attackby(obj/item/O, mob/living/user) + if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) + var/obj/item/clothing/accessory/petcollar/C = O + if(user.drop_item()) + C.forceMove(src) + collar = C + collar.equipped(src) + regenerate_icons() + to_chat(usr, "You put \the [C] around \the [src]'s neck.") + if(C.tagname) + name = C.tagname + real_name = C.tagname + return + else + return ..() + /mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) ..() switch(M.a_intent) if(INTENT_HELP) if(health > 0) - visible_message("[M] [response_help] [src].") + visible_message("[M] [response_help] [src].", "[M] [response_help] you.") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(INTENT_GRAB) @@ -12,12 +28,12 @@ if(INTENT_HARM, INTENT_DISARM) M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - visible_message("[M] [response_harm] [src]!") + visible_message("[M] [response_harm] [src]!", "[M] [response_harm] you!") playsound(loc, attacked_sound, 25, 1, -1) attack_threshold_check(harm_intent_damage) add_attack_logs(M, src, "Melee attacked with fists") updatehealth() - return 1 + return TRUE /mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) if(user.a_intent == INTENT_HARM) @@ -39,10 +55,11 @@ /mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) if(..()) //successful larva bite - var/damage = rand(5, 10) if(stat != DEAD) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - attack_threshold_check(damage) + var/damage = rand(5, 10) + . = attack_threshold_check(damage) + if(.) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) /mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) if(..()) @@ -51,21 +68,57 @@ /mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M) ..() - var/damage = rand(1, 3) - + var/damage = rand(15, 25) if(M.is_adult) - damage = rand(20, 40) - else - damage = rand(5, 35) - + damage = rand(20, 35) attack_threshold_check(damage) - return -/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE) - if(damage <= force_threshold || !damage_coeff[damagetype]) - visible_message("[src] looks unharmed.") +/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = "melee") + var/temp_damage = damage + if(!damage_coeff[damagetype]) + temp_damage = 0 else - apply_damage(damage, damagetype) + temp_damage *= damage_coeff[damagetype] + + if(temp_damage >= 0 && temp_damage <= force_threshold) + visible_message("[src] looks unharmed.") + return FALSE + else + apply_damage(damage, damagetype, null, getarmor(null, armorcheck)) + return TRUE + +/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + apply_damage(Proj.damage, Proj.damage_type) + Proj.on_hit(src, 0) + return FALSE + +/mob/living/simple_animal/ex_act(severity, origin) + if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) + return + ..() + var/bomb_armor = getarmor(null, "bomb") + switch(severity) + if(1) + if(prob(bomb_armor)) + adjustBruteLoss(500) + else + gib() + return + if(2) + var/bloss = 60 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) + if(3) + var/bloss = 30 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) + +/mob/living/simple_animal/blob_act(obj/structure/blob/B) + adjustBruteLoss(20) /mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y) if(!no_effect && !visual_effect_icon && melee_damage_upper) diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm new file mode 100644 index 00000000000..6899b40bea0 --- /dev/null +++ b/code/modules/mob/living/simple_animal/damage_procs.dm @@ -0,0 +1,37 @@ + +/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE) + if(status_flags & GODMODE) + return FALSE + var/oldbruteloss = bruteloss + bruteloss = Clamp(bruteloss + amount, 0, maxHealth) + if(oldbruteloss == bruteloss) + updating_health = FALSE + . = STATUS_UPDATE_NONE + else + . = STATUS_UPDATE_HEALTH + if(updating_health) + updatehealth() + +/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE) + if(damage_coeff[BRUTE]) + return adjustHealth(amount * damage_coeff[BRUTE], updating_health) + +/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE) + if(damage_coeff[BURN]) + return adjustHealth(amount * damage_coeff[BURN], updating_health) + +/mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE) + if(damage_coeff[OXY]) + return adjustHealth(amount * damage_coeff[OXY], updating_health) + +/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE) + if(damage_coeff[TOX]) + return adjustHealth(amount * damage_coeff[TOX], updating_health) + +/mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE) + if(damage_coeff[CLONE]) + return adjustHealth(amount * damage_coeff[CLONE], updating_health) + +/mob/living/simple_animal/adjustStaminaLoss(amount, updating_health = TRUE) + if(damage_coeff[STAMINA]) + return ..(amount*damage_coeff[STAMINA], updating_health) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 4dea368ad5e..5f54f77c053 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -94,26 +94,26 @@ new cat_type(loc) -/mob/living/simple_animal/pet/cat/handle_automated_action() - ..() - if(prob(1)) - custom_emote(1, pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) - icon_state = "[icon_living]_rest" - resting = 1 - update_canmove() - else if (prob(1)) - custom_emote(1, pick("sits down.", "crouches on its hind legs.", "looks alert.")) - icon_state = "[icon_living]_sit" - resting = 1 - update_canmove() - else if (prob(1)) - if (resting) - custom_emote(1, pick("gets up and meows.", "walks around.", "stops resting.")) - icon_state = "[icon_living]" - resting = 0 +/mob/living/simple_animal/pet/cat/Life() + if(!stat && !buckled && !client) + if(prob(1)) + custom_emote(1, pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) + icon_state = "[icon_living]_rest" + resting = 1 update_canmove() - else - custom_emote(1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat.")) + else if (prob(1)) + custom_emote(1, pick("sits down.", "crouches on its hind legs.", "looks alert.")) + icon_state = "[icon_living]_sit" + resting = 1 + update_canmove() + else if (prob(1)) + if (resting) + custom_emote(1, pick("gets up and meows.", "walks around.", "stops resting.")) + icon_state = "[icon_living]" + resting = 0 + update_canmove() + else + custom_emote(1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat.")) //MICE! if(eats_mice && isturf(loc) && !incapacitated()) @@ -128,10 +128,11 @@ if(T.cooldown < (world.time - 400)) custom_emote(1, "bats \the [T] around with its paw!") T.cooldown = world.time + + ..() + make_babies() -/mob/living/simple_animal/pet/cat/handle_automated_movement() - ..() if(!stat && !resting && !buckled) turns_since_scan++ if(turns_since_scan > 5) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index bdb479997dc..729a7d0b47d 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -38,18 +38,20 @@ udder = null return ..() -/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement() - ..() - //chance to go crazy and start wacking stuff - if(!enemies.len && prob(1)) - Retaliate() +/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired) + . = ..() + if(.) + //chance to go crazy and start wacking stuff + if(!enemies.len && prob(1)) + Retaliate() - if(enemies.len && prob(10)) - enemies = list() - LoseTarget() - visible_message("[src] calms down.") + if(enemies.len && prob(10)) + enemies = list() + LoseTarget() + visible_message("[src] calms down.") if(stat == CONSCIOUS) + udder.generateMilk() eat_plants() if(!pulledby) for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) @@ -58,11 +60,6 @@ if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step) Move(step, get_dir(src, step)) -/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired) - . = ..() - if(stat == CONSCIOUS) - udder.generateMilk() - /mob/living/simple_animal/hostile/retaliate/goat/Retaliate() ..() visible_message("[src] gets an evil-looking gleam in their eye.") diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 2c9cbc355f7..da0a59c99b7 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -56,7 +56,7 @@ visible_message("[src] chews through [C].") /mob/living/simple_animal/mouse/handle_automated_speech() - ..() + ..() if(prob(speak_chance)) for(var/mob/M in view()) M << squeak_sound @@ -73,7 +73,7 @@ /mob/living/simple_animal/mouse/Life() ..() - if(prob(0.5) && !ckey) + if(!stat && prob(0.5) && !ckey) stat = UNCONSCIOUS icon_state = "mouse_[mouse_color]_sleep" wander = 0 @@ -119,7 +119,7 @@ desc = "It's toast." death() -/mob/living/simple_animal/mouse/death(gibbed) +/mob/living/simple_animal/mouse/death(gibbed) // Only execute the below if we successfully died playsound(src, squeak_sound, 40, 1) . = ..(gibbed) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 6795f4ccec2..d6d23871b1f 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -76,20 +76,20 @@ venom_per_bite = 10 move_to_delay = 5 -/mob/living/simple_animal/hostile/poison/giant_spider/hunter/handle_automated_action() +/mob/living/simple_animal/hostile/poison/giant_spider/handle_automated_action() if(!..()) //AIStatus is off - return + return 0 if(AIStatus == AI_IDLE) //1% chance to skitter madly away if(!busy && prob(1)) stop_automated_movement = 1 - Goto(pick(orange(20, src)), move_to_delay) + Goto(pick(urange(20, src, 1)), move_to_delay) spawn(50) stop_automated_movement = 0 walk(src,0) return 1 -/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(var/C) +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(C) spawn(100) if(busy == MOVING_TO_TARGET) if(cocoon_target == C && get_dist(src,cocoon_target) > 1) @@ -101,9 +101,9 @@ if(..()) var/list/can_see = view(src, 10) if(!busy && prob(30)) //30% chance to stop wandering and do something - //first, check for potential food nearby to cocoon + //first, check for potential food nearby to cocoon for(var/mob/living/C in can_see) - if(C.stat && !istype(C,/mob/living/simple_animal/hostile/poison/giant_spider)) + if(C.stat && !istype(C, /mob/living/simple_animal/hostile/poison/giant_spider) && !C.anchored) cocoon_target = C busy = MOVING_TO_TARGET Goto(C, move_to_delay) @@ -123,13 +123,14 @@ for(var/obj/O in can_see) if(O.anchored) continue - if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery)) - cocoon_target = O - busy = MOVING_TO_TARGET - stop_automated_movement = 1 - Goto(O, move_to_delay) - //give up if we can't reach them after 10 seconds - GiveUp(O) + + if(isitem(O) || isstructure(O) || ismachinery(O)) + cocoon_target = O + busy = MOVING_TO_TARGET + stop_automated_movement = 1 + Goto(O, move_to_delay) + //give up if we can't reach them after 10 seconds + GiveUp(O) else if(busy == MOVING_TO_TARGET && cocoon_target) if(get_dist(src, cocoon_target) <= 1) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index a96c78d09d6..da34a3b2827 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -2,60 +2,60 @@ faction = list("hostile") stop_automated_movement_when_pulled = 0 obj_damage = 40 - environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls + environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls var/atom/target - var/ranged = 0 - var/rapid = 0 - var/projectiletype + var/ranged = FALSE + var/rapid = 0 //How many shots per volley. + var/rapid_fire_delay = 2 //Time between rapid fire shots + + var/dodging = FALSE + var/approaching_target = FALSE //We should dodge now + var/in_melee = FALSE //We should sidestep now + var/dodge_prob = 30 + var/sidestep_per_cycle = 1 //How many sidesteps per npcpool cycle when in melee + + var/projectiletype //set ONLY it and NULLIFY casingtype var, if we have ONLY projectile var/projectilesound - var/casingtype + var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING var/move_to_delay = 3 //delay for the automated movement. var/list/friends = list() + var/list/emote_taunt = list() + var/taunt_chance = 0 + + var/rapid_melee = 1 //Number of melee attacks between each npc pool tick. Spread evenly. + var/melee_queue_distance = 4 //If target is close enough start preparing to hit them if we have rapid_melee enabled + var/ranged_message = "fires" //Fluff text for ranged mobs - var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks + var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat. var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance + //These vars are related to how mobs locate and target var/robust_searching = 0 //By default, mobs have a simple searching method, set this to 1 for the more scrutinous searching (stat_attack, stat_exclusive, etc), should be disabled on most mobs var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius - var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3 - var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled - var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead. - var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses - var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction - - //typecache of things this mob will attack in DestroySurroundings() if it has environment_smash - var/list/environment_target_typecache = list( - /obj/machinery/door/window, - /obj/structure/window, - /obj/structure/closet, - /obj/structure/table, - /obj/structure/grille, - /obj/structure/girder, - /obj/structure/rack, - /obj/structure/computerframe, - /obj/machinery/constructable_frame, - /obj/structure/barricade) //turned into a typecache in New() + var/search_objects_timer_id //Timer for regaining our old search_objects value after being attacked + var/search_objects_regain_time = 30 //the delay between being attacked and gaining our old search_objects value back + var/list/wanted_objects = list() //A typecache of objects types that will be checked against to attack, should we have search_objects enabled + var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead. + var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses + var/attack_same = 0 //Set us to 1 to allow us to attack our own faction var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such - var/list/emote_taunt = list() - var/taunt_chance = 0 + var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects. var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach var/lose_patience_timeout = 300 //30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever - var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects. +/mob/living/simple_animal/hostile/Initialize(mapload) + . = ..() -/mob/living/simple_animal/hostile/New() - ..() if(!targets_from) targets_from = src - environment_target_typecache = typecacheof(environment_target_typecache) wanted_objects = typecacheof(wanted_objects) /mob/living/simple_animal/hostile/Destroy() @@ -73,16 +73,46 @@ if(AIStatus == AI_OFF) return 0 var/list/possible_targets = ListTargets() //we look around for potential targets and make it a list for later use. + if(environment_smash) EscapeConfinement() if(AICanContinue(possible_targets)) - DestroySurroundings() + if(!QDELETED(target) && !targets_from.Adjacent(target)) + DestroyPathToTarget() if(!MoveToTarget(possible_targets)) //if we lose our target if(AIShouldSleep(possible_targets)) // we try to acquire a new one toggle_ai(AI_IDLE) // otherwise we go idle return 1 +/mob/living/simple_animal/hostile/handle_automated_movement() + . = ..() + if(dodging && target && in_melee && isturf(loc) && isturf(target.loc)) + var/datum/cb = CALLBACK(src,.proc/sidestep) + if(sidestep_per_cycle > 1) //For more than one just spread them equally - this could changed to some sensible distribution later + var/sidestep_delay = SSnpcpool.wait / sidestep_per_cycle + for(var/i in 1 to sidestep_per_cycle) + addtimer(cb, (i - 1) * sidestep_delay) + else //Otherwise randomize it to make the players guessing. + addtimer(cb,rand(1, SSnpcpool.wait)) + +/mob/living/simple_animal/hostile/proc/sidestep() + if(!target || !isturf(target.loc) || !isturf(loc) || stat == DEAD) + return + var/target_dir = get_dir(src, target) + + var/static/list/cardinal_sidestep_directions = list(-90, -45, 0, 45, 90) + var/static/list/diagonal_sidestep_directions = list(-45, 0, 45) + var/chosen_dir = 0 + if (target_dir & (target_dir - 1)) + chosen_dir = pick(diagonal_sidestep_directions) + else + chosen_dir = pick(cardinal_sidestep_directions) + if(chosen_dir) + chosen_dir = turn(target_dir, chosen_dir) + Move(get_step(src, chosen_dir)) + face_atom(target) //Looks better if they keep looking at you when dodging + /mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user) if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client && user) FindTarget(list(user), 1) @@ -97,7 +127,6 @@ //////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// - /mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see if(!search_objects) . = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide @@ -108,7 +137,11 @@ if(can_see(targets_from, HM, vision_range)) . += HM else - . = oview(vision_range, targets_from) + . = list() // The following code is only very slightly slower than just returning oview(vision_range, targets_from), but it saves us much more work down the line, particularly when bees are involved + for(var/obj/A in oview(vision_range, targets_from)) + . += A + for(var/mob/A in oview(vision_range, targets_from)) + . += A /mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about . = list() @@ -153,59 +186,61 @@ var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random return chosen_target -/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target? - if(!the_target) - return 0 - if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it - return 0 +// Please do not add one-off mob AIs here, but override this function for your mob +/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target? + if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids + return FALSE + + if(ismob(the_target)) //Target is in godmode, ignore it. + var/mob/M = the_target + if(M.status_flags & GODMODE) + return FALSE + + if(see_invisible < the_target.invisibility) //Target's invisible to us, forget it + return FALSE if(search_objects < 2) if(isliving(the_target)) var/mob/living/L = the_target - var/faction_check = faction_check(L) + var/faction_check = faction_check_mob(L) if(robust_searching) - if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1) - return 0 - if(faction_check && !attack_same || !faction_check && attack_same == 2) - return 0 - if(L in friends) - return 0 - else - if(L.stat) - return 0 if(faction_check && !attack_same) - return 0 - return 1 + return FALSE + if(L.stat > stat_attack) + return FALSE + if(L in friends) + return FALSE + else + if((faction_check && !attack_same) || L.stat) + return FALSE + return TRUE - if(ishuman(the_target)) - var/mob/living/carbon/human/H = the_target - if(is_type_in_list(src, H.dna.species.ignored_by)) - return 0 - - if(istype(the_target, /obj/mecha)) + if(ismecha(the_target)) var/obj/mecha/M = the_target if(M.occupant)//Just so we don't attack empty mechs if(CanAttack(M.occupant)) - return 1 + return TRUE - if(istype(the_target, /obj/spacepod)) + if(isspacepod(the_target)) var/obj/spacepod/S = the_target - if(S.pilot) //Just so we don't attack empty pods + if(S.pilot)//Just so we don't attack empty mechs if(CanAttack(S.pilot)) - return 1 + return TRUE if(istype(the_target, /obj/machinery/porta_turret)) var/obj/machinery/porta_turret/P = the_target if(P.faction in faction) - return 0 + return FALSE if(!P.raised) //Don't attack invincible turrets - return 0 + return FALSE if(P.stat & BROKEN) //Or turrets that are already broken - return 0 - return 1 + return FALSE + return TRUE + if(isobj(the_target)) - if(attack_all_objects || is_type_in_list(the_target, wanted_objects)) - return 1 - return 0 + if(attack_all_objects || is_type_in_typecache(the_target, wanted_objects)) + return TRUE + + return FALSE /mob/living/simple_animal/hostile/proc/GiveTarget(new_target)//Step 4, give us our selected target target = new_target @@ -215,19 +250,39 @@ Aggro() return 1 -/mob/living/simple_animal/hostile/proc/MoveToTarget(var/list/possible_targets)//Step 5, handle movement between us and our target +//What we do after closing in +/mob/living/simple_animal/hostile/proc/MeleeAction(patience = TRUE) + if(rapid_melee > 1) + var/datum/callback/cb = CALLBACK(src, .proc/CheckAndAttack) + var/delay = SSnpcpool.wait / rapid_melee + for(var/i in 1 to rapid_melee) + addtimer(cb, (i - 1)*delay) + else + AttackingTarget() + if(patience) + GainPatience() + +/mob/living/simple_animal/hostile/proc/CheckAndAttack() + if(target && targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && !incapacitated()) + AttackingTarget() + +/mob/living/simple_animal/hostile/proc/MoveToTarget(list/possible_targets)//Step 5, handle movement between us and our target stop_automated_movement = 1 if(!target || !CanAttack(target)) LoseTarget() return 0 if(target in possible_targets) - if(target.z != z) + var/turf/T = get_turf(src) + if(target.z != T.z) LoseTarget() return 0 var/target_distance = get_dist(targets_from,target) if(ranged) //We ranged? Shoot at em if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown OpenFire(target) + if(!Process_Spacemove()) //Drifting + walk(src,0) + return 1 if(retreat_distance != null) //If we have a retreat distance, check if we need to run from our target if(target_distance <= retreat_distance) //If target's closer than our retreat distance, run walk_away(src,target,retreat_distance,move_to_delay) @@ -237,8 +292,11 @@ Goto(target,move_to_delay,minimum_distance) if(target) if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack - AttackingTarget() - GainPatience() + MeleeAction() + else + if(rapid_melee > 1 && target_distance <= melee_queue_distance) + MeleeAction(FALSE) + in_melee = FALSE //If we're just preparing to strike do not enter sidestep mode return 1 return 0 if(environment_smash) @@ -256,14 +314,18 @@ return 0 /mob/living/simple_animal/hostile/proc/Goto(target, delay, minimum_distance) + if(target == src.target) + approaching_target = TRUE + else + approaching_target = FALSE walk_to(src, target, minimum_distance, delay) -/mob/living/simple_animal/hostile/adjustHealth(damage) +/mob/living/simple_animal/hostile/adjustHealth(damage, updating_health = TRUE) . = ..() if(!ckey && !stat && search_objects < 3 && damage > 0)//Not unconscious, and we don't ignore mobs if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight - search_objects = 0 target = null + LoseSearchObjects() if(AIStatus != AI_ON && AIStatus != AI_OFF) toggle_ai(AI_ON) FindTarget() @@ -271,7 +333,9 @@ FindTarget() /mob/living/simple_animal/hostile/proc/AttackingTarget() - target.attack_animal(src) + SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target) + in_melee = TRUE + return target.attack_animal(src) /mob/living/simple_animal/hostile/proc/Aggro() vision_range = aggro_vision_range @@ -281,11 +345,13 @@ /mob/living/simple_animal/hostile/proc/LoseAggro() stop_automated_movement = 0 - vision_range = idle_vision_range + vision_range = initial(vision_range) taunt_chance = initial(taunt_chance) /mob/living/simple_animal/hostile/proc/LoseTarget() target = null + approaching_target = FALSE + in_melee = FALSE walk(src, 0) LoseAggro() @@ -302,8 +368,7 @@ do_alert_animation(src) playsound(loc, 'sound/machines/chime.ogg', 50, 1, -1) for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from)) - var/list/L = M.faction&faction - if(L.len) + if(faction_check_mob(M, TRUE)) if(M.AIStatus == AI_OFF) return else @@ -323,21 +388,18 @@ return visible_message("[src] [ranged_message] at [A]!") - if(rapid) - spawn(1) - Shoot(A) - spawn(4) - Shoot(A) - spawn(6) - Shoot(A) + + if(rapid > 1) + var/datum/callback/cb = CALLBACK(src, .proc/Shoot, A) + for(var/i in 1 to rapid) + addtimer(cb, (i - 1)*rapid_fire_delay) else Shoot(A) ranged_cooldown = world.time + ranged_cooldown_time /mob/living/simple_animal/hostile/proc/Shoot(atom/targeted_atom) - if(targeted_atom == targets_from.loc || targeted_atom == targets_from) + if( QDELETED(targeted_atom) || targeted_atom == targets_from.loc || targeted_atom == targets_from ) return - var/turf/startloc = get_turf(targets_from) if(casingtype) var/obj/item/ammo_casing/casing = new casingtype(startloc) @@ -354,32 +416,70 @@ if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space newtonian_move(get_dir(targeted_atom, targets_from)) P.original = targeted_atom + P.preparePixelProjectile(targeted_atom, get_turf(targeted_atom), src) P.fire() return P -/mob/living/simple_animal/hostile/proc/DestroySurroundings() +/mob/living/simple_animal/hostile/proc/CanSmashTurfs(turf/T) + return iswallturf(T) || ismineralturf(T) + +/mob/living/simple_animal/hostile/Move(atom/newloc, dir , step_x , step_y) + if(dodging && approaching_target && prob(dodge_prob) && moving_diagonally == 0 && isturf(loc) && isturf(newloc)) + return dodge(newloc, dir) + else + return ..() + +/mob/living/simple_animal/hostile/proc/dodge(moving_to,move_direction) + //Assuming we move towards the target we want to swerve toward them to get closer + var/cdir = turn(move_direction, 45) + var/ccdir = turn(move_direction, -45) + dodging = FALSE + . = Move(get_step(loc,pick(cdir,ccdir))) + if(!.)//Can't dodge there so we just carry on + . = Move(moving_to,move_direction) + dodging = TRUE + +/mob/living/simple_animal/hostile/proc/DestroyObjectsInDirection(direction) + var/turf/T = get_step(targets_from, direction) + if(QDELETED(T)) + return + if(T.Adjacent(targets_from)) + if(CanSmashTurfs(T)) + T.attack_animal(src) + return + for(var/obj/O in T.contents) + if(!O.Adjacent(targets_from)) + continue + if((ismachinery(O) || isstructure(O)) && O.density && environment_smash >= ENVIRONMENT_SMASH_STRUCTURES && !O.IsObscured()) + O.attack_animal(src) + return + +/mob/living/simple_animal/hostile/proc/DestroyPathToTarget() + if(environment_smash) + EscapeConfinement() + var/dir_to_target = get_dir(targets_from, target) + var/dir_list = list() + if(dir_to_target in diagonals) //it's diagonal, so we need two directions to hit + for(var/direction in cardinal) + if(direction & dir_to_target) + dir_list += direction + else + dir_list += dir_to_target + for(var/direction in dir_list) //now we hit all of the directions we got in this fashion, since it's the only directions we should actually need + DestroyObjectsInDirection(direction) + +/mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with megafauna destroying everything around them if(environment_smash) EscapeConfinement() for(var/dir in cardinal) - var/turf/T = get_step(targets_from, dir) - if(iswallturf(T) || ismineralturf(T)) - if(T.Adjacent(targets_from)) - T.attack_animal(src) - for(var/a in T) - var/atom/A = a - if(!A.Adjacent(targets_from)) - continue - if(is_type_in_typecache(A, environment_target_typecache)) - A.attack_animal(src) - return + DestroyObjectsInDirection(dir) /mob/living/simple_animal/hostile/proc/EscapeConfinement() if(buckled) buckled.attack_animal(src) if(!isturf(targets_from.loc) && targets_from.loc != null)//Did someone put us in something? - var/atom/A = get_turf(targets_from) + var/atom/A = targets_from.loc A.attack_animal(src)//Bang on it till we get out - return /mob/living/simple_animal/hostile/proc/FindHidden() if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper) || istype(target.loc, /obj/machinery/bodyscanner) || istype(target.loc, /obj/machinery/recharge_station)) @@ -420,9 +520,23 @@ LosePatience() lose_patience_timer_id = addtimer(CALLBACK(src, .proc/LoseTarget), lose_patience_timeout, TIMER_STOPPABLE) + /mob/living/simple_animal/hostile/proc/LosePatience() deltimer(lose_patience_timer_id) + +//These two procs handle losing and regaining search_objects when attacked by a mob +/mob/living/simple_animal/hostile/proc/LoseSearchObjects() + search_objects = 0 + deltimer(search_objects_timer_id) + search_objects_timer_id = addtimer(CALLBACK(src, .proc/RegainSearchObjects), search_objects_regain_time, TIMER_STOPPABLE) + + +/mob/living/simple_animal/hostile/proc/RegainSearchObjects(value) + if(!value) + value = initial(search_objects) + search_objects = value + /mob/living/simple_animal/hostile/consider_wakeup() ..() var/list/tlist @@ -455,4 +569,4 @@ if(isturf(M.loc)) . += M else if(M.loc.type in hostile_machines) - . += M.loc + . += M.loc \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 027bbb60a14..5a36c3fffa9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -46,7 +46,6 @@ Difficulty: Medium loot = list(/obj/item/stack/sheet/bone = 3) vision_range = 13 elimination = 1 - idle_vision_range = 13 appearance_flags = 0 mouse_opacity = MOUSE_OPACITY_ICON stat_attack = 1 // Overriden from /tg/ - otherwise Legion starts chasing its minions diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index f57559d549a..c5f11c501fc 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -18,19 +18,8 @@ damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) minbodytemp = 0 maxbodytemp = INFINITY + vision_range = 5 aggro_vision_range = 18 - idle_vision_range = 5 - environment_target_typecache = list( - /obj/machinery/door/window, - /obj/structure/window, - /obj/structure/closet, - /obj/structure/table, - /obj/structure/grille, - /obj/structure/girder, - /obj/structure/rack, - /obj/structure/barricade, - /obj/machinery/field, - /obj/machinery/power/emitter) var/list/crusher_loot var/medal_type var/score_type = BOSS_SCORE diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm index ad8dcf44699..4dca1caeb29 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm @@ -26,8 +26,8 @@ a_intent = INTENT_HARM speak_emote = list("chitters") attack_sound = 'sound/weapons/bladeslice.ogg' + vision_range = 2 aggro_vision_range = 9 - idle_vision_range = 2 turns_per_move = 5 loot = list(/obj/item/stack/ore/diamond{layer = 4.1}, /obj/item/stack/ore/diamond{layer = 4.1}) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm index cd73868a9e7..7de8935e5ca 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm @@ -8,8 +8,8 @@ icon_dead = "Goldgrub_dead" icon_gib = "syndicate_gib" vision_range = 2 + vision_range = 2 aggro_vision_range = 9 - idle_vision_range = 2 move_to_delay = 5 friendly = "harmlessly rolls into" maxHealth = 45 @@ -77,5 +77,5 @@ return /mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(damage) - idle_vision_range = 9 + vision_range = 9 . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm index dae7a688cb3..84b919266d0 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm @@ -26,8 +26,8 @@ attacktext = "pulverizes" attack_sound = 'sound/weapons/punch1.ogg' throw_message = "does nothing to the rocky hide of the" + vision_range = 5 aggro_vision_range = 9 - idle_vision_range = 5 move_force = MOVE_FORCE_VERY_STRONG move_resist = MOVE_FORCE_VERY_STRONG pull_force = MOVE_FORCE_VERY_STRONG diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm index 6e5c840a401..491e35cc621 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm @@ -38,7 +38,7 @@ animal_species = /mob/living/simple_animal/hostile/asteroid/gutlunch childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck = 45, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen = 55) - wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs) + wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/organ/internal) var/obj/item/udder/gutlunch/udder = null /mob/living/simple_animal/hostile/asteroid/gutlunch/New() diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index 43d239c59ce..ca8644e0566 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -11,8 +11,8 @@ move_to_delay = 14 ranged = 1 vision_range = 5 + vision_range = 5 aggro_vision_range = 9 - idle_vision_range = 5 speed = 3 maxHealth = 75 health = 75 diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 2e1e7508e1c..487ce431cdf 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -36,7 +36,6 @@ see_in_dark = 8 vision_range = 12 aggro_vision_range = 12 - idle_vision_range = 12 search_objects = 1 // So that it can see through walls diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm index 2f124e94479..8e53dc7cbbe 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -23,7 +23,7 @@ regen_points_per_hp = 2 // 50% higher regen speed stat_attack = 1 // ensures they will target people in crit, too! wander = 0 // wandering defeats the purpose of stealth - idle_vision_range = 3 // very low idle vision range + vision_range = 3 // very low idle vision range delay_web = 20 // double speed web_type = /obj/structure/spider/terrorweb/gray @@ -67,7 +67,6 @@ icon_living = "terror_gray_cloaked" if(!ckey) vision_range = 3 - idle_vision_range = 3 // Bugged, does not work yet. Also spams webs. Also doesn't look great. But... planned. move_to_delay = 15 // while invisible, slow. @@ -76,7 +75,6 @@ icon_state = "terror_gray" icon_living = "terror_gray" vision_range = 9 - idle_vision_range = 9 move_to_delay = 5 prob_ai_hides_in_vents = 10 diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm index 5b82f8d35dd..dba6853bc15 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -92,7 +92,7 @@ var/global/list/ts_spiderling_list = list() var/degenerate = 0 // if 1, they slowly degen until they all die off. Used by high-level abilities only. // Vision - idle_vision_range = 10 + vision_range = 10 aggro_vision_range = 10 see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 6955633efce..630d78ef085 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -3,15 +3,17 @@ icon = 'icons/mob/animal.dmi' health = 20 maxHealth = 20 + gender = PLURAL //placeholder + universal_understand = 1 + universal_speak = 0 status_flags = CANPUSH var/icon_living = "" var/icon_dead = "" var/icon_resting = "" var/icon_gib = null //We only try to show a gibbing animation if this exists. - - var/healable = 1 + var/flip_on_death = FALSE //Flip the sprite upside down on death. Mostly here for things lacking custom dead sprites. var/list/speak = list() var/speak_chance = 0 @@ -20,7 +22,6 @@ var/turns_per_move = 1 var/turns_since_move = 0 - universal_speak = 0 var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. var/wander = 1 // Does the mob wander around when idle? var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. @@ -38,11 +39,13 @@ var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp + //Healable by medical stacks? Defaults to yes. + var/healable = 1 + //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage var/list/atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) //Leaving something at 0 means it's off - has no maximum var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above - //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly var/melee_damage_lower = 0 var/melee_damage_upper = 0 @@ -53,7 +56,7 @@ var/attacktext = "attacks" var/attack_sound = null var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls + var/environment_smash = ENVIRONMENT_SMASH_NONE //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls var/speed = 1 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster var/can_hide = 0 @@ -66,6 +69,7 @@ var/next_scan_time = 0 var/animal_species //Sorry, no spider+corgi buttbabies. + var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against var/gold_core_spawnable = CHEM_MOB_SPAWN_INVALID //if CHEM_MOB_SPAWN_HOSTILE can be spawned by plasma with gold core, CHEM_MOB_SPAWN_FRIENDLY are 'friendlies' spawned with blood var/mob/living/carbon/human/master_commander = null //holding var for determining who own/controls a sentient simple animal (for sentience potions). @@ -73,20 +77,35 @@ var/mob/living/simple_animal/hostile/spawner/nest var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions + var/list/loot = list() //list of things spawned at mob's loc when it dies var/del_on_death = 0 //causes mob to be deleted on death, useful for mobs that spawn lootable corpses - var/attacked_sound = "punch" var/deathmessage = "" var/death_sound = null //The sound played on death + var/allow_movement_on_non_turfs = FALSE + + var/attacked_sound = "punch" + var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) var/can_have_ai = TRUE //once we have become sentient, we can never go back + var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. + //domestication + var/tame = 0 -/mob/living/simple_animal/Initialize() - ..() + var/my_z // I don't want to confuse this with client registered_z + +/mob/living/simple_animal/Initialize(mapload) + . = ..() GLOB.simple_animals[AIStatus] += src + if(gender == PLURAL) + gender = pick(MALE, FEMALE) + if(!real_name) + real_name = name + if(!loc) + stack_trace("Simple animal being instantiated in nullspace") verbs -= /mob/verb/observe if(!can_hide) verbs -= /mob/living/simple_animal/verb/hide @@ -114,11 +133,10 @@ return ..() -/mob/living/simple_animal/Login() - if(src && src.client) - src.client.screen = list() - client.screen += client.void - ..() +/mob/living/simple_animal/examine(mob/user) + . = ..() + if(stat == DEAD) + to_chat(user, "Upon closer examination, [p_they()] appear[p_s()] to be dead.") /mob/living/simple_animal/updatehealth(reason = "none given") ..(reason) @@ -147,11 +165,13 @@ create_debug_log("died of damage, trigger reason: [reason]") /mob/living/simple_animal/proc/handle_automated_action() + set waitfor = FALSE return /mob/living/simple_animal/proc/handle_automated_movement() + set waitfor = FALSE if(!stop_automated_movement && wander) - if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. + if((isturf(loc) || allow_movement_on_non_turfs) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. turns_since_move++ if(turns_since_move >= turns_per_move) if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled @@ -159,11 +179,12 @@ if(Process_Spacemove(anydir)) Move(get_step(src,anydir), anydir) turns_since_move = 0 - return + return 1 -/mob/living/simple_animal/proc/handle_automated_speech() +/mob/living/simple_animal/proc/handle_automated_speech(override) + set waitfor = FALSE if(speak_chance) - if(rand(0,200) < speak_chance) + if(prob(speak_chance) || override) if(speak && speak.len) if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) var/length = speak.len @@ -201,7 +222,7 @@ var/areatemp = get_temperature(environment) - if(abs(areatemp - bodytemperature) > 40 && !(BREATHLESS in mutations)) + if(abs(areatemp - bodytemperature) > 5 && !(BREATHLESS in mutations)) var/diff = areatemp - bodytemperature diff = diff / 5 bodytemperature += diff @@ -242,30 +263,24 @@ atmos_suitable = 0 if(!atmos_suitable) - adjustBruteLoss(unsuitable_atmos_damage) + adjustHealth(unsuitable_atmos_damage) handle_temperature_damage() /mob/living/simple_animal/proc/handle_temperature_damage() - if(bodytemperature < minbodytemp) - adjustBruteLoss(cold_damage_per_tick) - else if(bodytemperature > maxbodytemp) - adjustBruteLoss(heat_damage_per_tick) + if((bodytemperature < minbodytemp) || (bodytemperature > maxbodytemp)) + adjustHealth(unsuitable_atmos_damage) /mob/living/simple_animal/gib() if(icon_gib) flick(icon_gib, src) if(butcher_results) + var/atom/Tsec = drop_location() for(var/path in butcher_results) - for(var/i = 1; i <= butcher_results[path];i++) - new path(src.loc) + for(var/i in 1 to butcher_results[path]) + new path(Tsec) ..() - -/mob/living/simple_animal/blob_act() - adjustBruteLoss(20) - return - /mob/living/simple_animal/emote(act, m_type = 1, message = null, force) if(stat) return @@ -279,29 +294,13 @@ ..() -/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) - if(!Proj) - return - if((Proj.damage_type != STAMINA)) - adjustBruteLoss(Proj.damage) - Proj.on_hit(src, 0) - return FALSE +/mob/living/simple_animal/say_quote(message) + var/verb = "says" -/mob/living/simple_animal/attackby(obj/item/O, mob/living/user) - if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) - var/obj/item/clothing/accessory/petcollar/C = O - user.drop_item() - C.forceMove(src) - collar = C - collar.equipped(src) - regenerate_icons() - to_chat(usr, "You put \the [C] around \the [src]'s neck.") - if(C.tagname) - name = C.tagname - real_name = C.tagname - return - else - ..() + if(speak_emote.len) + verb = pick(speak_emote) + + return verb /mob/living/simple_animal/movement_delay() . = ..() @@ -312,21 +311,25 @@ /mob/living/simple_animal/Stat() ..() + if(statpanel("Status")) + stat(null, "Health: [round((health / maxHealth) * 100)]%") + return TRUE - statpanel("Status") - stat(null, "Health: [round((health / maxHealth) * 100)]%") +/mob/living/simple_animal/proc/drop_loot() + if(loot.len) + for(var/i in loot) + new i(loc) /mob/living/simple_animal/death(gibbed) // Only execute the below if we successfully died . = ..() if(!.) return FALSE + flying = FALSE if(nest) nest.spawned_mobs -= src nest = null - if(loot.len) - for(var/i in loot) - new i(loc) + drop_loot() if(!gibbed) if(death_sound) playsound(get_turf(src),death_sound, 200, 1) @@ -335,87 +338,41 @@ else if(!del_on_death) visible_message("\The [src] stops moving...") if(del_on_death) + //Prevent infinite loops if the mob Destroy() is overridden in such + //a manner as to cause a call to death() again + del_on_death = FALSE ghostize() qdel(src) else health = 0 icon_state = icon_dead + if(flip_on_death) + transform = transform.Turn(180) density = 0 - lying = 1 -/mob/living/simple_animal/ex_act(severity) - ..() - switch(severity) - if(1.0) - gib() - return - - if(2.0) - adjustBruteLoss(60) - - - if(3.0) - adjustBruteLoss(30) - -/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE) - if(status_flags & GODMODE) - return FALSE - var/oldbruteloss = bruteloss - bruteloss = Clamp(bruteloss + amount, 0, maxHealth) - if(oldbruteloss == bruteloss) - updating_health = FALSE - . = STATUS_UPDATE_NONE - else - . = STATUS_UPDATE_HEALTH - if(updating_health) - updatehealth() - -/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE) - if(damage_coeff[BRUTE]) - return adjustHealth(amount * damage_coeff[BRUTE], updating_health) - -/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE) - if(damage_coeff[BURN]) - return adjustHealth(amount * damage_coeff[BURN], updating_health) - -/mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE) - if(damage_coeff[OXY]) - return adjustHealth(amount * damage_coeff[OXY], updating_health) - -/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE) - if(damage_coeff[TOX]) - return adjustHealth(amount * damage_coeff[TOX], updating_health) - -/mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE) - if(damage_coeff[CLONE]) - return adjustHealth(amount * damage_coeff[CLONE], updating_health) - -/mob/living/simple_animal/adjustStaminaLoss(amount, updating_health = TRUE) - if(damage_coeff[STAMINA]) - return ..(amount*damage_coeff[STAMINA], updating_health) - -/mob/living/simple_animal/proc/CanAttack(var/atom/the_target) +/mob/living/simple_animal/proc/CanAttack(atom/the_target) if(see_invisible < the_target.invisibility) return FALSE + if(ismob(the_target)) + var/mob/M = the_target + if(M.status_flags & GODMODE) + return FALSE if(isliving(the_target)) var/mob/living/L = the_target if(L.stat != CONSCIOUS) return FALSE - if(istype(the_target, /obj/mecha)) + if(ismecha(the_target)) var/obj/mecha/M = the_target if(M.occupant) return FALSE - if(istype(the_target,/obj/spacepod)) + if(isspacepod(the_target)) var/obj/spacepod/S = the_target if(S.pilot) return FALSE return TRUE /mob/living/simple_animal/handle_fire() - return - -/mob/living/simple_animal/update_fire() - return + return TRUE /mob/living/simple_animal/IgniteMob() return FALSE @@ -423,32 +380,20 @@ /mob/living/simple_animal/ExtinguishMob() return -/mob/living/simple_animal/update_transform() - var/matrix/ntransform = matrix(transform) //aka transform.Copy() - var/changed = 0 - - if(resize != RESIZE_DEFAULT_SIZE) - changed++ - ntransform.Scale(resize) - resize = RESIZE_DEFAULT_SIZE - - if(changed) - animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT) - /mob/living/simple_animal/revive() ..() health = maxHealth + icon = initial(icon) icon_state = icon_living density = initial(density) update_canmove() - - + flying = initial(flying) /mob/living/simple_animal/proc/make_babies() // <3 <3 <3 if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress()) return FALSE next_scan_time = world.time + 400 - + var/alone = TRUE var/mob/living/simple_animal/partner var/children = 0 @@ -472,42 +417,6 @@ if(target) return new childspawn(target) -/mob/living/simple_animal/say_quote(var/message) - var/verb = "says" - - if(speak_emote.len) - verb = pick(speak_emote) - - return verb - -/mob/living/simple_animal/update_canmove(delay_action_updates = 0) - if(paralysis || stunned || weakened || stat || resting) - drop_r_hand() - drop_l_hand() - canmove = 0 - else if(buckled) - canmove = 0 - else - canmove = 1 - update_transform() - if(!delay_action_updates) - update_action_buttons_icon() - return canmove - -/mob/living/simple_animal/update_transform() - var/matrix/ntransform = matrix(transform) //aka transform.Copy() - var/changed = 0 - - if(resize != RESIZE_DEFAULT_SIZE) - changed++ - ntransform.Scale(resize) - resize = RESIZE_DEFAULT_SIZE - - if(changed) - animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT) - -/* Inventory */ - /mob/living/simple_animal/show_inv(mob/user as mob) if(!can_collar) return @@ -572,50 +481,36 @@ if(collar) . |= collar.GetAccess() -/* End Inventory */ +/mob/living/simple_animal/update_canmove(delay_action_updates = 0) + if(paralysis || stunned || weakened || stat || resting) + drop_r_hand() + drop_l_hand() + canmove = 0 + else if(buckled) + canmove = 0 + else + canmove = 1 + update_transform() + if(!delay_action_updates) + update_action_buttons_icon() + return canmove + +/mob/living/simple_animal/update_transform() + var/matrix/ntransform = matrix(transform) //aka transform.Copy() + var/changed = FALSE + + if(resize != RESIZE_DEFAULT_SIZE) + changed = TRUE + ntransform.Scale(resize) + resize = RESIZE_DEFAULT_SIZE + + if(changed) + animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT) /mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion toggle_ai(AI_OFF) can_have_ai = FALSE - return -/mob/living/simple_animal/can_hear() - . = TRUE - -/mob/living/simple_animal/proc/consider_wakeup() - if(pulledby || shouldwakeup) - toggle_ai(AI_ON) - -/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(!ckey && !stat)//Not unconscious - if(AIStatus == AI_IDLE) - toggle_ai(AI_ON) - -/mob/living/simple_animal/proc/toggle_ai(togglestatus) - if(!can_have_ai && (togglestatus != AI_OFF)) - return - if(AIStatus != togglestatus) - if(togglestatus > 0 && togglestatus < 5) - if(togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF) - var/turf/T = get_turf(src) - if(AIStatus == AI_Z_OFF) - SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src - else - SSidlenpcpool.idle_mobs_by_zlevel[T.z] += src - GLOB.simple_animals[AIStatus] -= src - GLOB.simple_animals[togglestatus] += src - AIStatus = togglestatus - else - stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]") - -/mob/living/simple_animal/onTransitZ(old_z, new_z) - ..() - if(AIStatus == AI_Z_OFF) - SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src - toggle_ai(initial(AIStatus)) - -// Simple animals will not be given night vision upon death, as that would result in issues when they are revived. /mob/living/simple_animal/grant_death_vision() sight |= SEE_TURFS sight |= SEE_MOBS @@ -642,4 +537,37 @@ return SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT) - sync_lighting_plane_alpha() \ No newline at end of file + sync_lighting_plane_alpha() + +/mob/living/simple_animal/proc/toggle_ai(togglestatus) + if(!can_have_ai && (togglestatus != AI_OFF)) + return + if(AIStatus != togglestatus) + if(togglestatus > 0 && togglestatus < 5) + if(togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF) + var/turf/T = get_turf(src) + if(AIStatus == AI_Z_OFF) + SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src + else + SSidlenpcpool.idle_mobs_by_zlevel[T.z] += src + GLOB.simple_animals[AIStatus] -= src + GLOB.simple_animals[togglestatus] += src + AIStatus = togglestatus + else + stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]") + +/mob/living/simple_animal/proc/consider_wakeup() + if(pulledby || shouldwakeup) + toggle_ai(AI_ON) + +/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE) + . = ..() + if(!ckey && !stat)//Not unconscious + if(AIStatus == AI_IDLE) + toggle_ai(AI_ON) + +/mob/living/simple_animal/onTransitZ(old_z, new_z) + ..() + if(AIStatus == AI_Z_OFF) + SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src + toggle_ai(initial(AIStatus)) \ No newline at end of file diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index f5f1924e395..66b4f2f9a16 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -56,9 +56,6 @@ if(abilities) client.verbs |= abilities - if(ishuman(src)) - client.screen += client.void - //HUD updates (antag hud, etc) //readd this mob's HUDs (antag, med, etc) reload_huds() diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 6209ce84949219b3688d7d0b099b0fbbc8d93d58..78778b27d97ed433d343728aeb7348a0673d7b4f 100644 GIT binary patch delta 15605 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 delta 15548 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 oCrxOBw|3^Y?f=$G2HYS~j7k{LH9W Date: Fri, 30 Aug 2019 20:59:20 -0400 Subject: [PATCH 02/13] ahhh that'd do it --- code/modules/mob/living/carbon/human/human.dm | 3 --- code/modules/mob/living/living.dm | 5 +++-- code/modules/mob/living/simple_animal/hostile/headcrab.dm | 4 ++-- .../mob/living/simple_animal/hostile/megafauna/bubblegum.dm | 6 +++--- .../living/simple_animal/hostile/megafauna/hierophant.dm | 4 ++-- code/modules/mob/living/simple_animal/hostile/syndicate.dm | 4 ++-- .../mob/living/simple_animal/hostile/venus_human_trap.dm | 2 +- code/modules/mob/mob.dm | 6 ------ 8 files changed, 13 insertions(+), 21 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 11d2e2b1395..a304d35a953 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -34,9 +34,6 @@ handcrafting = new() - var/mob/M = src - faction |= "\ref[M]" //what - // Set up DNA. if(dna) dna.ready_dna(src) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 57c67f5fd61..7ec7fea1dff 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2,6 +2,7 @@ . = ..() var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED] medhud.add_to_hud(src) + faction += "\ref[src]" /mob/living/prepare_huds() ..() @@ -256,10 +257,10 @@ death() to_chat(src, "You have given up life and succumbed to death.") - + /mob/living/proc/InCritical() return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS) - + /mob/living/ex_act(severity) ..() diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 1ef6f06259f..1d37f04312d 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -36,11 +36,11 @@ for(var/mob/living/L in T) if(L == src || L == A) continue - if(faction_check(L) && !attack_same) + if(faction_check_mob(L) && !attack_same) return visible_message("[src] [ranged_message] at [A]!") throw_at(A, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE) - ranged_cooldown = world.time + ranged_cooldown_time + ranged_cooldown = world.time + ranged_cooldown_time /mob/living/simple_animal/hostile/headcrab/proc/Zombify(mob/living/carbon/human/H) if(!H.check_death_method()) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index ac5e40025c6..10d258ff4dd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -195,7 +195,7 @@ Difficulty: Hard . = list() for(var/mob/living/L in targets) var/list/bloodpool = get_pools(get_turf(L), 0) - if(bloodpool.len && (!faction_check(L) || L.stat == DEAD)) + if(bloodpool.len && (!faction_check_mob(L) || L.stat == DEAD)) . += L /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack() @@ -246,7 +246,7 @@ Difficulty: Hard new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T) sleep(2.5) for(var/mob/living/L in T) - if(!faction_check(L)) + if(!faction_check_mob(L)) to_chat(L, "[src] rends you!") playsound(T, attack_sound, 100, 1, -1) var/limb_to_hit = pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg") @@ -262,7 +262,7 @@ Difficulty: Hard new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T) sleep(6) for(var/mob/living/L in T) - if(!faction_check(L)) + if(!faction_check_mob(L)) to_chat(L, "[src] drags you through the blood!") playsound(T, 'sound/misc/enter_blood.ogg', 100, 1, -1) var/turf/targetturf = get_step(src, dir) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index bb4e9297605..57fda64a094 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -536,7 +536,7 @@ Difficulty: Hard /obj/effect/temp_visual/hierophant/blast/proc/do_damage(turf/T) for(var/mob/living/L in T.contents - hit_things) //find and damage mobs... hit_things += L - if((friendly_fire_check && caster && caster.faction_check(L)) || L.stat == DEAD) + if((friendly_fire_check && caster && caster.faction_check_mob(L)) || L.stat == DEAD) continue if(L.client) flash_color(L.client, "#660099", 1) @@ -551,7 +551,7 @@ Difficulty: Hard for(var/obj/mecha/M in T.contents - hit_things) //and mechs. hit_things += M if(M.occupant) - if(friendly_fire_check && caster && caster.faction_check(M.occupant)) + if(friendly_fire_check && caster && caster.faction_check_mob(M.occupant)) continue to_chat(M.occupant, "Your [M.name] is struck by a [name]!") playsound(M,'sound/weapons/sear.ogg', 50, 1, -4) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 8cbef64d34b..059e7628ab8 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -159,7 +159,7 @@ continue if(depotarea.list_includes(body, depotarea.dead_list)) continue - if(faction_check(body)) + if(faction_check_mob(body)) continue say("Target [body]... terminated.") depotarea.list_add(body, depotarea.dead_list) @@ -190,7 +190,7 @@ /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/CanPass(atom/movable/mover, turf/target, height=0) if(isliving(mover)) var/mob/living/blocker = mover - if(faction_check(blocker)) + if(faction_check_mob(blocker)) return 1 return ..(mover, target, height) diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 52ec406fcbd..1565e0bbda0 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -90,7 +90,7 @@ if(grasping.len < max_grasps) grasping: for(var/mob/living/L in view(grasp_range, src)) - if(L == src || faction_check(L) || (L in grasping) || L == target) + if(L == src || faction_check_mob(L) || (L in grasping) || L == target) continue for(var/t in getline(src,L)) for(var/a in t) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3c2f9fc732b..c2d16069146 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1234,12 +1234,6 @@ var/list/slot_equipment_priority = list( \ /mob/proc/get_access() return list() //must return list or IGNORE_ACCESS -/mob/proc/faction_check(mob/target) - for(var/F in faction) - if(F in target.faction) - return 1 - return 0 - /mob/proc/create_attack_log(text, collapse = TRUE) LAZYINITLIST(attack_log) create_log_in_list(attack_log, text, collapse, last_log) From 97ff6bb33c9324c400f99b9e9589306c5a3fe68c Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Fri, 30 Aug 2019 22:02:41 -0400 Subject: [PATCH 03/13] refactors mice --- .../living/simple_animal/friendly/mouse.dm | 28 ++++++++----------- .../living/simple_animal/hostile/hostile.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 15 +++++----- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index da0a59c99b7..33adee324db 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -57,27 +57,21 @@ /mob/living/simple_animal/mouse/handle_automated_speech() ..() - if(prob(speak_chance)) + if(prob(speak_chance) && !incapacitated()) for(var/mob/M in view()) - M << squeak_sound + SEND_SOUND(M, squeak_sound) /mob/living/simple_animal/mouse/Life(seconds, times_fired) . = ..() - if(stat == UNCONSCIOUS) - if(ckey || prob(1)) - stat = CONSCIOUS - icon_state = "mouse_[mouse_color]" - wander = 1 - else if(prob(5)) - emote("snuffles") - -/mob/living/simple_animal/mouse/Life() - ..() - if(!stat && prob(0.5) && !ckey) - stat = UNCONSCIOUS - icon_state = "mouse_[mouse_color]_sleep" - wander = 0 - speak_chance = 0 + if(.) // Alive + if(!ckey) + if(resting) + if(prob(1)) + StopResting() + else if(prob(5)) + custom_emote(2, "snuffles") + else if(prob(0.5)) + StartResting() /mob/living/simple_animal/mouse/New() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index da34a3b2827..41ed10288c3 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -222,7 +222,7 @@ if(isspacepod(the_target)) var/obj/spacepod/S = the_target - if(S.pilot)//Just so we don't attack empty mechs + if(S.pilot)//Just so we don't attack empty pods if(CanAttack(S.pilot)) return TRUE diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 630d78ef085..cfe96411861 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -143,16 +143,15 @@ health = Clamp(health, 0, maxHealth) med_hud_set_status() -/mob/living/simple_animal/lay_down() +/mob/living/simple_animal/StartResting(updating = 1) ..() - handle_resting_state_icons() + if(icon_resting && stat != DEAD) + icon_state = icon_resting -/mob/living/simple_animal/proc/handle_resting_state_icons() - if(icon_resting) - if(resting && stat != DEAD) - icon_state = icon_resting - else if(stat != DEAD) - icon_state = icon_living +/mob/living/simple_animal/StopResting(updating = 1) + ..() + if(icon_resting && stat != DEAD) + icon_state = icon_living /mob/living/simple_animal/update_stat(reason = "none given") if(status_flags & GODMODE) From 133795d75cdda3fd2068bedf191a24679ffde59d Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Sat, 31 Aug 2019 00:17:37 -0400 Subject: [PATCH 04/13] more updates --- .../gamemodes/miniantags/bot_swarm/swarmer.dm | 8 +-- .../gamemodes/miniantags/guardian/guardian.dm | 2 +- .../miniantags/guardian/types/assassin.dm | 9 ++-- .../miniantags/guardian/types/fire.dm | 4 +- .../miniantags/guardian/types/healer.dm | 2 +- .../miniantags/guardian/types/lightning.dm | 4 +- .../miniantags/guardian/types/standard.dm | 2 +- code/game/gamemodes/miniantags/morph/morph.dm | 2 +- .../mining/lavaland/loot/colossus_loot.dm | 2 +- code/modules/mining/minebot.dm | 2 +- .../mob/living/simple_animal/bot/bot.dm | 4 +- .../mob/living/simple_animal/constructs.dm | 8 +-- .../mob/living/simple_animal/friendly/crab.dm | 13 ----- .../simple_animal/friendly/farm_animals.dm | 4 +- .../mob/living/simple_animal/hostile/alien.dm | 3 +- .../mob/living/simple_animal/hostile/bat.dm | 8 ++- .../mob/living/simple_animal/hostile/bees.dm | 21 +++++--- .../mob/living/simple_animal/hostile/carp.dm | 11 ++-- .../living/simple_animal/hostile/faithless.dm | 11 ++-- .../simple_animal/hostile/giant_spider.dm | 4 +- .../living/simple_animal/hostile/headslug.dm | 13 ++--- .../living/simple_animal/hostile/hellhound.dm | 13 ++--- .../living/simple_animal/hostile/illusion.dm | 4 +- .../simple_animal/hostile/jungle_animals.dm | 33 ++++++------ .../hostile/megafauna/bubblegum.dm | 6 ++- .../simple_animal/hostile/megafauna/drake.dm | 6 +-- .../hostile/megafauna/hierophant.dm | 9 +++- .../simple_animal/hostile/megafauna/legion.dm | 4 +- .../hostile/megafauna/megafauna.dm | 4 +- .../hostile/megafauna/swarmer.dm | 2 +- .../mob/living/simple_animal/hostile/mimic.dm | 40 ++++++-------- .../simple_animal/hostile/mining/basilisk.dm | 9 ++-- .../simple_animal/hostile/mining/goldgrub.dm | 9 ++-- .../simple_animal/hostile/mining/goliath.dm | 8 +-- .../simple_animal/hostile/mining/gutlunch.dm | 29 +++++++++-- .../simple_animal/hostile/mining/hivelord.dm | 1 + .../simple_animal/hostile/mining/mining.dm | 8 +-- .../living/simple_animal/hostile/mushroom.dm | 40 ++++++++++---- .../hostile/retaliate/retaliate.dm | 52 +++++++------------ .../simple_animal/hostile/retaliate/undead.dm | 8 ++- .../simple_animal/hostile/spaceworms.dm | 5 +- .../living/simple_animal/hostile/statue.dm | 6 +-- .../living/simple_animal/hostile/syndicate.dm | 3 +- .../hostile/terror_spiders/gray.dm | 2 +- .../hostile/terror_spiders/red.dm | 2 +- .../mob/living/simple_animal/hostile/tree.dm | 17 +++--- .../simple_animal/hostile/venus_human_trap.dm | 6 +++ 47 files changed, 236 insertions(+), 227 deletions(-) diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index fb3c10e25ec..3c0ca1955fb 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -158,9 +158,9 @@ ////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S//// /mob/living/simple_animal/hostile/swarmer/AttackingTarget() if(!isliving(target)) - target.swarmer_act(src) + return target.swarmer_act(src) else - ..() + return ..() /mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A) face_atom(A) @@ -352,11 +352,11 @@ /obj/structure/lattice/catwalk/swarmer_catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) to_chat(S, "We have created these for our own benefit. Aborting.") - return FALSE + return FALSE /obj/structure/shuttle/engine/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) to_chat(S, "This shuttle may be important to us later. Aborting.") - return FALSE + return FALSE ////END CTRL CLICK FOR SWARMERS//// diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 2b6040ed8b6..b8649985da1 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -123,7 +123,7 @@ med_hud_set_health() med_hud_set_status() -/mob/living/simple_animal/hostile/guardian/adjustHealth(amount) //The spirit is invincible, but passes on damage to the summoner +/mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE) //The spirit is invincible, but passes on damage to the summoner var/damage = amount * damage_transfer if(summoner) if(loc == summoner) diff --git a/code/game/gamemodes/miniantags/guardian/types/assassin.dm b/code/game/gamemodes/miniantags/guardian/types/assassin.dm index 5eb8c1b1cec..e9ea9239483 100644 --- a/code/game/gamemodes/miniantags/guardian/types/assassin.dm +++ b/code/game/gamemodes/miniantags/guardian/types/assassin.dm @@ -26,11 +26,12 @@ stat(null, "Stealth Cooldown Remaining: [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds") /mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget() - ..() - if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille))) - ToggleMode(1) + . = ..() + if(.) + if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille))) + ToggleMode(1) -/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE, forced = FALSE) +/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE) . = ..() if(. > 0 && toggle) ToggleMode(1) diff --git a/code/game/gamemodes/miniantags/guardian/types/fire.dm b/code/game/gamemodes/miniantags/guardian/types/fire.dm index 0c5052f48bd..09a202afb91 100644 --- a/code/game/gamemodes/miniantags/guardian/types/fire.dm +++ b/code/game/gamemodes/miniantags/guardian/types/fire.dm @@ -28,9 +28,9 @@ toggle = TRUE /mob/living/simple_animal/hostile/guardian/fire/AttackingTarget() - ..() + . = ..() if(toggle) - if(ishuman(target) && !summoner) + if(. && ishuman(target) && !summoner) spawn(0) new /obj/effect/hallucination/delusion(target.loc, target, force_kind = "custom", duration = 200, skip_nearby = 0, custom_icon = icon_state, custom_icon_file = icon) else diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm index d9be543f7e2..bf2c92ffb28 100644 --- a/code/game/gamemodes/miniantags/guardian/types/healer.dm +++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm @@ -43,7 +43,7 @@ stat(null, "Bluespace Beacon Cooldown Remaining: [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds") /mob/living/simple_animal/hostile/guardian/healer/AttackingTarget() - ..() + . = ..() if(toggle == TRUE) if(loc == summoner) to_chat(src, "You must be manifested to heal!") diff --git a/code/game/gamemodes/miniantags/guardian/types/lightning.dm b/code/game/gamemodes/miniantags/guardian/types/lightning.dm index 88d5a43143d..13b9b67f0a9 100644 --- a/code/game/gamemodes/miniantags/guardian/types/lightning.dm +++ b/code/game/gamemodes/miniantags/guardian/types/lightning.dm @@ -19,8 +19,8 @@ var/successfulshocks = 0 /mob/living/simple_animal/hostile/guardian/beam/AttackingTarget() - ..() - if(isliving(target) && target != src && target != summoner) + . = ..() + if(. && isliving(target) && target != src && target != summoner) cleardeletedchains() for(var/chain in enemychains) var/datum/beam/B = chain diff --git a/code/game/gamemodes/miniantags/guardian/types/standard.dm b/code/game/gamemodes/miniantags/guardian/types/standard.dm index 1380c4a2e95..dc85a48a480 100644 --- a/code/game/gamemodes/miniantags/guardian/types/standard.dm +++ b/code/game/gamemodes/miniantags/guardian/types/standard.dm @@ -19,7 +19,7 @@ battlecry = input /mob/living/simple_animal/hostile/guardian/punch/AttackingTarget() - ..() + . = ..() if(iscarbon(target) && target != summoner) if(length(battlecry) > 11)//no more then 11 letters in a battle cry. visible_message("[src] punches [target]!") diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index e774e893851..1da936b64ee 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -179,4 +179,4 @@ if(do_after(src, 20, target = I)) eat(I) return - target.attack_animal(src) + return ..() diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm index 9b6bd8c5893..48c4249fd62 100644 --- a/code/modules/mining/lavaland/loot/colossus_loot.dm +++ b/code/modules/mining/lavaland/loot/colossus_loot.dm @@ -380,7 +380,7 @@ medsensor.add_hud_to(src) /mob/living/simple_animal/hostile/lightgeist/AttackingTarget() - ..() + . = ..() if(isliving(target) && target != src) var/mob/living/L = target if(L.stat < DEAD) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 7e55a60d387..5a0c17d9e93 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -191,7 +191,7 @@ for(var/obj/item/stack/ore/O in contents) O.forceMove(drop_location()) -/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount) +/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount, updating_health = TRUE) if(mode != MINEDRONE_ATTACK && amount > 0) SetOffenseBehavior() . = ..() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 4793b91dee6..76f88220eda 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -241,10 +241,10 @@ else to_chat(user, "[src] is in pristine condition.") -/mob/living/simple_animal/bot/adjustHealth(amount) +/mob/living/simple_animal/bot/adjustHealth(amount, updating_health = TRUE) if(amount > 0 && prob(10)) new /obj/effect/decal/cleanable/blood/oil(loc) - return ..(amount) + . = ..() /mob/living/simple_animal/bot/updatehealth(reason = "none given") ..(reason) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index d5fabe96be4..3a26265466b 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -217,7 +217,7 @@ /mob/living/simple_animal/hostile/construct/builder/Found(atom/A) //what have we found here? - if(istype(A, /mob/living/simple_animal/hostile/construct)) //is it a construct? + if(isconstruct(A)) //is it a construct? var/mob/living/simple_animal/hostile/construct/C = A if(C.health < C.maxHealth) //is it hurt? let's go heal it if it is return 1 @@ -236,7 +236,7 @@ ..() if(isliving(target)) var/mob/living/L = target - if(istype(L, /mob/living/simple_animal/hostile/construct) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it + if(isconstruct(L) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it LoseTarget() return 0 if(L.health <= melee_damage_lower+melee_damage_upper) //ey bucko you're hurt as fuck let's go hit you @@ -245,7 +245,7 @@ /mob/living/simple_animal/hostile/construct/builder/Aggro() ..() - if(istype(target, /mob/living/simple_animal/hostile/construct)) //oh the target is a construct no need to flee + if(isconstruct(target)) //oh the target is a construct no need to flee retreat_distance = null minimum_distance = 1 @@ -256,7 +256,7 @@ /mob/living/simple_animal/hostile/construct/builder/hostile //actually hostile, will move around, hit things, heal other constructs AIStatus = AI_ON - environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP + environment_smash = ENVIRONMENT_SMASH_STRUCTURES //only token destruction, don't smash the cult wall NO STOP /////////////////////////////Behemoth///////////////////////// diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 94ecb71703b..565c899fc23 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -17,23 +17,10 @@ stop_automated_movement = 1 friendly = "pinches" ventcrawler = 2 - var/obj/item/inventory_head - var/obj/item/inventory_mask can_hide = 1 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY -/mob/living/simple_animal/crab/handle_automated_movement() - //CRAB movement - if(!stat) - if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc. - turns_since_move++ - if(turns_since_move >= turns_per_move) - var/east_vs_west = pick(4, 8) - if(Process_Spacemove(east_vs_west)) - Move(get_step(src, east_vs_west), east_vs_west) - turns_since_move = 0 - /mob/living/simple_animal/crab/Life(seconds, times_fired) . = ..() regenerate_icons() diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 729a7d0b47d..9d5990bb2d6 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -91,8 +91,8 @@ say("Nom") /mob/living/simple_animal/hostile/retaliate/goat/AttackingTarget() - ..() - if(isdiona(target)) + . = ..() + if(. && isdiona(target)) var/mob/living/carbon/human/H = target var/obj/item/organ/external/NB = pick(H.bodyparts) H.visible_message("[src] takes a big chomp out of [H]!", "[src] takes a big chomp out of your [NB.name]!") diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 0aa148eb031..52f149f0775 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -158,7 +158,8 @@ if(istype(target, /obj/effect/decal/cleanable)) visible_message("\The [src] cleans up \the [target].") qdel(target) - return + return TRUE var/atom/movable/M = target M.clean_blood() visible_message("\The [src] polishes \the [target].") + return TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index 2d16dcb3095..fdb05a51fd9 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -22,6 +22,9 @@ attacktext = "bites" attack_sound = 'sound/weapons/bite.ogg' + emote_taunt = list("flutters") + taunt_chance = 20 + 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 @@ -39,11 +42,6 @@ /mob/living/simple_animal/hostile/scarybat/Process_Spacemove(var/check_drift = 0) return ..() //No drifting in space for space carp! //original comments do not steal -/mob/living/simple_animal/hostile/scarybat/FindTarget() - . = ..() - if(.) - custom_emote(1, "flutters towards [.]") - /mob/living/simple_animal/hostile/scarybat/Found(var/atom/A)//This is here as a potential override to pick a specific target if available if(istype(A) && A == owner) return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 8b814076720..cf084086ae7 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -137,12 +137,13 @@ if(target == beehome) var/obj/structure/beebox/BB = target forceMove(BB) + toggle_ai(AI_IDLE) target = null wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home return //no don't attack the goddamm box else - ..() - if(isliving(target) && (!client || a_intent == INTENT_HARM)) + . = ..() + if(. && isliving(target) && (!client || a_intent == INTENT_HARM)) var/mob/living/L = target if(L.reagents) if(beegent) @@ -222,8 +223,8 @@ //leave pollination for the peasent bees /mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget() - ..() - if(beegent && isliving(target)) + . = ..() + if(. && beegent && isliving(target)) var/mob/living/L = target beegent.reaction_mob(L, TOUCH) L.reagents.add_reagent(beegent.id, rand(1, 5)) @@ -283,6 +284,14 @@ QDEL_NULL(queen) return ..() +/mob/living/simple_animal/hostile/poison/bees/consider_wakeup() + if(beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets + idle = min(100, ++idle) + if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM)) + toggle_ai(AI_ON) + forceMove(beehome.drop_location()) + else + ..() //Syndicate Bees /mob/living/simple_animal/hostile/poison/bees/syndi @@ -327,8 +336,8 @@ return TRUE /mob/living/simple_animal/hostile/poison/bees/syndi/AttackingTarget() - ..() - if(target && isliving(target)) + . = ..() + if(. && target && isliving(target)) var/mob/living/L = target if(L.stat) LoseTarget() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 299677804e2..48021ad2593 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -10,6 +10,8 @@ response_help = "pets the" response_disarm = "gently pushes aside the" response_harm = "hits the" + emote_taunt = list("gnashes") + taunt_chance = 30 speed = 0 maxHealth = 25 health = 25 @@ -50,14 +52,9 @@ /mob/living/simple_animal/hostile/carp/Process_Spacemove(var/movement_dir = 0) return 1 //No drifting in space for space carp! //original comments do not steal -/mob/living/simple_animal/hostile/carp/FindTarget() - . = ..() - if(.) - custom_emote(1, "gnashes at [.]!") - /mob/living/simple_animal/hostile/carp/AttackingTarget() - ..() - if(ishuman(target)) + . = ..() + if(. && ishuman(target)) var/mob/living/carbon/human/H = target H.adjustStaminaLoss(8) diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index f668312e88d..2b736ee7641 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -19,6 +19,8 @@ attacktext = "grips" attack_sound = 'sound/hallucinations/growl1.ogg' speak_emote = list("growls") + emote_taunt = list("wails") + taunt_chance = 25 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 @@ -29,14 +31,9 @@ /mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/movement_dir = 0) return 1 -/mob/living/simple_animal/hostile/faithless/FindTarget() - . = ..() - if(.) - custom_emote(1, "wails at [.]!") - /mob/living/simple_animal/hostile/faithless/AttackingTarget() - ..() - if(iscarbon(target)) + . = ..() + if(. && iscarbon(target)) var/mob/living/carbon/C = target if(prob(12)) C.Weaken(3) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index d6d23871b1f..a42535a66e3 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -40,8 +40,8 @@ /mob/living/simple_animal/hostile/poison/giant_spider/AttackingTarget() // This is placed here, NOT on /poison, because the other subtypes of /poison/ already override AttackingTarget() completely, and as such it would do nothing but confuse people there. - ..() - if(venom_per_bite > 0 && iscarbon(target) && (!client || a_intent == INTENT_HARM)) + . = ..() + if(. && venom_per_bite > 0 && iscarbon(target) && (!client || a_intent == INTENT_HARM)) var/mob/living/carbon/C = target var/inject_target = pick("chest", "head") if(C.can_inject(null, 0, inject_target, 0)) diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm index e2fc98c483f..a14ed91aa8f 100644 --- a/code/modules/mob/living/simple_animal/hostile/headslug.dm +++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm @@ -36,16 +36,14 @@ else if(mind) // Let's make this a feature egg.origin = mind for(var/obj/item/organ/internal/I in src) - I.loc = egg + I.forceMove(egg) visible_message("[src] plants something in [victim]'s flesh!", \ "We inject our egg into [victim]'s body!") egg_lain = 1 /mob/living/simple_animal/hostile/headslug/AttackingTarget() - if(egg_lain) - target.attack_animal(src) - return - if(iscarbon(target) && !issmall(target)) + . = ..() + if(. && !egg_lain && iscarbon(target) && !issmall(target)) // Changeling egg can survive in aliens! var/mob/living/carbon/C = target if(C.stat == DEAD) @@ -54,10 +52,7 @@ return Infect(target) to_chat(src, "With our egg laid, our death approaches rapidly...") - spawn(100) - death() - return - target.attack_animal(src) + addtimer(CALLBACK(src, .proc/death), 100) /obj/item/organ/internal/body_egg/changeling_egg name = "changeling egg" diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm index f3e110d0099..40318b914bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/hellhound.dm +++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm @@ -42,19 +42,16 @@ whisper_action.Grant(src) /mob/living/simple_animal/hostile/hellhound/handle_automated_action() - . = ..() + if(!..()) + return if(resting) if(!wants_to_rest()) custom_emote(1, "growls, and gets up.") playsound(get_turf(src), 'sound/hallucinations/growl2.ogg', 50, 1) - icon_state = "[icon_living]" - resting = 0 - update_canmove() + StopResting() else if(wants_to_rest()) custom_emote(1, "lays down, and starts to lick their wounds.") - icon_state = "[icon_resting]" - resting = 1 - update_canmove() + StartResting() /mob/living/simple_animal/hostile/hellhound/examine(mob/user) . = ..() @@ -97,7 +94,7 @@ /mob/living/simple_animal/hostile/hellhound/AttackingTarget() . = ..() - if(ishuman(target) && (!client || a_intent == INTENT_HARM)) + if(. && ishuman(target) && (!client || a_intent == INTENT_HARM)) special_aoe() /mob/living/simple_animal/hostile/hellhound/attackby(obj/item/C, mob/user, params) diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index 9ed59fb4ab5..29739a9d867 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -46,8 +46,8 @@ /mob/living/simple_animal/hostile/illusion/AttackingTarget() - ..() - if(istype(target, /mob/living) && prob(multiply_chance)) + . = ..() + if(. && isliving(target) && prob(multiply_chance)) var/mob/living/L = target if(L.stat == DEAD) return diff --git a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm index e34a5e0cb08..797beb9b11b 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm @@ -23,6 +23,9 @@ pixel_x = -16 see_in_dark = 8 + emote_taunt = list("nashes") + taunt_chance = 20 + harm_intent_damage = 8 melee_damage_lower = 15 melee_damage_upper = 15 @@ -33,18 +36,13 @@ var/stalk_tick_delay = 3 gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE -/mob/living/simple_animal/hostile/panther/FindTarget(var/list/possible_targets) +/mob/living/simple_animal/hostile/panther/AttackingTarget() . = ..() if(.) - emote("nashes at [.]") - -/mob/living/simple_animal/hostile/panther/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") + if(prob(15) && iscarbon(target)) + var/mob/living/carbon/C = target + C.Weaken(3) + C.visible_message("\the [src] knocks down \the [C]!") //*******// // Snake // @@ -67,6 +65,9 @@ maxHealth = 25 health = 25 + emote_taunt = list("hisses wickedly") + taunt_chance = 20 + harm_intent_damage = 2 melee_damage_lower = 3 melee_damage_upper = 10 @@ -77,13 +78,9 @@ var/stalk_tick_delay = 3 gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE -/mob/living/simple_animal/hostile/snake/FindTarget() - . = ..() - if(.) - emote("hisses wickedly") - /mob/living/simple_animal/hostile/snake/AttackingTarget() . =..() - var/mob/living/L = . - if(istype(L)) - L.apply_damage(rand(3,12), TOX) + if(.) + if(iscarbon(target)) + var/mob/living/carbon/C = target + C.apply_damage(rand(3, 12), TOX) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 10d258ff4dd..5b605551a22 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -122,12 +122,16 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget() if(!charging) - ..() + 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() if(charging) new /obj/effect/temp_visual/decoy/fading(loc, src) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 0789d00832d..00f67674546 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -62,14 +62,14 @@ Difficulty: Medium return ..() -/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount) +/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount, updating_health = TRUE) if(swooping) - return 0 + return FALSE return ..() /mob/living/simple_animal/hostile/megafauna/dragon/AttackingTarget() if(!swooping) - ..() + return ..() /mob/living/simple_animal/hostile/megafauna/dragon/DestroySurroundings() if(!swooping) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 57fda64a094..4ed44c616c8 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -123,13 +123,18 @@ Difficulty: Hard adjustHealth(-L.maxHealth*0.5) L.dust() +/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target) + . = ..() + if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets + return FALSE + /*/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target) var/targets_the_same = (new_target == target) . = ..() if(. && target && !targets_the_same) visible_message("\"[pick(target_phrases)]\"")*/ -/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount) +/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount, updating_health = TRUE) . = ..() if(src && amount > 0 && !blinking) wander = TRUE @@ -140,7 +145,7 @@ Difficulty: Hard if(target && isliving(target)) spawn(0) melee_blast(get_turf(target)) //melee attacks on living mobs produce a 3x3 blast - ..() + return ..() /mob/living/simple_animal/hostile/megafauna/hierophant/DestroySurroundings() if(!blinking) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 5a36c3fffa9..d26400bceca 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -55,8 +55,8 @@ Difficulty: Medium internal_gps = new/obj/item/gps/internal/legion(src) /mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget() - ..() - if(ishuman(target)) + . = ..() + if(. && ishuman(target)) var/mob/living/L = target if(L.stat == UNCONSCIOUS) var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index c5f11c501fc..b618ff9e650 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -59,8 +59,8 @@ loot = crusher_loot /mob/living/simple_animal/hostile/megafauna/AttackingTarget() - ..() - if(isliving(target)) + . = ..() + if(. && isliving(target)) var/mob/living/L = target if(L.stat != DEAD) if(!client && ranged && ranged_cooldown <= world.time) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index fa2479bb658..5a1d10edfb2 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -81,7 +81,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa new createtype(loc) -/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE, forced = FALSE) +/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE) . = ..() if(. > 0 && world.time > call_help_cooldown) call_help_cooldown = world.time + call_help_cooldown_amt diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 5c26fe1ba57..57277dc2d74 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -17,7 +17,9 @@ melee_damage_upper = 12 attacktext = "attacks" attack_sound = 'sound/weapons/bite.ogg' + emote_taunt = list("growls") speak_emote = list("creaks") + taunt_chance = 30 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 @@ -29,11 +31,6 @@ gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE del_on_death = 1 -/mob/living/simple_animal/hostile/mimic/FindTarget() - . = ..() - if(.) - custom_emote(1, "growls at [.]") - /mob/living/simple_animal/hostile/mimic/emp_act(severity) if(is_electronic) switch(severity) @@ -56,7 +53,7 @@ for(var/obj/item/I in loc) I.loc = src -/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings() +/mob/living/simple_animal/hostile/mimic/crate/DestroyPathToTarget() ..() if(prob(90)) icon_state = "[initial(icon_state)]open" @@ -77,15 +74,19 @@ . = ..() if(.) icon_state = initial(icon_state) + if(prob(15) && iscarbon(target)) + var/mob/living/carbon/C = target + C.Weaken(2) + C.visible_message("\The [src] knocks down \the [C]!", "\The [src] knocks you down!") /mob/living/simple_animal/hostile/mimic/crate/proc/trigger() if(!attempt_open) visible_message("[src] starts to move!") attempt_open = 1 -/mob/living/simple_animal/hostile/mimic/crate/adjustHealth(damage) +/mob/living/simple_animal/hostile/mimic/crate/adjustHealth(amount, updating_health = TRUE) trigger() - ..(damage) + . = ..() /mob/living/simple_animal/hostile/mimic/crate/LoseTarget() ..() @@ -96,18 +97,10 @@ var/obj/structure/closet/crate/C = new(get_turf(src)) // Put loot in crate for(var/obj/O in src) - O.loc = C + O.forceMove(C) // due to `del_on_death` return ..() -/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(2) - L.visible_message("\the [src] knocks down \the [L]!") - var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window) /mob/living/simple_animal/hostile/mimic/copy @@ -191,14 +184,11 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca ..() /mob/living/simple_animal/hostile/mimic/copy/AttackingTarget() - ..() - if(knockdown_people) - if(iscarbon(target)) - var/mob/living/carbon/C = target - if(prob(15)) - C.Weaken(2) - C.visible_message("\The [src] knocks down \the [C]!", \ - "\The [src] knocks you down!") + . = ..() + if(knockdown_people && . && prob(15) && iscarbon(target)) + var/mob/living/carbon/C = target + C.Weaken(2) + C.visible_message("\The [src] knocks down \the [C]!", "\The [src] knocks you down!") /mob/living/simple_animal/hostile/mimic/copy/Aggro() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm index 4dca1caeb29..f960471d510 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm @@ -41,13 +41,10 @@ flag = "energy" temperature = 50 -/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target) +/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(new_target) if(..()) //we have a target - if(isliving(target)) - var/mob/living/L = target - if(L.bodytemperature > 261) - L.bodytemperature = 261 - visible_message("The [src.name]'s stare chills [L.name] to the bone!") + if(isliving(target) && !target.Adjacent(targets_from) && ranged_cooldown <= world.time)//No more being shot at point blank or spammed with RNG beams + OpenFire(target) /mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity) switch(severity) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm index 7de8935e5ca..9066b84b5f6 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm @@ -48,14 +48,13 @@ retreat_distance = 10 minimum_distance = 10 if(will_burrow) - spawn(chase_time) - Burrow() + addtimer(CALLBACK(src, .proc/Burrow), chase_time) /mob/living/simple_animal/hostile/asteroid/goldgrub/AttackingTarget() if(istype(target, /obj/item/stack/ore)) EatOre(target) return - ..() + return ..() /mob/living/simple_animal/hostile/asteroid/goldgrub/proc/EatOre(var/atom/targeted_ore) for(var/obj/item/stack/ore/O in get_turf(targeted_ore)) @@ -69,13 +68,13 @@ /mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time if(!stat) - visible_message("The [src.name] buries into the ground, vanishing from sight!") + visible_message("The [name] buries into the ground, vanishing from sight!") qdel(src) /mob/living/simple_animal/hostile/asteroid/goldgrub/bullet_act(obj/item/projectile/P) visible_message("The [P.name] was repelled by [src.name]'s girth!") return -/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(damage) +/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(amount, updating_health = TRUE) vision_range = 9 . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm index 84b919266d0..02ce8bdac58 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm @@ -54,6 +54,8 @@ /mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() var/tturf = get_turf(target) + if(!isturf(tturf)) + return if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen visible_message("The [src.name] digs its tentacles under [target.name]!") new /obj/effect/temp_visual/goliath_tentacle/original(tturf, src) @@ -61,10 +63,10 @@ icon_state = icon_aggro pre_attack = FALSE -/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage) - ranged_cooldown-- +/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(amount, updating_health = TRUE) + ranged_cooldown -= 10 handle_preattack() - ..() + . = ..() /mob/living/simple_animal/hostile/asteroid/goliath/Aggro() vision_range = aggro_vision_range diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm index 491e35cc621..9fb2e041479 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm @@ -30,7 +30,7 @@ stop_automated_movement_when_pulled = TRUE stat_exclusive = TRUE robust_searching = TRUE - search_objects = TRUE + search_objects = 3 del_on_death = TRUE loot = list(/obj/effect/decal/cleanable/blood/gibs) deathmessage = "is pulped into bugmash." @@ -63,14 +63,35 @@ else ..() +/mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland + if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids + return FALSE + + if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it + return FALSE + + if(isliving(the_target)) + var/mob/living/L = the_target + + if(faction_check_mob(L) && !attack_same) + return FALSE + if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive) + return FALSE + + return TRUE + + if(isobj(the_target) && is_type_in_typecache(the_target, wanted_objects)) + return TRUE + + return FALSE + /mob/living/simple_animal/hostile/asteroid/gutlunch/AttackingTarget() - if(is_type_in_typecache(target, wanted_objects)) //we eats + if(is_type_in_typecache(target,wanted_objects)) //we eats udder.generateMilk() regenerate_icons() visible_message("[src] slurps up [target].") qdel(target) - return - ..() + return ..() /obj/item/udder/gutlunch name = "nutrient sac" diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index ca8644e0566..09c80107a41 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -44,6 +44,7 @@ /mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() OpenFire() + return TRUE /mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot() loot += crusher_loot //we don't butcher diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm index 434869c1d6d..ba4f00503e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm @@ -28,12 +28,14 @@ /mob/living/simple_animal/hostile/asteroid/Aggro() ..() - icon_state = icon_aggro + if(vision_range != aggro_vision_range) + icon_state = icon_aggro /mob/living/simple_animal/hostile/asteroid/LoseAggro() ..() - if(stat == CONSCIOUS) - icon_state = icon_living + if(stat == DEAD) + return + icon_state = icon_living /mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills if(!stat) diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 59c23953e6b..ce044284a26 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -61,21 +61,42 @@ health = maxHealth ..() -/mob/living/simple_animal/hostile/mushroom/adjustHealth(damage)//Possibility to flee from a fight just to make it more visually interesting +/mob/living/simple_animal/hostile/mushroom/CanAttack(atom/the_target) // Mushroom-specific version of CanAttack to handle stupid attack_same = 2 crap so we don't have to do it for literally every single simple_animal/hostile because this shit never gets spawned + if(!the_target || isturf(the_target) || istype(the_target, /atom/movable/lighting_object)) + return FALSE + + if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it + return FALSE + + if(isliving(the_target)) + var/mob/living/L = the_target + + if (!faction_check_mob(L) && attack_same == 2) + return FALSE + if(L.stat > stat_attack) + return FALSE + + return TRUE + + return FALSE + +/mob/living/simple_animal/hostile/mushroom/adjustHealth(amount, updating_health = TRUE)//Possibility to flee from a fight just to make it more visually interesting if(!retreat_distance && prob(33)) retreat_distance = 5 - spawn(30) - retreat_distance = null - ..() + addtimer(CALLBACK(src, .proc/stop_retreat), 30) + . = ..() -/mob/living/simple_animal/hostile/mushroom/attack_animal(var/mob/living/L) +/mob/living/simple_animal/hostile/mushroom/proc/stop_retreat() + retreat_distance = null + +/mob/living/simple_animal/hostile/mushroom/attack_animal(mob/living/L) if(istype(L, /mob/living/simple_animal/hostile/mushroom) && stat == DEAD) var/mob/living/simple_animal/hostile/mushroom/M = L if(faint_ticker < 2) - M.visible_message("[M] chews a bit on [src].") + M.visible_message("[M] chews a bit on [src].") faint_ticker++ - return - M.visible_message("[M] devours [src]!") + return TRUE + M.visible_message("[M] devours [src]!") var/level_gain = (powerlevel - M.powerlevel) if(level_gain >= -1 && !bruised && !M.ckey)//Player shrooms can't level up to become robust gods. if(level_gain < 1)//So we still gain a level if two mushrooms were the same level @@ -83,7 +104,8 @@ M.LevelUp(level_gain) M.adjustBruteLoss(-M.maxHealth) qdel(src) - ..() + return TRUE + return ..() /mob/living/simple_animal/hostile/mushroom/revive() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index 2e3718cd800..d3bf35671e2 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -1,20 +1,20 @@ /mob/living/simple_animal/hostile/retaliate var/list/enemies = list() -/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A) +/mob/living/simple_animal/hostile/retaliate/Found(atom/A) if(isliving(A)) var/mob/living/L = A if(!L.stat) return L else enemies -= L - else if(istype(A, /obj/mecha)) + else if(ismecha(A)) var/obj/mecha/M = A if(M.occupant) return A - else if(istype(A, /obj/spacepod)) - var/obj/spacepod/M = A - if(M.pilot) + else if(isspacepod(A)) + var/obj/spacepod/S = A + if(S.pilot) return A /mob/living/simple_animal/hostile/retaliate/ListTargets() @@ -25,48 +25,32 @@ return see /mob/living/simple_animal/hostile/retaliate/proc/Retaliate() - ..() - var/list/around = view(src, 7) + var/list/around = view(src, vision_range) for(var/atom/movable/A in around) if(A == src) continue if(isliving(A)) var/mob/living/M = A - var/faction_check = 0 - for(var/F in faction) - if(F in M.faction) - faction_check = 1 - break - if(faction_check && attack_same || !faction_check) + if(faction_check_mob(M) && attack_same || !faction_check_mob(M)) enemies |= M - else if(istype(A, /obj/mecha)) + else if(ismecha(A)) var/obj/mecha/M = A if(M.occupant) enemies |= M enemies |= M.occupant - else if(istype(A, /obj/spacepod)) - var/obj/spacepod/M = A - if(M.pilot) - enemies |= M - enemies |= M.pilot + else if(isspacepod(A)) + var/obj/spacepod/S = A + if(S.pilot) + enemies |= S + enemies |= S.pilot for(var/mob/living/simple_animal/hostile/retaliate/H in around) - var/retaliate_faction_check = 0 - for(var/F in faction) - if(F in H.faction) - retaliate_faction_check = 1 - break - if(retaliate_faction_check && !attack_same && !H.attack_same) + if(faction_check_mob(H) && !attack_same && !H.attack_same) H.enemies |= enemies return 0 -/mob/living/simple_animal/hostile/retaliate/adjustHealth(damage) - ..(damage) - Retaliate() - -/mob/living/simple_animal/hostile/retaliate/DestroySurroundings() - for(var/dir in cardinal) // North, South, East, West - var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir)) - if(istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table)) - obstacle.attack_animal(src) +/mob/living/simple_animal/hostile/retaliate/adjustHealth(amount, updating_health = TRUE) + . = ..() + if(amount > 0 && stat == CONSCIOUS) + Retaliate() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm index f9516739e6f..d80e68b7542 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm @@ -35,6 +35,9 @@ maxHealth = 20 health = 20 + emote_taunt = list("wails") + taunt_chance = 20 + harm_intent_damage = 10 melee_damage_lower = 2 melee_damage_upper = 3 @@ -51,11 +54,6 @@ /mob/living/simple_animal/hostile/retaliate/ghost/Process_Spacemove(var/check_drift = 0) return 1 -/mob/living/simple_animal/hostile/retaliate/ghost/FindTarget() - . = ..() - if(.) - custom_emote(1, "wails at [.]") - /mob/living/simple_animal/hostile/retaliate/ghost/Life(seconds, times_fired) if(target) invisibility = pick(0,0,60,invisibility) diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm index 93e03e8279e..fd569984920 100644 --- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm +++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm @@ -118,8 +118,9 @@ //Try to move onto target's turf and eat them /mob/living/simple_animal/hostile/spaceWorm/wormHead/AttackingTarget() - ..() - attemptToEat(target) + . = ..() + if(.) + attemptToEat(target) //Attempt to eat things we bump into, Mobs, Walls, Clowns /mob/living/simple_animal/hostile/spaceWorm/wormHead/Bump(atom/obstacle) diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 487ce431cdf..b32cae64675 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -86,11 +86,11 @@ if(can_be_seen(get_turf(loc))) if(client) to_chat(src, "You cannot attack, there are eyes on you!") - return + return FALSE else - ..() + return ..() -/mob/living/simple_animal/hostile/statue/DestroySurroundings() +/mob/living/simple_animal/hostile/statue/DestroyPathToTarget() if(!can_be_seen(get_turf(loc))) ..() diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 059e7628ab8..546fa3ad50d 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -135,6 +135,8 @@ LoseTarget() /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/handle_automated_action() + if(!..()) + return if(seen_enemy) aggro_cycles++ if(alert_on_timeout && !raised_alert && aggro_cycles >= 60) @@ -166,7 +168,6 @@ pointed(body) else scan_cycles++ - ..() /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/proc/raise_alert(var/reason) if(istype(depotarea) && (!raised_alert || seen_revived_enemy) && !depotarea.used_self_destruct) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm index 8e53dc7cbbe..9a986d1d4b0 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -58,7 +58,7 @@ if(invisibility > 0) GrayDeCloak() else - ..() + return ..() /mob/living/simple_animal/hostile/poison/terror_spider/proc/GrayCloak() visible_message("[src] hides in the vent.") diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm index 98556c63d34..91e70dd837d 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm @@ -58,7 +58,7 @@ visible_message("[src] retracts its fangs a little.") melee_damage_lower = melee_damage_lower_rage1 melee_damage_upper = melee_damage_upper_rage1 - ..() + return ..() /obj/structure/spider/terrorweb/red diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index 508e2934cf6..78f79dfc3b2 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -24,6 +24,8 @@ attacktext = "bites" attack_sound = 'sound/weapons/bite.ogg' speak_emote = list("pines") + emote_taunt = list("growls") + taunt_chance = 20 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 @@ -34,15 +36,10 @@ deathmessage = "is hacked into pieces!" del_on_death = 1 -/mob/living/simple_animal/hostile/tree/FindTarget() - . = ..() - if(.) - custom_emote(1, "growls at [.]") - /mob/living/simple_animal/hostile/tree/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) + . = ..() + if(. && iscarbon(target)) + var/mob/living/carbon/C = target if(prob(15)) - L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") \ No newline at end of file + C.Weaken(3) + C.visible_message("\the [src] knocks down \the [C]!") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 1565e0bbda0..c8e6b8c5d8e 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -105,6 +105,12 @@ /mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target) + for(var/turf/T in getline(src,target)) + if (T.density) + return + for(var/obj/O in T) + if(O.density) + return var/dist = get_dist(src,the_target) Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine) the_target.attack_animal(src) From c3e0eb57d43dad0ead3f7176382716464e481b64 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Sat, 31 Aug 2019 00:43:23 -0400 Subject: [PATCH 05/13] fixes goliaths --- .../modules/mob/living/simple_animal/hostile/mining/goliath.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm index 02ce8bdac58..323976003b8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm @@ -11,7 +11,6 @@ mouse_opacity = MOUSE_OPACITY_OPAQUE move_to_delay = 40 ranged = TRUE - ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight ranged_cooldown_time = 120 friendly = "wails at" speak_emote = list("bellows") @@ -190,4 +189,4 @@ /obj/effect/temp_visual/goliath_tentacle/proc/retract() icon_state = "Goliath_tentacle_retract" deltimer(timerid) - timerid = QDEL_IN(src, 5) + timerid = QDEL_IN(src, 7) From 2b615b7b10e4e204b9ee6face1ee188569bedb16 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Sat, 31 Aug 2019 18:23:59 -0400 Subject: [PATCH 06/13] blood drunk update --- code/__DEFINES/mobs.dm | 2 + .../temporary_visuals/miscellaneous.dm | 9 + .../hostile/megafauna/blood_drunk_miner.dm | 132 ++++++---- .../hostile/megafauna/megafauna.dm | 23 ++ .../simple_animal/hostile/mining_mobs.dm | 225 ------------------ .../living/simple_animal/hostile/russian.dm | 1 + .../living/simple_animal/hostile/syndicate.dm | 1 + icons/mob/actions/actions_animal.dmi | Bin 0 -> 5618 bytes 8 files changed, 116 insertions(+), 277 deletions(-) delete mode 100644 code/modules/mob/living/simple_animal/hostile/mining_mobs.dm create mode 100644 icons/mob/actions/actions_animal.dmi diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 608fcfcce20..11b03d7102a 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -218,3 +218,5 @@ #define hasorgans(A) (ishuman(A)) #define is_admin(user) (check_rights(R_ADMIN, 0, (user)) != 0) + +#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; \ No newline at end of file diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 7f1683ba415..d6dbf1dddbb 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -140,6 +140,15 @@ ..() animate(src, alpha = 0, time = duration) +/obj/effect/temp_visual/decoy/fading/threesecond + duration = 40 + +/obj/effect/temp_visual/decoy/fading/fivesecond + duration = 50 + +/obj/effect/temp_visual/decoy/fading/halfsecond + duration = 5 + /obj/effect/temp_visual/fire icon = 'icons/goonstation/effects/fire.dmi' icon_state = "3" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index d45e6f6ead8..db96f9fce96 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -34,7 +34,7 @@ Difficulty: Medium move_to_delay = 3 projectiletype = /obj/item/projectile/kinetic/miner projectilesound = 'sound/weapons/kenetic_accel.ogg' - ranged = 1 + ranged = TRUE ranged_cooldown_time = 16 pixel_x = -16 crusher_loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye) @@ -47,8 +47,12 @@ Difficulty: Medium var/dashing = FALSE var/dash_cooldown = 15 var/guidance = FALSE + var/transform_stop_attack = FALSE // stops the blood drunk miner from attacking after transforming his weapon until the next attack chain deathmessage = "falls to the ground, decaying into glowing particles." death_sound = "bodyfall" + attack_action_types = list(/datum/action/innate/megafauna_attack/dash, + /datum/action/innate/megafauna_attack/kinetic_accelerator, + /datum/action/innate/megafauna_attack/transform_weapon) /obj/item/gps/internal/miner icon_state = null @@ -56,13 +60,52 @@ Difficulty: Medium desc = "The sweet blood, oh, it sings to me." invisibility = 100 -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance - guidance = TRUE - -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize(mapload) . = ..() - if(. && prob(12)) - INVOKE_ASYNC(src, .proc/dash) + miner_saw = new(src) + internal_gps = new/obj/item/gps/internal/miner(src) + + // Add a zone selection UI; otherwise the mob can't melee attack properly. + zone_sel = new /obj/screen/zone_sel() + +/datum/action/innate/megafauna_attack/dash + name = "Dash To Target" + icon_icon = 'icons/mob/actions/actions.dmi' + button_icon_state = "sniper_zoom" + chosen_message = "You are now dashing to your target." + chosen_attack_num = 1 + +/datum/action/innate/megafauna_attack/kinetic_accelerator + name = "Fire Kinetic Accelerator" + icon_icon = 'icons/obj/guns/energy.dmi' + button_icon_state = "kineticgun" + chosen_message = "You are now shooting your kinetic accelerator." + chosen_attack_num = 2 + +/datum/action/innate/megafauna_attack/transform_weapon + name = "Transform Weapon" + icon_icon = 'icons/obj/lavaland/artefacts.dmi' + button_icon_state = "cleaving_saw" + chosen_message = "You are now transforming your weapon." + chosen_attack_num = 3 + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire() + if(client) + switch(chosen_attack) + if(1) + dash(target) + if(2) + shoot_ka() + if(3) + transform_weapon() + return + + Goto(target, move_to_delay, minimum_distance) + if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time) + dash_attack() + else + shoot_ka() + transform_weapon() /obj/item/melee/energy/cleaving_saw/miner //nerfed saw because it is very murdery force = 6 @@ -79,14 +122,6 @@ Difficulty: Medium icon_state = "ka_tracer" range = MINER_DASH_RANGE -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize() - . = ..() - miner_saw = new(src) - internal_gps = new/obj/item/gps/internal/miner(src) - - // Add a zone selection UI; otherwise the mob can't melee attack properly. - zone_sel = new /obj/screen/zone_sel() - /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE) var/adjustment_amount = amount * 0.1 if(world.time + adjustment_amount > next_move) @@ -104,16 +139,19 @@ Difficulty: Medium return FALSE return ..() -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity, target) +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity) if(dash()) return return ..() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/MeleeAction(patience = TRUE) + transform_stop_attack = FALSE + return ..() + /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget() - if(QDELETED(target)) - return - if(next_move > world.time || !Adjacent(target)) //some cheating - INVOKE_ASYNC(src, .proc/quick_attack_loop) + if(client) + transform_stop_attack = FALSE + if(QDELETED(target) || transform_stop_attack) return face_atom(target) if(isliving(target)) @@ -132,8 +170,6 @@ Difficulty: Medium miner_saw.melee_attack_chain(src, target) if(guidance) adjustHealth(-2) - transform_weapon() - INVOKE_ASYNC(src, .proc/quick_attack_loop) return TRUE /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) @@ -146,16 +182,10 @@ Difficulty: Medium . = ..() if(. && target && !targets_the_same) wander = TRUE - transform_weapon() - INVOKE_ASYNC(src, .proc/quick_attack_loop) -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire() - Goto(target, move_to_delay, minimum_distance) - if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time) - INVOKE_ASYNC(src, .proc/dash, target) - else - shoot_ka() - transform_weapon() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash_attack() + INVOKE_ASYNC(src, .proc/dash, target) + shoot_ka() /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/shoot_ka() if(ranged_cooldown <= world.time && get_dist(src, target) <= MINER_DASH_RANGE && !Adjacent(target)) @@ -166,21 +196,6 @@ Difficulty: Medium Shoot(target) changeNext_move(CLICK_CD_RANGE) -//I'm still of the belief that this entire proc needs to be wiped from existence. -// do not take my touching of it to be endorsement of it. ~mso -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop() - while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep. - stoplag(1) - sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about - if(QDELETED(target)) - return - if(dashing || next_move > world.time || !Adjacent(target)) - if(dashing && next_move <= world.time) - next_move = world.time + 1 - INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again. - return - AttackingTarget() - /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash(atom/dash_target) if(world.time < dash_cooldown) return @@ -189,7 +204,9 @@ Difficulty: Medium var/turf/own_turf = get_turf(src) if(!QDELETED(dash_target)) self_dist_to_target += get_dist(dash_target, own_turf) - for(var/turf/simulated/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf)) + for(var/turf/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf)) + if(O.density) + continue var/turf_dist_to_target = 0 if(!QDELETED(dash_target)) turf_dist_to_target += get_dist(dash_target, O) @@ -218,26 +235,29 @@ Difficulty: Medium var/turf/step_forward_turf = get_step(own_turf, get_cardinal_dir(own_turf, target_turf)) new /obj/effect/temp_visual/small_smoke/halfsecond(step_back_turf) new /obj/effect/temp_visual/small_smoke/halfsecond(step_forward_turf) - var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc, src) - animate(D, alpha = 0, time = 5) + var/obj/effect/temp_visual/decoy/fading/halfsecond/D = new (own_turf, src) forceMove(step_back_turf) playsound(own_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1) dashing = TRUE alpha = 0 animate(src, alpha = 255, time = 5) - sleep(2) + SLEEP_CHECK_DEATH(2) D.forceMove(step_forward_turf) forceMove(target_turf) playsound(target_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1) - sleep(1) + SLEEP_CHECK_DEATH(1) dashing = FALSE - shoot_ka() return TRUE /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon() if(time_until_next_transform <= world.time) miner_saw.transform_cooldown = 0 miner_saw.transform_weapon(src, TRUE) + if(!miner_saw.active) + rapid_melee = 5 // 4 deci cooldown before changes, npcpool subsystem wait is 20, 20/4 = 5 + else + rapid_melee = 3 // same thing but halved (slightly rounded up) + transform_stop_attack = TRUE icon_state = "miner[miner_saw.active ? "_transformed":""]" icon_living = "miner[miner_saw.active ? "_transformed":""]" time_until_next_transform = world.time + rand(50, 100) @@ -263,4 +283,12 @@ Difficulty: Medium sleep(4) animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL) +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance + guidance = TRUE + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget() + . = ..() + if(. && prob(12)) + INVOKE_ASYNC(src, .proc/dash) + #undef MINER_DASH_RANGE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index b618ff9e650..20df360a51a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -32,10 +32,15 @@ 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/chosen_attack = 1 // chosen attack num + var/list/attack_action_types = list() /mob/living/simple_animal/hostile/megafauna/New() ..() apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) + for(var/action_type in attack_action_types) + var/datum/action/innate/megafauna_attack/attack_action = new action_type() + attack_action.Grant(src) /mob/living/simple_animal/hostile/megafauna/Destroy() QDEL_NULL(internal_gps) @@ -113,3 +118,21 @@ SSmedals.SetScore(BOSS_SCORE, C, 1) SSmedals.SetScore(score_type, C, 1) return TRUE + +/datum/action/innate/megafauna_attack + name = "Megafauna Attack" + icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon_state = "" + var/mob/living/simple_animal/hostile/megafauna/M + var/chosen_message + var/chosen_attack_num = 0 + +/datum/action/innate/megafauna_attack/Grant(mob/living/L) + if(istype(L, /mob/living/simple_animal/hostile/megafauna)) + M = L + return ..() + return FALSE + +/datum/action/innate/megafauna_attack/Activate() + M.chosen_attack = chosen_attack_num + to_chat(M, chosen_message) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm deleted file mode 100644 index efc18895141..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ /dev/null @@ -1,225 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/ - vision_range = 2 - 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 - faction = list("mining") - weather_immunities = list("lava","ash") - obj_damage = 30 - environment_smash = 2 - minbodytemp = 0 - heat_damage_per_tick = 20 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "strikes" - status_flags = 0 - a_intent = INTENT_HARM - var/throw_message = "bounces off of" - var/icon_aggro = null // for swapping to when we get aggressive - see_in_dark = 8 - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - mob_size = MOB_SIZE_LARGE - -/mob/living/simple_animal/hostile/asteroid/Aggro() - ..() - icon_state = icon_aggro - -/mob/living/simple_animal/hostile/asteroid/LoseAggro() - ..() - if(stat == CONSCIOUS) - icon_state = icon_living - -/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills - if(!stat) - Aggro() - if(P.damage < 30 && P.damage_type != BRUTE) - P.damage = (P.damage / 3) - visible_message("The [P] has a reduced effect on [src]!") - ..() - -/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy - if(istype(AM, /obj/item)) - var/obj/item/T = AM - if(!stat) - Aggro() - if(T.throwforce <= 20) - visible_message("The [T.name] [src.throw_message] [src.name]!") - return - ..() - -/mob/living/simple_animal/hostile/asteroid/basilisk - name = "basilisk" - desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside." - icon = 'icons/mob/animal.dmi' - icon_state = "Basilisk" - icon_living = "Basilisk" - icon_aggro = "Basilisk_alert" - icon_dead = "Basilisk_dead" - icon_gib = "syndicate_gib" - move_to_delay = 20 - projectiletype = /obj/item/projectile/temp/basilisk - projectilesound = 'sound/weapons/pierce.ogg' - ranged = 1 - ranged_message = "stares" - ranged_cooldown_time = 30 - throw_message = "does nothing against the hard shell of" - vision_range = 2 - speed = 3 - maxHealth = 200 - health = 200 - harm_intent_damage = 5 - obj_damage = 60 - melee_damage_lower = 12 - melee_damage_upper = 12 - attacktext = "bites into" - a_intent = INTENT_HARM - speak_emote = list("chitters") - attack_sound = 'sound/weapons/bladeslice.ogg' - aggro_vision_range = 9 - idle_vision_range = 2 - turns_per_move = 5 - loot = list(/obj/item/stack/ore/diamond{layer = 4.1}, - /obj/item/stack/ore/diamond{layer = 4.1}) - -/obj/item/projectile/temp/basilisk - name = "freezing blast" - icon_state = "ice_2" - damage = 0 - damage_type = BURN - nodamage = 1 - flag = "energy" - temperature = 50 - -/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target) - if(..()) //we have a target - if(isliving(target)) - var/mob/living/L = target - if(L.bodytemperature > 261) - L.bodytemperature = 261 - visible_message("The [src.name]'s stare chills [L.name] to the bone!") - -/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity) - switch(severity) - if(1.0) - gib() - if(2.0) - adjustBruteLoss(140) - if(3.0) - adjustBruteLoss(110) - -/mob/living/simple_animal/hostile/asteroid/goliath - name = "goliath" - desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions." - icon = 'icons/mob/animal.dmi' - icon_state = "Goliath" - icon_living = "Goliath" - icon_aggro = "Goliath_alert" - icon_dead = "Goliath_dead" - icon_gib = "syndicate_gib" - attack_sound = 'sound/weapons/punch4.ogg' - mouse_opacity = MOUSE_OPACITY_OPAQUE - move_to_delay = 40 - ranged = 1 - ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight - ranged_cooldown_time = 120 - friendly = "wails at" - speak_emote = list("bellows") - vision_range = 4 - speed = 3 - maxHealth = 300 - health = 300 - harm_intent_damage = 1 //Only the manliest of men can kill a Goliath with only their fists. - obj_damage = 100 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "pulverizes" - attack_sound = 'sound/weapons/punch1.ogg' - throw_message = "does nothing to the rocky hide of the" - aggro_vision_range = 9 - idle_vision_range = 5 - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - var/pre_attack = 0 - loot = list(/obj/item/stack/sheet/animalhide/goliath_hide{layer = ABOVE_MOB_LAYER}) - -/mob/living/simple_animal/hostile/asteroid/goliath/Life() - ..() - handle_preattack() - -/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack() - if(ranged_cooldown <= world.time + ranged_cooldown_time * 0.25 && !pre_attack) - pre_attack++ - if(!pre_attack || stat || AIStatus == AI_IDLE) - return - icon_state = "Goliath_preattack" - -/mob/living/simple_animal/hostile/asteroid/goliath/revive() - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - ..() - -/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() - var/tturf = get_turf(target) - if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen - visible_message("The [src.name] digs its tentacles under [target.name]!") - new /obj/effect/goliath_tentacle/original(tturf) - ranged_cooldown = world.time + ranged_cooldown_time - icon_state = icon_aggro - pre_attack = 0 - return - -/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage) - ranged_cooldown-- - handle_preattack() - ..() - -/mob/living/simple_animal/hostile/asteroid/goliath/Aggro() - vision_range = aggro_vision_range - handle_preattack() - if(icon_state != icon_aggro) - icon_state = icon_aggro - return - -/obj/effect/goliath_tentacle/ - name = "Goliath tentacle" - icon = 'icons/mob/animal.dmi' - icon_state = "Goliath_tentacle" - var/latched = 0 - -/obj/effect/goliath_tentacle/New() - var/turftype = get_turf(src) - if(istype(turftype, /turf/simulated/mineral)) - var/turf/simulated/mineral/M = turftype - M.gets_drilled() - spawn(20) - Trip() - -/obj/effect/goliath_tentacle/original - -/obj/effect/goliath_tentacle/original/New() - for(var/obj/effect/goliath_tentacle/original/O in loc)//No more GG NO RE from 2+ goliaths simultaneously tentacling you - if(O != src) - qdel(src) - var/list/directions = cardinal.Copy() - var/counter - for(counter = 1, counter <= 3, counter++) - var/spawndir = pick(directions) - directions -= spawndir - var/turf/T = get_step(src,spawndir) - new /obj/effect/goliath_tentacle(T) - ..() - - -/obj/effect/goliath_tentacle/proc/Trip() - for(var/mob/living/M in src.loc) - M.Stun(5) - M.adjustBruteLoss(rand(10,15)) - latched = 1 - if(src && M) - visible_message("The [src.name] grabs hold of [M.name]!") - if(!latched) - qdel(src) - else - spawn(50) - qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index a4f7cce2f51..0c5f2647ae8 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -33,6 +33,7 @@ ranged = 1 retreat_distance = 5 minimum_distance = 5 + projectilesound = 'sound/weapons/gunshots/gunshot.ogg' casingtype = /obj/item/ammo_casing/a357 loot = list(/obj/effect/mob_spawn/human/corpse/russian/ranged, /obj/item/gun/projectile/revolver/mateba) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 546fa3ad50d..d95c18dd831 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -262,6 +262,7 @@ minimum_distance = 5 icon_state = "syndicateranged" icon_living = "syndicateranged" + projectilesound = 'sound/weapons/gunshots/gunshot.ogg' casingtype = /obj/item/ammo_casing/c45 loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, /obj/item/gun/projectile/automatic/c20r) diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e8f2d4ada8346079e62a06c1b84d9c3bc5b852fa GIT binary patch literal 5618 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 literal 0 HcmV?d00001 From 4a58c054205764b66dbd5a179742810b6ac76d48 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Mon, 2 Sep 2019 22:28:57 -0400 Subject: [PATCH 07/13] fixes and updates --- .../mob/living/simple_animal/friendly/cat.dm | 29 +++++++------- .../living/simple_animal/friendly/corgi.dm | 19 ++++----- .../mob/living/simple_animal/friendly/crab.dm | 4 -- .../simple_animal/friendly/farm_animals.dm | 40 ++++++++++--------- .../living/simple_animal/friendly/mouse.dm | 21 +++++----- .../mob/living/simple_animal/friendly/pug.dm | 9 ++--- .../mob/living/simple_animal/simple_animal.dm | 3 ++ 7 files changed, 61 insertions(+), 64 deletions(-) diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 5f54f77c053..928cd9789da 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -95,23 +95,24 @@ /mob/living/simple_animal/pet/cat/Life() - if(!stat && !buckled && !client) + ..() + make_babies() + + +/mob/living/simple_animal/pet/cat/handle_automated_action() + if(!stat && !buckled) if(prob(1)) custom_emote(1, pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) - icon_state = "[icon_living]_rest" - resting = 1 - update_canmove() - else if (prob(1)) + StartResting() + else if(prob(1)) custom_emote(1, pick("sits down.", "crouches on its hind legs.", "looks alert.")) icon_state = "[icon_living]_sit" - resting = 1 + resting = TRUE update_canmove() - else if (prob(1)) - if (resting) + else if(prob(1)) + if(resting) custom_emote(1, pick("gets up and meows.", "walks around.", "stops resting.")) - icon_state = "[icon_living]" - resting = 0 - update_canmove() + StopResting() else custom_emote(1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat.")) @@ -129,10 +130,8 @@ custom_emote(1, "bats \the [T] around with its paw!") T.cooldown = world.time - ..() - - make_babies() - +/mob/living/simple_animal/pet/cat/handle_automated_movement() + . = ..() if(!stat && !resting && !buckled) turns_since_scan++ if(turns_since_scan > 5) diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index d8f09f4cb78..c6a572e9679 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -451,9 +451,8 @@ response_harm = "kicks" gold_core_spawnable = CHEM_MOB_SPAWN_INVALID -/mob/living/simple_animal/pet/corgi/Ian/Life() - ..() - +/mob/living/simple_animal/pet/corgi/Ian/handle_automated_movement() + . = ..() //Feeding, chasing food, FOOOOODDDD if(!resting && !buckled) turns_since_scan++ @@ -580,9 +579,10 @@ /mob/living/simple_animal/pet/corgi/Lisa/Life() ..() - make_babies() +/mob/living/simple_animal/pet/corgi/Lisa/handle_automated_movement() + . = ..() if(!resting && !buckled) if(prob(1)) custom_emote(1, pick("dances around.","chases her tail.")) @@ -651,15 +651,16 @@ /mob/living/simple_animal/pet/corgi/Ian/borgi/Life(seconds, times_fired) ..() - if(emagged && prob(25)) - var/mob/living/carbon/target = locate() in view(10,src) - if(target) - shootAt(target) - //spark for no reason if(prob(5)) do_sparks(3, 1, src) +/mob/living/simple_animal/pet/corgi/Ian/borgi/handle_automated_action() + if(emagged && prob(25)) + var/mob/living/carbon/target = locate() in view(10, src) + if(target) + shootAt(target) + /mob/living/simple_animal/pet/corgi/Ian/borgi/death(gibbed) // Only execute the below if we successfully died . = ..(gibbed) diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 565c899fc23..aaa7736f017 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -21,10 +21,6 @@ can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY -/mob/living/simple_animal/crab/Life(seconds, times_fired) - . = ..() - regenerate_icons() - //COFFEE! SQUEEEEEEEEE! /mob/living/simple_animal/crab/Coffee name = "Coffee" diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 9d5990bb2d6..4ea4e4999cd 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -34,31 +34,33 @@ . = ..() /mob/living/simple_animal/hostile/retaliate/goat/Destroy() - qdel(udder) - udder = null + QDEL_NULL(udder) return ..() +/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_action() + if(!..()) + return + //chance to go crazy and start wacking stuff + if(!enemies.len && prob(1)) + Retaliate() + + if(enemies.len && prob(10)) + enemies = list() + LoseTarget() + visible_message("[src] calms down.") + + eat_plants() + if(!pulledby) + for(var/direction in shuffle(list(1, 2, 4, 8, 5, 6, 9, 10))) + var/step = get_step(src, direction) + if(step) + if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step) + Move(step, get_dir(src, step)) + /mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired) . = ..() - if(.) - //chance to go crazy and start wacking stuff - if(!enemies.len && prob(1)) - Retaliate() - - if(enemies.len && prob(10)) - enemies = list() - LoseTarget() - visible_message("[src] calms down.") - if(stat == CONSCIOUS) udder.generateMilk() - eat_plants() - if(!pulledby) - for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) - var/step = get_step(src, direction) - if(step) - if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step) - Move(step, get_dir(src, step)) /mob/living/simple_animal/hostile/retaliate/goat/Retaliate() ..() diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 33adee324db..ec9cb5cd884 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -58,20 +58,17 @@ /mob/living/simple_animal/mouse/handle_automated_speech() ..() if(prob(speak_chance) && !incapacitated()) - for(var/mob/M in view()) - SEND_SOUND(M, squeak_sound) + playsound(src, squeak_sound, 100, 1) -/mob/living/simple_animal/mouse/Life(seconds, times_fired) +/mob/living/simple_animal/mouse/handle_automated_movement() . = ..() - if(.) // Alive - if(!ckey) - if(resting) - if(prob(1)) - StopResting() - else if(prob(5)) - custom_emote(2, "snuffles") - else if(prob(0.5)) - StartResting() + if(resting) + if(prob(1)) + StopResting() + else if(prob(5)) + custom_emote(2, "snuffles") + else if(prob(0.5)) + StartResting() /mob/living/simple_animal/mouse/New() ..() diff --git a/code/modules/mob/living/simple_animal/friendly/pug.dm b/code/modules/mob/living/simple_animal/friendly/pug.dm index 36ce34094a0..c7b52928e8a 100644 --- a/code/modules/mob/living/simple_animal/friendly/pug.dm +++ b/code/modules/mob/living/simple_animal/friendly/pug.dm @@ -19,13 +19,12 @@ see_in_dark = 5 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY -/mob/living/simple_animal/pet/pug/Life() - ..() - +/mob/living/simple_animal/pet/pug/handle_automated_movement() + . = ..() if(!resting && !buckled) if(prob(1)) custom_emote(1, pick("chases its tail.")) spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2)) + for(var/i in list(1, 2, 4, 8, 4, 2, 1, 2, 4, 8, 4, 2, 1, 2, 4, 8, 4, 2)) dir = i - sleep(1) + sleep(1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index cfe96411861..b556fa24bec 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -489,6 +489,9 @@ canmove = 0 else canmove = 1 + if(!canmove) + walk(src, 0) //stop mid walk + update_transform() if(!delay_action_updates) update_action_buttons_icon() From 4ee863ea5f48caeb09e7fe836b3ad664b05c7d96 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Mon, 2 Sep 2019 22:30:21 -0400 Subject: [PATCH 08/13] fix again --- .../modules/mob/living/simple_animal/hostile/mining/gutlunch.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm index 9fb2e041479..23a900c1519 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm @@ -61,7 +61,7 @@ udder.milkAnimal(O, user) regenerate_icons() else - ..() + return ..() /mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids From 478d73921bb38a6c46c2391d743689c32e544f58 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Tue, 3 Sep 2019 01:00:10 -0400 Subject: [PATCH 09/13] alterations --- code/game/gamemodes/miniantags/revenant/revenant.dm | 2 +- .../mob/living/simple_animal/friendly/farm_animals.dm | 5 ++--- .../mob/living/simple_animal/hostile/giant_spider.dm | 7 +++---- .../simple_animal/hostile/megafauna/blood_drunk_miner.dm | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 740601f3798..f0d8ede6634 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -85,7 +85,7 @@ /mob/living/simple_animal/revenant/narsie_act() return //most humans will now be either bones or harvesters, but we're still un-alive. -/mob/living/simple_animal/revenant/adjustHealth(amount) +/mob/living/simple_animal/revenant/adjustHealth(amount, updating_health = TRUE) if(!revealed) return essence = max(0, essence-amount) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 4ea4e4999cd..0c9aa96728c 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -37,9 +37,8 @@ QDEL_NULL(udder) return ..() -/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_action() - if(!..()) - return +/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement() + . = ..() //chance to go crazy and start wacking stuff if(!enemies.len && prob(1)) Retaliate() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index a42535a66e3..ab802590ee3 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -76,9 +76,8 @@ venom_per_bite = 10 move_to_delay = 5 -/mob/living/simple_animal/hostile/poison/giant_spider/handle_automated_action() - if(!..()) //AIStatus is off - return 0 +/mob/living/simple_animal/hostile/poison/giant_spider/handle_automated_movement() //Hacky and ugly. + . = ..() if(AIStatus == AI_IDLE) //1% chance to skitter madly away if(!busy && prob(1)) @@ -97,7 +96,7 @@ busy = 0 stop_automated_movement = 0 -/mob/living/simple_animal/hostile/poison/giant_spider/nurse/handle_automated_action() +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/handle_automated_movement() //Hacky and ugly. if(..()) var/list/can_see = view(src, 10) if(!busy && prob(30)) //30% chance to stop wandering and do something diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index db96f9fce96..05bdf9c76a6 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -122,7 +122,7 @@ Difficulty: Medium icon_state = "ka_tracer" range = MINER_DASH_RANGE -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE) +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE) var/adjustment_amount = amount * 0.1 if(world.time + adjustment_amount > next_move) changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly From 1105d515e2a207480e87872b6b7e2f99a600ce6b Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Tue, 3 Sep 2019 02:53:56 -0400 Subject: [PATCH 10/13] spider fixes --- .../simple_animal/hostile/terror_spiders/reproduction.dm | 8 -------- .../hostile/terror_spiders/terror_spiders.dm | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm index 999405df2d8..7e90867e783 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm @@ -11,7 +11,6 @@ layer = 2.75 health = 3 var/stillborn = FALSE - faction = list("terrorspiders") var/spider_myqueen = null var/spider_mymother = null var/goto_mother = FALSE @@ -169,10 +168,8 @@ if(!grow_as) grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray, /mob/living/simple_animal/hostile/poison/terror_spider/green) var/mob/living/simple_animal/hostile/poison/terror_spider/S = new grow_as(loc) - S.faction = faction S.spider_myqueen = spider_myqueen S.spider_mymother = spider_mymother - S.master_commander = master_commander S.enemies = enemies qdel(src) @@ -186,10 +183,8 @@ var/obj/structure/spider/eggcluster/terror_eggcluster/C = new /obj/structure/spider/eggcluster/terror_eggcluster(get_turf(src)) C.spiderling_type = lay_type C.spiderling_number = lay_number - C.faction = faction C.spider_myqueen = spider_myqueen C.spider_mymother = src - C.master_commander = master_commander C.enemies = enemies if(spider_growinstantly) C.amount_grown = 250 @@ -202,7 +197,6 @@ desc = "A cluster of tiny spider eggs. They pulse with a strong inner life, and appear to have sharp thorns on the sides." icon_state = "eggs" var/spider_growinstantly = 0 - faction = list("terrorspiders") var/spider_myqueen = null var/spider_mymother = null var/spiderling_type = null @@ -244,10 +238,8 @@ var/obj/structure/spider/spiderling/terror_spiderling/S = new /obj/structure/spider/spiderling/terror_spiderling(get_turf(src)) if(spiderling_type) S.grow_as = spiderling_type - S.faction = faction S.spider_myqueen = spider_myqueen S.spider_mymother = spider_mymother - S.master_commander = master_commander S.enemies = enemies if(spider_growinstantly) S.amount_grown = 250 diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm index dba6853bc15..0fd357b0f11 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -364,7 +364,7 @@ var/global/list/ts_spiderling_list = list() to_chat(T, "TerrorSense: [msgtext]") /mob/living/simple_animal/hostile/poison/terror_spider/proc/CheckFaction() - if(faction.len != 1 || (!("terrorspiders" in faction)) || master_commander != null) + if(faction.len != 2 || (!("terrorspiders" in faction)) || master_commander != null) to_chat(src, "Your connection to the hive mind has been severed!") log_runtime(EXCEPTION("Terror spider with incorrect faction list at: [atom_loc_line(src)]")) gib() From fb7db36350797ec37d92e155560aa55bde1f4ebb Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Tue, 3 Sep 2019 03:34:15 -0400 Subject: [PATCH 11/13] fixed rapid mobs --- code/game/gamemodes/miniantags/guardian/types/ranged.dm | 3 +-- code/modules/mob/living/carbon/human/species/_species.dm | 2 -- code/modules/mob/living/carbon/human/species/shadow.dm | 4 ++-- code/modules/mob/living/simple_animal/hostile/hivebot.dm | 2 +- code/modules/mob/living/simple_animal/hostile/pirate.dm | 2 +- .../mob/living/simple_animal/hostile/retaliate/drone.dm | 2 +- code/modules/mob/living/simple_animal/hostile/syndicate.dm | 2 +- .../living/simple_animal/hostile/terror_spiders/empress.dm | 2 +- code/modules/mob/living/simple_animal/hostile/winter_mobs.dm | 2 +- 9 files changed, 9 insertions(+), 12 deletions(-) diff --git a/code/game/gamemodes/miniantags/guardian/types/ranged.dm b/code/game/gamemodes/miniantags/guardian/types/ranged.dm index fe8a566ad52..871d7be1183 100644 --- a/code/game/gamemodes/miniantags/guardian/types/ranged.dm +++ b/code/game/gamemodes/miniantags/guardian/types/ranged.dm @@ -11,10 +11,9 @@ melee_damage_upper = 10 damage_transfer = 0.9 projectiletype = /obj/item/projectile/guardian - ranged_cooldown_time = 10 + ranged_cooldown_time = 1 //fast! projectilesound = 'sound/effects/hit_on_shattered_glass.ogg' ranged = 1 - rapid = 1 range = 13 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE see_in_dark = 8 diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 3e295eb9b4c..33df376ff51 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -64,8 +64,6 @@ var/ventcrawler = 0 //Determines if the mob can go through the vents. var/has_fine_manipulation = 1 // Can use small items. - var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species - var/list/allowed_consumed_mobs = list() //If a species can consume mobs, put the type of mobs it can consume here. var/list/species_traits = list() diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index fb7fd2ebda1..b662e5152f9 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -8,8 +8,6 @@ unarmed_type = /datum/unarmed_attack/claws - ignored_by = list(/mob/living/simple_animal/hostile/faithless) - blood_color = "#CCCCCC" flesh_color = "#AAAAAA" has_organ = list( @@ -51,12 +49,14 @@ if(grant_vision_toggle) vision_toggle = new vision_toggle.Grant(H) + C.faction |= "faithless" /datum/species/shadow/on_species_loss(mob/living/carbon/human/H) ..() if(grant_vision_toggle && vision_toggle) H.vision_type = null vision_toggle.Remove(H) + C.faction -= "faithless" /datum/species/shadow/handle_life(mob/living/carbon/human/H) var/light_amount = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index 9695cacccd8..30572f19158 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -36,7 +36,7 @@ /mob/living/simple_animal/hostile/hivebot/rapid ranged = 1 - rapid = 1 + rapid = 3 retreat_distance = 5 minimum_distance = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 108daa031df..34a224ca5ce 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -36,7 +36,7 @@ icon_dead = "piratemelee_dead" projectilesound = 'sound/weapons/laser.ogg' ranged = 1 - rapid = 1 + rapid = 2 retreat_distance = 5 minimum_distance = 5 projectiletype = /obj/item/projectile/beam diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm index 709a238346a..bd3314d1453 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm @@ -7,7 +7,7 @@ icon_living = "drone3" icon_dead = "drone_dead" ranged = 1 - rapid = 1 + rapid = 3 speak_chance = 5 turns_per_move = 3 response_help = "pokes the" diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index d95c18dd831..f380d85be34 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -257,7 +257,7 @@ /mob/living/simple_animal/hostile/syndicate/ranged ranged = 1 - rapid = 1 + rapid = 2 retreat_distance = 5 minimum_distance = 5 icon_state = "syndicateranged" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm index 14353c4dfd0..90550dccdca 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm @@ -20,7 +20,7 @@ idle_ventcrawl_chance = 0 ai_playercontrol_allowtype = 0 ai_type = TS_AI_AGGRESSIVE - rapid = 1 + rapid = 3 canlay = 1000 spider_tier = TS_TIER_5 projectiletype = /obj/item/projectile/terrorqueenspit/empress diff --git a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm index f96ebabf014..d8fba34296b 100644 --- a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm @@ -117,7 +117,7 @@ maxHealth = 250 health = 250 ranged = 1 - rapid = 1 + rapid = 3 speed = 0 //he's lost some weight from the fighting projectiletype = /obj/item/projectile/ornament retreat_distance = 3 From c15b93804dd49a7331c98c4dec794ba203ed829a Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Tue, 3 Sep 2019 03:43:27 -0400 Subject: [PATCH 12/13] derp --- code/modules/mob/living/carbon/human/species/shadow.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index b662e5152f9..b21002e7225 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -49,14 +49,14 @@ if(grant_vision_toggle) vision_toggle = new vision_toggle.Grant(H) - C.faction |= "faithless" + H.faction |= "faithless" /datum/species/shadow/on_species_loss(mob/living/carbon/human/H) ..() if(grant_vision_toggle && vision_toggle) H.vision_type = null vision_toggle.Remove(H) - C.faction -= "faithless" + H.faction -= "faithless" /datum/species/shadow/handle_life(mob/living/carbon/human/H) var/light_amount = 0 From f76e214681078193587e315daed7f474804b219f Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Tue, 3 Sep 2019 14:32:36 -0400 Subject: [PATCH 13/13] re-include --- code/modules/mob/living/simple_animal/friendly/crab.dm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index aaa7736f017..1456e2f70fb 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -21,6 +21,16 @@ can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY +/mob/living/simple_animal/crab/handle_automated_movement() + //CRAB movement + if(!stat) + if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc. + turns_since_move++ + if(turns_since_move >= turns_per_move) + var/east_vs_west = pick(4, 8) + if(Process_Spacemove(east_vs_west)) + Move(get_step(src, east_vs_west), east_vs_west) + //COFFEE! SQUEEEEEEEEE! /mob/living/simple_animal/crab/Coffee name = "Coffee"