From 57ec6291a935a34a3fb392064e6d811e4be39f53 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sat, 24 Aug 2024 20:13:28 +0200 Subject: [PATCH 01/17] fix disarm bug --- .../living/simple_animal/hostile/retaliate/giant_lizard.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 6bb0202c2deb..25799cb37bd5 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -227,8 +227,9 @@ manual_emote(pick(pick(pet_emotes), "stares at [attacking_mob].", "nuzzles [attacking_mob].", "licks [attacking_mob]'s hand."), "nibbles [attacking_mob]'s arm.", "flicks its tongue at [attacking_mob].") if(prob(50)) playsound(loc, "giant_lizard_hiss", 25) - if(attacking_mob.a_intent == INTENT_DISARM && prob(75)) - step_to(src, get_step(loc, attacking_mob.dir), 0, LIZARD_SPEED_NORMAL) + if(attacking_mob.a_intent == INTENT_DISARM && prob(25)) + playsound(loc, 'sound/weapons/alien_knockdown.ogg', 25, 1) + KnockDown(0.4) //apply blood splatter when attacked by a sufficently damaging sharp weapon /mob/living/simple_animal/hostile/retaliate/giant_lizard/attackby(obj/item/weapon, mob/living/carbon/human/attacker) From 2bd082af94e1ee39bd626cefd28eea63166bdebe Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 08:35:48 +0200 Subject: [PATCH 02/17] stops the lizards from resting after moving --- .../hostile/retaliate/giant_lizard.dm | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 25799cb37bd5..622d5bf136e4 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -299,6 +299,20 @@ bleed_ticks-- add_splatter_floor(loc, is_small_pool) + //done before the parent proccall because it would result in it moving before resting + if(stance == HOSTILE_STANCE_IDLE && !client) + stop_automated_movement = FALSE + //if there's a friend on the same tile as us, don't bother getting up (cute!) + var/mob/living/carbon/friend = locate(/mob/living/carbon) in get_turf(src) + if((friend?.faction in faction_group) && resting) + chance_to_rest = 0 + + if(prob(chance_to_rest)) + set_resting(!resting) + chance_to_rest = 0 + + chance_to_rest += rand(1, 2) + . = ..() if(client) @@ -317,19 +331,6 @@ if(stance > HOSTILE_STANCE_ALERT) is_eating = FALSE - if(stance == HOSTILE_STANCE_IDLE) - stop_automated_movement = FALSE - //if there's a friend on the same tile as us, don't bother getting up (cute!) - var/mob/living/carbon/friend = locate(/mob/living/carbon) in get_turf(src) - if((friend?.faction in faction_group) && resting) - chance_to_rest = 0 - - if(prob(chance_to_rest)) - set_resting(!resting) - chance_to_rest = 0 - - chance_to_rest += rand(1, 2) - //if we're resting and something catches our interest, get up if(stance != HOSTILE_STANCE_IDLE && resting) set_resting(FALSE) From d104c0ad9552af230a1b4c66e77ebfb35e9d045a Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 11:28:59 +0200 Subject: [PATCH 03/17] adds structure destruction, fixes mob moving while still knocked down, increases combat range allowing for better skirmishing --- code/modules/mob/death.dm | 2 +- .../hostile/retaliate/giant_lizard.dm | 79 +++++++++++++++---- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 8aea59b96a81..ba74c06fcaf1 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -49,7 +49,7 @@ return 0 if(!gibbed) - visible_message("\The [src.name] [deathmessage]") + visible_message("[src.name] [deathmessage]") if(cause_data && !istype(cause_data)) stack_trace("death called with string cause ([cause_data]) instead of datum") diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 622d5bf136e4..f4992cfcd369 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -38,6 +38,7 @@ melee_damage_lower = 20 melee_damage_upper = 25 + break_stuff_probability = 100 attack_same = FALSE langchat_color = LIGHT_COLOR_GREEN @@ -46,6 +47,8 @@ ///If 0, moves the mob out of attacking into idle state. Used to prevent the mob from chasing down targets that did not mean to hurt it. var/aggression_value = 0 + ///Every type of structure that will can get attack in the DestroySurroundings() proc. + var/list/destruction_targets = list(/obj/structure/window, /obj/structure/closet, /obj/structure/surface/table, /obj/structure/grille, /obj/structure/barricade, /obj/structure/machinery/door, /obj/structure/largecrate) ///Emotes to play when being pet by a friend. var/list/pet_emotes = list("closes its eyes.", "growls happily.", "wags its tail.", "rolls on the ground.") @@ -71,7 +74,6 @@ var/retreat_attempts = 0 ///Tied directly to retreat_attempts. If our retreat fail, then we will completely stop trying to retreat for the length of this cooldown. COOLDOWN_DECLARE(retreat_cooldown) - ///The food object that the mob is trying to eat. var/food_target ///A list of foods the mob is interested in eating. @@ -93,6 +95,11 @@ pounce_callbacks[/turf] = DYNAMIC(/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_turf_wrapper) pounce_callbacks[/obj] = DYNAMIC(/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_obj_wrapper) +/mob/living/simple_animal/hostile/retaliate/giant_lizard/initialize_pass_flags(datum/pass_flags_container/pass_flags_container) + ..() + if (pass_flags_container) + pass_flags_container.flags_pass |= PASS_FLAGS_CRAWLER + //regular pain datum will make the mob die when trying to pounce after taking enough damage. /mob/living/simple_animal/hostile/retaliate/giant_lizard/initialize_pain() pain = new /datum/pain/xeno(src) @@ -187,9 +194,8 @@ RemoveSleepingIcon() update_transform() -/mob/living/simple_animal/hostile/retaliate/giant_lizard/death() +/mob/living/simple_animal/hostile/retaliate/giant_lizard/death(datum/cause_data/cause_data, gibbed = FALSE, deathmessage = "lets out a waning growl....") playsound(loc, 'sound/effects/giant_lizard_death.ogg', 70) - manual_emote("lets out a waning growl.") return ..() /mob/living/simple_animal/hostile/retaliate/giant_lizard/attack_hand(mob/living/carbon/human/attacking_mob) @@ -250,7 +256,7 @@ addtimer(VARSET_CALLBACK(src, speed, LIZARD_SPEED_NORMAL_CLIENT), 8 SECONDS) addtimer(VARSET_CALLBACK(src, is_retreating, FALSE), 8 SECONDS) else - MoveTo(target_mob, 12, TRUE, 8 SECONDS) + MoveTo(target_mob, 12, TRUE, 3 SECONDS) if(damage >= 10 && damagetype == BRUTE) add_splatter_floor(loc, TRUE) bleed_ticks = clamp(bleed_ticks + ceil(damage / 10), 0, 30) @@ -338,6 +344,10 @@ if(target_mob && !is_retreating && target_mob.stat == CONSCIOUS && stance == HOSTILE_STANCE_ATTACKING && COOLDOWN_FINISHED(src, pounce_cooldown) && (prob(75) || get_dist(src, target_mob) <= 5) && (target_mob in view(5, src))) pounce(target_mob) + //if we're trying to get away and there's obstacles around us, try to break them + if(target_mob && is_retreating && stance >= HOSTILE_STANCE_ALERT && destroy_surroundings) + INVOKE_ASYNC(src, PROC_REF(DestroySurroundings)) + if(target_mob || on_fire) return @@ -431,6 +441,22 @@ MoveTo(target_mob, 8, TRUE, 2 SECONDS, TRUE) //skirmish around our target return target + if(isStructure(inherited_target)) + var/obj/structure/structure = inherited_target + if(structure.unslashable) + return + + animation_attack_on(structure) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + visible_message(SPAN_DANGER("[src] slashes [structure]!"), SPAN_DANGER("You slash [structure]!"), null, 5, CHAT_TYPE_COMBAT_ACTION) + structure.update_health(rand(melee_damage_lower, melee_damage_upper) * 2) + return + + //if it's not an object or a structure, just swipe at it + animation_attack_on(inherited_target) + visible_message(SPAN_DANGER("[src] swipes at [inherited_target]!"), SPAN_DANGER("You swipe at [inherited_target]!"), null, 5, CHAT_TYPE_COMBAT_ACTION) + playsound(loc, 'sound/weapons/alien_claw_swipe.ogg', 10, 1) + //Used to handle attacks when a client is in the mob. Otherwise we'd default to a generic animal attack. /mob/living/simple_animal/hostile/retaliate/giant_lizard/UnarmedAttack(atom/target) var/tile_attack = FALSE @@ -446,9 +472,30 @@ target = targets break - if(isliving(target)) - AttackingTarget(target) - next_move = world.time + 8 + AttackingTarget(target) + //turf attacks are missed attacks so it should just be a minor penalty to attack delay + next_move = isturf(target) ? world.time + 4 : world.time + 8 + +/mob/living/simple_animal/hostile/retaliate/giant_lizard/DestroySurroundings() + if(prob(break_stuff_probability)) + for(var/obj/structure/obstacle in view(1, src)) + if(is_type_in_list(obstacle, destruction_targets)) + AttackingTarget(obstacle) + return + +//no longer checks for distance with ListTargets(). thershold for losing targets is increased, due to needing range for skirmishing +/mob/living/simple_animal/hostile/retaliate/giant_lizard/AttackTarget() + stop_automated_movement = TRUE + if(!target_mob || SA_attackable(target_mob)) + LoseTarget() + return + if(get_dist(src, target_mob) > 18) + LoseTarget() + return + if(in_range(src, target_mob)) //Attacking + AttackingTarget() + return TRUE + ///Proc for when the mob finds food and starts DEVOURING it. /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/handle_food(obj/item/reagent_container/food/snacks/food) @@ -539,26 +586,28 @@ MoveToTarget() //basic pack behaviour - for(var/mob/living/simple_animal/hostile/retaliate/giant_lizard/pack_member in view(7, src)) + for(var/mob/living/simple_animal/hostile/retaliate/giant_lizard/pack_member in view(12, src)) if(pack_member == src || pack_member.target_mob) continue pack_member.Retaliate() ///Proc for moving to targets. walk_to() doesn't check for resting and status effects so we will do it ourselves. /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/MoveTo(target, distance = 1, retreat = FALSE, time = 6 SECONDS, return_to_combat = FALSE) - if(stat == DEAD || HAS_TRAIT(src, TRAIT_INCAPACITATED) || HAS_TRAIT(src, TRAIT_FLOORED)) - return + //we have to check the icon_state because somehow it's still possible that it moves even if it looks like its stunned. + if(stat == DEAD || HAS_TRAIT(src, TRAIT_INCAPACITATED) || HAS_TRAIT(src, TRAIT_FLOORED) || icon_state == "Giant Lizard Knocked Down") + return FALSE if(resting) set_resting(FALSE) if(!retreat) walk_to(src, target ? target : get_turf(src), distance, move_to_delay) - return + return TRUE if(!is_retreating) is_retreating = TRUE stop_automated_movement = TRUE stance = HOSTILE_STANCE_ALERT walk_away(src, target ? target : get_turf(src), distance, LIZARD_SPEED_RETREAT) addtimer(CALLBACK(src, PROC_REF(stop_retreat), return_to_combat), time) + return TRUE //Proc that's called after the retreat has run its course. /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/stop_retreat(return_to_combat = FALSE) @@ -580,7 +629,7 @@ for(var/mob/living/carbon/hostile_mob in view(7, src)) if(hostile_mob.faction in faction_group) continue - MoveTo(hostile_mob, 10, TRUE, 3 SECONDS, FALSE) + MoveTo(hostile_mob, 10, TRUE, 2 SECONDS, FALSE) retreat_attempts++ return retreat_attempts = 0 @@ -594,9 +643,9 @@ stop_automated_movement = TRUE if(!target_mob || SA_attackable(target_mob)) stance = HOSTILE_STANCE_IDLE - if(target_mob in ListTargets(10)) - stance = HOSTILE_STANCE_ATTACKING - MoveTo(target_mob) + if(get_dist(src, target_mob) <= 18) + if(MoveTo(target_mob)) + stance = HOSTILE_STANCE_ATTACKING /mob/living/simple_animal/hostile/retaliate/giant_lizard/resist_fire() visible_message(SPAN_NOTICE("[src] rolls frantically on the ground to extinguish itself!")) From 466e13de29ce49e3a0f2607e50e304e92a462c99 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 11:43:24 +0200 Subject: [PATCH 04/17] fix comment typo --- .../mob/living/simple_animal/hostile/retaliate/giant_lizard.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index f4992cfcd369..4a4f6ec838a7 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -47,7 +47,7 @@ ///If 0, moves the mob out of attacking into idle state. Used to prevent the mob from chasing down targets that did not mean to hurt it. var/aggression_value = 0 - ///Every type of structure that will can get attack in the DestroySurroundings() proc. + ///Every type of structure that can get attacked in the DestroySurroundings() proc. var/list/destruction_targets = list(/obj/structure/window, /obj/structure/closet, /obj/structure/surface/table, /obj/structure/grille, /obj/structure/barricade, /obj/structure/machinery/door, /obj/structure/largecrate) ///Emotes to play when being pet by a friend. From cfe700135f4b7a86a13877a2651bc7ab34ae37c3 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 12:34:27 +0200 Subject: [PATCH 05/17] stops message spam when eating from allied hands --- .../mob/living/simple_animal/hostile/retaliate/giant_lizard.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 4a4f6ec838a7..472e4e5f6f00 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -509,7 +509,7 @@ playsound(loc,'sound/items/eatfood.ogg', 25, 1) for(var/mob/living/carbon/nearest_mob in view(7, src)) - if(nearest_mob != food.last_dropped_by || (nearest_mob in faction_group)) + if(nearest_mob != food.last_dropped_by || (nearest_mob.faction in faction_group)) continue face_atom(nearest_mob) manual_emote("stares curiously at [nearest_mob].") From 8cb05b2f0c2eaf41261c5738ef0ed445451535a2 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 14:07:39 +0200 Subject: [PATCH 06/17] switch between targets if original target is far away --- .../mob/living/simple_animal/hostile/retaliate/giant_lizard.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 472e4e5f6f00..030cf5067aea 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -574,7 +574,7 @@ //Immediately retaliate after being attacked. /mob/living/simple_animal/hostile/retaliate/giant_lizard/Retaliate() - if(stat == DEAD || target_mob || on_fire) + if(stat == DEAD || get_dist(src, target_mob) < 6 || on_fire) return aggression_value = clamp(aggression_value + 5, 0, 15) From 9017f71e5b7d9a72c34478367ad816c83809c288 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sun, 25 Aug 2024 20:13:55 +0200 Subject: [PATCH 07/17] add latespawn lizards --- code/_globalvars/misc.dm | 3 +++ .../objects/effects/landmarks/landmarks.dm | 18 ++++++++++++++++++ .../hostile/retaliate/giant_lizard.dm | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index 5d7955d85013..c790c822a61a 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -135,3 +135,6 @@ GLOBAL_VAR(xeno_queue_candidate_count) GLOBAL_VAR(obfs_x) /// A number between -500 and 500. GLOBAL_VAR(obfs_y) + +/// The current amount of giant lizards that are alive. +GLOBAL_VAR_INIT(giant_lizards_alive, 0) diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index f5f0e0b50c05..3d1bf4c509be 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -121,6 +121,8 @@ GLOB.monkey_spawns -= src return ..() +#define MAXIMUM_LIZARD_AMOUNT 5 + /obj/effect/landmark/lizard_spawn name = "lizard spawn" icon_state = "lizard_spawn" @@ -129,6 +131,22 @@ . = ..() if(prob(66)) new /mob/living/simple_animal/hostile/retaliate/giant_lizard(loc) + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(30 MINUTES, 45 MINUTES)) + +/obj/effect/landmark/lizard_spawn/proc/latespawn_lizard() + //if there's already a ton of lizards alive, try again later + if(GLOB.giant_lizards_alive > MAXIMUM_LIZARD_AMOUNT) + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), 10 MINUTES) + return + //if there's a living mob that can witness the spawn then try again later + for(var/mob/living/living_mob in range(7, src)) + if(living_mob.stat != DEAD || living_mob.client) + continue + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), 1 MINUTES) + return + new /mob/living/simple_animal/hostile/retaliate/giant_lizard(loc) + +#undef MAXIMUM_LIZARD_AMOUNT /obj/effect/landmark/latewhiskey name = "Whiskey Outpost Late join" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 030cf5067aea..b43abe02e519 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -90,6 +90,7 @@ /mob/living/simple_animal/hostile/retaliate/giant_lizard/Initialize() . = ..() + GLOB.giant_lizards_alive++ change_real_name(src, "[name] ([rand(1, 999)])") pounce_callbacks[/mob] = DYNAMIC(/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_mob_wrapper) pounce_callbacks[/turf] = DYNAMIC(/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_turf_wrapper) @@ -194,8 +195,15 @@ RemoveSleepingIcon() update_transform() +/mob/living/simple_animal/hostile/retaliate/giant_lizard/rejuvenate() + //if the mob was dead beforehand, it's now alive and therefore it's an extra lizard to the count + if(stat == DEAD) + GLOB.giant_lizards_alive++ + return ..() + /mob/living/simple_animal/hostile/retaliate/giant_lizard/death(datum/cause_data/cause_data, gibbed = FALSE, deathmessage = "lets out a waning growl....") playsound(loc, 'sound/effects/giant_lizard_death.ogg', 70) + GLOB.giant_lizards_alive-- return ..() /mob/living/simple_animal/hostile/retaliate/giant_lizard/attack_hand(mob/living/carbon/human/attacking_mob) From bf15f35e9ca8a2a4e6af438b5c3e7936dc4b3397 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Mon, 26 Aug 2024 09:17:38 +0200 Subject: [PATCH 08/17] stops pouncing from hurting own friends, now eats all meat products --- .../hostile/retaliate/giant_lizard.dm | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index b43abe02e519..d1d8ef09a802 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -367,13 +367,18 @@ //if we're hungry and we don't have already have our eyes on a snack, try eating food if possible if(!food_target && COOLDOWN_FINISHED(src, food_cooldown)) for(var/obj/item/reagent_container/food/snacks/food in view(6, src)) - if(!is_type_in_list(food, acceptable_foods)) - continue - food_target = food - stance = HOSTILE_STANCE_ALERT - stop_automated_movement = TRUE - MoveTo(food_target) - break + var/is_meat = FALSE + for(var/datum/reagent/nutriment/meat/meat in food.reagents.reagent_list) + if(istype(meat)) + is_meat = TRUE + break + + if(is_type_in_list(food, acceptable_foods) || is_meat) + food_target = food + stance = HOSTILE_STANCE_ALERT + stop_automated_movement = TRUE + MoveTo(food_target) + break //handling mobs that are invading our personal space if(stance <= HOSTILE_STANCE_ALERT && !food_target && COOLDOWN_FINISHED(src, calm_cooldown)) @@ -749,7 +754,7 @@ playsound(loc, "giant_lizard_hiss", 25) pounced_mob.KnockDown(0.5) step_to(src, pounced_mob) - if(!client) + if(!client && !(pounced_mob.faction in faction_group)) ravagingattack(pounced_mob) /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_turf(turf/turf_target) From 466e3becaf6ab975d90b31b44c3df009a53b47a4 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Mon, 26 Aug 2024 14:43:55 +0200 Subject: [PATCH 09/17] fix paralyze bug #2, increase damage against xenos, add tamable var --- .../hostile/retaliate/giant_lizard.dm | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index d1d8ef09a802..9815b6005e14 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -74,6 +74,8 @@ var/retreat_attempts = 0 ///Tied directly to retreat_attempts. If our retreat fail, then we will completely stop trying to retreat for the length of this cooldown. COOLDOWN_DECLARE(retreat_cooldown) + ///Can this mob be tamed? + var/tameable = TRUE ///The food object that the mob is trying to eat. var/food_target ///A list of foods the mob is interested in eating. @@ -140,7 +142,7 @@ /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/find_target_on_trait_loss() is_retreating = FALSE if(stance > HOSTILE_STANCE_ALERT) - FindTarget() + target_mob = FindTarget() MoveToTarget() //procs for handling sleeping icons when resting @@ -301,6 +303,12 @@ if(aggression_value > 0) aggression_value-- + //it is possible for the mob to keep a target_mob saved, yet be stuck in alert stance and never lose said target. + //this will cause it to be paralyzed and do nothing for the rest of its life, so this specific check is here to remedy that (hopefully) + if(!client && stance == HOSTILE_STANCE_ALERT && target_mob && !is_retreating && !on_fire) + target_mob = FindTarget() + MoveToTarget() + if(resting && stat != DEAD) health += maxHealth * 0.05 if(prob(33) && !HAS_TRAIT(src, TRAIT_INCAPACITATED) && !HAS_TRAIT(src, TRAIT_FLOORED)) @@ -365,7 +373,7 @@ stance = HOSTILE_STANCE_IDLE //if we're hungry and we don't have already have our eyes on a snack, try eating food if possible - if(!food_target && COOLDOWN_FINISHED(src, food_cooldown)) + if(tameable && !food_target && COOLDOWN_FINISHED(src, food_cooldown)) for(var/obj/item/reagent_container/food/snacks/food in view(6, src)) var/is_meat = FALSE for(var/datum/reagent/nutriment/meat/meat in food.reagents.reagent_list) @@ -443,6 +451,11 @@ target.attack_animal(src) animation_attack_on(target) + //xenos take extra damage + if(isxeno(target)) + var/extra_damage = rand(melee_damage_lower, melee_damage_upper) * 0.33 + target.apply_damage(extra_damage, BRUTE) + if(prob(33)) if(client && !is_retreating) is_retreating = TRUE @@ -632,7 +645,7 @@ if(!return_to_combat) //can't retreat? go back to fighting if(retreat_attempts >= 2) - FindTarget() + target_mob = FindTarget() MoveToTarget() retreat_attempts = 0 //seems like it's a life or death situation. we will stop trying to run away. @@ -648,7 +661,7 @@ retreat_attempts = 0 LoseTarget() else - FindTarget() + target_mob = FindTarget() MoveToTarget() //Replaced walk_to() with MoveTo(). @@ -677,6 +690,9 @@ for(var/times_to_attack = 3, times_to_attack > 0, times_to_attack--) if(Adjacent(target)) var/damage = rand(melee_damage_lower, melee_damage_upper) * 0.4 + //xenos take extra damage + if(isxeno(target)) + damage *= 1.33 var/attack_type = pick(ATTACK_SLASH, ATTACK_BITE) attacktext = attack_type ? "claws" : "bites" flick_attack_overlay(target, attack_type ? "slash" : "animalbite") @@ -692,6 +708,7 @@ face_atom(target) sleep(0.5 SECONDS) successful_attacks++ + if(successful_attacks == 3 && !COOLDOWN_FINISHED(src, pounce_cooldown)) to_chat(src, SPAN_BOLDWARNING("The bloodlust invigorates you! You will be ready to pounce much sooner.")) COOLDOWN_START(src, pounce_cooldown, COOLDOWN_TIMELEFT(src, pounce_cooldown) * 0.5) From a2771a8ba2357b3199bc94ba358092ce3ce0d6c7 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Mon, 26 Aug 2024 14:45:11 +0200 Subject: [PATCH 10/17] replace random number with max attack distance --- .../living/simple_animal/hostile/retaliate/giant_lizard.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 9815b6005e14..b34a84f2b18e 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -45,6 +45,8 @@ ///Reference to the ZZzzz sleep overlay when resting. var/sleep_overlay + ///How far the mob is willing to chase before losing its target. + var/max_attack_distance = 16 ///If 0, moves the mob out of attacking into idle state. Used to prevent the mob from chasing down targets that did not mean to hurt it. var/aggression_value = 0 ///Every type of structure that can get attacked in the DestroySurroundings() proc. @@ -515,7 +517,7 @@ if(!target_mob || SA_attackable(target_mob)) LoseTarget() return - if(get_dist(src, target_mob) > 18) + if(get_dist(src, target_mob) > max_attack_distance) LoseTarget() return if(in_range(src, target_mob)) //Attacking @@ -669,7 +671,7 @@ stop_automated_movement = TRUE if(!target_mob || SA_attackable(target_mob)) stance = HOSTILE_STANCE_IDLE - if(get_dist(src, target_mob) <= 18) + if(get_dist(src, target_mob) <= max_attack_distance) if(MoveTo(target_mob)) stance = HOSTILE_STANCE_ATTACKING From 64107670e552fe744284cf36f54a870e9e42c9d4 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Tue, 27 Aug 2024 13:31:56 +0200 Subject: [PATCH 11/17] adds wounds overlay, tongue flicks, lowers latespawn --- .../objects/effects/landmarks/landmarks.dm | 5 +- .../hostile/retaliate/giant_lizard.dm | 129 ++++++++++++++++-- icons/mob/mob_64.dmi | Bin 3116 -> 4413 bytes 3 files changed, 124 insertions(+), 10 deletions(-) diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index 3d1bf4c509be..9a518a71350c 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -131,12 +131,13 @@ . = ..() if(prob(66)) new /mob/living/simple_animal/hostile/retaliate/giant_lizard(loc) - addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(30 MINUTES, 45 MINUTES)) + if(prob(50)) + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(35 MINUTES, 50 MINUTES)) /obj/effect/landmark/lizard_spawn/proc/latespawn_lizard() //if there's already a ton of lizards alive, try again later if(GLOB.giant_lizards_alive > MAXIMUM_LIZARD_AMOUNT) - addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), 10 MINUTES) + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(15 MINUTES, 25 MINUTES)) return //if there's a living mob that can witness the spawn then try again later for(var/mob/living/living_mob in range(7, src)) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index b34a84f2b18e..7857caa55a25 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -34,7 +34,7 @@ speak_chance = 2 speak_emote = "hisses" emote_hear = list("hisses.", "growls.", "roars.", "bellows.") - emote_see = list("shakes its head.", "wags its tail.", "flicks its tongue.", "yawns.") + emote_see = list("shakes its head.", "wags its tail.", "yawns.") melee_damage_lower = 20 melee_damage_upper = 25 @@ -44,6 +44,10 @@ ///Reference to the ZZzzz sleep overlay when resting. var/sleep_overlay + ///Reference to the tongue flick overlay. + var/atom/movable/vis_obj/giant_lizard_icon_holder/tongue_icon_holder + ///Reference to the wound icon. + var/atom/movable/vis_obj/giant_lizard_icon_holder/wound_icon_holder ///How far the mob is willing to chase before losing its target. var/max_attack_distance = 16 @@ -80,8 +84,8 @@ var/tameable = TRUE ///The food object that the mob is trying to eat. var/food_target - ///A list of foods the mob is interested in eating. - var/list/acceptable_foods = list(/obj/item/reagent_container/food/snacks/meat, /obj/item/reagent_container/food/snacks/packaged_meal, /obj/item/reagent_container/food/snacks/resin_fruit) + ///A list of foods the mob is interested in eating. The mob will eat anything that has meat protein in it even if it's not in this list. + var/list/acceptable_foods = list(/obj/item/reagent_container/food/snacks/packaged_meal, /obj/item/reagent_container/food/snacks/resin_fruit) ///Is the mob currently eating the food_target? var/is_eating = FALSE ///Cooldown dictating how long the mob will wait between eating food. @@ -92,8 +96,59 @@ ///Cooldown for when the mob calms down, so the mob doesn't start attacking immediately after calming down. COOLDOWN_DECLARE(calm_cooldown) +//For displaying wound states, and the tongue flicker. +/atom/movable/vis_obj/giant_lizard_icon_holder + icon = 'icons/mob/mob_64.dmi' + +//Due to being constrained to 64x64, we need to change the icon's offsets manually whenever the mob's dir is changed. +/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/change_tongue_offset(datum/source, olddir, newdir, rest_update = FALSE) + SIGNAL_HANDLER + + if(newdir == olddir && !rest_update) + return + if(!newdir) + newdir = dir + + switch(newdir) + if(WEST) + if(resting) + tongue_icon_holder.pixel_x = 7 + tongue_icon_holder.pixel_y = -4 + return + + tongue_icon_holder.pixel_x = -2 + tongue_icon_holder.pixel_y = 0 + + if(EAST) + if(resting) + tongue_icon_holder.pixel_x = -7 + tongue_icon_holder.pixel_y = -4 + return + + tongue_icon_holder.pixel_x = 2 + tongue_icon_holder.pixel_y = 0 + if(SOUTH) + tongue_icon_holder.pixel_x = 0 + tongue_icon_holder.pixel_y = 0 + //there is no north facing tongue animation + +/mob/living/simple_animal/hostile/retaliate/giant_lizard/face_dir(ndir, specific_dir) + //there is no north or south facing rest sprite, so updating the direction would mess up tongue flicking. + if(resting && ndir == NORTH || ndir == SOUTH) + return + return ..() + + /mob/living/simple_animal/hostile/retaliate/giant_lizard/Initialize() . = ..() + wound_icon_holder = new(null, src) + tongue_icon_holder = new(null, src) + tongue_icon_holder.pixel_x = 2 + vis_contents += wound_icon_holder + vis_contents += tongue_icon_holder + + RegisterSignal(src, COMSIG_ATOM_DIR_CHANGE, PROC_REF(change_tongue_offset)) + GLOB.giant_lizards_alive++ change_real_name(src, "[name] ([rand(1, 999)])") pounce_callbacks[/mob] = DYNAMIC(/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/pounced_mob_wrapper) @@ -102,7 +157,7 @@ /mob/living/simple_animal/hostile/retaliate/giant_lizard/initialize_pass_flags(datum/pass_flags_container/pass_flags_container) ..() - if (pass_flags_container) + if(pass_flags_container) pass_flags_container.flags_pass |= PASS_FLAGS_CRAWLER //regular pain datum will make the mob die when trying to pounce after taking enough damage. @@ -166,6 +221,7 @@ walk_to(src, 0) /mob/living/simple_animal/hostile/retaliate/giant_lizard/update_transform(instant_update = FALSE) + tongue_icon_holder.alpha = alpha if(stat == DEAD) icon_state = icon_dead else if(body_position == LYING_DOWN) @@ -173,16 +229,53 @@ icon_state = "Giant Lizard Sleeping" else icon_state = "Giant Lizard Knocked Down" + tongue_icon_holder.alpha = 0 + //we can't stop an animation that's called via flick(). best we can do is hide it. else icon_state = icon_living + update_wounds() + change_tongue_offset(rest_update = TRUE) return ..() + +#define NO_WOUNDS 4 +#define SMALL_WOUNDS 3 +#define BIG_WOUNDS 2 + +/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/update_wounds() + if(!wound_icon_holder) + return + + var/health_threshold = max(ceil((health * 4) / (maxHealth)), 0) //From 0 to 4, in 25% chunks + switch(health_threshold) + if(NO_WOUNDS) + health_threshold = "none" + if(SMALL_WOUNDS) + health_threshold = "Wounds Small" + if(0 to BIG_WOUNDS) + health_threshold = "Wounds Big" + + if(health > 0) + if(health_threshold == "none") + wound_icon_holder.icon_state = "none" + else if(body_position == LYING_DOWN) + if(!HAS_TRAIT(src, TRAIT_INCAPACITATED) && !HAS_TRAIT(src, TRAIT_FLOORED)) + wound_icon_holder.icon_state = "Giant Lizard [health_threshold] Rest" + else + wound_icon_holder.icon_state = "Giant Lizard [health_threshold] Stun" + else + wound_icon_holder.icon_state = "Giant Lizard [health_threshold]" + +#undef NO_WOUNDS +#undef SMALL_WOUNDS +#undef BIG_WOUNDS + /mob/living/simple_animal/hostile/retaliate/giant_lizard/get_examine_text(mob/user) . = ..() if(stat == DEAD || user == src) desc = "A large, wolf-like reptile." if(user == src) - . += SPAN_NOTICE("\nRest on the ground to restore 5% of your health every second.") + . += SPAN_NOTICE("\nRest on the ground to restore 5% of your health every two seconds.") . += SPAN_NOTICE("You're able to pounce targets by using [client && client.prefs && client.prefs.toggle_prefs & TOGGLE_MIDDLE_MOUSE_CLICK ? "middle-click" : "shift-click"].") . += SPAN_NOTICE("You will aggressively maul targets that are prone. Any click on yourself will be passed down to mobs below you, so feel free to click on your sprite in order to attack pounced targets.") else if((user.faction in faction_group)) @@ -195,6 +288,9 @@ /mob/living/simple_animal/hostile/retaliate/giant_lizard/set_resting(new_resting, silent, instant) . = ..() + //north and south rest sprites don't exist, we need to set it to WEST for tongue flicks to work properly + if(resting && dir == NORTH || dir == SOUTH) + setDir(WEST) if(!resting) RemoveSleepingIcon() update_transform() @@ -242,9 +338,10 @@ chance_to_rest = 0 if(COOLDOWN_FINISHED(src, emote_cooldown)) COOLDOWN_START(src, emote_cooldown, rand(5, 8) SECONDS) - manual_emote(pick(pick(pet_emotes), "stares at [attacking_mob].", "nuzzles [attacking_mob].", "licks [attacking_mob]'s hand."), "nibbles [attacking_mob]'s arm.", "flicks its tongue at [attacking_mob].") + manual_emote(pick(pick(pet_emotes), "stares at [attacking_mob].", "nuzzles [attacking_mob].", "licks [attacking_mob]'s hand."), "nibbles [attacking_mob]'s arm.") if(prob(50)) playsound(loc, "giant_lizard_hiss", 25) + flick("Giant Lizard Tongue", tongue_icon_holder) if(attacking_mob.a_intent == INTENT_DISARM && prob(25)) playsound(loc, 'sound/weapons/alien_knockdown.ogg', 25, 1) KnockDown(0.4) @@ -268,10 +365,11 @@ addtimer(VARSET_CALLBACK(src, speed, LIZARD_SPEED_NORMAL_CLIENT), 8 SECONDS) addtimer(VARSET_CALLBACK(src, is_retreating, FALSE), 8 SECONDS) else - MoveTo(target_mob, 12, TRUE, 3 SECONDS) + MoveTo(target_mob, 12, TRUE, 4.5 SECONDS) if(damage >= 10 && damagetype == BRUTE) add_splatter_floor(loc, TRUE) bleed_ticks = clamp(bleed_ticks + ceil(damage / 10), 0, 30) + update_wounds() ///Proc that forces the mob to disengage and try to extinguish itself. Will not be called if the mob is already retreating. /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/try_to_extinguish() @@ -313,9 +411,13 @@ if(resting && stat != DEAD) health += maxHealth * 0.05 + update_wounds() if(prob(33) && !HAS_TRAIT(src, TRAIT_INCAPACITATED) && !HAS_TRAIT(src, TRAIT_FLOORED)) AddSleepingIcon() + if(stat != DEAD && !HAS_TRAIT(src, TRAIT_INCAPACITATED) && !HAS_TRAIT(src, TRAIT_FLOORED) && prob(25)) + flick("Giant Lizard Tongue", tongue_icon_holder) + if(bleed_ticks) var/is_small_pool = FALSE if(bleed_ticks < 10) @@ -420,7 +522,6 @@ else if(!check_food_loc(food_target) && Adjacent(food_target)) INVOKE_ASYNC(src, PROC_REF(handle_food), food_target) - /mob/living/simple_animal/hostile/retaliate/giant_lizard/bullet_act(obj/projectile/projectile) . = ..() if(projectile.damage) @@ -831,6 +932,18 @@ sound = "giant_lizard_hiss" emote_type = EMOTE_AUDIBLE|EMOTE_VISIBLE +/datum/emote/living/giant_lizard/flicktongue + key = "flicktongue" + message = "flicks its tongue." + emote_type = EMOTE_VISIBLE + +/datum/emote/living/giant_lizard/flicktongue/run_emote(mob/living/simple_animal/hostile/retaliate/giant_lizard/user, params, type_override, intentional) + . = ..() + if(!.) + return + + flick("Giant Lizard Tongue", user.tongue_icon_holder) + #undef ATTACK_SLASH #undef ATTACK_BITE #undef LIZARD_SPEED_NORMAL diff --git a/icons/mob/mob_64.dmi b/icons/mob/mob_64.dmi index 8ac2194b3eb2d30b700781475b7805f7a7c0df45..ece08490fa5b989d3504b1685f8471d410530ae3 100644 GIT binary patch literal 4413 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 From 3ed142382a25e57b98b5c65f4cf872875686905f Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Tue, 27 Aug 2024 20:25:56 +0200 Subject: [PATCH 12/17] fix (and slightly unoptimize) tongue flicker offsets --- .../hostile/retaliate/giant_lizard.dm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index 7857caa55a25..d6141837a6d4 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -101,11 +101,11 @@ icon = 'icons/mob/mob_64.dmi' //Due to being constrained to 64x64, we need to change the icon's offsets manually whenever the mob's dir is changed. -/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/change_tongue_offset(datum/source, olddir, newdir, rest_update = FALSE) +//apparantly movement sets both olddir and newdir to the same value, in comparison to manually switching facing which returns the right values. +//i don't know if there's any worthwhile performance gain in having a second signal exclusively for movement so we can check if the olddir and newdir are same. +/mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/change_tongue_offset(datum/source, olddir, newdir) SIGNAL_HANDLER - if(newdir == olddir && !rest_update) - return if(!newdir) newdir = dir @@ -134,10 +134,15 @@ /mob/living/simple_animal/hostile/retaliate/giant_lizard/face_dir(ndir, specific_dir) //there is no north or south facing rest sprite, so updating the direction would mess up tongue flicking. - if(resting && ndir == NORTH || ndir == SOUTH) + if(resting && (ndir == NORTH || ndir == SOUTH)) return return ..() +//we also have to check for the keybind apparantly... +/mob/living/simple_animal/hostile/retaliate/giant_lizard/keybind_face_direction(direction) + if(resting && (direction == NORTH || direction == SOUTH)) + return + return ..() /mob/living/simple_animal/hostile/retaliate/giant_lizard/Initialize() . = ..() @@ -234,7 +239,7 @@ else icon_state = icon_living update_wounds() - change_tongue_offset(rest_update = TRUE) + change_tongue_offset() return ..() @@ -934,7 +939,7 @@ /datum/emote/living/giant_lizard/flicktongue key = "flicktongue" - message = "flicks its tongue." + message = null emote_type = EMOTE_VISIBLE /datum/emote/living/giant_lizard/flicktongue/run_emote(mob/living/simple_animal/hostile/retaliate/giant_lizard/user, params, type_override, intentional) From 750f1a8a9aa69773da5048ec990291cce47a7ea5 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Wed, 28 Aug 2024 12:11:13 +0200 Subject: [PATCH 13/17] increase latespawn chance again it's honestly pretty funny to see people get mauled by them --- code/game/objects/effects/landmarks/landmarks.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index 9a518a71350c..37ee0af31ecc 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -131,8 +131,7 @@ . = ..() if(prob(66)) new /mob/living/simple_animal/hostile/retaliate/giant_lizard(loc) - if(prob(50)) - addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(35 MINUTES, 50 MINUTES)) + addtimer(CALLBACK(src, PROC_REF(latespawn_lizard)), rand(35 MINUTES, 50 MINUTES)) /obj/effect/landmark/lizard_spawn/proc/latespawn_lizard() //if there's already a ton of lizards alive, try again later From b074b3ad984a8c36d1c8099a15077c5626593c85 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Wed, 28 Aug 2024 12:13:09 +0200 Subject: [PATCH 14/17] lower the maximum though --- code/game/objects/effects/landmarks/landmarks.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index 37ee0af31ecc..7b9235263a97 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -121,7 +121,7 @@ GLOB.monkey_spawns -= src return ..() -#define MAXIMUM_LIZARD_AMOUNT 5 +#define MAXIMUM_LIZARD_AMOUNT 4 /obj/effect/landmark/lizard_spawn name = "lizard spawn" From 6d1ff12e5f7e8e8a9d09832456358632d598a05c Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Wed, 28 Aug 2024 16:56:16 +0200 Subject: [PATCH 15/17] add resin door breaking --- .../simple_animal/hostile/retaliate/giant_lizard.dm | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index d6141837a6d4..bd4b01de6b0f 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -54,7 +54,7 @@ ///If 0, moves the mob out of attacking into idle state. Used to prevent the mob from chasing down targets that did not mean to hurt it. var/aggression_value = 0 ///Every type of structure that can get attacked in the DestroySurroundings() proc. - var/list/destruction_targets = list(/obj/structure/window, /obj/structure/closet, /obj/structure/surface/table, /obj/structure/grille, /obj/structure/barricade, /obj/structure/machinery/door, /obj/structure/largecrate) + var/list/destruction_targets = list(/obj/structure/mineral_door/resin, /obj/structure/window, /obj/structure/closet, /obj/structure/surface/table, /obj/structure/grille, /obj/structure/barricade, /obj/structure/machinery/door, /obj/structure/largecrate) ///Emotes to play when being pet by a friend. var/list/pet_emotes = list("closes its eyes.", "growls happily.", "wags its tail.", "rolls on the ground.") @@ -580,10 +580,17 @@ if(structure.unslashable) return + var/is_xeno_structure = FALSE + if(structure.flags_obj & OBJ_ORGANIC) + is_xeno_structure = TRUE + animation_attack_on(structure) - playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + playsound(loc, is_xeno_structure ? "alien_resin_break" : 'sound/effects/metalhit.ogg', 25) visible_message(SPAN_DANGER("[src] slashes [structure]!"), SPAN_DANGER("You slash [structure]!"), null, 5, CHAT_TYPE_COMBAT_ACTION) - structure.update_health(rand(melee_damage_lower, melee_damage_upper) * 2) + var/damage_multiplier = 2 + if(is_xeno_structure) + damage_multiplier = !client ? 15 : 5 //ai mobs need that extra oomph else they won't be able to break anything before they die + structure.update_health(rand(melee_damage_lower, melee_damage_upper) * damage_multiplier) return //if it's not an object or a structure, just swipe at it From 2ff99d00fa0d9b66bf53225b0ecec66e2c748ee7 Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Thu, 29 Aug 2024 13:47:59 +0200 Subject: [PATCH 16/17] fix pred taming --- code/__DEFINES/mode.dm | 1 + code/game/gamemodes/cm_initialize.dm | 1 + code/modules/gear_presets/yautja.dm | 2 ++ 3 files changed, 4 insertions(+) diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 368553468af0..b30978d8f8d5 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -295,6 +295,7 @@ DEFINE_BITFIELD(whitelist_status, list( #define FACTION_LIST_MARINE_WY list(FACTION_MARINE, FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_WY) #define FACTION_LIST_MARINE_UPP list(FACTION_MARINE, FACTION_UPP) #define FACTION_LIST_MARINE_TWE list(FACTION_MARINE, FACTION_TWE) +#define FACTION_LIST_YAUTJA list(FACTION_YAUTJA) // Xenomorphs #define FACTION_PREDALIEN "Predalien" diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index 4a208b00a796..998e469f087b 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -165,6 +165,7 @@ Additional game mode variables. player.mind_initialize() //Will work on ghosts too, but won't add them to active minds. player.mind.setup_human_stats() player.faction = FACTION_YAUTJA + player.faction_group = FACTION_LIST_YAUTJA players += player.mind return players diff --git a/code/modules/gear_presets/yautja.dm b/code/modules/gear_presets/yautja.dm index 8ffd8664a977..9b8e64948c62 100644 --- a/code/modules/gear_presets/yautja.dm +++ b/code/modules/gear_presets/yautja.dm @@ -4,6 +4,7 @@ languages = list(LANGUAGE_YAUTJA) rank = "Predator" faction = FACTION_YAUTJA + faction_group = FACTION_LIST_YAUTJA uses_special_name = TRUE skills = /datum/skills/yautja/warrior @@ -23,6 +24,7 @@ /datum/equipment_preset/yautja/load_id(mob/living/carbon/human/new_human) new_human.job = rank new_human.faction = faction + new_human.faction_group = faction_group /datum/equipment_preset/yautja/load_vanity(mob/living/carbon/human/new_human) return //No vanity items for Yautja! From 0fb4b458bf7b4bdebe090fdf1e834138375bc7ee Mon Sep 17 00:00:00 2001 From: Vile Beggar Date: Sat, 31 Aug 2024 08:16:06 +0200 Subject: [PATCH 17/17] fix sound being made when set on fire and dead --- .../mob/living/simple_animal/hostile/retaliate/giant_lizard.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm index bd4b01de6b0f..f56e19915ab2 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/giant_lizard.dm @@ -378,7 +378,7 @@ ///Proc that forces the mob to disengage and try to extinguish itself. Will not be called if the mob is already retreating. /mob/living/simple_animal/hostile/retaliate/giant_lizard/proc/try_to_extinguish() - if(is_retreating || !on_fire || client) + if(is_retreating || !on_fire || client || stat == DEAD || body_position == LYING_DOWN) return //forget EVERYTHING. we need to stop the flames!!!