diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm index 16c3fb9eb12..ee93fa28b39 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm @@ -55,7 +55,7 @@ #define COMSIG_ATOM_ATTACK_AI "atom_attack_ai" /// from base of atom/attack_larva(): (mob/user, list/modifiers) #define COMSIG_ATOM_ATTACK_LARVA "atom_attack_larva" -///from relay_attackers element: (atom/attacker, attack_flags) +///from relay_attackers element: (atom/attacker, attack_flags, direction) #define COMSIG_ATOM_WAS_ATTACKED "atom_was_attacked" ///Called before a atom gets something tilted on them. If [COMPONENT_IMMUNE_TO_TILT_AND_CRUSH] is returned in a signal, the atom will be unaffected: (atom/target, atom/source) #define COMSIG_PRE_TILT_AND_CRUSH "atom_pre_tilt_and_crush" @@ -64,13 +64,14 @@ #define COMSIG_POST_TILT_AND_CRUSH "atom_post_tilt_and_crush" /// Called when an atom is splashed with something: (atom/source) #define COMSIG_ATOM_SPLASHED "atom_splashed" - ///The damage type of the weapon projectile is non-lethal stamina #define ATTACKER_STAMINA_ATTACK (1<<0) ///the attacker is shoving the source #define ATTACKER_SHOVING (1<<1) /// The attack is a damaging-type attack #define ATTACKER_DAMAGING_ATTACK (1<<2) + /// The attack was ranged + #define ATTACK_RANGED (1<<3) /// Called on the atom being hit, from /datum/component/anti_magic/on_attack() : (obj/item/weapon, mob/user, antimagic_flags) #define COMSIG_ATOM_HOLYATTACK "atom_holyattacked" diff --git a/code/__DEFINES/dcs/signals/signals_mining.dm b/code/__DEFINES/dcs/signals/signals_mining.dm index 3ef84b1f7b6..13ec648c1ba 100644 --- a/code/__DEFINES/dcs/signals/signals_mining.dm +++ b/code/__DEFINES/dcs/signals/signals_mining.dm @@ -3,6 +3,7 @@ /// Fired by a mob which has been grabbed by a goliath #define COMSIG_GOLIATH_TENTACLED_GRABBED "comsig_goliath_tentacle_grabbed" + #define COMPONENT_GOLIATH_CANCEL_TENTACLE_GRAB (1<<0) /// Fired by a goliath tentacle which is returning to the earth #define COMSIG_GOLIATH_TENTACLE_RETRACTING "comsig_goliath_tentacle_retracting" /// Fired by a mob which has triggered a brimdust explosion from itself (not the mobs that get hit) diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index a847220c2de..b8a03d015fc 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1591,6 +1591,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Demolition modifier when hitting this object is inverted (ie, 1 / demolition) #define TRAIT_INVERTED_DEMOLITION "demolition_inverted" +/// Ignores demolition modifiers +#define TRAIT_IGNORE_DEMOLITION "ignore_demolition" + /// Makes the mob immune to carpotoxin #define TRAIT_CARPOTOXIN_IMMUNE "carpotoxin_immune" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 4e389caad2d..ee2eee0d900 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -58,6 +58,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HAS_LABEL" = TRAIT_HAS_LABEL, "TRAIT_HEARING_SENSITIVE" = TRAIT_HEARING_SENSITIVE, "TRAIT_HYPERSPACED" = TRAIT_HYPERSPACED, + "TRAIT_IGNORE_DEMOLITION" = TRAIT_IGNORE_DEMOLITION, "TRAIT_IMMERSED" = TRAIT_IMMERSED, "TRAIT_INVERTED_DEMOLITION" = TRAIT_INVERTED_DEMOLITION, "TRAIT_IRRADIATED" = TRAIT_IRRADIATED, diff --git a/code/datums/components/leash.dm b/code/datums/components/leash.dm index 7a44d09f56f..2047d3ffb87 100644 --- a/code/datums/components/leash.dm +++ b/code/datums/components/leash.dm @@ -2,17 +2,17 @@ /// but teleporting if necessary. /datum/component/leash /// The owner of the leash. If this is qdeleted, the leash is as well. - var/atom/movable/owner - + var/atom/owner /// The maximum distance you can move from your owner var/distance - /// The object type to create on the old turf when forcibly teleporting out var/force_teleport_out_effect - /// The object type to create on the new turf when forcibly teleporting out var/force_teleport_in_effect - + /// Avoid sending out "too far" bubbles + var/silent = FALSE + /// Should we snap instead of teleporting back? + var/snap_on_teleport = FALSE VAR_PRIVATE // Pathfinding can yield, so only move us closer if this is the best one current_path_tick = 0 @@ -21,10 +21,12 @@ performing_path_move = FALSE /datum/component/leash/Initialize( - atom/movable/owner, + atom/owner, distance = 3, force_teleport_out_effect, force_teleport_in_effect, + silent = FALSE, + snap_on_teleport = FALSE, ) . = ..() @@ -32,8 +34,8 @@ stack_trace("Parent must be a movable") return COMPONENT_INCOMPATIBLE - if (!ismovable(owner)) - stack_trace("[owner] (owner) is not a movable") + if (!isatom(owner)) + stack_trace("[owner] (owner) is not an atom") return COMPONENT_INCOMPATIBLE if (!isnum(distance)) @@ -52,18 +54,22 @@ src.distance = distance src.force_teleport_out_effect = force_teleport_out_effect src.force_teleport_in_effect = force_teleport_in_effect + src.silent = silent + src.snap_on_teleport = snap_on_teleport RegisterSignal(owner, COMSIG_QDELETING, PROC_REF(on_owner_qdel)) + RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_parent_pre_move)) + check_distance() + + if (!ismovable(owner)) + return + var/static/list/container_connections = list( COMSIG_MOVABLE_MOVED = PROC_REF(on_owner_moved), ) - AddComponent(/datum/component/connect_containers, owner, container_connections) RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_owner_moved)) - RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_parent_pre_move)) - - check_distance() /datum/component/leash/Destroy() owner = null @@ -97,7 +103,7 @@ if (get_dist(new_location_turf, owner) <= distance) return NONE - if (ismob(source)) + if (ismob(source) && !silent) source.balloon_alert(source, "too far!") return COMPONENT_MOVABLE_BLOCK_PRE_MOVE @@ -158,6 +164,10 @@ /datum/component/leash/proc/force_teleport_back(reason) PRIVATE_PROC(TRUE) + if (snap_on_teleport) + qdel(src) + return + var/atom/movable/movable_parent = parent if (force_teleport_out_effect) @@ -170,7 +180,8 @@ if (ismob(movable_parent)) SSblackbox.record_feedback("tally", "leash_force_teleport_back", 1, reason) - movable_parent.balloon_alert(movable_parent, "moved out of range!") + if(!silent) + movable_parent.balloon_alert(movable_parent, "moved out of range!") SEND_SIGNAL(parent, COMSIG_LEASH_FORCE_TELEPORT) diff --git a/code/datums/elements/relay_attackers.dm b/code/datums/elements/relay_attackers.dm index 6dd9e8dfd47..b5bae4f80b7 100644 --- a/code/datums/elements/relay_attackers.dm +++ b/code/datums/elements/relay_attackers.dm @@ -37,25 +37,25 @@ /datum/element/relay_attackers/proc/after_attackby(atom/target, obj/item/weapon, mob/attacker, list/modifiers) SIGNAL_HANDLER if(weapon.force) - relay_attacker(target, attacker, weapon.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, attacker, weapon.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK, get_dir(target, attacker)) /datum/element/relay_attackers/proc/on_attack_generic(atom/target, mob/living/attacker, list/modifiers) SIGNAL_HANDLER // Check for a shove. if(LAZYACCESS(modifiers, RIGHT_CLICK)) - relay_attacker(target, attacker, ATTACKER_SHOVING) + relay_attacker(target, attacker, ATTACKER_SHOVING, get_dir(target, attacker)) return // Else check for combat mode. if(attacker.combat_mode) - relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK, get_dir(target, attacker)) return /datum/element/relay_attackers/proc/on_attack_npc(atom/target, mob/living/attacker) SIGNAL_HANDLER if(attacker.melee_damage_upper > 0) - relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK, get_dir(target, attacker)) /// Even if another component blocked this hit, someone still shot at us /datum/element/relay_attackers/proc/on_bullet_act(atom/target, obj/projectile/hit_projectile) @@ -64,7 +64,7 @@ return if(!ismob(hit_projectile.firer)) return - relay_attacker(target, hit_projectile.firer, hit_projectile.damage_type == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, hit_projectile.firer, ATTACK_RANGED | hit_projectile.damage_type == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK, get_dir(target, hit_projectile)) /// Even if another component blocked this hit, someone still threw something /datum/element/relay_attackers/proc/on_hitby(atom/target, atom/movable/hit_atom, datum/thrownthing/throwingdatum) @@ -77,16 +77,16 @@ var/atom/thrown_by = throwingdatum?.get_thrower() if(!istype(thrown_by)) return - relay_attacker(target, thrown_by, hit_item.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, thrown_by, ATTACK_RANGED | hit_item.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK, get_dir(target, hit_atom)) /datum/element/relay_attackers/proc/on_attack_hulk(atom/target, mob/attacker) SIGNAL_HANDLER - relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK, get_dir(target, attacker)) /datum/element/relay_attackers/proc/on_attack_mech(atom/target, obj/vehicle/sealed/mecha/mecha_attacker, mob/living/pilot, mecha_attack_cooldown) SIGNAL_HANDLER - relay_attacker(target, mecha_attacker, ATTACKER_DAMAGING_ATTACK) + relay_attacker(target, mecha_attacker, ATTACKER_DAMAGING_ATTACK, get_dir(target, mecha_attacker)) /// Send out a signal identifying whoever just attacked us (usually a mob but sometimes a mech or turret) -/datum/element/relay_attackers/proc/relay_attacker(atom/victim, atom/attacker, attack_flags) - SEND_SIGNAL(victim, COMSIG_ATOM_WAS_ATTACKED, attacker, attack_flags) +/datum/element/relay_attackers/proc/relay_attacker(atom/victim, atom/attacker, attack_flags, direction) + SEND_SIGNAL(victim, COMSIG_ATOM_WAS_ATTACKED, attacker, attack_flags, direction) diff --git a/code/game/objects/effects/temporary_visuals/effect_trail.dm b/code/game/objects/effects/temporary_visuals/effect_trail.dm index 5eed9462dfd..e8ab9526f51 100644 --- a/code/game/objects/effects/temporary_visuals/effect_trail.dm +++ b/code/game/objects/effects/temporary_visuals/effect_trail.dm @@ -27,7 +27,7 @@ return INITIALIZE_HINT_QDEL AddElement(/datum/element/floor_loving) - AddComponent(/datum/component/spawner, spawn_types = list(spawned_effect), max_spawned = max_spawned, spawn_time = spawn_interval) + add_spawner() src.target = target movement = GLOB.move_manager.move_towards(src, chasing = target, delay = move_speed, home = homing, timeout = duration, flags = MOVEMENT_LOOP_START_FAST) @@ -35,6 +35,9 @@ if (isliving(target)) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_invalid)) +/obj/effect/temp_visual/effect_trail/proc/add_spawner() + AddComponent(/datum/component/spawner, spawn_types = list(spawned_effect), max_spawned = max_spawned, spawn_time = spawn_interval) + /// Destroy ourselves if the target is no longer valid /obj/effect/temp_visual/effect_trail/proc/on_target_invalid() SIGNAL_HANDLER diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 99ba1a935d4..f24a699d54f 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -419,6 +419,8 @@ slowdown = 7 breakouttime = 30 SECONDS slot_flags = ITEM_SLOT_LEGCUFFED + /// Icon state for the legcuff overlay + var/legcuff_state = "legcuff" /** * # Bear trap diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 167ca422109..3db7bc1c079 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -357,6 +357,8 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) /// Returns modifier to how much damage this object does to a target considered vulnerable to "demolition" (other objects, robots, etc) /obj/proc/get_demolition_modifier(obj/target) + if(HAS_TRAIT(target, TRAIT_IGNORE_DEMOLITION)) + return 1 if(HAS_TRAIT(target, TRAIT_INVERTED_DEMOLITION)) return (1 / demolition_mod) return demolition_mod diff --git a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm index 55533341d89..bb07998534c 100644 --- a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm @@ -336,6 +336,9 @@ fired_from = null return ..() +/obj/projectile/destabilizer/is_hostile_projectile() + return TRUE + /obj/projectile/destabilizer/proc/on_parry(mob/user) SIGNAL_HANDLER boosted = TRUE diff --git a/code/modules/mining/equipment/monster_organs/rush_gland.dm b/code/modules/mining/equipment/monster_organs/rush_gland.dm index 894a9dbe0db..69c79974170 100644 --- a/code/modules/mining/equipment/monster_organs/rush_gland.dm +++ b/code/modules/mining/equipment/monster_organs/rush_gland.dm @@ -34,7 +34,9 @@ /obj/item/organ/monster_core/rush_gland/proc/trigger_organ_action_on_sig(datum/source) SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(trigger_organ_action)) + return COMPONENT_GOLIATH_CANCEL_TENTACLE_GRAB /** * Status effect: Makes you run faster and ignore damage speed penalties for a short duration. diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm index e558939f8e3..41a1a0f228a 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm @@ -15,9 +15,16 @@ var/beam_duration = 2 SECONDS /// How long do we wind up before firing? var/charge_duration = 1 SECONDS + /// Have we been hit and have to abort the blast? + var/abort_blast = FALSE /// A list of all the beam parts. var/list/beam_parts = list() +/datum/action/cooldown/mob_cooldown/brimbeam/Grant(mob/granted_to) + . = ..() + if(owner) + owner.AddElement(/datum/element/relay_attackers) + /datum/action/cooldown/mob_cooldown/brimbeam/Destroy() extinguish_laser() return ..() @@ -25,6 +32,7 @@ /datum/action/cooldown/mob_cooldown/brimbeam/Activate(atom/target) StartCooldown(360 SECONDS) + abort_blast = FALSE owner.face_atom(target) owner.move_resist = MOVE_FORCE_VERY_STRONG owner.balloon_alert_to_viewers("charging...") @@ -32,17 +40,20 @@ var/mutable_appearance/direction_emissive = emissive_appearance('icons/mob/simple/lavaland/lavaland_monsters.dmi', "brimdemon_telegraph_dir", owner, alpha = 150, effect_type = EMISSIVE_NO_BLOOM) owner.add_overlay(direction_overlay) owner.add_overlay(direction_emissive) + RegisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_owner_attacked)) - var/fully_charged = do_after(owner, delay = charge_duration, target = owner) + var/fully_charged = do_after(owner, delay = charge_duration, target = owner, extra_checks = CALLBACK(src, PROC_REF(beam_charge_check))) owner.cut_overlay(direction_overlay) owner.cut_overlay(direction_emissive) if (!fully_charged) + UnregisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED) StartCooldown() return TRUE if (!fire_laser()) var/static/list/fail_emotes = list("coughs.", "wheezes.", "belches out a puff of black smoke.") owner.manual_emote(pick(fail_emotes)) + UnregisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED) StartCooldown() return TRUE @@ -51,11 +62,20 @@ demon.icon_state = demon.firing_icon_state demon.update_appearance(UPDATE_OVERLAYS) - do_after(owner, delay = beam_duration, target = owner, hidden = TRUE) + do_after(owner, delay = beam_duration, target = owner, hidden = TRUE, extra_checks = CALLBACK(src, PROC_REF(beam_charge_check))) + UnregisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED) extinguish_laser() StartCooldown() return TRUE +/datum/action/cooldown/mob_cooldown/brimbeam/proc/on_owner_attacked(datum/source, atom/attacker, attack_flags, direction) + SIGNAL_HANDLER + if (!(attack_flags & ATTACK_RANGED) && !(direction & owner.dir)) + abort_blast = TRUE + +/datum/action/cooldown/mob_cooldown/brimbeam/proc/beam_charge_check() + return !abort_blast + /// Create a laser in the direction we are facing /datum/action/cooldown/mob_cooldown/brimbeam/proc/fire_laser() owner.visible_message(span_danger("[owner] fires a brimbeam!")) @@ -67,7 +87,7 @@ if(affected_turf.opacity) break var/blocked = FALSE - for(var/obj/potential_block in affected_turf.contents) + for(var/obj/potential_block in affected_turf) if(potential_block.opacity) blocked = TRUE break @@ -77,8 +97,8 @@ new_brimbeam.dir = owner.dir beam_parts += new_brimbeam new_brimbeam.assign_creator(owner) - for(var/mob/living/hit_mob in affected_turf.contents) - hit_mob.apply_damage(damage = 25, damagetype = BURN) + for(var/mob/living/hit_mob in affected_turf) + hit_mob.apply_damage(25, BURN, blocked = hit_mob.run_armor_check(null, LASER, silent = TRUE), wound_bonus = CANT_WOUND) to_chat(hit_mob, span_userdanger("You're blasted by [owner]'s brimbeam!")) RegisterSignal(new_brimbeam, COMSIG_QDELETING, PROC_REF(extinguish_laser)) // In case idk a singularity eats it or something if(!length(beam_parts)) @@ -126,16 +146,10 @@ return ..() /obj/effect/brimbeam/process() - var/atom/ignore = creator?.resolve() + var/ignore = creator?.resolve() for(var/mob/living/hit_mob in get_turf(src)) - if(hit_mob == ignore) - continue - damage(hit_mob) - -/// Hurt the passed mob -/obj/effect/brimbeam/proc/damage(mob/living/hit_mob) - hit_mob.apply_damage(damage = 5, damagetype = BURN) - to_chat(hit_mob, span_danger("You're damaged by [src]!")) + if(hit_mob != ignore) + hit_mob.apply_damage(7, BURN, blocked = hit_mob.run_armor_check(null, LASER, silent = TRUE), wound_bonus = CANT_WOUND) /// Ignore damage dealt to this mob /obj/effect/brimbeam/proc/assign_creator(mob/living/maker) diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index 6aef2570060..7b982ddf5be 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -9,7 +9,7 @@ pixel_x = -12 base_pixel_x = -12 gender = MALE // Female ones are the bipedal elites - speed = 30 + speed = 12 basic_mob_flags = IMMUNE_TO_FISTS maxHealth = 300 health = 300 @@ -197,7 +197,7 @@ This one is clearly ancient, and its tentacles constantly churn the earth around it." maxHealth = 400 health = 400 - crusher_drop_chance = 30 // Wow a whole 5% more likely, how generous + crusher_drop_chance = 100 /// Don't re-check nearby turfs for this long COOLDOWN_DECLARE(retarget_turfs_cooldown) /// List of places we might spawn a tentacle, if we're alive @@ -214,7 +214,7 @@ tentacle_target_turfs -= target_turf continue if (prob(10)) - new /obj/effect/goliath_tentacle(target_turf) + new /obj/effect/goliath_tentacle(target_turf, src) /mob/living/basic/mining/goliath/ancient/immortal/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) . = ..() @@ -224,7 +224,7 @@ /// Store nearby turfs in our list so we can pop them out later /mob/living/basic/mining/goliath/ancient/immortal/proc/cache_nearby_turfs() - COOLDOWN_START(src, retarget_turfs_cooldown, 10 SECONDS) + COOLDOWN_START(src, retarget_turfs_cooldown, 5 SECONDS) LAZYCLEARLIST(tentacle_target_turfs) for(var/turf/open/floor in orange(4, loc)) LAZYADD(tentacle_target_turfs, floor) diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm index 31eecc03629..d1336aa9094 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm @@ -20,12 +20,12 @@ return ..() /datum/action/cooldown/mob_cooldown/goliath_tentacles/Activate(atom/target) - new /obj/effect/goliath_tentacle(target) - var/list/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/spawndir = pick_n_take(directions) + new /obj/effect/goliath_tentacle(target, owner) + for(var/spawndir in GLOB.cardinals) var/turf/adjacent_target = get_step(target, spawndir) - if(adjacent_target) + if(isgroundlessturf(adjacent_target) && !islava(adjacent_target)) + continue + if(isopenturf(adjacent_target) || ismineralturf(adjacent_target)) new /obj/effect/goliath_tentacle(adjacent_target) if (isliving(target)) @@ -51,7 +51,7 @@ for (var/dir in directions) var/turf/adjacent_target = get_step(target, dir) if(adjacent_target) - new /obj/effect/goliath_tentacle(adjacent_target) + new /obj/effect/goliath_tentacle/drag(adjacent_target, owner) owner.visible_message(span_warning("[owner] unleashes tentacles from the ground around it!")) StartCooldown() return TRUE @@ -70,7 +70,7 @@ shared_cooldown = NONE /datum/action/cooldown/mob_cooldown/tentacle_grasp/Activate(atom/target) - new /obj/effect/temp_visual/effect_trail/burrowed_tentacle(owner.loc, target) + new /obj/effect/temp_visual/effect_trail/burrowed_tentacle(owner.loc, target, owner) if (isliving(target)) owner.visible_message(span_warning("[owner] reaches for [target] with its tentacles!")) StartCooldown() @@ -83,4 +83,20 @@ move_speed = 2 homing = FALSE spawn_interval = 0.1 SECONDS - spawned_effect = /obj/effect/goliath_tentacle + spawned_effect = /obj/effect/goliath_tentacle/drag + /// Mob who fired us + var/mob/living/owner = null + +/obj/effect/temp_visual/effect_trail/burrowed_tentacle/Initialize(mapload, atom/target, mob/living/owner) + . = ..() + src.owner = owner + +/obj/effect/temp_visual/effect_trail/burrowed_tentacle/Destroy() + . = ..() + owner = null + +/obj/effect/temp_visual/effect_trail/burrowed_tentacle/add_spawner() + AddComponent(/datum/component/spawner, spawn_types = list(spawned_effect), max_spawned = max_spawned, spawn_time = spawn_interval, spawn_callback = CALLBACK(src, PROC_REF(on_tentacle_spawned))) + +/obj/effect/temp_visual/effect_trail/burrowed_tentacle/proc/on_tentacle_spawned(obj/effect/goliath_tentacle/tentacle) + tentacle.set_owner(owner) diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm index 5fe6e9d891d..60dfd7a15d0 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm @@ -36,7 +36,7 @@ return ..() var/mob/living/target = controller.blackboard[target_key] // Interrupt attack chain to use tentacles, unless the target is already tentacled - if (ismecha(target) || (isliving(target) && !target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled))) + if (ismecha(target) || (isliving(target) && !target.get_item_by_slot(ITEM_SLOT_LEGCUFFED))) var/datum/action/cooldown/using_action = controller.blackboard[BB_GOLIATH_TENTACLES] if (using_action?.IsAvailable()) return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED @@ -48,7 +48,7 @@ /datum/ai_planning_subtree/targeted_mob_ability/goliath_tentacles/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/target = controller.blackboard[target_key] - if (!(isliving(target) || ismecha(target)) || (isliving(target) && target.has_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled))) + if (!(isliving(target) || ismecha(target)) || (isliving(target) && target.get_item_by_slot(ITEM_SLOT_LEGCUFFED))) return // Target can be an item or already grabbed, we don't want to tentacle those var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0 if (time_on_target < MIN_TIME_TO_TENTACLE) diff --git a/code/modules/mob/living/basic/lavaland/goliath/tentacle.dm b/code/modules/mob/living/basic/lavaland/goliath/tentacle.dm index cc9546474ec..b5af54e4da0 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/tentacle.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/tentacle.dm @@ -13,9 +13,13 @@ /// Lower bound of damage to inflict var/min_damage = 10 /// Upper bound of damage to inflict - var/max_damage = 15 + var/max_damage = 15 + /// Type of legcuff we spawn + var/trap_type = /obj/item/restraints/legcuffs/goliath_tentacle + /// Mob who fired the tentacle + var/mob/living/owner = null -/obj/effect/goliath_tentacle/Initialize(mapload) +/obj/effect/goliath_tentacle/Initialize(mapload, mob/living/goliath) . = ..() if (ismineralturf(loc)) var/turf/closed/mineral/floor = loc @@ -28,11 +32,24 @@ deltimer(action_timer) action_timer = addtimer(CALLBACK(src, PROC_REF(animate_grab)), 0.7 SECONDS, TIMER_STOPPABLE) update_appearance(UPDATE_OVERLAYS) + set_owner(goliath) /obj/effect/goliath_tentacle/Destroy() deltimer(action_timer) return ..() +/obj/effect/goliath_tentacle/proc/set_owner(mob/living/goliath) + if (owner) + UnregisterSignal(owner, COMSIG_QDELETING) + owner = goliath + if (owner) + RegisterSignal(owner, COMSIG_QDELETING, PROC_REF(on_owner_del)) + +/obj/effect/goliath_tentacle/proc/on_owner_del(datum/source) + SIGNAL_HANDLER + owner = null + retract() + /// Change to next icon state and set up grapple /obj/effect/goliath_tentacle/proc/animate_grab() icon_state = "goliath_tentacle_wiggle" @@ -42,20 +59,31 @@ /// Grab everyone we share space with. If it's nobody, go home. /obj/effect/goliath_tentacle/proc/grab() + var/trapped_mobs = FALSE for (var/mob/living/victim in loc) - if (victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_TENTACLE_IMMUNE)) + if (victim.stat == DEAD || owner && victim.faction_check_atom(owner)) + continue + if (HAS_TRAIT(victim, TRAIT_TENTACLE_IMMUNE) || SEND_SIGNAL(victim, COMSIG_GOLIATH_TENTACLED_GRABBED) & COMPONENT_GOLIATH_CANCEL_TENTACLE_GRAB) + continue + var/obj/item/restraints/legcuffs/goliath_tentacle/trap = new trap_type(loc, victim, src) + if (QDELETED(trap)) continue balloon_alert(victim, "grabbed") visible_message(span_danger("[src] grabs hold of [victim]!")) - victim.adjust_brute_loss(rand(min_damage, max_damage)) - if (victim.apply_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled, grapple_time, src)) - buckle_mob(victim, TRUE) - SEND_SIGNAL(victim, COMSIG_GOLIATH_TENTACLED_GRABBED) + victim.apply_damage(rand(min_damage, max_damage), BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG), wound_bonus = CANT_WOUND) + trapped_mobs = TRUE + for (var/obj/vehicle/sealed/mecha/mech in loc) mech.take_damage(rand(min_damage, max_damage), damage_type = BRUTE, damage_flag = MELEE, sound_effect = TRUE) - if (!has_buckled_mobs()) + + // Already retracting + if (icon_state == "goliath_tentacle_retract") + return + + if (!trapped_mobs) retract() return + deltimer(action_timer) action_timer = addtimer(CALLBACK(src, PROC_REF(retract)), grapple_time, TIMER_STOPPABLE) @@ -64,7 +92,6 @@ if (icon_state == "goliath_tentacle_retract") return // Already retracting SEND_SIGNAL(src, COMSIG_GOLIATH_TENTACLE_RETRACTING) - unbuckle_all_mobs(force = TRUE) icon_state = "goliath_tentacle_retract" update_appearance(UPDATE_OVERLAYS) deltimer(action_timer) @@ -77,54 +104,136 @@ /obj/effect/goliath_tentacle/attack_hand(mob/living/user, list/modifiers) . = ..() - if (. || !has_buckled_mobs()) - return - retract() - return TRUE + if(!.) + retract() + return TRUE -/// Goliath tentacle stun with special removal conditions -/datum/status_effect/incapacitating/stun/goliath_tentacled - id = "goliath_tentacled" - duration = 10 SECONDS - /// The tentacle that is tenderly holding us close +/// An alternative variant which drags the mob in towards the goliath +/obj/effect/goliath_tentacle/drag + trap_type = /obj/item/restraints/legcuffs/goliath_tentacle/drag + +/obj/item/restraints/legcuffs/goliath_tentacle + name = "tentacle mass" + desc = "A writhing tentacle constricting one of your limbs." + icon_state = "goliath_tentacle" + slowdown = 4 + breakouttime = 6 SECONDS + resistance_flags = LAVA_PROOF | FIRE_PROOF + obj_flags = CONDUCTS_ELECTRICITY | CAN_BE_HIT + item_flags = DROPDEL + legcuff_state = "goliath_tentacle" + uses_integrity = TRUE + max_integrity = 75 // 3 PKC swings, 5 bayonet swings + /// Tentacle we're attached to var/obj/effect/goliath_tentacle/tentacle + /// Leash component linking the victim to the turf + var/datum/component/leash/leash + /// Beam between the victim and the tentacle tile + var/datum/beam/beam_effect -/datum/status_effect/incapacitating/stun/goliath_tentacled/on_creation(mob/living/new_owner, set_duration, obj/effect/goliath_tentacle/tentacle) +/obj/item/restraints/legcuffs/goliath_tentacle/Initialize(mapload, mob/living/target, obj/effect/goliath_tentacle/tentacle) . = ..() - if (!.) - return + ADD_TRAIT(src, TRAIT_IGNORE_DEMOLITION, INNATE_TRAIT) src.tentacle = tentacle + if (!target?.equip_to_slot_if_possible(src, ITEM_SLOT_LEGCUFFED, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) + return INITIALIZE_HINT_QDEL -/datum/status_effect/incapacitating/stun/goliath_tentacled/on_apply() +/obj/item/restraints/legcuffs/goliath_tentacle/Destroy(force) . = ..() - RegisterSignal(owner, COMSIG_CARBON_PRE_MISC_HELP, PROC_REF(on_helped)) - RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_TENTACLE_IMMUNE), COMSIG_BRIMDUST_EXPLOSION), PROC_REF(release)) - RegisterSignals(tentacle, list(COMSIG_QDELETING, COMSIG_GOLIATH_TENTACLE_RETRACTING), PROC_REF(on_tentacle_left)) + if (tentacle) + tentacle.retract() + tentacle = null + if (leash) + UnregisterSignal(leash, COMSIG_QDELETING) + QDEL_NULL(leash) + QDEL_NULL(beam_effect) -/datum/status_effect/incapacitating/stun/goliath_tentacled/on_remove() +/obj/item/restraints/legcuffs/goliath_tentacle/equipped(mob/living/user, slot, initial) . = ..() - UnregisterSignal(owner, list(COMSIG_CARBON_PRE_MISC_HELP, SIGNAL_ADDTRAIT(TRAIT_TENTACLE_IMMUNE), COMSIG_BRIMDUST_EXPLOSION)) - if (isnull(tentacle)) + if (slot != ITEM_SLOT_LEGCUFFED || leash) return - UnregisterSignal(tentacle, list(COMSIG_QDELETING, COMSIG_GOLIATH_TENTACLE_RETRACTING)) + leash_target(user) + +/obj/item/restraints/legcuffs/goliath_tentacle/proc/release(datum/source) + SIGNAL_HANDLER + qdel(src) + +/obj/item/restraints/legcuffs/goliath_tentacle/proc/on_tentacle_left(datum/source) + SIGNAL_HANDLER + if (tentacle) + UnregisterSignal(tentacle, list(COMSIG_QDELETING, COMSIG_GOLIATH_TENTACLE_RETRACTING)) + tentacle = null + release() + +/obj/item/restraints/legcuffs/goliath_tentacle/proc/leash_target(mob/living/user) + leash = user.AddComponent(/datum/component/leash, owner = get_turf(user), distance = 1, silent = TRUE) + beam_effect = user.Beam(get_turf(user), "goliath_tentacle", beam_type = /obj/effect/ebeam/goliath, emissive = FALSE) + RegisterSignal(beam_effect.visuals, COMSIG_CLICK, PROC_REF(on_beam_click)) + RegisterSignals(user, list(SIGNAL_ADDTRAIT(TRAIT_TENTACLE_IMMUNE), COMSIG_BRIMDUST_EXPLOSION), PROC_REF(release)) + RegisterSignals(tentacle, list(COMSIG_QDELETING, COMSIG_GOLIATH_TENTACLE_RETRACTING), PROC_REF(on_tentacle_left)) + RegisterSignal(leash, COMSIG_QDELETING, PROC_REF(release)) + +/obj/item/restraints/legcuffs/goliath_tentacle/proc/on_beam_click(atom/source, atom/location, control, params, mob/user) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(process_beam_click), source, location, params, user) + +/obj/item/restraints/legcuffs/goliath_tentacle/proc/process_beam_click(atom/source, atom/location, params, mob/user) + if(world.time <= user.next_move) + return + + var/obj/item/held_thing = user.get_active_held_item() + if (!istype(held_thing)) + return + + var/turf/nearest_turf = null + for (var/turf/line_turf in get_line(get_turf(src), get_turf(beam_effect.target))) + if (line_turf.IsReachableBy(user)) + nearest_turf = line_turf + break + + if (isnull(nearest_turf)) + return + + if (!user.can_perform_action(nearest_turf)) + nearest_turf.balloon_alert(user, "cannot reach!") + return + + held_thing.melee_attack_chain(user, src, params2list(params)) + user.changeNext_move(held_thing.attack_speed) + playsound(user, held_thing.hitsound || 'sound/effects/blob/attackblob.ogg', held_thing.get_clamped_volume(), TRUE, extrarange = held_thing.stealthy_audio ? SILENCED_SOUND_EXTRARANGE : -1, falloff_distance = 0) + +/obj/item/restraints/legcuffs/goliath_tentacle/play_attack_sound(damage_amount, damage_type, damage_flag) + return + +/obj/item/restraints/legcuffs/goliath_tentacle/drag + +/obj/item/restraints/legcuffs/goliath_tentacle/drag/Initialize(mapload, mob/living/target, obj/effect/goliath_tentacle/tentacle) + . = ..() + QDEL_IN(src, 15 SECONDS) + if (. != INITIALIZE_HINT_QDEL) + START_PROCESSING(SSprocessing, src) + +/obj/item/restraints/legcuffs/goliath_tentacle/drag/Destroy(force) + . = ..() + STOP_PROCESSING(SSprocessing, src) + +/obj/item/restraints/legcuffs/goliath_tentacle/drag/process(seconds_per_tick) + if (leash.distance <= 1) + return PROCESS_KILL + leash.set_distance(leash.distance - 1) + +/obj/item/restraints/legcuffs/goliath_tentacle/drag/leash_target(mob/living/user) + if (!tentacle?.owner) + return ..() + leash = user.AddComponent(/datum/component/leash, owner = tentacle.owner, distance = get_dist(user, tentacle.owner), silent = TRUE) + beam_effect = user.Beam(tentacle.owner, "goliath_tentacle", beam_type = /obj/effect/ebeam/goliath, emissive = FALSE) + RegisterSignal(beam_effect.visuals, COMSIG_CLICK, PROC_REF(on_beam_click)) + RegisterSignals(user, list(SIGNAL_ADDTRAIT(TRAIT_TENTACLE_IMMUNE), COMSIG_BRIMDUST_EXPLOSION), PROC_REF(release)) + RegisterSignals(tentacle.owner, COMSIG_QDELETING, PROC_REF(on_tentacle_left)) + RegisterSignal(leash, COMSIG_QDELETING, PROC_REF(release)) tentacle.retract() tentacle = null -/// Some kind soul has rescued us -/datum/status_effect/incapacitating/stun/goliath_tentacled/proc/on_helped(mob/source, mob/helping) - SIGNAL_HANDLER - release() - source.visible_message(span_notice("[helping] rips [source] from the tentacle's grasp!")) - return COMPONENT_BLOCK_MISC_HELP - -/// Something happened to make the tentacle let go -/datum/status_effect/incapacitating/stun/goliath_tentacled/proc/release() - SIGNAL_HANDLER - owner.remove_status_effect(/datum/status_effect/incapacitating/stun/goliath_tentacled) - -/// Something happened to our associated tentacle -/datum/status_effect/incapacitating/stun/goliath_tentacled/proc/on_tentacle_left() - SIGNAL_HANDLER - UnregisterSignal(tentacle, list(COMSIG_QDELETING, COMSIG_GOLIATH_TENTACLE_RETRACTING)) // No endless loops for us please - tentacle = null - release() +/obj/effect/ebeam/goliath + name = "goliath tentacle" + mouse_opacity = MOUSE_OPACITY_ICON diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index 26c90918672..f738e35bf8c 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -75,7 +75,7 @@ /mob/living/basic/mining/legion/update_overlays() . = ..() if (stat != DEAD && has_emissive) // Shouldn't really happen but just in case - . += emissive_appearance(icon, "[icon_living]_e", src, effect_type = EMISSIVE_NO_BLOOM) + . += emissive_appearance(icon, "[icon_living]_e", src, effect_type = EMISSIVE_BLOOM) /// Put a corpse in this guy /mob/living/basic/mining/legion/proc/consume(mob/living/carbon/human/consumed) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index ff81f32ffc0..8d5082d4c08 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -5,7 +5,8 @@ BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_AGGRO_RANGE = 5, // Unobservant - BB_BASIC_MOB_FLEE_DISTANCE = 6, + BB_RANGED_SKIRMISH_MIN_DISTANCE = 4, + BB_RANGED_SKIRMISH_MAX_DISTANCE = 6, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -15,8 +16,8 @@ /datum/ai_planning_subtree/call_reinforcements/mining, /datum/ai_planning_subtree/random_speech/legion, /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/maintain_distance, /datum/ai_planning_subtree/targeted_mob_ability, - /datum/ai_planning_subtree/flee_target/legion, ) /// Chase and attack whatever we are targeting, if it's friendly we will heal them diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index 6906121b4b8..bd9b2addff6 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -14,7 +14,7 @@ BB_LOBSTROSITY_EXPLOIT_TRAITS = list(TRAIT_INCAPACITATED, TRAIT_FLOORED, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT), BB_LOBSTROSITY_FINGER_LUST = 0, BB_LOBSTROSITY_NAIVE_HUNTER = FALSE, - BB_BASIC_MOB_FLEE_DISTANCE = 8, + BB_BASIC_MOB_FLEE_DISTANCE = 6, BB_EAT_FOOD_COOLDOWN = 3 MINUTES, BB_ONLY_FISH_WHILE_HUNGRY = TRUE, BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm index 15df9f7eba1..cd45eb9c6ec 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm @@ -2,6 +2,8 @@ blackboard = list( BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining, + BB_RANGED_SKIRMISH_MIN_DISTANCE = 3, + BB_RANGED_SKIRMISH_MAX_DISTANCE = 5, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e4735864937..e2b93ca0271 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -195,14 +195,15 @@ * @param {number} breakouttime - The time it takes to break the cuffs. Use SECONDS/MINUTES defines * @param {number} cuff_break - Speed multiplier, 0 is default, see _DEFINES\combat.dm */ -/mob/living/carbon/proc/cuff_resist(obj/item/cuffs, breakouttime = 1 MINUTES, cuff_break = 0) +/mob/living/carbon/proc/cuff_resist(obj/item/cuffs, breakouttime = null, cuff_break = 0) if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, cuffs) & COMSIG_MOB_BLOCK_CUFF_REMOVAL)) return //The blocking object should sent a fluff-appropriate to_chat about cuff removal being blocked if(cuffs.item_flags & BEING_REMOVED) to_chat(src, span_warning("You're already attempting to remove [cuffs]!")) return cuffs.item_flags |= BEING_REMOVED - breakouttime = cuffs.breakouttime + if (isnull(breakouttime)) + breakouttime = cuffs.breakouttime if(!cuff_break) visible_message(span_warning("[src] attempts to remove [cuffs]!")) to_chat(src, span_notice("You attempt to remove [cuffs]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)")) diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 0c1cae2fe17..8c011445492 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -379,10 +379,13 @@ /mob/living/carbon/update_worn_legcuffs() remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") - if(legcuffed) - overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/simple/mob.dmi', "legcuff1", -LEGCUFF_LAYER) - apply_overlay(LEGCUFF_LAYER) - throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed) + if(!legcuffed) + return + if(astype(legcuffed, /obj/item/restraints/legcuffs)?.legcuff_state) + var/obj/item/restraints/legcuffs/cuffs = legcuffed + overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/simple/mob.dmi', cuffs.legcuff_state, -LEGCUFF_LAYER) + apply_overlay(LEGCUFF_LAYER) + throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed) /mob/living/carbon/update_worn_head() remove_overlay(HEAD_LAYER) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index d62fa709e77..fd4c4d58a96 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -230,19 +230,19 @@ min_damage = 30 max_damage = 35 -/obj/effect/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner) +/obj/effect/goliath_tentacle/broodmother/patch/Initialize(mapload, mob/living/goliath) . = ..() INVOKE_ASYNC(src, PROC_REF(createpatch)) /obj/effect/goliath_tentacle/broodmother/patch/proc/createpatch() var/tentacle_locs = spiral_range_turfs(1, get_turf(src)) for(var/T in tentacle_locs) - new /obj/effect/goliath_tentacle/broodmother(T) + new /obj/effect/goliath_tentacle/broodmother(T, owner) var/list/directions = GLOB.cardinals.Copy() for(var/i in directions) var/turf/T = get_step(get_turf(src), i) T = get_step(T, i) - new /obj/effect/goliath_tentacle/broodmother(T) + new /obj/effect/goliath_tentacle/broodmother(T, owner) #undef CALL_CHILDREN #undef RAGE diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index f3107b31af3..a4003d92987 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -163,7 +163,7 @@ variable = TRUE /datum/movespeed_modifier/goliath_mount - multiplicative_slowdown = -27.5 + multiplicative_slowdown = -9.5 /datum/movespeed_modifier/goldgrub_mount multiplicative_slowdown = -4.5 diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index a4a9bbb8443..c9723f51e2b 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/mob/simple/mob.dmi b/icons/mob/simple/mob.dmi index 74b90ffd95b..d34276cd3f3 100644 Binary files a/icons/mob/simple/mob.dmi and b/icons/mob/simple/mob.dmi differ diff --git a/icons/obj/weapons/restraints.dmi b/icons/obj/weapons/restraints.dmi index ddd3bf96436..aa24ef81c40 100644 Binary files a/icons/obj/weapons/restraints.dmi and b/icons/obj/weapons/restraints.dmi differ