diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index daa5d4285f9..6dc90ea4d64 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -141,5 +141,8 @@ /// The next time at which this mob can call for reinforcements #define BB_BASIC_MOB_REINFORCEMENTS_COOLDOWN "BB_basic_mob_reinforcements_cooldown" +/// the direction we started when executing stare at things +#define BB_STARTING_DIRECTION "BB_startdir" + ///Text we display when we befriend someone #define BB_FRIENDLY_MESSAGE "friendly_message" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index ac48989a59f..d3dce4b065a 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -603,6 +603,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_LAVA_STOPPED "lava_stopped" ///Chasms will be safe to cross while they've this trait. #define TRAIT_CHASM_STOPPED "chasm_stopped" +///Chasms will be safe to cross if there is something with this trait on it +#define TRAIT_CHASM_STOPPER "chasm_stopper" ///The effects of the immerse element will be halted while this trait is present. #define TRAIT_IMMERSE_STOPPED "immerse_stopped" /// The effects of hyperspace drift are blocked when the tile has this trait diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 64ddcfe4b4b..1b93d58dae3 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -66,6 +66,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED, "TRAIT_WADDLING" = TRAIT_WADDLING, "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE, + "TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER, ), /datum/controller/subsystem/economy = list( "TRAIT_MARKET_CRASHING" = TRAIT_MARKET_CRASHING, diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index 9829dfc3f52..b4406857ac1 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -109,6 +109,9 @@ return CHASM_NOT_DROPPING if(dropped_thing.throwing || (dropped_thing.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) return CHASM_REGISTER_SIGNALS + for(var/atom/thing_to_check as anything in parent) + if(HAS_TRAIT(thing_to_check, TRAIT_CHASM_STOPPER)) + return CHASM_NOT_DROPPING //Flies right over the chasm if(ismob(dropped_thing)) diff --git a/code/game/area/areas/away_content.dm b/code/game/area/areas/away_content.dm index e7f56393a66..db4900a1edd 100644 --- a/code/game/area/areas/away_content.dm +++ b/code/game/area/areas/away_content.dm @@ -23,6 +23,18 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30" has_gravity = STANDARD_GRAVITY ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg','sound/ambience/ambiodd.ogg','sound/ambience/ambinice.ogg') +/area/awaymission/museum + name = "Nanotrasen Museum" + icon_state = "awaycontent28" + sound_environment = SOUND_ENVIRONMENT_CONCERT_HALL + +/area/awaymission/museum/mothroachvoid + static_lighting = FALSE + base_lighting_alpha = 200 + base_lighting_color = "#FFF4AA" + sound_environment = SOUND_ENVIRONMENT_PLAIN + ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/ambiodd.ogg','sound/ambience/ambinice.ogg') + /area/awaymission/errorroom name = "Super Secret Room" static_lighting = FALSE diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 5d390019f9b..eca8d88da4b 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -66,3 +66,12 @@ /obj/machinery/door/poddoor/shutters/window/preopen icon_state = "open" density = FALSE + +/obj/machinery/door/poddoor/shutters/window/indestructible + name = "hardened windowed shutters" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + +/obj/machinery/door/poddoor/shutters/window/indestructible/preopen + icon_state = "open" + density = FALSE + opacity = FALSE diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 24c0ac8bda5..fbc27e3dac1 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -549,6 +549,19 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/ai, 32) connected_display.receive_signal(status_signal) +/obj/machinery/status_display/random_message + current_mode = SD_MESSAGE + /// list to pick the first line from + var/list/firstline_to_secondline = list() + +/obj/machinery/status_display/random_message/Initialize(mapload, ndir, building) + if(firstline_to_secondline?.len) + message1 = pick(firstline_to_secondline) + message2 = firstline_to_secondline[message1] + return ..() // status displays call update appearance on init so i suppose we should set the messages before calling parent as to not call it twice + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/random_message, 32) + #undef MAX_STATIC_WIDTH #undef FONT_STYLE #undef SCROLL_RATE diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 1a1dc80fe25..7fe6c59075f 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -486,6 +486,9 @@ ignite() return ..() +/obj/effect/decal/cleanable/fuel_pool/hivis + icon_state = "fuel_pool_hivis" + /obj/effect/decal/cleanable/rubble name = "rubble" desc = "A pile of rubble." diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index e63e7e39c4a..cd8a859f86f 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -117,8 +117,7 @@ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) s.start() - if(ismob(triggerer)) - mineEffect(triggerer) + mineEffect(triggerer) triggered = TRUE SEND_SIGNAL(src, COMSIG_MINE_TRIGGERED, triggerer) qdel(src) diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm index a014857994a..ecfa560bfe6 100644 --- a/code/game/objects/effects/step_triggers.dm +++ b/code/game/objects/effects/step_triggers.dm @@ -19,7 +19,7 @@ /obj/effect/step_trigger/proc/on_entered(datum/source, H as mob|obj) SIGNAL_HANDLER - if(!H) + if(!H || H == src) return if(isobserver(H) && !affect_ghosts) return @@ -138,6 +138,26 @@ if (T) A.forceMove(T) +/* Teleports atoms directly to an offset, no randomness, looping hallways! */ + +/obj/effect/step_trigger/teleporter/offset + var/teleport_x_offset = 0 + var/teleport_y_offset = 0 + +/obj/effect/step_trigger/teleporter/offset/on_entered(datum/source, H as mob|obj, atom/old_loc) + if(!old_loc?.Adjacent(loc)) // prevents looping, if we were teleported into this then the old loc is usually not adjacent + return + return ..() + +/obj/effect/step_trigger/teleporter/offset/Trigger(atom/movable/poor_soul) + var/turf/destination = locate(x + teleport_x_offset, y + teleport_y_offset, z) + if(!destination) + return + poor_soul.forceMove(destination) + var/mob/living/living_soul = poor_soul + if(istype(living_soul) && living_soul.client) + living_soul.client.move_delay = 0 + /* Fancy teleporter, creates sparks and smokes when used */ /obj/effect/step_trigger/teleport_fancy diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 8eba5081d22..7ac22d00897 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -403,3 +403,61 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_keycardpad, 32) playsound(src, SFX_SPARKS, 100, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) do_sparks(3, cardinal_only = FALSE, source = src) qdel(src) + +/obj/structure/puzzle_blockade/oneway + name = "one-way gate" + desc = "A wall of solid light, likely defending something important. Virtually indestructible." + icon = 'icons/obj/structures.dmi' + icon_state = "oneway" + base_icon_state = "oneway" + light_color = COLOR_BIOLUMINESCENCE_BLUE + light_range = 1 + density = FALSE + +/obj/structure/puzzle_blockade/oneway/update_icon_state() + icon_state = "[base_icon_state][density ? "" : "-off"]" + return ..() + +/obj/structure/puzzle_blockade/oneway/CanAllowThrough(atom/movable/mover, border_dir) + return ..() && (REVERSE_DIR(border_dir) == dir || get_turf(mover) == get_turf(src)) + +/obj/structure/puzzle_blockade/oneway/CanAStarPass(border_dir, datum/can_pass_info/pass_info) + return REVERSE_DIR(border_dir) == dir + +/obj/structure/puzzle_blockade/oneway/try_signal(datum/source) + density = FALSE + update_appearance(UPDATE_ICON) + +/obj/effect/puzzle_poddoor_open + name = "puzzle-poddoor relay" + desc = "activates poddoors if activated with a puzzle signal." + icon = 'icons/effects/mapping_helpers.dmi' + icon_state = "" + anchored = TRUE + invisibility = INVISIBILITY_MAXIMUM + /// if we receive a puzzle signal with this we do our thing + var/queue_id + /// door id + var/id + +/obj/effect/puzzle_poddoor_open/Initialize(mapload) + . = ..() + if(isnull(id) || isnull(queue_id)) + log_mapping("[src] id:[id] has no id or door id and has been deleted") + return INITIALIZE_HINT_QDEL + + SSqueuelinks.add_to_queue(src, queue_id) + +/obj/effect/puzzle_poddoor_open/MatchedLinks(id, list/partners) + for(var/partner in partners) + RegisterSignal(partner, COMSIG_PUZZLE_COMPLETED, PROC_REF(try_signal)) + +/obj/effect/puzzle_poddoor_open/proc/try_signal(datum/source) + SIGNAL_HANDLER + var/openclose + for(var/obj/machinery/door/poddoor/door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor)) + if(door.id != id) + continue + if(isnull(openclose)) + openclose = door.density + INVOKE_ASYNC(door, openclose ? TYPE_PROC_REF(/obj/machinery/door/poddoor, open) : TYPE_PROC_REF(/obj/machinery/door/poddoor, close)) diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index a38659aaefe..82e89314d68 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -305,3 +305,12 @@ anchored = FALSE density = TRUE deconstructible = TRUE + +/obj/structure/fluff/wallsign + name = "direction sign" + desc = "Now, where to go?" + density = FALSE + icon = 'icons/obj/fluff/general.dmi' + icon_state = "wallsign" + +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fluff/wallsign, 32) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index dc1c7548d49..0e50c983d88 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -932,6 +932,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/reinforced/tinted/frosted/spaw icon_state = "clockwork_window-single" glass_type = /obj/item/stack/sheet/bronze +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/bronze/spawner, 0) + /obj/structure/window/bronze/unanchored anchored = FALSE diff --git a/code/game/turfs/closed/indestructible.dm b/code/game/turfs/closed/indestructible.dm index b8c386ecf10..f1243b68a84 100644 --- a/code/game/turfs/closed/indestructible.dm +++ b/code/game/turfs/closed/indestructible.dm @@ -121,6 +121,16 @@ SKYRAT EDIT REMOVAL END */ smoothing_groups = SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS canSmoothWith = SMOOTH_GROUP_WALLS +/turf/closed/indestructible/reinforced/titanium + name = "reinforced titanium imitation wall" + desc = "A huge chunk of reinforced metal used to separate rooms. Naturally, to cut down on costs, this is just a really good paint job to resemble titanium. Effectively impervious to conventional methods of destruction." + icon = 'icons/turf/walls/shuttle_wall.dmi' + icon_state = "shuttle_wall-0" + base_icon_state = "shuttle_wall" + +/turf/closed/indestructible/reinforced/titanium/nodiagonal + icon_state = "shuttle_wall-15" + smoothing_flags = SMOOTH_BITMASK /turf/closed/indestructible/riveted icon = 'icons/turf/walls/riveted.dmi' diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm index 48ab1ceca38..142d966172b 100644 --- a/code/game/turfs/open/chasm.dm +++ b/code/game/turfs/open/chasm.dm @@ -119,3 +119,19 @@ /turf/open/chasm/true/apply_components(mapload) AddComponent(/datum/component/chasm, null, mapload) //Don't pass anything for below_turf. + +/turf/open/chasm/true/no_smooth + smoothing_flags = NONE + +/turf/open/chasm/true/no_smooth/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + return FALSE + +/turf/open/chasm/true/no_smooth/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data) + return FALSE + +/turf/open/chasm/true/no_smooth/attackby(obj/item/item, mob/user, params, area/area_restriction) + if(istype(item, /obj/item/stack/rods)) + return + else if(istype(item, /obj/item/stack/tile/iron)) + return + return ..() diff --git a/code/modules/awaymissions/away_props.dm b/code/modules/awaymissions/away_props.dm index f6d1a830a91..1ed0a1ec0ff 100644 --- a/code/modules/awaymissions/away_props.dm +++ b/code/modules/awaymissions/away_props.dm @@ -118,3 +118,19 @@ icon = 'icons/turf/floors.dmi' icon_state = "floor" hidden = TRUE + +/// only player mobs (has ckey) may pass, reverse for the opposite +/obj/effect/playeronly_barrier + name = "player-only barrier" + desc = "You shall pass." + icon = 'icons/effects/mapping_helpers.dmi' + icon_state = "blocker" + anchored = TRUE + invisibility = INVISIBILITY_MAXIMUM + var/reverse = FALSE //Block if has ckey + +/obj/effect/playeronly_barrier/CanAllowThrough(mob/living/mover, border_dir) + . = ..() + if(!istype(mover)) + return + return isnull(mover.ckey) == reverse diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm new file mode 100644 index 00000000000..20210d56cc9 --- /dev/null +++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm @@ -0,0 +1,131 @@ +/obj/machinery/computer/terminal/museum + name = "exhibit info terminal" + desc = "A relatively low-tech info board. Not as low-tech as an actual sign though. Appears to be quite old." + upperinfo = "Nanotrasen Museum Exhibit Info" + icon_state = "plaque" + icon_screen = "plaque_screen" + icon_keyboard = null + +/obj/effect/replica_spawner //description and name are intact, better to make a new fluff object for stuff that is not actually ingame as an object + name = "replica creator" + desc = "This creates a fluff object that looks exactly like the input, but like obviously a replica. Do not for the love of god use with stuff that has Initialize side effects." + icon = 'icons/hud/screen_gen.dmi' + icon_state = "x2" + invisibility = INVISIBILITY_ABSTRACT //nope, can't see this + anchored = TRUE + density = TRUE + opacity = FALSE + var/replica_path = /obj/structure/fluff + var/target_path + var/obvious_replica = TRUE + +/obj/effect/replica_spawner/Initialize(mapload) + . = ..() + if(isnull(target_path)) + return INITIALIZE_HINT_QDEL //no use to make a replica of null + var/atom/appearance_object = new target_path + var/atom/new_replica = new replica_path(loc) + + new_replica.icon = appearance_object.icon + new_replica.icon_state = appearance_object.icon_state + new_replica.copy_overlays(appearance_object.appearance, cut_old = TRUE) + new_replica.density = appearance_object.density //for like nondense showers and stuff + + new_replica.name = "[appearance_object.name][obvious_replica ? " replica" : ""]" + new_replica.desc = "[appearance_object.desc][obvious_replica ? " ..except this one is a replica.": ""]" + qdel(appearance_object) + qdel(src) + return INITIALIZE_HINT_QDEL + +/obj/structure/fluff/dnamod + name = "DNA Modifier" + desc = "DNA Manipulator replica. Essentially just a box of cool lights." + icon = 'icons/obj/service/hydroponics/equipment.dmi' + icon_state = "dnamod" + density = TRUE + +/obj/structure/fluff/preserved_borer + name = "preserved borer exhibit" + desc = "A preserved cortical borer. Probably been there long enough to not last long outside the exhibit." + icon = 'icons/obj/structures.dmi' + icon_state = "preservedborer" + density = TRUE + +/obj/structure/fluff/balloon_nuke + name = "nuclear balloon explosive" + desc = "You probably shouldn't stick around to see if this is inflated." + icon = /obj/machinery/nuclearbomb::icon + icon_state = /obj/machinery/nuclearbomb::icon_state + density = TRUE + max_integrity = 5 //one tap + +/obj/structure/fluff/balloon_nuke/atom_destruction() + playsound(loc, 'sound/effects/cartoon_pop.ogg', 75, vary = TRUE) + ..() + +/obj/structure/fluff/fake_camera + name = /obj/machinery/camera::name + desc = /obj/machinery/camera::desc + icon = /obj/machinery/camera::icon + icon_state = /obj/machinery/camera::icon_state + +/obj/structure/fluff/fake_scrubber + name = /obj/machinery/atmospherics/components/unary/vent_scrubber::name + desc = /obj/machinery/atmospherics/components/unary/vent_scrubber::desc + icon = /obj/machinery/atmospherics/components/unary/vent_scrubber::icon + layer = /obj/machinery/atmospherics/components/unary/vent_scrubber::layer + plane = FLOOR_PLANE + icon_state = "scrub_on" + +/obj/structure/fluff/fake_vent + name = /obj/machinery/atmospherics/components/unary/vent_pump::name + desc = /obj/machinery/atmospherics/components/unary/vent_pump::desc + icon = /obj/machinery/atmospherics/components/unary/vent_pump::icon + layer = /obj/machinery/atmospherics/components/unary/vent_scrubber::layer + plane = FLOOR_PLANE + icon_state = "vent_out" + +/turf/open/mirage + icon = 'icons/turf/floors.dmi' + icon_state = "mirage" + invisibility = INVISIBILITY_ABSTRACT + /// target turf x and y are offsets from our location instead of a direct coordinate + var/offset = TRUE + /// tile range that we show, 2 means that the target tile and two tiles ahead of it in our direction will show + var/range + var/target_turf_x = 0 + var/target_turf_y = 0 + /// if not specified, uses our Z + var/target_turf_z + +/turf/open/mirage/Initialize(mapload) + . = ..() + if(isnull(range)) + range = world.view + var/used_z = target_turf_z || z //if target z is not defined, use ours + var/turf/target = locate(offset ? target_turf_x + x : target_turf_x, offset ? target_turf_y + y : target_turf_y, used_z) + AddElement(/datum/element/mirage_border, target, dir, range) + +/obj/effect/mapping_helpers/ztrait_injector/museum + traits_to_add = list(ZTRAIT_NOPARALLAX = TRUE, ZTRAIT_NOXRAY = TRUE, ZTRAIT_NOPHASE = TRUE, ZTRAIT_BASETURF = /turf/open/indestructible/plating, ZTRAIT_SECRET = TRUE) + +/obj/effect/smooths_with_walls + name = "effect that smooths with walls" + desc = "to supplement /turf/open/mirage." + icon = 'icons/hud/screen_gen.dmi' + icon_state = "x2" + invisibility = INVISIBILITY_ABSTRACT + anchored = TRUE + density = TRUE + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS + +/obj/item/paper/fluff/museum/noend + name = "scrambled note" + default_raw_text = {"this place, +
god whose idea was to build a museum in the void in the middle of god knows where there is no reason we should have done this +
and those mannequins why do they stare back where the fuck did you get these from +
how would we even get visitors here +
sometimes i can catch them moving +
+
we should have never come here"} diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index 7676801a0a9..faaaf9e4206 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -1395,3 +1395,32 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) var/turf/our_turf = get_turf(src) // In case a locker ate us or something our_turf.AddElement(/datum/element/bombable_turf) return INITIALIZE_HINT_QDEL + +/// this helper buckles all mobs on the tile to the first buckleable object +/obj/effect/mapping_helpers/mob_buckler + name = "Buckle Mob" + icon_state = "buckle" + late = TRUE + ///whether we force a buckle + var/force_buckle = FALSE + +/obj/effect/mapping_helpers/mob_buckler/Initialize(mapload) + . = ..() + var/atom/movable/buckle_to + var/list/mobs = list() + for(var/atom/movable/possible_buckle as anything in loc) + if(isnull(buckle_to) && possible_buckle.can_buckle) + buckle_to = possible_buckle + continue + + if(isliving(possible_buckle)) + mobs += possible_buckle + + if(isnull(buckle_to)) + log_mapping("[type] at [x] [y] [z] did not find anything to buckle to") + return INITIALIZE_HINT_QDEL + + for(var/mob/living/mob as anything in mobs) + buckle_to.buckle_mob(mob, force = force_buckle) + + return INITIALIZE_HINT_QDEL diff --git a/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm b/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm new file mode 100644 index 00000000000..7b6bf6c8399 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/statue/mannequin.dm @@ -0,0 +1,89 @@ +/mob/living/basic/statue/mannequin + name = "mannequin" + desc = "Oh, so this is a dress-up game now." + icon = 'icons/mob/human/mannequin.dmi' + icon_state = "mannequin_wood_male" + icon_living = "mannequin_wood_male" + icon_dead = "mannequin_wood_male" + health = 300 + maxHealth = 300 + melee_damage_lower = 15 + melee_damage_upper = 30 + sentience_type = SENTIENCE_ARTIFICIAL + ai_controller = /datum/ai_controller/basic_controller/stares_at_people + /// the path to a fake item we will hold in our right hand + var/obj/item/held_item + /// the path to a fake hat we will wear + var/obj/item/hat + +/mob/living/basic/statue/mannequin/Initialize(mapload) + . = ..() + update_appearance() + +/mob/living/basic/statue/mannequin/update_overlays() + . = ..() + if(held_item) + . += mutable_appearance(initial(held_item.righthand_file), initial(held_item.inhand_icon_state)) + if(hat) + . += mutable_appearance(initial(hat.worn_icon), initial(hat.worn_icon_state) || initial(hat.icon_state)) + +/datum/ai_controller/basic_controller/stares_at_people + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_AGGRO_RANGE = 6, + ) + + ai_movement = /datum/ai_movement/dumb + idle_behavior = null + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/face_target_or_face_initial, // we be creepy and all + ) + +/datum/ai_planning_subtree/face_target_or_face_initial + +/datum/ai_planning_subtree/face_target_or_face_initial/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(isnull(controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET])) + return + var/mob/living/we = controller.pawn + controller.blackboard[BB_STARTING_DIRECTION] = we.dir + controller.queue_behavior(/datum/ai_behavior/face_target_or_face_initial, BB_BASIC_MOB_CURRENT_TARGET) + +/datum/ai_behavior/face_target_or_face_initial + +/datum/ai_behavior/face_target_or_face_initial/setup(datum/ai_controller/controller, target_key) + . = ..() + var/atom/movable/target = controller.blackboard[target_key] + return ismovable(target) && isturf(target.loc) && ismob(controller.pawn) + +/datum/ai_behavior/face_target_or_face_initial/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + . = ..() + var/atom/movable/target = controller.blackboard[target_key] + var/mob/living/we = controller.pawn + if(isnull(target) || get_dist(we, target) > 8) + we.dir = controller.blackboard[BB_STARTING_DIRECTION] + finish_action(controller, TRUE) + else + we.face_atom(target) + +/mob/living/basic/statue/mannequin/suspicious + name = "mannequin?" + desc = "Their eyes follow you." + health = 1500 //yeah uhh avoid these + maxHealth = 1500 + ai_controller = /datum/ai_controller/basic_controller/suspicious_mannequin + +/datum/ai_controller/basic_controller/suspicious_mannequin + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_AGGRO_RANGE = 14, + BB_EMOTE_KEY = "scream", //spooky + ) + + ai_movement = /datum/ai_movement/jps //threat + idle_behavior = null + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/run_emote, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/code/modules/mob/living/basic/vermin/mothroach.dm b/code/modules/mob/living/basic/vermin/mothroach.dm index 15f82d38f85..4c06665a14a 100644 --- a/code/modules/mob/living/basic/vermin/mothroach.dm +++ b/code/modules/mob/living/basic/vermin/mothroach.dm @@ -73,3 +73,10 @@ planning_subtrees = list( /datum/ai_planning_subtree/random_speech/mothroach, ) + +/mob/living/basic/mothroach/bar + name = "mothroach bartender" + desc = "A mothroach serving drinks. Look at him go." + icon_state = "barroach" + icon_living = "barroach" + icon_dead = "barroach_dead" diff --git a/code/modules/transport/tram/tram_controller.dm b/code/modules/transport/tram/tram_controller.dm index 5665755520e..22504b6118b 100644 --- a/code/modules/transport/tram/tram_controller.dm +++ b/code/modules/transport/tram/tram_controller.dm @@ -672,6 +672,11 @@ dispatch_transport(destination_platform = push_destination) return push_destination + +/datum/transport_controller/linear/tram/slow //for some reason speed is set to initial() in the code but if i touched it it would probably break so + speed_limiter = 3 + base_speed_limiter = 3 + /** * The physical cabinet on the tram. Acts as the interface between players and the controller datum. */ diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 7a57529b8ff..89a7333865e 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -86,6 +86,7 @@ if(radial_travel) AddElement(/datum/element/contextual_screentip_bare_hands, lmb_text = "Send Transport") + ADD_TRAIT(src, TRAIT_CHASM_STOPPER, INNATE_TRAIT) set_movement_registrations() //since transport_controller datums find all connected platforms when a transport structure first creates it and then @@ -936,3 +937,7 @@ var/throw_target = get_edge_target_turf(src, throw_direction) var/datum/callback/land_slam = new(passenger, TYPE_PROC_REF(/mob/living/, tram_slam_land)) passenger.throw_at(throw_target, 400, 4, force = MOVE_FORCE_OVERPOWERING, callback = land_slam) + +/obj/structure/transport/linear/tram/slow + transport_controller_type = /datum/transport_controller/linear/tram/slow + speed_limiter = /datum/transport_controller/linear/tram/slow::speed_limiter diff --git a/config/awaymissionconfig.txt b/config/awaymissionconfig.txt index 7278655a39b..0a96d93984a 100644 --- a/config/awaymissionconfig.txt +++ b/config/awaymissionconfig.txt @@ -7,9 +7,7 @@ #Do NOT tick the maps during compile -- the game uses this list to decide which map to load. Ticking the maps will result in them ALL being loaded at once. #DO tick the associated code file for the away mission you are enabling. Otherwise, the map will be trying to reference objects which do not exist, which will cause runtime errors! -#_maps/RandomZLevels/blackmarketpackers.dmm #_maps/RandomZLevels/TheBeach.dmm -#_maps/RandomZLevels/centcomAway.dmm #_maps/RandomZLevels/moonoutpost19.dmm #_maps/RandomZLevels/undergroundoutpost45.dmm #_maps/RandomZLevels/caves.dmm @@ -17,3 +15,4 @@ #_maps/RandomZLevels/research.dmm #_maps/RandomZLevels/SnowCabin.dmm #_maps/RandomZLevels/blackmesa.dmm +#_maps/RandomZLevels/museum.dmm diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 1b2f617972a..fcb4e262d7c 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/mapping_helpers.dmi b/icons/effects/mapping_helpers.dmi index d28d2770ec4..351bb5f00c4 100644 Binary files a/icons/effects/mapping_helpers.dmi and b/icons/effects/mapping_helpers.dmi differ diff --git a/icons/mob/simple/animal.dmi b/icons/mob/simple/animal.dmi index 3bd3438bc62..7fcf0e9d65e 100644 Binary files a/icons/mob/simple/animal.dmi and b/icons/mob/simple/animal.dmi differ diff --git a/icons/obj/fluff/general.dmi b/icons/obj/fluff/general.dmi index 2628eea8746..1aa7ae5c898 100644 Binary files a/icons/obj/fluff/general.dmi and b/icons/obj/fluff/general.dmi differ diff --git a/icons/obj/machines/computer.dmi b/icons/obj/machines/computer.dmi index cba0069cf6f..aae3a83a455 100644 Binary files a/icons/obj/machines/computer.dmi and b/icons/obj/machines/computer.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 40420db3705..1e6a2ba6872 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 6fc1178a6b4..89b4876c0ce 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/tgstation.dme b/tgstation.dme index fb1e85f2942..ee20e3d2a98 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4461,6 +4461,7 @@ #include "code\modules\mapfluff\ruins\lavalandruin_code\watcher_grave.dm" #include "code\modules\mapfluff\ruins\objects_and_mobs\ash_walker_den.dm" #include "code\modules\mapfluff\ruins\objects_and_mobs\cursed_slot_machine.dm" +#include "code\modules\mapfluff\ruins\objects_and_mobs\museum.dm" #include "code\modules\mapfluff\ruins\objects_and_mobs\necropolis_gate.dm" #include "code\modules\mapfluff\ruins\objects_and_mobs\sin_ruins.dm" #include "code\modules\mapfluff\ruins\spaceruin_code\allamericandiner.dm" @@ -4865,6 +4866,7 @@ #include "code\modules\mob\living\basic\space_fauna\spider\spiderlings\spiderling_subtypes.dm" #include "code\modules\mob\living\basic\space_fauna\spider\young_spider\young_spider.dm" #include "code\modules\mob\living\basic\space_fauna\spider\young_spider\young_spider_subtypes.dm" +#include "code\modules\mob\living\basic\space_fauna\statue\mannequin.dm" #include "code\modules\mob\living\basic\space_fauna\statue\statue.dm" #include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\fugu_gland.dm" #include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\inflation.dm"