diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 97e4b0dbd1e8..be96a2e32b85 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -152,6 +152,8 @@ most of them are tied into map-placed objects. This should be reworked in the fu /// Ancients only #define ACCESS_YAUTJA_ANCIENT 392 +/// Anything in a tutorial sequence that shouldn't be accessed +#define ACCESS_TUTORIAL_LOCKED 998 ///Temporary, just so I can flag places I need to change #define ACCESS_COME_BACK_TO_ME 999 diff --git a/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm b/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm index 6614272d33e5..2e247cdccc73 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm @@ -67,3 +67,6 @@ #define COMSIG_HUMAN_SURGERY_APPLY_MODIFIERS "human_surgery_apply_modifiers" /// From /mob/living/carbon/human/proc/get_flags_cold_protection() #define COMSIG_HUMAN_COLD_PROTECTION_APPLY_MODIFIERS "human_cold_protection_apply_modifiers" + +/// From /obj/item/proc/dig_out_shrapnel() : () +#define COMSIG_HUMAN_SHRAPNEL_REMOVED "human_shrapnel_removed" diff --git a/code/__DEFINES/dcs/signals/atom/mob/living/signals_living.dm b/code/__DEFINES/dcs/signals/atom/mob/living/signals_living.dm index 89f3951e7c99..cea905dd1011 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/living/signals_living.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/living/signals_living.dm @@ -29,7 +29,19 @@ #define COMSIG_LIVING_PRE_COLLIDE "living_pre_collide" #define COMPONENT_LIVING_COLLIDE_HANDLED (1<<0) +/// From /mob/living/proc/do_ghost() : (mob/dead/observer/ghost) +#define COMSIG_LIVING_GHOSTED "living_ghosted" + +/// From /mob/living/carbon/human/attack_hand() : (mob/living/carbon/human/attacked_mob) +#define COMSIG_LIVING_ATTACKHAND_HUMAN "living_attackhand_human" + +/// From /obj/item/reagent_container/hypospray/attack() : (obj/item/reagent_container/hypospray/injector) +#define COMSIG_LIVING_HYPOSPRAY_INJECTED "living_hypospray_injected" + ///from base of mob/living/set_buckled(): (new_buckled) #define COMSIG_LIVING_SET_BUCKLED "living_set_buckled" ///from base of mob/living/set_body_position() #define COMSIG_LIVING_SET_BODY_POSITION "living_set_body_position" + +/// from base of /mob/living/apply_status_effect(): (datum/status_effect/new_effect) +#define COMSIG_LIVING_APPLY_EFFECT "living_apply_effect" diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm index f288f5d94584..58021ba564a2 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm @@ -131,5 +131,42 @@ /// From /obj/item/proc/pickup() : (obj/item/picked_up) #define COMSIG_MOB_PICKUP_ITEM "mob_pickup_item" +/// From /obj/item/proc/attack_self() : (obj/item/used) +#define COMSIG_MOB_ITEM_ATTACK_SELF "mob_item_attack_self" + +/// From /obj/item/proc/dropped() : (obj/item/dropped) +#define COMSIG_MOB_ITEM_DROPPED "mob_item_dropped" + + +/// From /obj/item/reagent_container/food/snacks/proc/on_Consume() : (obj/item/reagent_container/food/snacks/eaten_food) +#define COMSIG_MOB_EATEN_SNACK "mob_eaten_snack" + +/// From /atom/proc/attackby() : (atom/attacked, obj/item/attacked_with) +#define COMSIG_MOB_PARENT_ATTACKBY "mob_parent_attackby" + +/// From /obj/item/weapon/gun/proc/reload_into_chamber() : (obj/item/weapon/gun/empty_gun) +#define COMSIG_MOB_GUN_EMPTY "mob_gun_empty" + +/// From /obj/item/weapon/gun/proc/reload() : (obj/item/weapon/gun/reloaded) +#define COMSIG_MOB_RELOADED_GUN "mob_reloaded_gun" + +/// From /mob/proc/get_status_tab_items() : (list/status_list) +#define COMSIG_MOB_GET_STATUS_TAB_ITEMS "mob_get_status_tab_items" + +/// From /datum/tutorial/proc/update_objective() : (new_objective) +#define COMSIG_MOB_TUTORIAL_UPDATE_OBJECTIVE "mob_tutorial_update_objective" + +/// From /mob/proc/swap_hand() : () +#define COMSIG_MOB_SWAPPED_HAND "mob_swapped_hand" + +/// From /mob/proc/a_intent_change() : (new_intent) +#define COMSIG_MOB_INTENT_CHANGE "mob_intent_change" + +/// From /obj/item/grab/proc/progress_passive() : (mob/living/carbon/human/grabber) +#define COMSIG_MOB_AGGRESSIVELY_GRABBED "mob_aggressively_grabbed" + #define COMSIG_MOB_AGGRESIVE_GRAB_CANCEL (1<<0) + /// Cancels all running cloaking effects on target #define COMSIG_MOB_EFFECT_CLOAK_CANCEL "mob_effect_cloak_cancel" + +#define COMSIG_MOB_END_TUTORIAL "mob_end_tutorial" diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index b5f2bb3ff6a9..c870a55ed746 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -30,6 +30,16 @@ /// from /obj/proc/afterbuckle() #define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" +/// from /obj/structure/machinery/cryopod/go_out() +#define COMSIG_CRYOPOD_GO_OUT "cryopod_go_out" + +/// from /proc/vendor_successful_vend() : (obj/structure/machinery/cm_vending/vendor, list/itemspec, mob/living/carbon/human/user) +#define COMSIG_VENDOR_SUCCESSFUL_VEND "vendor_successful_vend" + +/// from /obj/limb/proc/remove_all_bleeding() : (external, internal) +#define COMSIG_LIMB_STOP_BLEEDING "limb_stop_bleeding" + #define COMSIG_DROPSHIP_ADD_EQUIPMENT "dropship_add_equipment" #define COMSIG_DROPSHIP_REMOVE_EQUIPMENT "dropship_remove_equipment" + #define COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED "structure_crate_squad_launched" diff --git a/code/__DEFINES/dcs/signals/signals_client.dm b/code/__DEFINES/dcs/signals/signals_client.dm index 6733e0703514..3968f654c486 100644 --- a/code/__DEFINES/dcs/signals/signals_client.dm +++ b/code/__DEFINES/dcs/signals/signals_client.dm @@ -27,6 +27,3 @@ /// Called when something is removed from a client's screen : /client/proc/remove_from_screen(screen_remove) #define COMSIG_CLIENT_SCREEN_REMOVE "client_screen_remove" - -/// When a mind is transfered to another mob at /datum/mind/proc/transfer_to() -#define COMSIG_CLIENT_MIND_TRANSFER "mind_transfer" diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm new file mode 100644 index 000000000000..7f9f33ea483c --- /dev/null +++ b/code/__DEFINES/mob.dm @@ -0,0 +1 @@ +#define DEFAULT_MOB_STATUS_FLAGS CANKNOCKDOWN|CANPUSH|STATUS_FLAGS_DEBILITATE diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index d37c9185fa6d..8c93957c3ca0 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -221,6 +221,8 @@ #define TRAIT_HARDCORE "t_hardcore" /// If the mob is able to use the vulture rifle or spotting scope #define TRAIT_VULTURE_USER "t_vulture_user" +/// If the mob is currently loading a tutorial +#define TRAIT_IN_TUTORIAL "t_IN_TUTORIAL" /// If the mob is cloaked in any form #define TRAIT_CLOAKED "t_cloaked" @@ -297,6 +299,7 @@ GLOBAL_LIST_INIT(mob_traits, list( TRAIT_REAGENT_SCANNER, TRAIT_ABILITY_BURROWED, TRAIT_VULTURE_USER, + TRAIT_IN_TUTORIAL, )) /* @@ -403,6 +406,8 @@ GLOBAL_LIST(trait_name_map) #define TRAIT_SOURCE_JOB "t_s_job" ///Status trait forced by staff #define TRAIT_SOURCE_ADMIN "t_s_admin" +/// Status trait coming from a tutorial +#define TRAIT_SOURCE_TUTORIAL "t_s_tutorials" ///Status trait coming from equipment #define TRAIT_SOURCE_EQUIPMENT(slot) "t_s_equipment_[slot]" ///Status trait coming from skill diff --git a/code/__DEFINES/tutorial.dm b/code/__DEFINES/tutorial.dm new file mode 100644 index 000000000000..75dc7f6da21f --- /dev/null +++ b/code/__DEFINES/tutorial.dm @@ -0,0 +1,6 @@ +#define TUTORIAL_ATOM_FROM_TRACKING(path, varname) var##path/##varname = tracking_atoms[##path] + +#define TUTORIAL_CATEGORY_BASE "Base" // Shouldn't be used outside of base types +#define TUTORIAL_CATEGORY_SS13 "Space Station 13" +#define TUTORIAL_CATEGORY_MARINE "Marine" +#define TUTORIAL_CATEGORY_XENO "Xenomorph" diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm index 01a972485fa2..8b3d1b0a3809 100644 --- a/code/__HELPERS/level_traits.dm +++ b/code/__HELPERS/level_traits.dm @@ -1,4 +1,3 @@ - #define is_admin_level(z) SSmapping.level_trait(z, ZTRAIT_ADMIN) #define is_ground_level(z) SSmapping.level_trait(z, ZTRAIT_GROUND) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 7425046da7c7..9faa74354494 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -2088,3 +2088,15 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list( if(NORTHWEST) return list(NORTHWEST, NORTH, WEST) + +/// Returns TRUE if the target is somewhere that the game should not interact with if possible +/// In this case, admin Zs and tutorial areas +/proc/should_block_game_interaction(atom/target) + if(is_admin_level(target.z)) + return TRUE + + var/area/target_area = get_area(target) + if(target_area?.block_game_interaction) + return TRUE + + return FALSE diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index c6052da33199..8d77920a59cc 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -3,6 +3,7 @@ /obj/item/proc/attack_self(mob/user) SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK_SELF, src) if(flags_item & CAN_DIG_SHRAPNEL && ishuman(user)) dig_out_shrapnel(user) @@ -11,6 +12,7 @@ /atom/proc/attackby(obj/item/W, mob/living/user,list/mods) if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, mods) & COMPONENT_NO_AFTERATTACK) return TRUE + SEND_SIGNAL(user, COMSIG_MOB_PARENT_ATTACKBY, src, W) return FALSE /atom/movable/attackby(obj/item/W, mob/living/user) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index f87778355755..21dd804f09c4 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -29,7 +29,7 @@ if(ismob(target) || isVehicle(target)) if(isxeno(target) && SSticker.mode.check_xeno_late_join(src)) //if it's a xeno and all checks are alright, we are gonna try to take their body var/mob/living/carbon/xenomorph/xeno = target - if(xeno.stat == DEAD || is_admin_level(xeno.z) || xeno.aghosted) + if(xeno.stat == DEAD || should_block_game_interaction(xeno) || xeno.aghosted) to_chat(src, SPAN_WARNING("You cannot join as [xeno].")) do_observe(xeno) return FALSE diff --git a/code/_onclick/xeno.dm b/code/_onclick/xeno.dm index cc785f32f426..ad4ba9d72546 100644 --- a/code/_onclick/xeno.dm +++ b/code/_onclick/xeno.dm @@ -111,7 +111,7 @@ so that it doesn't double up on the delays) so that it applies the delay immedia if(alt_pressed && shift_pressed) if(istype(target, /mob/living/carbon/xenomorph)) var/mob/living/carbon/xenomorph/xeno = target - if(!QDELETED(xeno) && xeno.stat != DEAD && !is_admin_level(xeno.z) && xeno.check_state(TRUE) && xeno.hivenumber == hivenumber) + if(!QDELETED(xeno) && xeno.stat != DEAD && !should_block_game_interaction(xeno) && xeno.check_state(TRUE) && xeno.hivenumber == hivenumber) overwatch(xeno) next_move = world.time + 3 // Some minimal delay so this isn't crazy spammy return TRUE diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index c6d6f008acd6..2e11ba8a96cb 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -46,6 +46,7 @@ SUBSYSTEM_DEF(ticker) var/totalPlayers = 0 //used for pregame stats on statpanel var/totalPlayersReady = 0 //used for pregame stats on statpanel + var/tutorial_disabled = FALSE //zonenote /datum/controller/subsystem/ticker/Initialize(timeofday) load_mode() diff --git a/code/datums/ammo/ammo.dm b/code/datums/ammo/ammo.dm index 48a387e54d20..7a4006deee73 100644 --- a/code/datums/ammo/ammo.dm +++ b/code/datums/ammo/ammo.dm @@ -106,7 +106,7 @@ SHOULD_NOT_SLEEP(TRUE) return -/datum/ammo/proc/on_embed(mob/embedded_mob, obj/limb/target_organ) +/datum/ammo/proc/on_embed(mob/embedded_mob, obj/limb/target_organ, silent = FALSE) return /datum/ammo/proc/do_at_max_range(obj/projectile/P) diff --git a/code/datums/ammo/misc.dm b/code/datums/ammo/misc.dm index 607a6e517a7c..3aaba8443efb 100644 --- a/code/datums/ammo/misc.dm +++ b/code/datums/ammo/misc.dm @@ -178,7 +178,7 @@ accurate_range = 12 shell_speed = AMMO_SPEED_TIER_1 -/datum/ammo/souto/on_embed(mob/embedded_mob, obj/limb/target_organ) +/datum/ammo/souto/on_embed(mob/embedded_mob, obj/limb/target_organ, silent = FALSE) if(ishuman(embedded_mob) && !isyautja(embedded_mob)) if(istype(target_organ)) target_organ.embed(new can_type) diff --git a/code/datums/components/tutorial_status.dm b/code/datums/components/tutorial_status.dm new file mode 100644 index 000000000000..97b8d408bcb5 --- /dev/null +++ b/code/datums/components/tutorial_status.dm @@ -0,0 +1,25 @@ +/datum/component/tutorial_status + dupe_mode = COMPONENT_DUPE_UNIQUE + /// What the mob's current tutorial status is, displayed in the status panel + var/tutorial_status = "" + +/datum/component/tutorial_status/Initialize() + . = ..() + if(!ismob(parent)) + return COMPONENT_INCOMPATIBLE + +/datum/component/tutorial_status/RegisterWithParent() + ..() + RegisterSignal(parent, COMSIG_MOB_TUTORIAL_UPDATE_OBJECTIVE, PROC_REF(update_objective)) + RegisterSignal(parent, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) + +/datum/component/tutorial_status/proc/update_objective(datum/source, objective_text) + SIGNAL_HANDLER + + tutorial_status = objective_text + +/datum/component/tutorial_status/proc/get_status_tab_item(datum/source, list/status_tab_items) + SIGNAL_HANDLER + + if(tutorial_status) + status_tab_items += "Tutorial Objective: " + tutorial_status diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 933b547aa1f2..ae19a3044678 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -206,8 +206,8 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) sleep(40) var/list/jobs_to_check = GLOB.ROLES_CIC + GLOB.ROLES_AUXIL_SUPPORT + GLOB.ROLES_MISC + GLOB.ROLES_POLICE + GLOB.ROLES_ENGINEERING + GLOB.ROLES_REQUISITION + GLOB.ROLES_MEDICAL + GLOB.ROLES_MARINES - for(var/mob/living/carbon/human/H in GLOB.human_mob_list) - if(is_admin_level(H.z)) + for(var/mob/living/carbon/human/H as anything in GLOB.human_mob_list) + if(should_block_game_interaction(H)) continue if(H.job in jobs_to_check) manifest_inject(H) diff --git a/code/datums/effects/bleeding.dm b/code/datums/effects/bleeding.dm index e6cb184850d4..2171580a94db 100644 --- a/code/datums/effects/bleeding.dm +++ b/code/datums/effects/bleeding.dm @@ -19,6 +19,13 @@ if(L && istype(L)) limb = L +/datum/effects/bleeding/Destroy() + if(limb) + SEND_SIGNAL(limb, COMSIG_LIMB_STOP_BLEEDING, TRUE, FALSE) + limb.bleeding_effects_list -= src + limb = null + return ..() + /datum/effects/bleeding/validate_atom(atom/A) if(isobj(A)) return FALSE @@ -48,12 +55,6 @@ duration += damage * (blood_duration_multiplier / BLOOD_ADD_PENALTY) blood_loss += damage / (blood_loss_divider * BLOOD_ADD_PENALTY) //Make the first hit count, adding on bleeding has a penalty -/datum/effects/bleeding/Destroy() - if(limb) - limb.bleeding_effects_list -= src - return ..() - - /datum/effects/bleeding/external var/buffer_blood_loss = 0 diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 207310ac34c5..6a4276208d13 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -177,7 +177,7 @@ teleatom.visible_message(SPAN_DANGER("[teleatom] bounces off of the portal!")) return 0 - if(is_admin_level(destination.z)) + if(should_block_game_interaction(destination)) if(length(teleatom.search_contents_for(/obj/item/storage/backpack/holding))) teleatom.visible_message(SPAN_DANGER("The Bag of Holding bounces off of the portal!")) return 0 diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 205032f46a97..74f445f21597 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -44,8 +44,6 @@ msg_admin_niche("[key]/[ckey] has tried to transfer to deleted [new_character].") return - SEND_SIGNAL(current.client, COMSIG_CLIENT_MIND_TRANSFER, new_character) - if(current) current.mind = null //remove ourself from our old body's mind variable SSnano.nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user diff --git a/code/datums/status_effects/_status_effect_helpers.dm b/code/datums/status_effects/_status_effect_helpers.dm index 0ee952200610..02a4f9a5ccea 100644 --- a/code/datums/status_effects/_status_effect_helpers.dm +++ b/code/datums/status_effects/_status_effect_helpers.dm @@ -40,6 +40,7 @@ // Create the status effect with our mob + our arguments var/datum/status_effect/new_instance = new new_effect(arguments) + SEND_SIGNAL(src, COMSIG_LIVING_APPLY_EFFECT, new_instance) if(!QDELETED(new_instance)) return new_instance diff --git a/code/datums/supply_packs/black_market.dm b/code/datums/supply_packs/black_market.dm index 36d890e2b3d5..43e0358a96f9 100644 --- a/code/datums/supply_packs/black_market.dm +++ b/code/datums/supply_packs/black_market.dm @@ -101,7 +101,7 @@ Non-USCM items, from CLF, UPP, colonies, etc. Mostly combat-related. new /obj/item/clothing/head/helmet/marine/veteran/UPP(src) new /obj/item/clothing/under/marine/veteran/UPP(src) new /obj/item/clothing/suit/storage/marine/faction/UPP(src) - new /obj/item/clothing/shoes/marine/upp(src) + new /obj/item/clothing/shoes/marine/upp/knife(src) new /obj/item/clothing/gloves/marine/veteran(src) new /obj/item/storage/backpack/lightpack/five_slot(src) if(5) //freelancer diff --git a/code/datums/tutorial/_tutorial.dm b/code/datums/tutorial/_tutorial.dm new file mode 100644 index 000000000000..5423453bbdb9 --- /dev/null +++ b/code/datums/tutorial/_tutorial.dm @@ -0,0 +1,259 @@ +GLOBAL_LIST_EMPTY_TYPED(ongoing_tutorials, /datum/tutorial) + +/// A tutorial datum contains a set of instructions for a player tutorial, such as what to spawn, what's scripted to occur, and so on. +/datum/tutorial + /// What the tutorial is called, is player facing + var/name = "Base" + /// Internal ID of the tutorial, kept for save files + var/tutorial_id = "base" + /// A short 1-2 sentence description of the tutorial itself + var/desc = "" + /// What the tutorial's icon in the UI should look like + var/icon_state = "" + /// What category the tutorial should be under + var/category = TUTORIAL_CATEGORY_BASE + /// Ref to the bottom-left corner tile of the tutorial room + var/turf/bottom_left_corner + /// Ref to the turf reservation for this tutorial + var/datum/turf_reservation/reservation + /// Ref to the player who is doing the tutorial + var/mob/tutorial_mob + /// If the tutorial will be ending soon + var/tutorial_ending = FALSE + /// A dict of type:atom ref for some important junk that should be trackable + var/list/tracking_atoms = list() + /// What map template should be used for the tutorial + var/datum/map_template/tutorial/tutorial_template = /datum/map_template/tutorial/s12x12 + /// What is the parent path of this, to exclude from the tutorial menu + var/parent_path = /datum/tutorial + /// A dictionary of "bind_name" : "keybind_button". The inverse of `key_bindings` on a client's prefs + var/list/player_bind_dict = list() + +/datum/tutorial/Destroy(force, ...) + GLOB.ongoing_tutorials -= src + QDEL_NULL(reservation) // Its Destroy() handles releasing reserved turfs + + tutorial_mob = null // We don't delete it because the turf reservation will typically clean it up + + QDEL_LIST_ASSOC_VAL(tracking_atoms) + + return ..() + +/// The proc to begin doing everything related to the tutorial +/datum/tutorial/proc/start_tutorial(mob/starting_mob) + SHOULD_CALL_PARENT(TRUE) + + if(!starting_mob?.client) + return FALSE + + ADD_TRAIT(starting_mob, TRAIT_IN_TUTORIAL, TRAIT_SOURCE_TUTORIAL) + + tutorial_mob = starting_mob + + reservation = SSmapping.RequestBlockReservation(initial(tutorial_template.width), initial(tutorial_template.height)) + if(!reservation) + return FALSE + + var/turf/bottom_left_corner_reservation = locate(reservation.bottom_left_coords[1], reservation.bottom_left_coords[2], reservation.bottom_left_coords[3]) + var/datum/map_template/tutorial/template = new tutorial_template + template.load(bottom_left_corner_reservation, FALSE, TRUE) + var/obj/landmark = locate(/obj/effect/landmark/tutorial_bottom_left) in GLOB.landmarks_list + bottom_left_corner = get_turf(landmark) + qdel(landmark) + + if(!verify_template_loaded()) + abort_tutorial() + return FALSE + + generate_binds() + + GLOB.ongoing_tutorials |= src + var/area/tutorial_area = get_area(bottom_left_corner) + tutorial_area.update_base_lighting() // this will be entirely dark otherwise + init_map() + if(!tutorial_mob) + end_tutorial() + + return TRUE + +/// The proc used to end and clean up the tutorial +/datum/tutorial/proc/end_tutorial(completed = FALSE) + SHOULD_CALL_PARENT(TRUE) + + if(tutorial_mob) + remove_action(tutorial_mob, /datum/action/tutorial_end) // Just in case to make sure the client can't try and leave the tutorial while it's mid-cleanup + if(tutorial_mob.client?.prefs && completed) + tutorial_mob.client.prefs.completed_tutorials |= tutorial_id + tutorial_mob.client.prefs.save_character() + var/mob/new_player/new_player = new + if(!tutorial_mob.mind) + tutorial_mob.mind_initialize() + + tutorial_mob.mind.transfer_to(new_player) + + if(!QDELETED(src)) + qdel(src) + +/// Verify the template loaded fully and without error. +/datum/tutorial/proc/verify_template_loaded() + // We subtract 1 from x and y because the bottom left corner doesn't start at the walls. + var/turf/true_bottom_left_corner = locate( + reservation.bottom_left_coords[1], + reservation.bottom_left_coords[2], + reservation.bottom_left_coords[3], + ) + // We subtract 1 from x and y here because the bottom left corner counts as the first tile + var/turf/top_right_corner = locate( + true_bottom_left_corner.x + initial(tutorial_template.width) - 1, + true_bottom_left_corner.y + initial(tutorial_template.height) - 1, + true_bottom_left_corner.z + ) + for(var/turf/tile as anything in block(true_bottom_left_corner, top_right_corner)) + // For some reason I'm unsure of, the template will not always fully load, leaving some tiles to be space tiles. So, we check all tiles in the (small) tutorial area + // and tell start_tutorial to abort if there's any space tiles. + if(istype(tile, /turf/open/space)) + return FALSE + + return TRUE + +/// Something went very, very wrong during load so let's abort +/datum/tutorial/proc/abort_tutorial() + to_chat(tutorial_mob, SPAN_BOLDWARNING("Something went wrong during tutorial load, please try again!")) + end_tutorial(FALSE) + +/datum/tutorial/proc/add_highlight(atom/target, color = "#d19a02") + target.add_filter("tutorial_highlight", 2, list("type" = "outline", "color" = color, "size" = 1)) + +/datum/tutorial/proc/remove_highlight(atom/target) + target.remove_filter("tutorial_highlight") + +/datum/tutorial/proc/add_to_tracking_atoms(atom/reference) + tracking_atoms[reference.type] = reference + +/datum/tutorial/proc/remove_from_tracking_atoms(atom/reference) + tracking_atoms -= reference.type + +/// Broadcast a message to the player's screen +/datum/tutorial/proc/message_to_player(message) + playsound_client(tutorial_mob.client, 'sound/effects/radiostatic.ogg', tutorial_mob.loc, 25, FALSE) + tutorial_mob.play_screen_text(message, /atom/movable/screen/text/screen_text/command_order/tutorial, rgb(103, 214, 146)) + to_chat(tutorial_mob, SPAN_NOTICE(message)) + +/// Updates a player's objective in their status tab +/datum/tutorial/proc/update_objective(message) + SEND_SIGNAL(tutorial_mob, COMSIG_MOB_TUTORIAL_UPDATE_OBJECTIVE, message) + +/// Initialize the tutorial mob. +/datum/tutorial/proc/init_mob() + tutorial_mob.AddComponent(/datum/component/tutorial_status) + give_action(tutorial_mob, /datum/action/tutorial_end, null, null, src) + ADD_TRAIT(tutorial_mob, TRAIT_IN_TUTORIAL, TRAIT_SOURCE_TUTORIAL) + +/// Ends the tutorial after a certain amount of time. +/datum/tutorial/proc/tutorial_end_in(time = 5 SECONDS, completed = TRUE) + tutorial_ending = TRUE + addtimer(CALLBACK(src, PROC_REF(end_tutorial), completed), time) + +/// Initialize any objects that need to be in the tutorial area from the beginning. +/datum/tutorial/proc/init_map() + return + +/// Returns a turf offset by offset_x (left-to-right) and offset_y (up-to-down) +/datum/tutorial/proc/loc_from_corner(offset_x = 0, offset_y = 0) + RETURN_TYPE(/turf) + return locate(bottom_left_corner.x + offset_x, bottom_left_corner.y + offset_y, bottom_left_corner.z) + +/// Handle the player ghosting out +/datum/tutorial/proc/on_ghost(datum/source, mob/dead/observer/ghost) + SIGNAL_HANDLER + + var/mob/new_player/new_player = new + if(!ghost.mind) + ghost.mind_initialize() + + ghost.mind.transfer_to(new_player) + + end_tutorial(FALSE) + +/// A wrapper for signals to call end_tutorial() +/datum/tutorial/proc/signal_end_tutorial(datum/source) + SIGNAL_HANDLER + + end_tutorial(FALSE) + +/// Called whenever the tutorial_mob logs out +/datum/tutorial/proc/on_logout(datum/source) + SIGNAL_HANDLER + + if(tutorial_mob.aghosted) + return + + end_tutorial(FALSE) + +/// Generate a dictionary of button : action for use of referencing what keys to press +/datum/tutorial/proc/generate_binds() + if(!tutorial_mob.client?.prefs) + return + + for(var/bind in tutorial_mob.client.prefs.key_bindings) + var/action = tutorial_mob.client.prefs.key_bindings[bind] + // We presume the first action under a certain binding is the one we want. + if(action[1] in player_bind_dict) + player_bind_dict[action[1]] += bind + else + player_bind_dict[action[1]] = list(bind) + +/// Getter for player_bind_dict. Provide an action name like "North" or "quick_equip" +/datum/tutorial/proc/retrieve_bind(action_name) + if(!action_name) + return + + if(!(action_name in player_bind_dict)) + return "Undefined" + + return player_bind_dict[action_name][1] + +/datum/action/tutorial_end + name = "Stop Tutorial" + action_icon_state = "hologram_exit" + /// Weakref to the tutorial this is related to + var/datum/weakref/tutorial + +/datum/action/tutorial_end/New(Target, override_icon_state, datum/tutorial/selected_tutorial) + . = ..() + tutorial = WEAKREF(selected_tutorial) + +/datum/action/tutorial_end/action_activate() + if(!tutorial) + return + + var/datum/tutorial/selected_tutorial = tutorial.resolve() + if(selected_tutorial.tutorial_ending) + return + + selected_tutorial.end_tutorial() + + +/datum/map_template/tutorial + name = "Tutorial Zone (12x12)" + mappath = "maps/tutorial/tutorial_12x12.dmm" + width = 12 + height = 12 + +/datum/map_template/tutorial/s12x12 + +/datum/map_template/tutorial/s8x9 + name = "Tutorial Zone (8x9)" + mappath = "maps/tutorial/tutorial_8x9.dmm" + width = 8 + height = 9 + +/datum/map_template/tutorial/s8x9/no_baselight + name = "Tutorial Zone (8x9) (No Baselight)" + mappath = "maps/tutorial/tutorial_8x9_nb.dmm" + +/datum/map_template/tutorial/s7x7 + name = "Tutorial Zone (7x7)" + mappath = "maps/tutorial/tutorial_7x7.dmm" + width = 7 + height = 7 diff --git a/code/datums/tutorial/_tutorial_menu.dm b/code/datums/tutorial/_tutorial_menu.dm new file mode 100644 index 000000000000..42eb3f6aabfa --- /dev/null +++ b/code/datums/tutorial/_tutorial_menu.dm @@ -0,0 +1,83 @@ +/datum/tutorial_menu + /// List of ["name" = name, "tutorials" = ["name" = name, "path" = "path", "id" = tutorial_id]] + var/static/list/categories = list() + + +/datum/tutorial_menu/New() + if(!length(categories)) + var/list/categories_2 = list() + for(var/datum/tutorial/tutorial as anything in subtypesof(/datum/tutorial)) + if(initial(tutorial.parent_path) == tutorial) + continue + + if(!(initial(tutorial.category) in categories_2)) + categories_2[initial(tutorial.category)] = list() + + categories_2[initial(tutorial.category)] += list(list( + "name" = initial(tutorial.name), + "path" = "[tutorial]", + "id" = initial(tutorial.tutorial_id), + "description" = initial(tutorial.desc), + "image" = initial(tutorial.icon_state), + )) + + for(var/category in categories_2) + categories += list(list( + "name" = category, + "tutorials" = categories_2[category], + )) + + +/datum/tutorial_menu/proc/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TutorialMenu") + ui.open() + +/datum/tutorial_menu/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/tutorial), + ) + +/datum/tutorial_menu/ui_state(mob/user) + if(istype(get_area(user), /area/misc/tutorial)) + return GLOB.never_state + + return GLOB.new_player_state + + +/datum/tutorial_menu/ui_static_data(mob/user) + var/list/data = list() + + data["tutorial_categories"] = categories + if(user.client?.prefs) + data["completed_tutorials"] = user.client.prefs.completed_tutorials + else + data["completed_tutorials"] = list() + + return data + + +/datum/tutorial_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("select_tutorial") + var/datum/tutorial/path + if(!params["tutorial_path"]) + return + + path = text2path(params["tutorial_path"]) + + if(!path || !isnewplayer(usr)) + return + + if(HAS_TRAIT(usr, TRAIT_IN_TUTORIAL) || istype(get_area(usr), /area/misc/tutorial)) + to_chat(usr, SPAN_NOTICE("You are currently in a tutorial, or one is loading. Please be patient.")) + return + + path = new path + path.start_tutorial(usr) + return TRUE diff --git a/code/datums/tutorial/creating_a_tutorial.md b/code/datums/tutorial/creating_a_tutorial.md new file mode 100644 index 000000000000..96a7cb886820 --- /dev/null +++ b/code/datums/tutorial/creating_a_tutorial.md @@ -0,0 +1,96 @@ +# Tutorial Creation + +[ToC] + +## Step 1: Identifying the Goal + +Your first objective when making a tutorial should be to have a clear and concise vision of what you want the tutorial to convey to the user. People absorb information better in smaller chunks, so you should ideally keep a tutorial to one section of information at a time. + +For example, if you are making a tutorial for new CM players, it should be split into multiple parts like: + +- Basics +- Medical +- Weaponry +- Requisitions/Communication + +## Step 2: Coding + +For an example of the current code standards for tutorials, see [this](https://github.com/cmss13-devs/cmss13/pull/4442/files#diff-843b2f84360b9b932dfc960027992f2b5117667962bfa8da14f9a35f0179a926) file. + +The API for tutorials is designed to be very simple, so I'll go over all the base `/datum/tutorial` procs and some vars here: + +### Variables +- `name` + - This is the player-facing name of the tutorial. +- `tutorial_id` + - This is the back-end ID of the tutorial, used for save files. Try not to change a tutorial's ID after it's on the live server. +- `category` + - This is what category the tutorial should be under. Use the `TUTORIAL_CATEGORY_XXXX` macros. +- `tutorial_template` + - This is what type the map template of the tutorial should be. The default space is 12x12; ideally make it so it fits the given scale of the tutorial with some wiggle room for the player to move around. +- `parent_path` + - This is the top-most parent `/datum/tutorial` path, used to exclude abstract parents from the tutorial menu. For example, `/datum/tutorial/marine/basic` would have a `parent_path` of `/datum/tutorial/marine`, since that path is the top-most abstract path. + +### Procs +- `start_tutorial(mob/starting_mob)` + - This proc starts the tutorial, setting up the map template and player. This should be overridden with a parent call before any overridden code. +- `end_tutorial(completed = FALSE)` + - This proc ends the tutorial, sending the player back to the lobby and deleting the tutorial itself. A parent call on any subtypes should be at the end of the overridden segment. If `completed` is `TRUE`, then the tutorial will save as a completed one for the user. +- `add_highlight(atom/target, color = "#d19a02")` + - This proc adds a highlight filter around an atom, by default this color. Successive calls of highlight on the same atom will override the last. +- `remove_highlight(atom/target)` + - This proc removes the tutorial highlight from a target. +- `add_to_tracking_atoms(atom/reference)` + - This proc will add a reference to the tutorial's tracked atom dictionary. For what a tracked atom is, see Step 2.1. +- `remove_from_tracking_atoms(atom/reference)` + - This proc will remove a reference from the tutorial's tracked atom dictionary. For what a tracked atom is, see Step 2.1. +- `message_to_player(message)` + - This proc is the ideal way to communicate to a player. It is visually similar to overwatch messages or weather alerts, but appears and disappears much faster. The messages sent should be consise, but can have a degree of dialogue to them. +- `update_objective(message)` + - This proc is used to update the player's objective in their status panel. This should be only what is required and how to do it without any dialogue or extra text. +- `init_mob()` + - This proc is used to initialize the mob and set them up correctly. +- `init_map()` + - This proc does nothing by default, but can be overriden to spawn any atoms necessary for the tutorial from the very start. +- `tutorial_end_in(time = 5 SECONDS, completed = TRUE)` + - This proc will end the tutorial in the given time, defaulting to 5 seconds. Once the proc is called, the player will be booted back to the menu screen after the time is up. Will mark the tutorial as completed if `completed` is `TRUE` +- `loc_from_corner(offset_x = 0, offset_y = 0)` + - This proc will return a turf offset from the bottom left corner of the tutorial zone. Keep in mind, the bottom left corner is NOT on a wall, it is on the first floor on the bottom left corner. `offset_x` and `offset_y` are used to offset what turf you want to get, and should never be negative. + +## Step 2.1: Tracking Atoms +Naturally, you will need to keep track of certain objects or mobs for signal purposes, so the tracking system exists to fill that purpose. When you add a reference to the tracking atom list with `add_to_tracking_atoms()`, it gets put into a dictionary of `{path : reference}`. Because of this limitation, you should not track more than 1 object of the same type. To get a tracked atom, use of the `TUTORIAL_ATOM_FROM_TRACKING(path, varname)` macro is recommended. `path` should be replaced with the precise typepath of the tracked atom, and `varname` should be replaced with the variable name you wish to use. If an object is going to be deleted, remove it with `remove_from_tracking_atoms()` first. + +## Step 2.2: Scripting Format +Any proc whose main purpose is to advance the tutorial will be hereon referred to as a "script proc", as part of the entire "script". In the vast majority of cases, a script proc should hand off to the next using signals. Here is an example from `basic_marine.dm`: + +```javascript +/datum/tutorial/marine/basic/proc/on_cryopod_exit() + SIGNAL_HANDLER + + UnregisterSignal(tracking_atoms[/obj/structure/machinery/cryopod/tutorial], COMSIG_CRYOPOD_GO_OUT) + message_to_player("Good. You may notice the yellow \"food\" icon on the right side of your screen. Proceed to the outlined Food Vendor and vend the USCM Protein Bar.") + update_objective("Vend a USCM Protein Bar from the outlined ColMarTech Food Vendor.") + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial, food_vendor) + add_highlight(food_vendor) + food_vendor.req_access = list() + RegisterSignal(food_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND, PROC_REF(on_food_vend)) + +``` + +Line-by-line: + - `SIGNAL_HANDLER` is necessary as this proc was called via signal. + - Here we are unregistering the signal we registered in the previous proc to call this one, which in this case was waiting for the player to leave the tracked cryopod. + - Now, we tell the user the next step in the script, which is sent to their screen. + - Here we update the player's status panel with similar info to the above line, but far more condensed. + - Since we need to access the food vendor, we use the `TUTORIAL_ATOM_FROM_TRACKING()` macro to get a ref to it. + - We add a yellow outline to the food vendor to make it more clear what is wanted of the player + - The tutorial food vendors are locked to `ACCESS_TUTORIAL_LOCKED` by default, so here we remove that access requirement + - And finally, we register a signal for the next script proc, waiting for the user to vend something from the food vendor. + + +## Step 2.3: Quirks & Tips +- Generally speaking, you will want to create `/tutorial` subtypes of anything you add in the tutorial, should it need any special functions or similar. +- Restrict access from players as much as possible. As seen in the example above, restricting access to vendors and similar machines is recommended to prevent sequence breaking. Additionally, avoid adding anything that detracts from the tutorial itself. +- Attempt to avoid softlocks when possible. If someone could reasonably do something (e.g. firing every bullet they have at a ranged target and missing, now unable to kill them and progress) that could softlock them, then there should be a fallback of some sort. However, accomodations don't need to be made for people who purposefully cause a softlock; there's a "stop tutorial" button for a reason. +- When calling `message_to_player()` or `update_objective()`, **bold** the names of objects, items, and keybinds. +- Attempt to bind as many scripting signals to the `tutorial_mob` as possible. The nature of SS13 means something as sequence-heavy as this will always be fragile, so keeping the fragility we can affect to a minimum is imperative. diff --git a/code/datums/tutorial/marine/_marine.dm b/code/datums/tutorial/marine/_marine.dm new file mode 100644 index 000000000000..ceb0ba8ab550 --- /dev/null +++ b/code/datums/tutorial/marine/_marine.dm @@ -0,0 +1,21 @@ +/datum/tutorial/marine + category = TUTORIAL_CATEGORY_MARINE + parent_path = /datum/tutorial/marine + icon_state = "marine" + +/datum/tutorial/marine/init_mob() + var/mob/living/carbon/human/new_character = new(bottom_left_corner) + new_character.lastarea = get_area(bottom_left_corner) + + setup_human(new_character, tutorial_mob) + + //SSround_recording.recorder.track_player(new_character) //zonenote: check if necessary + + new_character.marine_snowflake_points = MARINE_TOTAL_SNOWFLAKE_POINTS + new_character.marine_buyable_categories = MARINE_CAN_BUY_ALL + + tutorial_mob = new_character + RegisterSignal(tutorial_mob, COMSIG_LIVING_GHOSTED, PROC_REF(on_ghost)) + RegisterSignal(tutorial_mob, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH, COMSIG_MOB_END_TUTORIAL), PROC_REF(signal_end_tutorial)) + RegisterSignal(tutorial_mob, COMSIG_MOB_LOGOUT, PROC_REF(on_logout)) + return ..() diff --git a/code/datums/tutorial/marine/basic_marine.dm b/code/datums/tutorial/marine/basic_marine.dm new file mode 100644 index 000000000000..be49977f7a48 --- /dev/null +++ b/code/datums/tutorial/marine/basic_marine.dm @@ -0,0 +1,208 @@ +/datum/tutorial/marine/basic + name = "Marine - Basic" + desc = "A tutorial to get you acquainted with the very basics of how to play a groundside marine role." + tutorial_id = "marine_basic_1" + tutorial_template = /datum/map_template/tutorial/s8x9/no_baselight + /// How many items need to be vended from the clothing vendor for the script to continue, if something vends 2 items (for example), increase this number by 2. + var/clothing_items_to_vend = 8 + /// How many items need to be vended from the gun vendor to continue + var/gun_items_to_vend = 2 + +// START OF SCRIPTING + +/datum/tutorial/marine/basic/start_tutorial(mob/starting_mob) + . = ..() + if(!.) + return + + var/obj/item/device/flashlight/flashlight = new(loc_from_corner(2, 3)) + flashlight.anchored = TRUE + flashlight.set_light_power(4) + flashlight.set_light_range(12) + flashlight.icon = null + flashlight.set_light_on(TRUE) + add_to_tracking_atoms(flashlight) + + init_mob() + message_to_player("This is the tutorial for marine rifleman. Leave the cryopod by pressing [retrieve_bind("North")] or [retrieve_bind("East")] to continue.") + update_objective("Exit the cryopod by pressing [retrieve_bind("North")] or [retrieve_bind("East")].") + RegisterSignal(tracking_atoms[/obj/structure/machinery/cryopod/tutorial], COMSIG_CRYOPOD_GO_OUT, PROC_REF(on_cryopod_exit)) + +/datum/tutorial/marine/basic/proc/on_cryopod_exit() + SIGNAL_HANDLER + + UnregisterSignal(tracking_atoms[/obj/structure/machinery/cryopod/tutorial], COMSIG_CRYOPOD_GO_OUT) + message_to_player("Good. You may notice the yellow \"food\" icon on the right side of your screen. Proceed to the outlined Food Vendor and vend the USCM Protein Bar.") + update_objective("Vend a USCM Protein Bar from the outlined ColMarTech Food Vendor.") + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial, food_vendor) + add_highlight(food_vendor) + food_vendor.req_access = list() + RegisterSignal(food_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND, PROC_REF(on_food_vend)) + +/datum/tutorial/marine/basic/proc/on_food_vend(datum/source, obj/structure/machinery/cm_vending/vendor, list/itemspec, mob/living/carbon/human/user) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial, food_vendor) + UnregisterSignal(food_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND) + remove_highlight(food_vendor) + food_vendor.req_access = list(ACCESS_TUTORIAL_LOCKED) + message_to_player("Now click on your character with the USCM Protein Bar in-hand until it is fully eaten. If you accidentally switched hands, switch back with [retrieve_bind("swap_hands")].") + update_objective("Eat the USCM Protein Bar by clicking on yourself while holding it, until it is gone.") + RegisterSignal(tutorial_mob, COMSIG_MOB_EATEN_SNACK, PROC_REF(on_foodbar_eaten)) + +/datum/tutorial/marine/basic/proc/on_foodbar_eaten(datum/source, obj/item/reagent_container/food/snacks/eaten_food) + SIGNAL_HANDLER + + if(!istype(eaten_food, /obj/item/reagent_container/food/snacks/protein_pack) || eaten_food.reagents.total_volume) + return + + UnregisterSignal(source, COMSIG_MOB_EATEN_SNACK) + message_to_player("Good. Now move to the outlined vendor and vend everything inside.") + update_objective("Vend everything inside the ColMarTech Automated Closet.") + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/clothing/tutorial, clothing_vendor) + add_highlight(clothing_vendor) + clothing_vendor.req_access = list() + RegisterSignal(clothing_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND, PROC_REF(on_clothing_vend)) + +/datum/tutorial/marine/basic/proc/on_clothing_vend(datum/source) + SIGNAL_HANDLER + + clothing_items_to_vend-- + if(clothing_items_to_vend <= 0) + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/clothing/tutorial, clothing_vendor) + UnregisterSignal(clothing_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND) + clothing_vendor.req_access = list(ACCESS_TUTORIAL_LOCKED) + remove_highlight(clothing_vendor) + message_to_player("Now, the room will darken. Take a flare out of your flare pouch by clicking on it with an empty hand, and then light it by using it in-hand with [retrieve_bind("activate_inhand")].") + update_objective("Click on your flare pouch to remove a flare before using it in-hand.") + var/obj/item/storage/pouch/flare/flare_pouch = locate(/obj/item/storage/pouch/flare) in tutorial_mob.contents + if(flare_pouch) + add_highlight(flare_pouch) + RegisterSignal(tutorial_mob, COMSIG_MOB_ITEM_ATTACK_SELF, PROC_REF(on_flare_light)) + addtimer(CALLBACK(src, PROC_REF(dim_room)), 2.5 SECONDS) + +/datum/tutorial/marine/basic/proc/on_flare_light(datum/source, obj/item/used) + SIGNAL_HANDLER + + if(!istype(used, /obj/item/device/flashlight/flare)) + return + + UnregisterSignal(tutorial_mob, COMSIG_MOB_ITEM_ATTACK_SELF) + var/obj/item/storage/pouch/flare/flare_pouch = locate(/obj/item/storage/pouch/flare) in tutorial_mob.contents + if(flare_pouch) + remove_highlight(flare_pouch) + + message_to_player("Now throw the flare by clicking on a nearby tile, or dropping it with [retrieve_bind("drop_item")].") + update_objective("Throw the flare by clicking on a nearby tile, or dropping it with [retrieve_bind("drop_item")].") + RegisterSignal(tutorial_mob, COMSIG_MOB_ITEM_DROPPED, PROC_REF(on_flare_throw)) + +/datum/tutorial/marine/basic/proc/on_flare_throw(datum/source, obj/item/thrown) + SIGNAL_HANDLER + + if(!istype(thrown, /obj/item/device/flashlight/flare)) + return + + UnregisterSignal(tutorial_mob, COMSIG_MOB_ITEM_DROPPED) + message_to_player("Good. Now, the room will brighten again. Proceed to the highlighted vendor and vend a M41A Pulse Rifle MK2, along with a magazine.") + update_objective("Vend everything from the ColMarTech Automated Weapons Rack.") + addtimer(CALLBACK(src, PROC_REF(brighten_room)), 1.5 SECONDS) + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial, gun_vendor) + gun_vendor.req_access = list() + add_highlight(gun_vendor) + RegisterSignal(gun_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND, PROC_REF(on_gun_vend)) + +/datum/tutorial/marine/basic/proc/on_gun_vend(datum/source) + SIGNAL_HANDLER + + gun_items_to_vend-- + if(gun_items_to_vend <= 0) + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial, gun_vendor) + gun_vendor.req_access = list(ACCESS_TUTORIAL_LOCKED) + remove_highlight(gun_vendor) + UnregisterSignal(gun_vendor, COMSIG_VENDOR_SUCCESSFUL_VEND) + message_to_player("Now insert the magazine into the M41A Pulse Rifle by having the magazine in your active hand and hitting the Pulse Rifle with it. If it is in the off-hand, switch with [retrieve_bind("swap_hands")].") + update_objective("Insert the M41A magazine by hitting the M41A Pulse Rifle with it.") + RegisterSignal(tutorial_mob, COMSIG_MOB_RELOADED_GUN, PROC_REF(on_magazine_insert)) + +/datum/tutorial/marine/basic/proc/on_magazine_insert(datum/source, atom/attacked, obj/item/attacked_with) + SIGNAL_HANDLER + + UnregisterSignal(tutorial_mob, COMSIG_MOB_RELOADED_GUN) + message_to_player("Good. Now wield your gun by using it in-hand with [retrieve_bind("activate_inhand")].") + update_objective("Wield your gun with two hands by pressing [retrieve_bind("activate_inhand")] with the gun in your main hand.") + RegisterSignal(tutorial_mob, COMSIG_MOB_ITEM_ATTACK_SELF, PROC_REF(on_gun_wield)) + +/datum/tutorial/marine/basic/proc/on_gun_wield(datum/source, obj/item/used) + SIGNAL_HANDLER + + if(!istype(used, /obj/item/weapon/gun/rifle/m41a)) + return + + UnregisterSignal(tutorial_mob, COMSIG_MOB_ITEM_ATTACK_SELF) + message_to_player("Now, shoot at the highlighted Xenomorph until it dies.") + update_objective("Shoot at the Xenomorph until it dies.") + var/mob/living/carbon/xenomorph/drone/tutorial/xeno_dummy = new(loc_from_corner(4, 5)) + add_to_tracking_atoms(xeno_dummy) + add_highlight(xeno_dummy, COLOUR_VIVID_RED) + RegisterSignal(xeno_dummy, COMSIG_MOB_DEATH, PROC_REF(on_xeno_death)) + RegisterSignal(tutorial_mob, COMSIG_MOB_GUN_EMPTY, PROC_REF(on_magazine_empty)) // I'd like to prevent unwilling softlocks as much as I can + +/// Non-contiguous part of the script, called if the user manages to run out of ammo in the gun without the xeno dying +/datum/tutorial/marine/basic/proc/on_magazine_empty(obj/item/weapon/gun/empty_gun) + SIGNAL_HANDLER + + UnregisterSignal(tutorial_mob, COMSIG_MOB_GUN_EMPTY) + message_to_player("Your gun's out of ammo. Go grab some more from the Weaponry Vendor and kill the Xenomorph.") + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial, gun_vendor) + gun_vendor.req_access = list() + gun_vendor.load_ammo() // 99 magazines, to make sure that the xeno dies + +/datum/tutorial/marine/basic/proc/on_xeno_death(datum/source) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/xenomorph/drone/tutorial, xeno_dummy) + UnregisterSignal(xeno_dummy, COMSIG_MOB_DEATH) + UnregisterSignal(tutorial_mob, COMSIG_MOB_GUN_EMPTY) + remove_highlight(xeno_dummy) + addtimer(CALLBACK(src, PROC_REF(disappear_xeno)), 2.5 SECONDS) + message_to_player("Very good. This is the end of the tutorial, proceed to the next one to learn the basics of Medical. You will be sent back to the lobby screen momentarily.") + update_objective("") + tutorial_end_in(7.5 SECONDS, TRUE) + + +// END OF SCRIPTING +// START OF SCRIPT HELPERS + +/datum/tutorial/marine/basic/proc/dim_room() + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/device/flashlight, flashlight) + flashlight.set_light_on(FALSE) + +/datum/tutorial/marine/basic/proc/brighten_room() + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/device/flashlight, flashlight) + flashlight.set_light_on(TRUE) + +/datum/tutorial/marine/basic/proc/disappear_xeno() + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/xenomorph/drone/tutorial, xeno_dummy) + animate(xeno_dummy, time = 5 SECONDS, alpha = 0) + remove_from_tracking_atoms(xeno_dummy) + QDEL_IN(xeno_dummy, 5.5 SECONDS) + +// END OF SCRIPT HELPERS + +/datum/tutorial/marine/basic/init_mob() + . = ..() + arm_equipment(tutorial_mob, /datum/equipment_preset/tutorial) + + TUTORIAL_ATOM_FROM_TRACKING(/obj/structure/machinery/cryopod/tutorial, tutorial_pod) + tutorial_pod.go_in_cryopod(tutorial_mob, TRUE, FALSE) + + +/datum/tutorial/marine/basic/init_map() + var/obj/structure/machinery/cryopod/tutorial/tutorial_pod = new(bottom_left_corner) + add_to_tracking_atoms(tutorial_pod) + var/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial/food_vendor = new(loc_from_corner(0, 2)) + add_to_tracking_atoms(food_vendor) + var/obj/structure/machinery/cm_vending/clothing/tutorial/clothing_vendor = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(clothing_vendor) + var/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial/gun_vendor = new(loc_from_corner(0, 5)) + add_to_tracking_atoms(gun_vendor) diff --git a/code/datums/tutorial/marine/medical_basic.dm b/code/datums/tutorial/marine/medical_basic.dm new file mode 100644 index 000000000000..3a42a6d2ecc2 --- /dev/null +++ b/code/datums/tutorial/marine/medical_basic.dm @@ -0,0 +1,174 @@ +/datum/tutorial/marine/medical_basic + name = "Marine - Medical (Basic)" + desc = "Learn how to treat common injuries you may face as a marine." + tutorial_id = "marine_medical_1" + tutorial_template = /datum/map_template/tutorial/s7x7 + +// START OF SCRIPTING + +/datum/tutorial/marine/medical_basic/start_tutorial(mob/starting_mob) + . = ..() + if(!.) + return + + init_mob() + message_to_player("This is the tutorial for the basics of medical that you will need to know for playing a marine role.") + addtimer(CALLBACK(src, PROC_REF(brute_tutorial)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/brute_tutorial() + message_to_player("The first kind of damage is Brute, the most common kind. It represents physical trauma from things like punches, weapons, or guns.") + var/mob/living/living_mob = tutorial_mob + living_mob.adjustBruteLoss(10) + addtimer(CALLBACK(src, PROC_REF(brute_tutorial_2)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/brute_tutorial_2() + message_to_player("You can observe if you have Brute or Burn damage by clicking on yourself with an empty hand on help intent.") + update_objective("Click on yourself with an empty hand.") + RegisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN, PROC_REF(on_health_examine)) + +/datum/tutorial/marine/medical_basic/proc/on_health_examine(datum/source, mob/living/carbon/human/attacked_mob) + SIGNAL_HANDLER + + if(attacked_mob != tutorial_mob) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN) + message_to_player("Good. Now, you have taken some brute damage. Bicaridine is used to fix brute over time. Pick up the bicaridine EZ autoinjector and use it in-hand.") + update_objective("Inject yourself with the bicaridine injector.") + var/obj/item/reagent_container/hypospray/autoinjector/bicaridine/skillless/one_use/brute_injector = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(brute_injector) + add_highlight(brute_injector) + RegisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED, PROC_REF(on_brute_inject)) + +/datum/tutorial/marine/medical_basic/proc/on_brute_inject(datum/source, obj/item/reagent_container/hypospray/injector) + SIGNAL_HANDLER + + if(!istype(injector, /obj/item/reagent_container/hypospray/autoinjector/bicaridine/skillless/one_use)) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED) + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/reagent_container/hypospray/autoinjector/bicaridine/skillless/one_use, brute_injector) + remove_highlight(brute_injector) + message_to_player("All medicines take time to work after injection. Next is Burn damage. It is obtained from things like acid or being set on fire.") + update_objective("") + var/mob/living/living_mob = tutorial_mob + living_mob.adjustFireLoss(10) + addtimer(CALLBACK(src, PROC_REF(burn_tutorial)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/burn_tutorial() + message_to_player("Kelotane is used to fix burn over time. Inject yourself with the kelotane EZ autoinjector.") + update_objective("Inject yourself with the kelotane injector.") + var/obj/item/reagent_container/hypospray/autoinjector/kelotane/skillless/one_use/burn_injector = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(burn_injector) + add_highlight(burn_injector) + RegisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED, PROC_REF(on_burn_inject)) + + +/datum/tutorial/marine/medical_basic/proc/on_burn_inject(datum/source, obj/item/reagent_container/hypospray/injector) + SIGNAL_HANDLER + + if(!istype(injector, /obj/item/reagent_container/hypospray/autoinjector/kelotane/skillless/one_use)) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED) + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/reagent_container/hypospray/autoinjector/kelotane/skillless/one_use, burn_injector) + remove_highlight(burn_injector) + message_to_player("Good. Now, when you normally take damage, you will also feel pain. Pain slows you down and can knock you out if left unchecked.") + update_objective("") + var/mob/living/living_mob = tutorial_mob + living_mob.pain.apply_pain(PAIN_CHESTBURST_STRONG) + addtimer(CALLBACK(src, PROC_REF(pain_tutorial)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/pain_tutorial() + message_to_player("Tramadol is used to reduce your pain. Inject yourself with the tramadol EZ autoinjector.") + update_objective("Inject yourself with the tramadol injector.") + var/obj/item/reagent_container/hypospray/autoinjector/tramadol/skillless/one_use/pain_injector = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(pain_injector) + add_highlight(pain_injector) + RegisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED, PROC_REF(on_pain_inject)) + +/datum/tutorial/marine/medical_basic/proc/on_pain_inject(datum/source, obj/item/reagent_container/hypospray/injector) + SIGNAL_HANDLER + + if(!istype(injector, /obj/item/reagent_container/hypospray/autoinjector/tramadol/skillless/one_use)) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_HYPOSPRAY_INJECTED) + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/reagent_container/hypospray/autoinjector/tramadol/skillless/one_use, pain_injector) + remove_highlight(pain_injector) + message_to_player("Good. Keep in mind that you can overdose on chemicals, so don't inject yourself with the same chemical too much too often. In the field, injectors have 3 uses.") + update_objective("Don't overdose! Generally, 3 injections of a chemical will overdose you.") + var/mob/living/living_mob = tutorial_mob + living_mob.pain.apply_pain(-PAIN_CHESTBURST_STRONG) // just to make sure + addtimer(CALLBACK(src, PROC_REF(bleed_tutorial)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/bleed_tutorial() + message_to_player("You can sometimes start bleeding from things like bullets or slashes. Losing blood will accumulate oxygen damage, eventually causing death.") + update_objective("") + var/mob/living/carbon/human/human_mob = tutorial_mob + var/obj/limb/chest/mob_chest = locate(/obj/limb/chest) in human_mob.limbs + mob_chest.add_bleeding(damage_amount = 15) + addtimer(CALLBACK(src, PROC_REF(bleed_tutorial_2)), 4 SECONDS) + +/datum/tutorial/marine/medical_basic/proc/bleed_tutorial_2() + message_to_player("Bleeding wounds can clot themselves over time, or you can fix it quickly with gauze. Pick up the gauze and click on yourself while targeting your chest.") + update_objective("Gauze your chest, or let it clot on its own.") + var/obj/item/stack/medical/bruise_pack/two/bandage = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(bandage) + add_highlight(bandage) + var/mob/living/carbon/human/human_mob = tutorial_mob + var/obj/limb/chest/mob_chest = locate(/obj/limb/chest) in human_mob.limbs + RegisterSignal(mob_chest, COMSIG_LIMB_STOP_BLEEDING, PROC_REF(on_chest_bleed_stop)) + +/datum/tutorial/marine/medical_basic/proc/on_chest_bleed_stop(datum/source, external, internal) + SIGNAL_HANDLER + + // If you exit on this step, your limbs get deleted, which stops the bleeding, which progresses the tutorial despite it ending + if(!tutorial_mob || QDELETED(src)) + return + + var/mob/living/carbon/human/human_mob = tutorial_mob + var/obj/limb/chest/mob_chest = locate(/obj/limb/chest) in human_mob.limbs + UnregisterSignal(mob_chest, COMSIG_LIMB_STOP_BLEEDING) + + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/stack/medical/bruise_pack/two, bandage) + remove_from_tracking_atoms(bandage) + remove_highlight(bandage) + qdel(bandage) + + message_to_player("Good. Sometimes, a bullet or bone shard can result in you getting shrapnel, dealing damage over time. Pick up the knife and use it in-hand to remove the shrapnel.") + update_objective("Remove your shrapnel by using the knife in-hand.") + var/mob/living/living_mob = tutorial_mob + living_mob.pain.feels_pain = FALSE + + var/obj/item/attachable/bayonet/knife = new(loc_from_corner(0, 4)) + add_to_tracking_atoms(knife) + add_highlight(knife) + + var/obj/item/shard/shrapnel/tutorial/shrapnel = new + shrapnel.on_embed(tutorial_mob, mob_chest, TRUE) + + RegisterSignal(tutorial_mob, COMSIG_HUMAN_SHRAPNEL_REMOVED, PROC_REF(on_shrapnel_removed)) + +/datum/tutorial/marine/medical_basic/proc/on_shrapnel_removed() + SIGNAL_HANDLER + + UnregisterSignal(tutorial_mob, COMSIG_HUMAN_SHRAPNEL_REMOVED) + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/attachable/bayonet, knife) + remove_highlight(knife) + message_to_player("Good. This is the end of the basic marine medical tutorial. The tutorial will end shortly.") + update_objective("Tutorial completed.") + tutorial_end_in(5 SECONDS) + +// END OF SCRIPTING +// START OF SCRIPT HELPERS + +// END OF SCRIPT HELPERS + +/datum/tutorial/marine/medical_basic/init_mob() + . = ..() + arm_equipment(tutorial_mob, /datum/equipment_preset/tutorial/fed) + + +/datum/tutorial/marine/medical_basic/init_map() + new /obj/structure/surface/table/almayer(loc_from_corner(0, 4)) diff --git a/code/datums/tutorial/ss13/_ss13.dm b/code/datums/tutorial/ss13/_ss13.dm new file mode 100644 index 000000000000..53cf5c918ee9 --- /dev/null +++ b/code/datums/tutorial/ss13/_ss13.dm @@ -0,0 +1,41 @@ +/datum/tutorial/ss13 + category = TUTORIAL_CATEGORY_SS13 + parent_path = /datum/tutorial/ss13 + icon_state = "ss13" + +/datum/tutorial/ss13/init_mob() + tutorial_mob.close_spawn_windows() + + var/mob/living/carbon/human/new_character = new(bottom_left_corner) + new_character.lastarea = get_area(bottom_left_corner) + + tutorial_mob.client.prefs.copy_all_to(new_character) + + if(tutorial_mob.client.prefs.be_random_body) + var/datum/preferences/rand_prefs = new() + rand_prefs.randomize_appearance(new_character) + + new_character.job = tutorial_mob.job + new_character.name = tutorial_mob.real_name + new_character.voice = tutorial_mob.real_name + + new_character.sec_hud_set_ID() + new_character.hud_set_squad() + + SSround_recording.recorder.track_player(new_character) + + if(tutorial_mob.mind) + tutorial_mob.mind_initialize() + tutorial_mob.mind.transfer_to(new_character, TRUE) + tutorial_mob.mind.setup_human_stats() + + INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) + INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) + INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_hair)) + + tutorial_mob = new_character + RegisterSignal(tutorial_mob, COMSIG_LIVING_GHOSTED, PROC_REF(on_ghost)) + RegisterSignal(tutorial_mob, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH, COMSIG_MOB_END_TUTORIAL), PROC_REF(signal_end_tutorial)) + RegisterSignal(tutorial_mob, COMSIG_MOB_LOGOUT, PROC_REF(on_logout)) + arm_equipment(tutorial_mob, /datum/equipment_preset/tutorial/fed) + return ..() diff --git a/code/datums/tutorial/ss13/basic_ss13.dm b/code/datums/tutorial/ss13/basic_ss13.dm new file mode 100644 index 000000000000..65bb0cac94f4 --- /dev/null +++ b/code/datums/tutorial/ss13/basic_ss13.dm @@ -0,0 +1,84 @@ +/datum/tutorial/ss13/basic + name = "Space Station 13 - Basic" + desc = "Learn the very basics of Space Station 13. Recommended if you haven't played before." + tutorial_id = "ss13_basic_1" + tutorial_template = /datum/map_template/tutorial/s7x7 + +// START OF SCRIPTING + +/datum/tutorial/ss13/basic/start_tutorial(mob/starting_mob) + . = ..() + if(!.) + return + + init_mob() + message_to_player("This is the tutorial for the basics of Space Station 13. Any current instructions can be found in the top-right corner, in the status panel.") + update_objective("Here's where it'll be!") + + addtimer(CALLBACK(src, PROC_REF(require_move)), 4 SECONDS) // check if this is a good amount of time + +/datum/tutorial/ss13/basic/proc/require_move() + message_to_player("Now, move in any direction using [retrieve_bind("North")], [retrieve_bind("West")], [retrieve_bind("South")], or [retrieve_bind("East")].") + update_objective("Move in any direction using the [retrieve_bind("North")][retrieve_bind("West")][retrieve_bind("South")][retrieve_bind("East")] keys.") + + RegisterSignal(tutorial_mob, COMSIG_MOB_MOVE_OR_LOOK, PROC_REF(on_move)) + +/datum/tutorial/ss13/basic/proc/on_move(datum/source, actually_moving, direction, specific_direction) + SIGNAL_HANDLER + + if(!actually_moving) // The mob just looked in a different dir instead of moving + return + + UnregisterSignal(tutorial_mob, COMSIG_MOB_MOVE_OR_LOOK) + + message_to_player("Good. Now, switch hands with [retrieve_bind("swap_hands")].") + update_objective("Switch hands with [retrieve_bind("swap_hands")].") + + RegisterSignal(tutorial_mob, COMSIG_MOB_SWAPPED_HAND, PROC_REF(on_hand_swap)) + +/datum/tutorial/ss13/basic/proc/on_hand_swap(datum/source) + SIGNAL_HANDLER + + UnregisterSignal(tutorial_mob, COMSIG_MOB_SWAPPED_HAND) + + message_to_player("Good. Now, pick up the satchel that just spawned and equip it with [retrieve_bind("quick_equip")].") + update_objective("Pick up the satchel and equip it with [retrieve_bind("quick_equip")].") + + var/obj/item/storage/backpack/marine/satchel/satchel = new(loc_from_corner(2, 2)) + add_to_tracking_atoms(satchel) + add_highlight(satchel) + + RegisterSignal(tutorial_mob, COMSIG_HUMAN_EQUIPPED_ITEM, PROC_REF(on_satchel_equip)) + +/datum/tutorial/ss13/basic/proc/on_satchel_equip(datum/source, obj/item/equipped, slot) + SIGNAL_HANDLER + + if(!istype(equipped, /obj/item/storage/backpack/marine/satchel) || (slot != WEAR_BACK)) + return + + UnregisterSignal(tutorial_mob, COMSIG_HUMAN_EQUIPPED_ITEM) + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/storage/backpack/marine/satchel, satchel) + remove_highlight(satchel) + message_to_player("Now, say anything by pressing [retrieve_bind("Say")].") + update_objective("Speak using [retrieve_bind("Say")].") + + RegisterSignal(tutorial_mob, COMSIG_LIVING_SPEAK, PROC_REF(on_speak)) + +/datum/tutorial/ss13/basic/proc/on_speak(datum/source) + SIGNAL_HANDLER + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_SPEAK) + message_to_player("Excellent. The next tutorial will cover intents. The tutorial will end shortly.") + update_objective("") + tutorial_end_in(5 SECONDS, TRUE) + +// END OF SCRIPTING +// START OF SCRIPT HELPERS + + + +// END OF SCRIPT HELPERS + +/datum/tutorial/ss13/basic/init_mob() + . = ..() + tutorial_mob.forceMove(loc_from_corner(2, 1)) diff --git a/code/datums/tutorial/ss13/intents.dm b/code/datums/tutorial/ss13/intents.dm new file mode 100644 index 000000000000..d67b2ac1b4a1 --- /dev/null +++ b/code/datums/tutorial/ss13/intents.dm @@ -0,0 +1,113 @@ +/datum/tutorial/ss13/intents + name = "Space Station 13 - Intents" + desc = "Learn how the intent interaction system works." + icon_state = "intents" + tutorial_id = "ss13_intents_1" + tutorial_template = /datum/map_template/tutorial/s7x7 + +// START OF SCRIPTING + +/datum/tutorial/ss13/intents/start_tutorial(mob/starting_mob) + . = ..() + if(!.) + return + + init_mob() + message_to_player("This is the tutorial for the intents system of Space Station 13. The highlighted UI element in the bottom-right corner is your current intent.") + var/datum/hud/human/human_hud = tutorial_mob.hud_used + add_highlight(human_hud.action_intent) + + addtimer(CALLBACK(src, PROC_REF(require_help)), 4.5 SECONDS) + +/datum/tutorial/ss13/intents/proc/require_help() + tutorial_mob.a_intent_change(INTENT_DISARM) + message_to_player("Your intent has been changed off of help. Change back to it by pressing [retrieve_bind("select_help_intent")].") + update_objective("Change to help intent by pressing [retrieve_bind("select_help_intent")].") + + RegisterSignal(tutorial_mob, COMSIG_MOB_INTENT_CHANGE, PROC_REF(on_help_intent)) + +/datum/tutorial/ss13/intents/proc/on_help_intent(datum/source, new_intent) + SIGNAL_HANDLER + + if(new_intent != INTENT_HELP) + return + + UnregisterSignal(tutorial_mob, COMSIG_MOB_INTENT_CHANGE) + + var/mob/living/carbon/human/dummy/tutorial/tutorial_dummy = new(loc_from_corner(2, 3)) + add_to_tracking_atoms(tutorial_dummy) + + message_to_player("The first of the intents is help intent. It is used to harmlessly touch others, put out fire, give CPR, and similar. Click on the Test Dummy to give them a pat on the back.") + update_objective("Click on the dummy on help intent.") + + RegisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN, PROC_REF(on_help_attack)) + +/datum/tutorial/ss13/intents/proc/on_help_attack(datum/source, mob/living/carbon/human/attacked_mob) + SIGNAL_HANDLER + + if((attacked_mob == src) || (tutorial_mob.a_intent != INTENT_HELP)) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN) + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human/dummy/tutorial, tutorial_dummy) + tutorial_dummy.status_flags = DEFAULT_MOB_STATUS_FLAGS + REMOVE_TRAIT(tutorial_dummy, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + tutorial_dummy.anchored = FALSE + + message_to_player("The second intent is disarm, selectable with [retrieve_bind("select_disarm_intent")]. Disarm is used to shove people, which can make them drop items or fall to the ground. Shove the Test Dummy until it falls over.") + update_objective("Switch to disarm intent by pressing [retrieve_bind("select_disarm_intent")] and shove the dummy to the ground.") + + RegisterSignal(tutorial_dummy, COMSIG_LIVING_APPLY_EFFECT, PROC_REF(on_shove_down)) + +/datum/tutorial/ss13/intents/proc/on_shove_down(datum/source, datum/status_effect/new_effect) + SIGNAL_HANDLER + + if(!istype(new_effect, /datum/status_effect/incapacitating/knockdown)) + return + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human/dummy/tutorial, tutorial_dummy) + UnregisterSignal(tutorial_dummy, COMSIG_LIVING_APPLY_EFFECT) + tutorial_dummy.rejuvenate() + + message_to_player("The third intent is grab. Grab is used to grab people in either a passive, aggressive, or chokehold grab. Grab successively to \"upgrade\" your grab. Aggressively grab the Test Dummy.") + update_objective("Aggressively grab the dummy by grabbing them twice.") + + + RegisterSignal(tutorial_dummy, COMSIG_MOB_AGGRESSIVELY_GRABBED, PROC_REF(on_aggrograb)) + +/datum/tutorial/ss13/intents/proc/on_aggrograb(datum/source, mob/living/carbon/human/choker) + SIGNAL_HANDLER + + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human/dummy/tutorial, tutorial_dummy) + UnregisterSignal(tutorial_dummy, COMSIG_MOB_AGGRESSIVELY_GRABBED) + + message_to_player("The final intent is harm. Harm is used to injure people with your fists or a melee weapon. Punch the Test Dummy with an empty hand.") + update_objective("Attack the dummy with an empty hand.") + + RegisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN, PROC_REF(on_harm_attack)) + +/datum/tutorial/ss13/intents/proc/on_harm_attack(datum/source, mob/living/carbon/human/attacked_mob) + SIGNAL_HANDLER + + if((attacked_mob == src) || (tutorial_mob.a_intent != INTENT_HARM)) + return + + UnregisterSignal(tutorial_mob, COMSIG_LIVING_ATTACKHAND_HUMAN) + TUTORIAL_ATOM_FROM_TRACKING(/mob/living/carbon/human/dummy/tutorial, tutorial_dummy) + tutorial_dummy.status_flags = GODMODE + + message_to_player("Excellent. Those are the basics of the intent system. The tutorial will end shortly.") + update_objective("") + + tutorial_end_in(5 SECONDS, TRUE) + +// END OF SCRIPTING +// START OF SCRIPT HELPERS + + + +// END OF SCRIPT HELPERS + +/datum/tutorial/ss13/intents/init_mob() + . = ..() + tutorial_mob.forceMove(loc_from_corner(2, 0)) diff --git a/code/datums/tutorial/tutorial_example.dm b/code/datums/tutorial/tutorial_example.dm new file mode 100644 index 000000000000..9042346f8d39 --- /dev/null +++ b/code/datums/tutorial/tutorial_example.dm @@ -0,0 +1,74 @@ +/datum/tutorial/marine/example + name = "Example Tutorial" + tutorial_id = "example" // This won't show up in the list, so this'll be irrelevant anyway. + category = TUTORIAL_CATEGORY_BASE + parent_path = /datum/tutorial/marine/example + +// START OF SCRIPTING + +/datum/tutorial/marine/example/start_tutorial(mob/starting_mob) + // Here, we're calling parent and checking its return value. If it has a falsey one (as done by !.), then something went wrong and we should abort + // There isn't really a reason that you _shouldn't_ have this + . = ..() + if(!.) + return + + // Init_mob() isn't called by default, so we call it here + init_mob() + // As is standard, we give a message to the player and update their status panel with what we want done. + message_to_player("This is an example tutorial. Perform any emote to continue.") + update_objective("Do any emote.") + // This makes the player (tutorial_mob) listen for the COMSIG_MOB_EMOTE event, which will then call on_emote() when it hears it. + RegisterSignal(tutorial_mob, COMSIG_MOB_EMOTE, PROC_REF(on_emote)) + +/datum/tutorial/marine/example/proc/on_emote(datum/source) + // With any proc called via signal (see the RegisterSignal line above for details), we add SIGNAL_HANDLER to it. + SIGNAL_HANDLER + + // Now that we've gotten the signal and started the script, we want to immediately stop listening for it. + UnregisterSignal(tutorial_mob, COMSIG_MOB_EMOTE) + message_to_player("Good. Now, pick up that can of Weyland-Yutani Aspen Beer.") + update_objective("Pick up that can.") + // This macro takes a specific type path (the same used in init_map()) and a variable name to retrieve an object from the tracked object list + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/reagent_container/food/drinks/cans/aspen, beer_can) + // Now we're adding a yellow highlight around the can to make sure people know what we're talking about + add_highlight(beer_can) + // Now, we always prefer to register signals on the tutorial_mob (as opposed to the beer_can) whenever possible + RegisterSignal(tutorial_mob, COMSIG_MOB_PICKUP_ITEM, PROC_REF(on_can_pickup)) + +/// We get these arguments from the signal's definition. If you have VSC, ctrl+click on COMSIG_MOB_PICKUP_ITEM above. When dealing with a signal proc, `datum/source` is always the first argument, then any added ones +/datum/tutorial/marine/example/proc/on_can_pickup(datum/source, obj/item/picked_up) + SIGNAL_HANDLER + + // Since we're just listening for the mob picking anything up, we want to confirm that the picked up item is the can before continuing. If it's not, then we return and keep listening. + if(!istype(picked_up, /obj/item/reagent_container/food/drinks/cans/aspen)) + // If we hit this return here, then the picked up item wasn't the can, so we abort and keep listening. + return + + // Since we passed the above if statement, stop listening for item pickups. + UnregisterSignal(tutorial_mob, COMSIG_MOB_PICKUP_ITEM) + // Let's get the tracked beer can again. + TUTORIAL_ATOM_FROM_TRACKING(/obj/item/reagent_container/food/drinks/cans/aspen, beer_can) + // And remove the highlight now that it's picked up + remove_highlight(beer_can) + message_to_player("Very good. This is the end of the example tutorial. You will be sent back to the lobby screen momentarily.") + // 7.5 seconds after the above message is sent, kick the player out and end the tutorial. + tutorial_end_in(7.5 SECONDS, TRUE) + + +// END OF SCRIPTING +// START OF SCRIPT HELPERS + +// END OF SCRIPT HELPERS + +/datum/tutorial/marine/example/init_mob() + . = ..() + // We give the tutorial mob a basic ID so they can use general vendors and etc. This is here because not all marine tutorials may want to use a naked equipment preset. + arm_equipment(tutorial_mob, /datum/equipment_preset/tutorial) + + +/datum/tutorial/marine/example/init_map() + // Here we're initializing a new can that we want to track, so we spawn it 2 tiles to the left and up from the bottom left corner of the tutorial zone + var/obj/item/reagent_container/food/drinks/cans/aspen/the_can = new(loc_from_corner(2, 2)) + // Now we start tracking it + add_to_tracking_atoms(the_can) diff --git a/code/game/area/admin_level.dm b/code/game/area/admin_level.dm index 00b408c04adf..bfca1481155e 100644 --- a/code/game/area/admin_level.dm +++ b/code/game/area/admin_level.dm @@ -144,3 +144,22 @@ /area/misc/testroom requires_power = FALSE name = "Test Room" + +/area/misc/tutorial + name = "Tutorial Zone" + icon_state = "tutorial" + requires_power = FALSE + flags_area = AREA_NOTUNNEL|AREA_AVOID_BIOSCAN + statistic_exempt = TRUE + ceiling = CEILING_METAL + block_game_interaction = TRUE + unique = TRUE + + base_lighting_alpha = 255 + +/area/misc/tutorial/Initialize(mapload, ...) + . = ..() + update_base_lighting() + +/area/misc/tutorial/no_baselight + base_lighting_alpha = 0 diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 536e29599597..9699db527102 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -79,6 +79,10 @@ var/used_environ = 0 var/used_oneoff = 0 //one-off power usage + /// If this area is outside the game's normal interactivity and should be excluded from things like EOR reports and crew monitors. + /// Doesn't need to be set for areas/Z levels that are marked as admin-only + var/block_game_interaction = FALSE + /area/New() // This interacts with the map loader, so it needs to be set immediately diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index 981966082919..c017733de7fd 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -350,7 +350,7 @@ Additional game mode variables. if(cur_xeno.aghosted) continue //aghosted xenos don't count var/area/area = get_area(cur_xeno) - if(is_admin_level(cur_xeno.z) && (!area || !(area.flags_area & AREA_ALLOW_XENO_JOIN))) + if(should_block_game_interaction(cur_xeno) && (!area || !(area.flags_area & AREA_ALLOW_XENO_JOIN))) continue //xenos on admin z level don't count if(!istype(cur_xeno)) continue diff --git a/code/game/gamemodes/colonialmarines/colonialmarines.dm b/code/game/gamemodes/colonialmarines/colonialmarines.dm index bc5d6b69228c..f64c2432486b 100644 --- a/code/game/gamemodes/colonialmarines/colonialmarines.dm +++ b/code/game/gamemodes/colonialmarines/colonialmarines.dm @@ -329,7 +329,7 @@ var/datum/hive_status/HS for(var/HN in GLOB.hive_datum) HS = GLOB.hive_datum[HN] - if(HS.living_xeno_queen && !is_admin_level(HS.living_xeno_queen.loc.z)) + if(HS.living_xeno_queen && !should_block_game_interaction(HS.living_xeno_queen.loc)) //Some Queen is alive, we shouldn't end the game yet return round_finished = MODE_INFESTATION_M_MINOR diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost/whiskey_output_waves.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost/whiskey_output_waves.dm index 6e2738a83788..1ec07b9d8fec 100644 --- a/code/game/gamemodes/colonialmarines/whiskey_outpost/whiskey_output_waves.dm +++ b/code/game/gamemodes/colonialmarines/whiskey_outpost/whiskey_output_waves.dm @@ -32,7 +32,7 @@ for(var/mob/living/carbon/xenomorph/X as anything in GLOB.living_xeno_list) var/area/A = get_area(X) - if(is_admin_level(X.z) && (!A || !(A.flags_area & AREA_ALLOW_XENO_JOIN)) || X.aghosted) continue //xenos on admin z level and aghosted ones don't count + if(should_block_game_interaction(X) && (!A || !(A.flags_area & AREA_ALLOW_XENO_JOIN)) || X.aghosted) continue //xenos on admin z level and aghosted ones don't count if(istype(X) && !X.client) if((X.away_timer >= XENO_LEAVE_TIMER) || (islarva(X) && X.away_timer >= XENO_LEAVE_TIMER_LARVA)) available_xenos += X diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 56decd8f0c02..094b899c1691 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -237,32 +237,10 @@ if(!istype(NP)) return - NP.spawning = TRUE - NP.close_spawn_windows() - var/mob/living/carbon/human/new_character = new(NP.loc) new_character.lastarea = get_area(NP.loc) - NP.client.prefs.copy_all_to(new_character, title) - - if (NP.client.prefs.be_random_body) - var/datum/preferences/TP = new() - TP.randomize_appearance(new_character) - - new_character.job = NP.job - new_character.name = NP.real_name - new_character.voice = NP.real_name - - if(NP.mind) - NP.mind_initialize() - NP.mind.transfer_to(new_character, TRUE) - NP.mind.setup_human_stats() - - // Update the character icons - // This is done in set_species when the mob is created as well, but - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_hair)) + setup_human(new_character, NP) return new_character diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index b9ea018ba98f..190d51d3f7b8 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -4,7 +4,7 @@ /mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf) if(!T) return 1 - if(is_admin_level(T.z)) + if(should_block_game_interaction(T)) return 1 if(T.z > 6) return 1 diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index cad4fd4fc747..1a00e194b5eb 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -69,7 +69,7 @@ return attack_hand(user) /obj/structure/machinery/computer/cameras/attack_hand(mob/user) - if(!admin_console && is_admin_level(z)) + if(!admin_console && should_block_game_interaction(src)) to_chat(user, SPAN_DANGER("Unable to establish a connection: \black You're too far away from the ship!")) return if(inoperable()) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index ab5dc6448f4b..69c2c897e276 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -519,7 +519,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li if(mob.client) to_chat(mob, SPAN_NOTICE("You feel cool air surround you. You go numb as your senses turn inward.")) to_chat(mob, SPAN_BOLDNOTICE("If you log out or close your client now, your character will permanently removed from the round in 10 minutes. If you ghost, timer will be decreased to 2 minutes.")) - if(!is_admin_level(src.z)) // Set their queue time now because the client has to actually leave to despawn and at that point the client is lost + if(!should_block_game_interaction(src)) // Set their queue time now because the client has to actually leave to despawn and at that point the client is lost mob.client.player_details.larva_queue_time = max(mob.client.player_details.larva_queue_time, world.time) var/area/location = get_area(src) if(mob.job != GET_MAPPED_ROLE(JOB_SQUAD_MARINE)) @@ -536,6 +536,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li icon_state = "body_scanner_open" set_light(0) playsound(src, 'sound/machines/pod_open.ogg', 30) + SEND_SIGNAL(src, COMSIG_CRYOPOD_GO_OUT) #ifdef OBJECTS_PROXY_SPEECH // Transfers speech to occupant @@ -554,3 +555,40 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li return move_inside(target) + + +/obj/structure/machinery/cryopod/tutorial + silent_exit = TRUE + +/obj/structure/machinery/cryopod/tutorial/process() + return + +/obj/structure/machinery/cryopod/tutorial/go_in_cryopod(mob/mob, silent = FALSE, del_them = TRUE) + if(occupant) + return + mob.forceMove(src) + occupant = mob + icon_state = "body_scanner_closed" + set_light(2) + time_entered = world.time + if(del_them) + despawn_occupant() + +/obj/structure/machinery/cryopod/tutorial/despawn_occupant() + SSminimaps.remove_marker(occupant) + + if(ishuman(occupant)) + var/mob/living/carbon/human/man = occupant + man.species.handle_cryo(man) + + icon_state = "body_scanner_open" + set_light(0) + + + var/mob/new_player/new_player = new + + if(!occupant.mind) + occupant.mind_initialize() + + occupant.mind.transfer_to(new_player) + SEND_SIGNAL(occupant, COMSIG_MOB_END_TUTORIAL) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 942d70f80705..e43598c4e248 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -177,7 +177,7 @@ if(src.listening_level == TELECOMM_GROUND_Z) // equals the station src.listening_level = position.z return 1 - else if(is_admin_level(position.z)) + else if(should_block_game_interaction(position)) src.listening_level = TELECOMM_GROUND_Z return 1 return 0 @@ -229,7 +229,7 @@ /obj/structure/machinery/telecomms/relay/Options_Menu() var/dat = "" - if(is_admin_level(z)) + if(should_block_game_interaction(src)) dat += "
Signal Locked to Station: [listening_level == TELECOMM_GROUND_Z ? "TRUE" : "FALSE"]" dat += "
Broadcasting: [broadcasting ? "YES" : "NO"]" dat += "
Receiving: [receiving ? "YES" : "NO"]" diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 8ea00ce4061d..8b6622121b86 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -98,7 +98,7 @@ var/turf/T = get_turf(R) if (!T) continue - if(is_admin_level(T.z)) + if(should_block_game_interaction(T)) continue var/tmpname = T.loc.name if(areaindex[tmpname]) @@ -118,7 +118,7 @@ continue var/turf/T = get_turf(M) if(T) continue - if(is_admin_level(T.z)) continue + if(should_block_game_interaction(T)) continue var/tmpname = M.real_name if(areaindex[tmpname]) tmpname = "[tmpname] ([++areaindex[tmpname]])" diff --git a/code/game/machinery/vending/cm_vending.dm b/code/game/machinery/vending/cm_vending.dm index 6415e1d0acd5..5568a5fda600 100644 --- a/code/game/machinery/vending/cm_vending.dm +++ b/code/game/machinery/vending/cm_vending.dm @@ -1239,8 +1239,10 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( if(islist(prod_type)) for(var/each_type in prod_type) vendor_successful_vend_one(each_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) + SEND_SIGNAL(src, COMSIG_VENDOR_SUCCESSFUL_VEND, src, itemspec, user) else vendor_successful_vend_one(prod_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) + SEND_SIGNAL(src, COMSIG_VENDOR_SUCCESSFUL_VEND, src, itemspec, user) if(vend_flags & VEND_LIMITED_INVENTORY) itemspec[2]-- diff --git a/code/game/machinery/vending/vendor_types/food.dm b/code/game/machinery/vending/vendor_types/food.dm index 10e1a035cb0b..62ed5124727e 100644 --- a/code/game/machinery/vending/vendor_types/food.dm +++ b/code/game/machinery/vending/vendor_types/food.dm @@ -25,6 +25,27 @@ list("W-Y Flask", 5, /obj/item/reagent_container/food/drinks/flask/weylandyutani, VENDOR_ITEM_REGULAR) ) +/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial + hackable = FALSE + wrenchable = FALSE + req_access = list(ACCESS_TUTORIAL_LOCKED) + +/obj/structure/machinery/cm_vending/sorted/marine_food/tutorial/populate_product_list(scale) + listed_products = list( + list("PREPARED MEALS", -1, null, null), + list("USCM Prepared Meal (Chicken)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal5, VENDOR_ITEM_REGULAR), + list("USCM Prepared Meal (Cornbread)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal1, VENDOR_ITEM_REGULAR), + list("USCM Prepared Meal (Pasta)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal3, VENDOR_ITEM_REGULAR), + list("USCM Prepared Meal (Pizza)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal4, VENDOR_ITEM_REGULAR), + list("USCM Prepared Meal (Pork)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal2, VENDOR_ITEM_REGULAR), + list("USCM Prepared Meal (Tofu)", 0, /obj/item/reagent_container/food/snacks/mre_pack/meal6, VENDOR_ITEM_REGULAR), + list("USCM Protein Bar", 1, /obj/item/reagent_container/food/snacks/protein_pack, VENDOR_ITEM_RECOMMENDED), + list("FLASKS", -1, null, null), + list("Canteen", 0, /obj/item/reagent_container/food/drinks/flask/canteen, VENDOR_ITEM_REGULAR), + list("Metal Flask", 0, /obj/item/reagent_container/food/drinks/flask, VENDOR_ITEM_REGULAR), + list("USCM Flask", 0, /obj/item/reagent_container/food/drinks/flask/marine, VENDOR_ITEM_REGULAR), + list("W-Y Flask", 0, /obj/item/reagent_container/food/drinks/flask/weylandyutani, VENDOR_ITEM_REGULAR) + ) //------------BOOZE-O-MAT VENDOR--------------- /obj/structure/machinery/cm_vending/sorted/boozeomat diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm index 6a770e89984e..e021b6fe0879 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm @@ -53,6 +53,34 @@ list("M94 Marking Flare Pack", round(scale * 10), /obj/item/storage/box/m94, VENDOR_ITEM_RECOMMENDED) ) +/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial + name = "\improper ColMarTech Automated Weapons Rack" + desc = "An automated weapon rack hooked up to a big storage of standard-issue weapons." + icon_state = "guns" + req_access = list(ACCESS_TUTORIAL_LOCKED) + req_one_access = list() + hackable = FALSE + vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY | VEND_TO_HAND + +/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial/populate_product_list(scale) + listed_products = list( + list("PRIMARY FIREARMS", -1, null, null), + list("M41A Pulse Rifle MK2", 1, /obj/item/weapon/gun/rifle/m41a, VENDOR_ITEM_RECOMMENDED), + + list("PRIMARY AMMUNITION", -1, null, null), + list("M41A Magazine (10x24mm)", 1, /obj/item/ammo_magazine/rifle, VENDOR_ITEM_RECOMMENDED), + ) + +/// Called if the tutorial mob somehow uses an entire magazine without the xeno dying +/obj/structure/machinery/cm_vending/sorted/cargo_guns/squad_prep/tutorial/proc/load_ammo() + listed_products = list( + list("PRIMARY FIREARMS", -1, null, null), + list("M41A Pulse Rifle MK2", 0, /obj/item/weapon/gun/rifle/m41a, VENDOR_ITEM_RECOMMENDED), + + list("PRIMARY AMMUNITION", -1, null, null), + list("M41A Magazine (10x24mm)", 99, /obj/item/ammo_magazine/rifle, VENDOR_ITEM_RECOMMENDED), + ) + //------------SQUAD PREP UNIFORM VENDOR--------------- diff --git a/code/game/machinery/vending/vendor_types/squad_prep/tutorial.dm b/code/game/machinery/vending/vendor_types/squad_prep/tutorial.dm new file mode 100644 index 000000000000..c1cedd85c7fc --- /dev/null +++ b/code/game/machinery/vending/vendor_types/squad_prep/tutorial.dm @@ -0,0 +1,30 @@ +GLOBAL_LIST_INIT(cm_vending_clothing_tutorial, list( + list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), + list("Standard Marine Apparel", 0, list(/obj/item/clothing/under/marine, /obj/item/clothing/shoes/marine/knife, /obj/item/clothing/gloves/marine, /obj/item/clothing/head/helmet/marine), MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), + + list("ARMOR (CHOOSE 1)", 0, null, null, null), + list("Medium Armor", 0, /obj/item/clothing/suit/storage/marine/medium, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + + list("BACKPACK (CHOOSE 1)", 0, null, null, null), + list("Satchel", 0, /obj/item/storage/backpack/marine/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_RECOMMENDED), + + list("BELT (CHOOSE 1)", 0, null, null, null), + list("M276 Ammo Load Rig", 0, /obj/item/storage/belt/marine, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED), + + list("POUCHES (CHOOSE 1)", 0, null, null, null), + list("Flare Pouch (Full)", 0, /obj/item/storage/pouch/flare/full, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_RECOMMENDED), + + )) // The pouch uses a different category so they only get one + +/obj/structure/machinery/cm_vending/clothing/tutorial + name = "\improper ColMarTech Automated Marine Equipment Rack" + desc = "An automated rack hooked up to a colossal storage of Marine Rifleman standard-issue equipment." + icon_state = "mar_rack" + show_points = TRUE + vendor_theme = VENDOR_THEME_USCM + req_access = list(ACCESS_TUTORIAL_LOCKED) + + vendor_role = list() + +/obj/structure/machinery/cm_vending/clothing/tutorial/get_listed_products(mob/user) + return GLOB.cm_vending_clothing_tutorial diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index 5f4a374ba31c..45cc6fd8b5fa 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -508,3 +508,7 @@ /// In landmarks.dm and not unit_test.dm so it is always active in the mapping tools. /obj/effect/landmark/unit_test_top_right name = "unit test zone top right" + +/// Marks the bottom left of the tutorial zone. +/obj/effect/landmark/tutorial_bottom_left + name = "tutorial bottom left" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 11da4cce6d98..7cb2781b253b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -364,6 +364,7 @@ cases. Override_icon_state should be a list.*/ qdel(src) SEND_SIGNAL(src, COMSIG_ITEM_DROPPED, user) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_DROPPED, src) if(drop_sound && (src.loc?.z)) playsound(src, drop_sound, dropvol, drop_vary) src.do_drop_animation(user) @@ -708,7 +709,7 @@ cases. Override_icon_state should be a list.*/ if(WEAR_IN_SHOES) if(human.shoes && istype(human.shoes, /obj/item/clothing/shoes)) var/obj/item/clothing/shoes/shoes = human.shoes - if(shoes.attempt_insert_item(human, src)) + if(shoes.can_be_inserted(src)) return TRUE return FALSE if(WEAR_IN_SCABBARD) diff --git a/code/game/objects/items/devices/teleportation.dm b/code/game/objects/items/devices/teleportation.dm index 793f399ecdf0..8dea3b872cd1 100644 --- a/code/game/objects/items/devices/teleportation.dm +++ b/code/game/objects/items/devices/teleportation.dm @@ -48,7 +48,7 @@ if (usr.stat || usr.is_mob_restrained()) return var/turf/current_location = get_turf(usr)//What turf is the user on? - if(!current_location || is_admin_level(current_location.z))//If turf was not found or they're on z level 2. + if(!current_location || should_block_game_interaction(current_location))//If turf was not found or they're on z level 2. to_chat(usr, "[src] is malfunctioning.") return if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) @@ -140,7 +140,7 @@ ..() var/turf/current_location = get_turf(user)//What turf is the user on? - if(!current_location || is_admin_level(current_location.z))//If turf was not found or they're on z level 2 + if(!current_location || should_block_game_interaction(current_location))//If turf was not found or they're on z level 2 to_chat(user, SPAN_NOTICE("\The [src] is malfunctioning.")) return var/list/L = list( ) diff --git a/code/game/objects/items/reagent_containers/autoinjectors.dm b/code/game/objects/items/reagent_containers/autoinjectors.dm index 46463e628c1d..04a3a15585ab 100644 --- a/code/game/objects/items/reagent_containers/autoinjectors.dm +++ b/code/game/objects/items/reagent_containers/autoinjectors.dm @@ -139,6 +139,12 @@ item_state = "emptyskill" skilllock = SKILL_MEDICAL_DEFAULT +/obj/item/reagent_container/hypospray/autoinjector/tramadol/skillless/one_use + desc = "An EZ autoinjector loaded with 1 use of Tramadol, a weak but effective painkiller for normal wounds. Doesn't require any training to use." + volume = 15 + amount_per_transfer_from_this = 15 + uses_left = 1 + /obj/item/reagent_container/hypospray/autoinjector/oxycodone name = "oxycodone autoinjector (EXTREME PAINKILLER)" chemname = "oxycodone" @@ -164,6 +170,12 @@ item_state = "emptyskill" skilllock = SKILL_MEDICAL_DEFAULT +/obj/item/reagent_container/hypospray/autoinjector/kelotane/skillless/one_use + desc = "An EZ autoinjector loaded with 1 use of Kelotane, a common burn medicine. Doesn't require any training to use." + volume = 15 + amount_per_transfer_from_this = 15 + uses_left = 1 + /obj/item/reagent_container/hypospray/autoinjector/bicaridine name = "bicaridine autoinjector" chemname = "bicaridine" @@ -180,6 +192,12 @@ item_state = "emptyskill" skilllock = SKILL_MEDICAL_DEFAULT +/obj/item/reagent_container/hypospray/autoinjector/bicaridine/skillless/one_use + desc = "An EZ autoinjector loaded with 1 use of Bicaridine, a common brute and circulatory damage medicine. Doesn't require any training to use." + volume = 15 + amount_per_transfer_from_this = 15 + uses_left = 1 + /obj/item/reagent_container/hypospray/autoinjector/inaprovaline name = "inaprovaline autoinjector" chemname = "inaprovaline" diff --git a/code/game/objects/items/reagent_containers/food/snacks.dm b/code/game/objects/items/reagent_containers/food/snacks.dm index 927501286f13..076a4f77cf01 100644 --- a/code/game/objects/items/reagent_containers/food/snacks.dm +++ b/code/game/objects/items/reagent_containers/food/snacks.dm @@ -21,6 +21,7 @@ //Placeholder for effect that trigger on eating that aren't tied to reagents. /obj/item/reagent_container/food/snacks/proc/On_Consume(mob/M) SEND_SIGNAL(src, COMSIG_SNACK_EATEN, M) + SEND_SIGNAL(M, COMSIG_MOB_EATEN_SNACK, src) if(!usr) return if(!reagents.total_volume) diff --git a/code/game/objects/items/reagent_containers/hypospray.dm b/code/game/objects/items/reagent_containers/hypospray.dm index fcea8997f0b5..5e268d35a33d 100644 --- a/code/game/objects/items/reagent_containers/hypospray.dm +++ b/code/game/objects/items/reagent_containers/hypospray.dm @@ -206,6 +206,7 @@ to_chat(user, SPAN_NOTICE(" You inject [M] with [src].")) to_chat(M, SPAN_WARNING("You feel a tiny prick!")) playsound(loc, injectSFX, injectVOL, 1) + SEND_SIGNAL(M, COMSIG_LIVING_HYPOSPRAY_INJECTED, src) reagents.reaction(M, INGEST) if(M.reagents) diff --git a/code/game/objects/items/shards.dm b/code/game/objects/items/shards.dm index 84c3d5b83427..dab573e6f5a5 100644 --- a/code/game/objects/items/shards.dm +++ b/code/game/objects/items/shards.dm @@ -81,7 +81,7 @@ /obj/item/large_shrapnel/proc/on_embedded_movement(mob/living/embedded_mob) return -/obj/item/large_shrapnel/proc/on_embed(mob/embedded_mob, obj/limb/target_organ) +/obj/item/large_shrapnel/proc/on_embed(mob/embedded_mob, obj/limb/target_organ, silent = FALSE) return /obj/item/large_shrapnel/at_rocket_dud @@ -180,14 +180,14 @@ cell_explosion(get_turf(target), 200, 150, EXPLOSION_FALLOFF_SHAPE_LINEAR, direction, create_cause_data("[cause] UXO detonation", user)) qdel(src) -/obj/item/large_shrapnel/at_rocket_dud/on_embed(mob/embedded_mob, obj/limb/target_organ) +/obj/item/large_shrapnel/at_rocket_dud/on_embed(mob/embedded_mob, obj/limb/target_organ, silent = FALSE) if(!ishuman(embedded_mob)) return var/mob/living/carbon/human/H = embedded_mob if(H.species.flags & NO_SHRAPNEL) return if(istype(target_organ)) - target_organ.embed(src) + target_organ.embed(src, silent) /obj/item/large_shrapnel/at_rocket_dud/on_embedded_movement(mob/living/embedded_mob) if(!ishuman(embedded_mob)) @@ -212,14 +212,14 @@ source_sheet_type = null var/damage_on_move = 0.5 -/obj/item/shard/shrapnel/proc/on_embed(mob/embedded_mob, obj/limb/target_organ) +/obj/item/shard/shrapnel/proc/on_embed(mob/embedded_mob, obj/limb/target_organ, silent = FALSE) if(!ishuman(embedded_mob)) return var/mob/living/carbon/human/H = embedded_mob if(H.species.flags & NO_SHRAPNEL) return if(istype(target_organ)) - target_organ.embed(src) + target_organ.embed(src, silent) /obj/item/shard/shrapnel/proc/on_embedded_movement(mob/living/embedded_mob) if(!ishuman(embedded_mob)) @@ -228,7 +228,7 @@ if(H.species.flags & NO_SHRAPNEL) return var/obj/limb/organ = embedded_organ - if(istype(organ)) + if(istype(organ) && damage_on_move) organ.take_damage(damage_on_move * count, 0, 0, no_limb_loss = TRUE) embedded_mob.pain.apply_pain(damage_on_move * count) @@ -261,3 +261,7 @@ name = "alien bone fragments" icon_state = "alienbonechips" desc = "Sharp, jagged fragments of alien bone. Looks like the previous owner exploded violently..." + +/obj/item/shard/shrapnel/tutorial + damage_on_move = 0 + diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index f96903cfb687..5434aa006137 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -95,6 +95,9 @@ to_chat(user, SPAN_WARNING("There are no wounds on [possessive] [affecting.display_name].")) return TRUE +/obj/item/stack/medical/bruise_pack/two + amount = 2 + /obj/item/stack/medical/ointment name = "ointment" desc = "Used to treat burns, infected wounds, and relieve itching in unusual places." diff --git a/code/game/objects/items/storage/large_holster.dm b/code/game/objects/items/storage/large_holster.dm index b02dff1bdbcc..3f653926f8b3 100644 --- a/code/game/objects/items/storage/large_holster.dm +++ b/code/game/objects/items/storage/large_holster.dm @@ -253,9 +253,12 @@ to_chat(user, SPAN_WARNING("[src] must be equipped before you can switch types.")) return - var/obj/item/weapon/gun/flamer/M240T/flamer = user.get_active_hand() - if(!istype(flamer)) - to_chat(user, SPAN_WARNING("You must be holding [flamer] to use [src].")) + if(!linked_flamer) + to_chat(user, SPAN_WARNING("An incinerator unit must be linked in order to switch fuel types.")) + return + + if(user.get_active_hand() != linked_flamer) + to_chat(user, SPAN_WARNING("You must be holding [linked_flamer] to use [src].")) return if(!active_fuel) @@ -276,8 +279,8 @@ to_chat(user, "You switch the fuel tank to [active_fuel.caliber]") playsound(src, 'sound/machines/click.ogg', 25, TRUE) - flamer.current_mag = active_fuel - flamer.update_icon() + linked_flamer.current_mag = active_fuel + linked_flamer.update_icon() return TRUE diff --git a/code/game/objects/items/weapons/blades.dm b/code/game/objects/items/weapons/blades.dm index 2fe80f123bce..a2a4aa8db75d 100644 --- a/code/game/objects/items/weapons/blades.dm +++ b/code/game/objects/items/weapons/blades.dm @@ -213,6 +213,8 @@ else INVOKE_ASYNC(embedded_human, TYPE_PROC_REF(/mob, emote), "me", 1, pick("winces.", "grimaces.", "flinches.")) + SEND_SIGNAL(embedded_human, COMSIG_HUMAN_SHRAPNEL_REMOVED) + else to_chat(user, SPAN_NOTICE("You couldn't find any shrapnel.")) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index cc9f1fe53fea..7747a45ed9da 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -278,6 +278,11 @@ if (iszombie(user)) return + // mobs that become immobilized should not be able to buckle themselves. + if(M == user && HAS_TRAIT(user, TRAIT_IMMOBILIZED)) + to_chat(user, SPAN_WARNING("You are unable to do this in your current state.")) + return + if(density) density = FALSE if(!step(M, get_dir(M, src)) && loc != M.loc) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 069d932d991b..bfc3c579f36c 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -1442,7 +1442,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) world.log << "## ERROR: Eek. The supply/elevator datum is missing somehow." return - if(!is_admin_level(SSshuttle.vehicle_elevator.z)) + if(!should_block_game_interaction(SSshuttle.vehicle_elevator)) to_chat(usr, SPAN_WARNING("The elevator needs to be in the cargo bay dock to call a vehicle up. Ask someone to send it away.")) return diff --git a/code/modules/admin/player_panel/actions/general.dm b/code/modules/admin/player_panel/actions/general.dm index a47a42d44cc2..e4ebc9fb85dd 100644 --- a/code/modules/admin/player_panel/actions/general.dm +++ b/code/modules/admin/player_panel/actions/general.dm @@ -68,17 +68,9 @@ message_admins("[key_name_admin(user)] has sent [key_name_admin(target)] back to the Lobby.") - var/mob/new_player/NP = new() - - if(!target.mind) - target.mind_initialize() - - target.mind.transfer_to(NP) - - qdel(target) + target.send_to_lobby() return TRUE - /datum/player_action/force_say action_tag = "mob_force_say" name = "Force Say" diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 300c999b885b..e9587319a160 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -378,6 +378,22 @@ Insert("[icon_name]_big", iconBig) return ..() +/datum/asset/spritesheet/tutorial + name = "tutorial" + +/datum/asset/spritesheet/tutorial/register() + for(var/icon_state in icon_states('icons/misc/tutorial.dmi')) + var/icon/icon_sprite = icon('icons/misc/tutorial.dmi', icon_state) + icon_sprite.Scale(128, 128) + Insert(icon_state, icon_sprite) + + var/icon/retrieved_icon = icon('icons/mob/hud/human_dark.dmi', "intent_all") + retrieved_icon.Scale(128, 128) + Insert("intents", retrieved_icon) + + return ..() + + /datum/asset/spritesheet/gun_lineart name = "gunlineart" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c11d35451656..29676ddb4ac8 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -239,6 +239,8 @@ GLOBAL_LIST_INIT(bgstate_options, list( /// if this client has tooltips enabled var/tooltips = TRUE + /// A list of tutorials that the client has completed, saved across rounds + var/list/completed_tutorials = list() /// If this client has auto observe enabled, used by /datum/orbit_menu var/auto_observe = TRUE @@ -1995,7 +1997,8 @@ GLOBAL_LIST_INIT(bgstate_options, list( if(!istype(character)) return - find_assigned_slot(job_title, is_late_join) + if(job_title) + find_assigned_slot(job_title, is_late_join) if(check_datacore && !(be_random_body && be_random_name)) for(var/datum/data/record/record as anything in GLOB.data_core.locked) if(record.fields["name"] == real_name) @@ -2302,6 +2305,22 @@ GLOBAL_LIST_INIT(bgstate_options, list( show_browser(user, dat, "Character Traits", "character_traits") update_preview_icon(TRUE) +/// Converts a client's list of completed tutorials into a string for saving +/datum/preferences/proc/tutorial_list_to_savestring() + if(!length(completed_tutorials)) + return "" + + var/return_string = "" + var/last_id = completed_tutorials[length(completed_tutorials)] + for(var/tutorial_id in completed_tutorials) + return_string += tutorial_id + (tutorial_id != last_id ? ";" : "") + return return_string + +/// Converts a saved string of completed tutorials into a list for in-game use +/datum/preferences/proc/tutorial_savestring_to_list(savestring) + completed_tutorials = splittext(savestring, ";") + return completed_tutorials + #undef MENU_MARINE #undef MENU_XENOMORPH #undef MENU_CO diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index c67effe90eb1..2261ddf5ebfa 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -480,6 +480,10 @@ S["uplinklocation"] >> uplinklocation S["exploit_record"] >> exploit_record + var/tutorial_string = "" + S["completed_tutorials"] >> tutorial_string + tutorial_savestring_to_list(tutorial_string) + //Sanitize metadata = sanitize_text(metadata, initial(metadata)) real_name = reject_bad_name(real_name) @@ -625,6 +629,8 @@ S["uplinklocation"] << uplinklocation S["exploit_record"] << exploit_record + S["completed_tutorials"] << tutorial_list_to_savestring() + return 1 /// checks through keybindings for outdated unbound keys and updates them diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index d6596474885c..91f42fbafe79 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -336,41 +336,64 @@ permeability_coefficient = 0.50 slowdown = SHOES_SLOWDOWN blood_overlay_type = "feet" + /// The currently inserted item. var/obj/item/stored_item - var/list/items_allowed + /// List of item types that can be inserted. + var/list/allowed_items_typecache + /// An item which should be inserted when the shoes are spawned. + var/obj/item/spawn_item_type var/shoes_blood_amt = 0 -///Checks if you can put the item inside of the shoes -/obj/item/clothing/shoes/proc/attempt_insert_item(mob/user, obj/item/attacking_item, insert_after = FALSE) - if(!items_allowed) - return +/obj/item/clothing/shoes/Initialize(mapload, ...) + . = ..() + if(allowed_items_typecache) + allowed_items_typecache = typecacheof(allowed_items_typecache) + if(spawn_item_type) + _insert_item(new spawn_item_type(src)) + +/// Returns a boolean indicating if `item_to_insert` can be inserted into the shoes. +/obj/item/clothing/shoes/proc/can_be_inserted(obj/item/item_to_insert) + // If the shoes can't actually hold an item. + if(allowed_items_typecache == null) + return FALSE + // If there's already an item inside. if(stored_item) - return - var/allowed = FALSE - for(var/allowed_item in items_allowed) - if(istype(attacking_item, allowed_item)) - allowed = TRUE - break - if(!allowed) - return - if(!insert_after) - return TRUE - insert_item(user, attacking_item) - -///Puts the item inside of the shoe -/obj/item/clothing/shoes/proc/insert_item(mob/user, obj/item/attacking_item) - stored_item = attacking_item - user.drop_inv_item_to_loc(attacking_item, src) - to_chat(user, SPAN_NOTICE("You slide [attacking_item] into [src].")) - playsound(user, 'sound/weapons/gun_shotgun_shell_insert.ogg', 15, 1) + return FALSE + // If `item_to_insert` isn't in the whitelist. + if(!is_type_in_typecache(item_to_insert, allowed_items_typecache)) + return FALSE + // If all of those passed, `item_to_insert` can be inserted. + return TRUE + +/** + * Try to insert `item_to_insert` into the shoes. + * + * Returns `TRUE` if it succeeded, or `FALSE` if [/obj/item/clothing/shoes/proc/can_be_inserted] failed, or `user` couldn't drop the item. + */ +/obj/item/clothing/shoes/proc/attempt_insert_item(mob/user, obj/item/item_to_insert) + if(!can_be_inserted(item_to_insert)) + return FALSE + // Try to drop the item and place it inside `src`. + if(!user.drop_inv_item_to_loc(item_to_insert, src)) + return FALSE + _insert_item(item_to_insert) + to_chat(user, SPAN_NOTICE("You slide [item_to_insert] into [src].")) + playsound(user, 'sound/weapons/gun_shotgun_shell_insert.ogg', 15, TRUE) + return TRUE + +/// Insert `item_to_insert` directly into the shoes without bothering with any checks. +/// (In the majority of cases [/obj/item/clothing/shoes/proc/attempt_insert_item()] should be used instead of this.) +/obj/item/clothing/shoes/proc/_insert_item(obj/item/item_to_insert) + PROTECTED_PROC(TRUE) + stored_item = item_to_insert update_icon() -///Removes the item from the shoes +/// Remove `stored_item` from the shoes, and place it into the `user`'s active hand. /obj/item/clothing/shoes/proc/remove_item(mob/user) - if(!user.put_in_active_hand(stored_item)) + if(!stored_item || !user.put_in_active_hand(stored_item)) return to_chat(user, SPAN_NOTICE("You slide [stored_item] out of [src].")) - playsound(user, 'sound/weapons/gun_shotgun_shell_insert.ogg', 15, 1) + playsound(user, 'sound/weapons/gun_shotgun_shell_insert.ogg', 15, TRUE) stored_item = null update_icon() @@ -380,10 +403,8 @@ user.update_inv_shoes() /obj/item/clothing/shoes/Destroy() - if(stored_item) - qdel(stored_item) - stored_item = null - . = ..() + QDEL_NULL(stored_item) + return ..() /obj/item/clothing/shoes/get_examine_text(mob/user) . = ..() @@ -391,17 +412,14 @@ . += "\nIt is storing \a [stored_item]." /obj/item/clothing/shoes/attack_hand(mob/living/user) - if(!stored_item) //Only allow someone to take out the stored_item if it's being worn or held. So you can pick them up off the floor - return ..() - if(user.is_mob_incapacitated()) - return ..() - if(loc != user) + // Only allow someone to take out the `stored_item` if it's being worn or held, so that you can pick them up off the floor. + if(!stored_item || loc != user || user.is_mob_incapacitated()) return ..() remove_item(user) /obj/item/clothing/shoes/attackby(obj/item/attacking_item, mob/living/user) . = ..() - user.equip_to_slot_if_possible(attacking_item, WEAR_IN_SHOES) + attempt_insert_item(user, attacking_item) /obj/item/clothing/equipped(mob/user, slot, silent) if(is_valid_slot(slot, TRUE)) //is it going to a matching clothing slot? diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index b5ec4f3ab924..4318e1a3b184 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -41,7 +41,14 @@ /obj/item/clothing/shoes/red/knife name = "dirty red shoes" desc = "Stylish red shoes with a small space to hold a knife." - items_allowed = list(/obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, /obj/item/weapon/gun/pistol/clfpistol, /obj/item/tool/screwdriver, /obj/item/weapon/straight_razor) + allowed_items_typecache = list( + /obj/item/attachable/bayonet, + /obj/item/weapon/throwing_knife, + /obj/item/weapon/gun/pistol/holdout, + /obj/item/weapon/gun/pistol/clfpistol, + /obj/item/tool/screwdriver, + /obj/item/weapon/straight_razor, + ) /obj/item/clothing/shoes/white name = "white shoes" @@ -90,5 +97,3 @@ ..() if (istype(H, /obj/item/handcuffs)) attach_cuffs(H, user) - - diff --git a/code/modules/clothing/shoes/marine_shoes.dm b/code/modules/clothing/shoes/marine_shoes.dm index c7eb4ba53982..7855075c2fb4 100644 --- a/code/modules/clothing/shoes/marine_shoes.dm +++ b/code/modules/clothing/shoes/marine_shoes.dm @@ -18,47 +18,46 @@ min_cold_protection_temperature = SHOE_MIN_COLD_PROT max_heat_protection_temperature = SHOE_MAX_HEAT_PROT siemens_coefficient = 0.7 - var/armor_stage = 0 - items_allowed = list(/obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, /obj/item/weapon/gun/pistol/clfpistol, /obj/item/tool/screwdriver, /obj/item/tool/surgery/scalpel, /obj/item/weapon/straight_razor) - var/knife_type + allowed_items_typecache = list( + /obj/item/attachable/bayonet, + /obj/item/weapon/throwing_knife, + /obj/item/weapon/gun/pistol/holdout, + /obj/item/weapon/gun/pistol/clfpistol, + /obj/item/tool/screwdriver, + /obj/item/tool/surgery/scalpel, + /obj/item/weapon/straight_razor, + ) drop_sound = "armorequip" -/obj/item/clothing/shoes/marine/Initialize(mapload, ...) - . = ..() - if(knife_type) - stored_item = new knife_type(src) - update_icon() - /obj/item/clothing/shoes/marine/update_icon() - if(stored_item && !armor_stage) + if(stored_item) icon_state = "[initial(icon_state)]-1" else - if(!armor_stage) - icon_state = initial(icon_state) + icon_state = initial(icon_state) /obj/item/clothing/shoes/marine/knife - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/jungle icon_state = "marine_jungle" desc = "Don't go walkin' slow, the devil's on the loose." /obj/item/clothing/shoes/marine/jungle/knife - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/brown icon_state = "marine_brown" desc = "Standard issue combat boots for combat scenarios or combat situations. All combat, all the time. These are brown." /obj/item/clothing/shoes/marine/brown/knife - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/monkey name = "monkey combat boots" desc = "A sturdy pair of combat boots, the reflection of the polished leather reflects your true self." icon_state = "monkey_shoes" item_state = "monkey_shoes" - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/upp name = "military combat boots" @@ -67,10 +66,9 @@ armor_bullet = CLOTHING_ARMOR_HIGHPLUS armor_bomb = CLOTHING_ARMOR_MEDIUM armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH - knife_type = /obj/item/attachable/bayonet/upp -/obj/item/clothing/shoes/marine/upp_knife - knife_type = /obj/item/attachable/bayonet/upp +/obj/item/clothing/shoes/marine/upp/knife + spawn_item_type = /obj/item/attachable/bayonet/upp /obj/item/clothing/shoes/marine/joe name = "biohazard boots" @@ -80,7 +78,7 @@ armor_bio = CLOTHING_ARMOR_MEDIUMHIGH armor_rad = CLOTHING_ARMOR_MEDIUMHIGH armor_internaldamage = CLOTHING_ARMOR_MEDIUMLOW - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/dress name = "dress shoes" @@ -120,7 +118,13 @@ flags_heat_protection = BODY_FLAG_FEET flags_inventory = FPRINT|NOSLIPPING siemens_coefficient = 0.6 - items_allowed = list(/obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, /obj/item/weapon/gun/pistol/clfpistol, /obj/item/weapon/straight_razor) + allowed_items_typecache = list( + /obj/item/attachable/bayonet, + /obj/item/weapon/throwing_knife, + /obj/item/weapon/gun/pistol/holdout, + /obj/item/weapon/gun/pistol/clfpistol, + /obj/item/weapon/straight_razor, + ) /obj/item/clothing/shoes/veteran/pmc/update_icon() if(stored_item) @@ -128,10 +132,8 @@ else icon_state = initial(icon_state) -/obj/item/clothing/shoes/veteran/pmc/knife/Initialize(mapload, ...) - . = ..() - stored_item = new /obj/item/attachable/bayonet(src) - update_icon() +/obj/item/clothing/shoes/veteran/pmc/knife + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/veteran/pmc/commando name = "\improper PMC commando boots" @@ -141,22 +143,13 @@ siemens_coefficient = 0.2 unacidable = TRUE -/obj/item/clothing/shoes/veteran/pmc/commando/knife/Initialize(mapload, ...) - . = ..() - stored_item = new /obj/item/attachable/bayonet(src) - update_icon() +/obj/item/clothing/shoes/veteran/pmc/commando/knife + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/veteran/pmc/van_bandolier name = "hiking boots" desc = "Over stone, over ice, through sun and sand, mud and snow, into raging water and hungry bog, these will never let you down." - -/obj/item/clothing/shoes/veteran/pmc/van_bandolier/New() - ..() - var/obj/item/attachable/bayonet/upp/knife = new(src) - knife.name = "\improper Fairbairn-Sykes fighting knife" - knife.desc = "This isn't for dressing game or performing camp chores. It's almost certainly not an original. Almost." - stored_item = knife - update_icon() + spawn_item_type = /obj/item/attachable/bayonet/van_bandolier /obj/item/clothing/shoes/veteran/pmc/commando/cbrn name = "\improper M3 MOPP boots" @@ -165,22 +158,18 @@ item_state = "cbrn" armor_rad = CLOTHING_ARMOR_GIGAHIGHPLUS armor_bio = CLOTHING_ARMOR_GIGAHIGHPLUS - -/obj/item/clothing/shoes/veteran/pmc/commando/cbrn/Initialize(mapload, ...) - . = ..() - stored_item = new /obj/item/attachable/bayonet(src) - update_icon() + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/corporate name = "rugged boots" desc = "These synth-leather boots seem high quality when first worn, but quickly detoriate, especially in the environments the corporate security members these are issued to operate in. Still, better than nothing." - knife_type = /obj/item/attachable/bayonet + spawn_item_type = /obj/item/attachable/bayonet /obj/item/clothing/shoes/marine/ress name = "armored sandals" icon_state = "sandals" item_state = "sandals" - items_allowed = null + allowed_items_typecache = null /obj/item/clothing/shoes/hiking name = "hiking shoes" @@ -201,7 +190,13 @@ flags_heat_protection = BODY_FLAG_FEET flags_inventory = FPRINT|NOSLIPPING siemens_coefficient = 0.6 - items_allowed = list(/obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, /obj/item/weapon/gun/pistol/clfpistol, /obj/item/weapon/straight_razor) + allowed_items_typecache = list( + /obj/item/attachable/bayonet, + /obj/item/weapon/throwing_knife, + /obj/item/weapon/gun/pistol/holdout, + /obj/item/weapon/gun/pistol/clfpistol, + /obj/item/weapon/straight_razor, + ) var/weed_slowdown_mult = 0.5 /obj/item/clothing/shoes/hiking/equipped(mob/user, slot, silent) @@ -239,7 +234,7 @@ flags_heat_protection = BODY_FLAG_FEET flags_inventory = FPRINT|NOSLIPPING siemens_coefficient = 0.6 - items_allowed = list( + allowed_items_typecache = list( /obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, @@ -248,7 +243,4 @@ flags_atom = NO_NAME_OVERRIDE /obj/item/clothing/shoes/royal_marine/knife -/obj/item/clothing/shoes/royal_marine/knife/Initialize(mapload, ...) - . = ..() - stored_item = new /obj/item/attachable/bayonet/rmc(src) - update_icon() + spawn_item_type = /obj/item/attachable/bayonet/rmc diff --git a/code/modules/cm_aliens/structures/tunnel.dm b/code/modules/cm_aliens/structures/tunnel.dm index 1f0f98c14361..8e2993704f31 100644 --- a/code/modules/cm_aliens/structures/tunnel.dm +++ b/code/modules/cm_aliens/structures/tunnel.dm @@ -221,7 +221,7 @@ return XENO_NO_DELAY_ACTION if(!hive.tunnels.len) - to_chat(M, SPAN_WARNING("\The [src] doesn't seem to lead anywhere.")) + to_chat(M, SPAN_WARNING("[src] doesn't seem to lead anywhere.")) return XENO_NO_DELAY_ACTION if(contents.len > 2) @@ -236,11 +236,11 @@ tunnel_time = TUNNEL_ENTER_LARVA_DELAY if(M.mob_size >= MOB_SIZE_BIG) - M.visible_message(SPAN_XENONOTICE("[M] begins heaving their huge bulk down into \the [src]."), \ - SPAN_XENONOTICE("We begin heaving our monstrous bulk into \the [src].")) + M.visible_message(SPAN_XENONOTICE("[M] begins heaving their huge bulk down into [src]."), + SPAN_XENONOTICE("We begin heaving our monstrous bulk into [src] ([tunnel_desc]).")) else - M.visible_message(SPAN_XENONOTICE("\The [M] begins crawling down into \the [src]."), \ - SPAN_XENONOTICE("We begin crawling down into \the [src].")) + M.visible_message(SPAN_XENONOTICE("[M] begins crawling down into [src]."), + SPAN_XENONOTICE("We begin crawling down into [src] ([tunnel_desc]).")) xeno_attack_delay(M) if(!do_after(M, tunnel_time, INTERRUPT_NO_NEEDHAND, BUSY_ICON_GENERIC)) @@ -252,7 +252,7 @@ to_chat(M, SPAN_HIGHDANGER("Alt + Click the tunnel to exit, Ctrl + Click to choose a destination.")) pick_tunnel(M) else - to_chat(M, SPAN_WARNING("\The [src] ended unexpectedly, so we return back up.")) + to_chat(M, SPAN_WARNING("[src] ended unexpectedly, so we return back up.")) return XENO_NO_DELAY_ACTION /obj/structure/tunnel/maint_tunnel diff --git a/code/modules/cm_marines/dropship_ammo.dm b/code/modules/cm_marines/dropship_ammo.dm index 9f28518915ea..19086b36c957 100644 --- a/code/modules/cm_marines/dropship_ammo.dm +++ b/code/modules/cm_marines/dropship_ammo.dm @@ -251,7 +251,7 @@ for(var/i=1 to 16) //This is how many tiles within that area of effect will be randomly ignited var/turf/U = pick(turf_list) turf_list -= U - fire_spread_recur(impact, create_cause_data(fired_from.name, source_mob), 1, null, 5, 75, "#EE6515")//Very, very intense, but goes out very quick + fire_spread_recur(U, create_cause_data(fired_from.name, source_mob), 1, null, 5, 75, "#EE6515")//Very, very intense, but goes out very quick if(!ammo_count && !QDELETED(src)) qdel(src) //deleted after last laser beam is fired and impact the ground. diff --git a/code/modules/cm_marines/marines_consoles.dm b/code/modules/cm_marines/marines_consoles.dm index 994e9f1ddcb2..00a8c442b770 100644 --- a/code/modules/cm_marines/marines_consoles.dm +++ b/code/modules/cm_marines/marines_consoles.dm @@ -819,7 +819,7 @@ GLOBAL_LIST_EMPTY_TYPED(crewmonitor, /datum/crewmonitor) var/turf/pos = get_turf(H) if(!pos) continue - if(is_admin_level(pos.z)) + if(should_block_game_interaction(H)) continue // The entry for this human diff --git a/code/modules/cm_marines/smartgun_mount.dm b/code/modules/cm_marines/smartgun_mount.dm index 765f7a673812..21c8a58e279b 100644 --- a/code/modules/cm_marines/smartgun_mount.dm +++ b/code/modules/cm_marines/smartgun_mount.dm @@ -703,6 +703,9 @@ if((dir == NORTH) && (angle > 180) && (abs(360 - angle) > shoot_degree)) // If north and shooting to the left, we do some extra math return + if((dir == NORTH) && (angle < 180) && (angle > shoot_degree)) + return + else if((dir != NORTH) && (abs(angle - dir2angle(dir)) > shoot_degree)) return diff --git a/code/modules/cm_preds/thrall_items.dm b/code/modules/cm_preds/thrall_items.dm index 80b4d42c16e2..708b230d5c11 100644 --- a/code/modules/cm_preds/thrall_items.dm +++ b/code/modules/cm_preds/thrall_items.dm @@ -35,7 +35,7 @@ ) thrall = TRUE - items_allowed = list( + allowed_items_typecache = list( /obj/item/attachable/bayonet, /obj/item/weapon/throwing_knife, /obj/item/weapon/gun/pistol/holdout, diff --git a/code/modules/cm_preds/yaut_items.dm b/code/modules/cm_preds/yaut_items.dm index a648f2392d47..22e1318a7358 100644 --- a/code/modules/cm_preds/yaut_items.dm +++ b/code/modules/cm_preds/yaut_items.dm @@ -3,7 +3,7 @@ //Thrall subtypes are located in /code/modules/cm_preds/thrall_items.dm /proc/add_to_missing_pred_gear(obj/item/W) - if(!is_admin_level(W.z)) + if(!should_block_game_interaction(W)) GLOB.loose_yautja_gear |= W /proc/remove_from_missing_pred_gear(obj/item/W) @@ -217,7 +217,7 @@ siemens_coefficient = 0.2 min_cold_protection_temperature = SHOE_MIN_COLD_PROT max_heat_protection_temperature = SHOE_MAX_HEAT_PROT - items_allowed = list( + allowed_items_typecache = list( /obj/item/weapon/yautja/knife, /obj/item/weapon/gun/energy/yautja/plasmapistol, ) @@ -259,10 +259,9 @@ armor_rad = CLOTHING_ARMOR_MEDIUMHIGH armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH -/obj/item/clothing/shoes/yautja/hunter/knife/New() - ..() - stored_item = new /obj/item/weapon/yautja/knife(src) - update_icon() +/obj/item/clothing/shoes/yautja/hunter/knife + spawn_item_type = /obj/item/weapon/yautja/knife + /obj/item/clothing/under/chainshirt name = "ancient alien mesh suit" desc = "A strange alloy weave in the form of a vest. It feels cold with an alien weight." @@ -394,7 +393,7 @@ var/mob/living/carbon/human/H = user var/ship_to_tele = list("Yautja Ship" = -1, "Human Ship" = "Human") - if(!HAS_TRAIT(H, TRAIT_YAUTJA_TECH) || is_admin_level(H.z)) + if(!HAS_TRAIT(H, TRAIT_YAUTJA_TECH) || should_block_game_interaction(H)) to_chat(user, SPAN_WARNING("You fiddle with it, but nothing happens!")) return diff --git a/code/modules/gear_presets/clf.dm b/code/modules/gear_presets/clf.dm index d89e349a62c1..7748f4e0c558 100644 --- a/code/modules/gear_presets/clf.dm +++ b/code/modules/gear_presets/clf.dm @@ -918,7 +918,7 @@ new_human.equip_to_slot_or_del(new /obj/item/weapon/gun/smartgun/clf(new_human), WEAR_J_STORE) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/smartgunner/clf/full(new_human), WEAR_WAIST) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/survival/full(new_human), WEAR_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/full(new_human), WEAR_R_STORE) diff --git a/code/modules/gear_presets/corpses.dm b/code/modules/gear_presets/corpses.dm index ca2b2e2ab52d..72513a95f880 100644 --- a/code/modules/gear_presets/corpses.dm +++ b/code/modules/gear_presets/corpses.dm @@ -111,7 +111,7 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/sec(new_human), WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/marine(new_human), WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(new_human), WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/rebreather/scarf(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine(new_human), WEAR_HANDS) if(prob(25)) @@ -738,7 +738,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/UPP, WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/device/binoculars, WEAR_IN_JACKET) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) add_random_survivor_equipment(new_human) @@ -854,7 +854,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/freelancer, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/freelancer, WEAR_JACKET) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/dutch, WEAR_L_EAR) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/marine, WEAR_WAIST) diff --git a/code/modules/gear_presets/fun.dm b/code/modules/gear_presets/fun.dm index 68253afbf90a..44b2a1a1157a 100644 --- a/code/modules/gear_presets/fun.dm +++ b/code/modules/gear_presets/fun.dm @@ -327,7 +327,7 @@ //head new_human.equip_to_slot_or_del(new /obj/item/clothing/head/ivanberet, WEAR_HEAD) //limb - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/ivan, WEAR_WAIST) diff --git a/code/modules/gear_presets/other.dm b/code/modules/gear_presets/other.dm index 6a9fa4d6f55a..d97a032337ee 100644 --- a/code/modules/gear_presets/other.dm +++ b/code/modules/gear_presets/other.dm @@ -69,7 +69,7 @@ //generic clothing new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/freelancer, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/freelancer, WEAR_JACKET) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) spawn_merc_helmet(new_human) //storage and specific stuff, they all get an ERT medpouch. @@ -149,7 +149,7 @@ new_human.equip_to_slot_or_del(FREELANCER, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/freelancer, WEAR_JACKET) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) spawn_merc_helmet(new_human) @@ -216,7 +216,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/freelancer, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/freelancer, WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/freelancer/beret, WEAR_HEAD) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) if(new_human.disabilities & NEARSIGHTED) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health/prescription(new_human), WEAR_EYES) @@ -774,7 +774,7 @@ /datum/equipment_preset/other/xeno_cultist/load_gear(mob/living/carbon/human/new_human) new_human.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chaplain/cultist(new_human), WEAR_BODY) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/lightpack(new_human), WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/tools/full(new_human), WEAR_R_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/survival/full(new_human), WEAR_L_STORE) @@ -952,3 +952,21 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/tools/tank(new_human), WEAR_R_STORE) //*****************************************************************************************************/ + + +/datum/equipment_preset/tutorial + name = "Tutorial" + faction = FACTION_MARINE + flags = EQUIPMENT_PRESET_EXTRA + faction_group = FACTION_LIST_MARINE + languages = list(LANGUAGE_ENGLISH) + idtype = /obj/item/card/id + /// If the player should start out underfed + var/underfed = TRUE + +/datum/equipment_preset/tutorial/load_status(mob/living/carbon/human/new_human) + if(underfed) + new_human.nutrition = NUTRITION_LOW + +/datum/equipment_preset/tutorial/fed + underfed = FALSE diff --git a/code/modules/gear_presets/survivors/misc.dm b/code/modules/gear_presets/survivors/misc.dm index 396c38054965..692833bfa82b 100644 --- a/code/modules/gear_presets/survivors/misc.dm +++ b/code/modules/gear_presets/survivors/misc.dm @@ -242,7 +242,7 @@ Everything below isn't used or out of place. new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/freelancer, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/freelancer, WEAR_JACKET) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) spawn_merc_helmet(new_human) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/dutch, WEAR_L_EAR) diff --git a/code/modules/gear_presets/survivors/sorokyne_strata/preset_sorokyne_strata.dm b/code/modules/gear_presets/survivors/sorokyne_strata/preset_sorokyne_strata.dm index f53f25326b69..220034399293 100644 --- a/code/modules/gear_presets/survivors/sorokyne_strata/preset_sorokyne_strata.dm +++ b/code/modules/gear_presets/survivors/sorokyne_strata/preset_sorokyne_strata.dm @@ -5,7 +5,7 @@ /datum/equipment_preset/survivor/engineer/soro/load_gear(mob/living/carbon/human/new_human) new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/UPP(new_human), WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(new_human), WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/snow_suit/soviet(new_human), WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/ushanka(new_human), WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/rebreather/scarf(new_human), WEAR_FACE) @@ -19,7 +19,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/rank/veteran/soviet_uniform_01(new_human), WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/snow_suit/soviet(new_human), WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/sec(new_human), WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/rebreather/scarf(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/ushanka(new_human), WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine(new_human), WEAR_HANDS) @@ -71,4 +71,3 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/lockable/liaison, WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET) ..() - diff --git a/code/modules/gear_presets/survivors/trijent/crashlanding_upp_bar_insert_trijent.dm b/code/modules/gear_presets/survivors/trijent/crashlanding_upp_bar_insert_trijent.dm index 324cfbe3bf7a..99589582cbf6 100644 --- a/code/modules/gear_presets/survivors/trijent/crashlanding_upp_bar_insert_trijent.dm +++ b/code/modules/gear_presets/survivors/trijent/crashlanding_upp_bar_insert_trijent.dm @@ -26,7 +26,7 @@ uniform.roll_suit_sleeves(new_human) new_human.equip_to_slot_or_del(uniform, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/accessory/patch/upp (new_human), WEAR_ACCESSORY) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp_knife(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/flare(new_human), WEAR_R_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/full/alternate(new_human), WEAR_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/lightpack/five_slot(new_human), WEAR_BACK) @@ -207,4 +207,4 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/accessory/patch/upp, WEAR_ACCESSORY) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/tools/uppsynth, WEAR_R_STORE) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) diff --git a/code/modules/gear_presets/synths.dm b/code/modules/gear_presets/synths.dm index 3b2efd8c22be..9a181c817020 100644 --- a/code/modules/gear_presets/synths.dm +++ b/code/modules/gear_presets/synths.dm @@ -317,7 +317,7 @@ WEAR_WAIST = /obj/item/storage/belt/marine, WEAR_HANDS = /obj/item/clothing/gloves/marine/veteran, WEAR_R_HAND = /obj/item/storage/pouch/flare/full, - WEAR_FEET = /obj/item/clothing/shoes/marine/upp, + WEAR_FEET = /obj/item/clothing/shoes/marine/upp/knife, WEAR_L_HAND = /obj/item/storage/large_holster/katana/full ) diff --git a/code/modules/gear_presets/upp.dm b/code/modules/gear_presets/upp.dm index dc79f87c5135..0b3b4d4ecfb5 100644 --- a/code/modules/gear_presets/upp.dm +++ b/code/modules/gear_presets/upp.dm @@ -78,7 +78,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/UPP, WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/device/binoculars, WEAR_IN_JACKET) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) if(SSmapping.configs[GROUND_MAP].environment_traits[MAP_COLD]) @@ -151,7 +151,7 @@ /datum/equipment_preset/upp/soldier/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UM5 Personal Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -261,7 +261,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/medical/lifesaver/upp/full, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //póckets var/obj/item/storage/pouch/magazine/large/ppouch = new() @@ -280,7 +280,7 @@ /datum/equipment_preset/upp/medic/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Medic Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/medic, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UL6 Personal Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/support, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -435,7 +435,7 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/belt/marine/upp/sapper(new_human), WEAR_WAIST) //limb new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/insulated(new_human), WEAR_HANDS) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/ert(new_human), WEAR_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/construction/full(new_human), WEAR_R_STORE) @@ -443,7 +443,7 @@ /datum/equipment_preset/upp/sapper/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UM5 Personal Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -556,7 +556,7 @@ new_human.equip_to_slot_or_del(UPP, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/UPP/heavy, WEAR_JACKET) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/explosive/C4, WEAR_R_STORE) @@ -582,7 +582,7 @@ /datum/equipment_preset/upp/specialist/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UH7 Heavy Plated Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/heavy, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -683,7 +683,7 @@ new_human.equip_to_slot_or_del(UPP, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/faction/UPP/heavy, WEAR_JACKET) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/explosive/C4, WEAR_R_STORE) @@ -707,7 +707,7 @@ /datum/equipment_preset/upp/machinegunner/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UH7 Heavy Plated Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/heavy, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -829,7 +829,7 @@ if(4) //25% new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/revolver, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/flamertank, WEAR_R_STORE) @@ -843,7 +843,7 @@ /datum/equipment_preset/upp/leader/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UH7 Heavy Plated Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/heavy, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -979,7 +979,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/security/MP/UPP/full, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/autoinjector/full, WEAR_L_STORE) @@ -990,7 +990,7 @@ /datum/equipment_preset/upp/military_police/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/mp, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UL4 camouflaged jacket", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/mp, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), @@ -1140,7 +1140,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/np92, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1155,7 +1155,7 @@ /datum/equipment_preset/upp/officer/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -1300,7 +1300,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1315,7 +1315,7 @@ /datum/equipment_preset/upp/officer/senior/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -1461,7 +1461,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1476,7 +1476,7 @@ /datum/equipment_preset/upp/officer/kapitan/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -1622,7 +1622,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1637,7 +1637,7 @@ /datum/equipment_preset/upp/officer/major/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -1783,7 +1783,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1798,7 +1798,7 @@ /datum/equipment_preset/upp/officer/lt_kolonel/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -1944,7 +1944,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -1959,7 +1959,7 @@ /datum/equipment_preset/upp/officer/kolonel/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -2105,7 +2105,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -2120,7 +2120,7 @@ /datum/equipment_preset/upp/officer/may_gen/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -2266,7 +2266,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -2281,7 +2281,7 @@ /datum/equipment_preset/upp/officer/ley_gen/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -2427,7 +2427,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/t73/leader, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_L_STORE) @@ -2442,7 +2442,7 @@ /datum/equipment_preset/upp/officer/gen/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/officer, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -2583,7 +2583,7 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/belt/shotgun/upp/heavybuck(new_human), WEAR_WAIST) //limb new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/insulated(new_human), WEAR_HANDS) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) //pockets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/ert(new_human), WEAR_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/explosive/C4, WEAR_R_STORE) @@ -2667,7 +2667,7 @@ //waist new_human.equip_to_slot_or_del(new /obj/item/storage/belt/medical/lifesaver/upp/full, WEAR_WAIST) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //póckets var/obj/item/storage/pouch/magazine/large/ppouch = new() @@ -2836,7 +2836,7 @@ new_human.equip_to_slot_or_del(new /obj/item/explosive/grenade/high_explosive/upp, WEAR_IN_JACKET) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) var/maybegloves = prob(80) ? pick(/obj/item/clothing/gloves/black, /obj/item/clothing/gloves/marine/veteran/upp, /obj/item/clothing/gloves/combat) : null if(maybegloves) new_human.equip_to_slot_or_del(new maybegloves, WEAR_HANDS) @@ -2865,7 +2865,7 @@ /datum/equipment_preset/upp/conscript/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), list("Ration", 0, /obj/item/reagent_container/food/snacks/upp, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY), @@ -2933,7 +2933,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/np92/suppressed, WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -2954,7 +2954,7 @@ /datum/equipment_preset/upp/commando/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/commando, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/kdo, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -3055,7 +3055,7 @@ new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/type71/ap, WEAR_IN_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -3085,7 +3085,7 @@ /datum/equipment_preset/upp/commando/medic/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues Medic", 0, /obj/item/clothing/under/marine/veteran/UPP/medic, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/kdo/medic, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -3225,7 +3225,7 @@ new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/type71/ap, WEAR_IN_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap/beret, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -3249,7 +3249,7 @@ /datum/equipment_preset/upp/commando/leader/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/commando, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/UPP/kdo/command, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -3369,7 +3369,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/type47/np92/suppressed, WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp/weak, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -3399,7 +3399,7 @@ new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/type71/ap, WEAR_IN_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp/weak, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -3438,7 +3438,7 @@ new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/type71/ap, WEAR_IN_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/uppcap/beret, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel/scout_cloak/upp/weak, WEAR_BACK) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc/upp, WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/m42_night_goggles/upp, WEAR_EYES) @@ -3472,7 +3472,7 @@ /datum/equipment_preset/upp/tank/load_gear(mob/living/carbon/human/new_human) new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/UPP(new_human), WEAR_BODY) - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/UPP/cct(new_human), WEAR_L_EAR) new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/welding(new_human), WEAR_EYES) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow(new_human), WEAR_HANDS) @@ -3611,7 +3611,7 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/belt/medical/lifesaver/upp/full, WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/reagent_container/hypospray/autoinjector/oxycodone, WEAR_IN_BELT) //limbs - new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp, WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/upp/knife, WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/upp, WEAR_HANDS) //póckets new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large, WEAR_R_STORE) @@ -3630,7 +3630,7 @@ /datum/equipment_preset/upp/doctor/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), - list("Boots", 0, /obj/item/clothing/shoes/marine/upp, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Boots", 0, /obj/item/clothing/shoes/marine/upp/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Medic Fatigues", 0, /obj/item/clothing/under/marine/veteran/UPP/medic, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), list("UL6 Personal Armor", 0, /obj/item/clothing/suit/storage/marine/faction/UPP/support, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY), list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/upp, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), diff --git a/code/modules/gear_presets/uscm.dm b/code/modules/gear_presets/uscm.dm index 7cee0802e479..8289bdfe09cb 100644 --- a/code/modules/gear_presets/uscm.dm +++ b/code/modules/gear_presets/uscm.dm @@ -30,7 +30,7 @@ /datum/equipment_preset/uscm/load_preset(mob/living/carbon/human/new_human, randomise, count_participant) . = ..() - if(!auto_squad_name || (is_admin_level(new_human.z) && !ert_squad)) + if(!auto_squad_name || (should_block_game_interaction(new_human) && !ert_squad)) return if(!GLOB.data_core.manifest_modify(new_human.real_name, WEAKREF(new_human), assignment, rank)) GLOB.data_core.manifest_inject(new_human) diff --git a/code/modules/maptext_alerts/screen_alerts.dm b/code/modules/maptext_alerts/screen_alerts.dm index b096d3b3718f..8e59574ecf1f 100644 --- a/code/modules/maptext_alerts/screen_alerts.dm +++ b/code/modules/maptext_alerts/screen_alerts.dm @@ -64,6 +64,26 @@ style_open = "" style_close = "" +/atom/movable/screen/text/screen_text/command_order/tutorial + letters_per_update = 4 // overall, pretty fast while not immediately popping in + play_delay = 0.1 + fade_out_delay = 2.5 SECONDS + fade_out_time = 0.5 SECONDS + +/atom/movable/screen/text/screen_text/command_order/tutorial/end_play() + if(!player) + qdel(src) + return + + if(player.mob || HAS_TRAIT(player.mob, TRAIT_IN_TUTORIAL)) + return ..() + + for(var/atom/movable/screen/text/screen_text/command_order/tutorial/tutorial_message in player.screen_texts) + LAZYREMOVE(player.screen_texts, tutorial_message) + qdel(tutorial_message) + + return ..() + ///proc for actually playing this screen_text on a mob. /atom/movable/screen/text/screen_text/proc/play_to_client() player?.add_to_screen(src) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 430f959a7718..83bc0c3750f7 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -463,7 +463,7 @@ Works together with spawning an observer, noted above. ghost.langchat_make_image() SStgui.on_transfer(src, ghost) - if(is_admin_level((get_turf(src))?.z)) // Gibbed humans ghostize the brain in their head which itself is z 0 + if(should_block_game_interaction(src)) // Gibbed humans ghostize the brain in their head which itself is z 0 ghost.timeofdeath = 1 // Bypass respawn limit if you die on the admin zlevel ghost.key = key @@ -547,7 +547,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp msg_admin_niche("[key_name_admin(client)] has ghosted. [ADMIN_JMP(location)]") log_game("[key_name_admin(client)] has ghosted.") var/mob/dead/observer/ghost = ghostize((is_nested && nest && !QDELETED(nest))) //FALSE parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - if(ghost && !is_admin_level(z)) + SEND_SIGNAL(src, COMSIG_LIVING_GHOSTED, ghost) + if(ghost && !should_block_game_interaction(src)) ghost.timeofdeath = world.time // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers or lesser drone diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index d71a908d627a..8a0f0f8aa1e9 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -347,13 +347,12 @@ W.forceMove(B) equipped = 1 if(WEAR_IN_SHOES) - if(!shoes) - return + // If the player isn't wearing shoes, or the shoes somehow aren't shoes. if(!istype(shoes, /obj/item/clothing/shoes)) return - if(shoes.stored_item) - return - shoes.attempt_insert_item(src, shoes, TRUE) + // If the item was successfully inserted. + if(shoes.attempt_insert_item(src, W)) + equipped = 1 // what is this proc if(WEAR_IN_SCABBARD) if(src.back && istype(src.back, /obj/item/storage/large_holster)) var/obj/item/storage/large_holster/B = src.back diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b523cef08eec..d2e0db929624 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1445,7 +1445,7 @@ /mob/living/carbon/human/verb/remove_your_splints() set name = "Remove Your Splints" - set category = "Object" + set category = "IC" remove_splints() @@ -1748,3 +1748,28 @@ // clamped to max 500 if(dizziness > 100 && !is_dizzy) INVOKE_ASYNC(src, PROC_REF(dizzy_process)) + +/proc/setup_human(mob/living/carbon/human/target, mob/new_player/new_player, is_late_join = FALSE) + new_player.spawning = TRUE + new_player.close_spawn_windows() + new_player.client.prefs.copy_all_to(target, new_player.job, is_late_join) + + if(new_player.client.prefs.be_random_body) + var/datum/preferences/rand_prefs = new() + rand_prefs.randomize_appearance(target) + + target.job = new_player.job + target.name = new_player.real_name + target.voice = new_player.real_name + + if(new_player.mind) + new_player.mind_initialize() + new_player.mind.transfer_to(target, TRUE) + new_player.mind.setup_human_stats() + + target.sec_hud_set_ID() + target.hud_set_squad() + + INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) + INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) + INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, update_hair)) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 8f032288065b..f14b023b81da 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -4,9 +4,11 @@ if(..()) return TRUE + SEND_SIGNAL(attacking_mob, COMSIG_LIVING_ATTACKHAND_HUMAN, src) + if((attacking_mob != src) && check_shields(0, attacking_mob.name)) visible_message(SPAN_DANGER("[attacking_mob] attempted to touch [src]!"), null, null, 5) - return 0 + return FALSE switch(attacking_mob.a_intent) if(INTENT_HELP) diff --git a/code/modules/mob/living/carbon/human/human_dummy.dm b/code/modules/mob/living/carbon/human/human_dummy.dm index 061ac3cea05f..1f90c618fd38 100644 --- a/code/modules/mob/living/carbon/human/human_dummy.dm +++ b/code/modules/mob/living/carbon/human/human_dummy.dm @@ -73,3 +73,12 @@ GLOBAL_LIST_EMPTY(dummy_mob_list) /mob/living/carbon/human/dummy/add_to_all_mob_huds() return + + +/mob/living/carbon/human/dummy/tutorial // Effectively an even more disabled dummy + +/mob/living/carbon/human/dummy/tutorial/Initialize(mapload) + . = ..() + status_flags = GODMODE + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_TUTORIAL) + anchored = TRUE diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index b54f03e2ce7d..3d372376d1e7 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -354,8 +354,7 @@ current_storage.attempt_item_insertion(equipping_item, disable_warning, src) back.update_icon() if(WEAR_IN_SHOES) - shoes.attempt_insert_item(src, equipping_item, TRUE) - shoes.update_icon() + shoes.attempt_insert_item(src, equipping_item) if(WEAR_IN_SCABBARD) var/obj/item/storage/current_storage = back current_storage.attempt_item_insertion(equipping_item, disable_warning, src) @@ -495,7 +494,8 @@ /// Multiplier for how quickly the user can strip things. var/user_speed = user.get_skill_duration_multiplier(SKILL_CQC) /// The total skill level of CQC & Police - var/target_skills = (target.skills.get_skill_level(SKILL_CQC) + target.skills.get_skill_level(SKILL_POLICE)) + var/target_skills = 0 + target_skills += (target.skills?.get_skill_level(SKILL_CQC) + target.skills?.get_skill_level(SKILL_POLICE)) /// Delay then gets + 0.5s per skill level, so long as not dead or cuffed. if(!(target.stat || target.handcuffed)) @@ -571,5 +571,3 @@ /mob/living/carbon/human/drop_inv_item_on_ground(obj/item/I, nomoveupdate, force) remember_dropped_object(I) return ..() - - diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index e799c21d3f20..9a1dfcb0e9a5 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -160,7 +160,7 @@ /obj/item/alien_embryo/proc/become_larva() // We do not allow chest bursts on the Centcomm Z-level, to prevent // stranded players from admin experiments and other issues - if(!affected_mob || is_admin_level(affected_mob.z)) + if(!affected_mob || should_block_game_interaction(affected_mob)) return stage = 6 // Increase the stage value to prevent this proc getting repeated diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm index a2ade5cd0512..d6f963747e33 100644 --- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm @@ -143,7 +143,7 @@ return var/area/xeno_area = get_area(new_xeno) - if(!is_admin_level(new_xeno.z) || (xeno_area.flags_atom & AREA_ALLOW_XENO_JOIN)) + if(!should_block_game_interaction(new_xeno) || (xeno_area.flags_atom & AREA_ALLOW_XENO_JOIN)) switch(new_xeno.tier) //They have evolved, add them to the slot count IF they are in regular game space if(2) hive.tier_2_xenos |= new_xeno diff --git a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm index 3160c5e20bc7..0b0efbc0f34f 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm @@ -43,12 +43,12 @@ var/list/possible_xenos = list() for(var/mob/living/carbon/xenomorph/T in GLOB.living_xeno_list) - if (T != X && !is_admin_level(T.z) && X.hivenumber == T.hivenumber) // Can't overwatch yourself, Xenos in Thunderdome, or Xenos in other hives + if (T != X && !should_block_game_interaction(T) && X.hivenumber == T.hivenumber) // Can't overwatch yourself, Xenos in Thunderdome, or Xenos in other hives possible_xenos += T var/mob/living/carbon/xenomorph/selected_xeno = tgui_input_list(X, "Target", "Watch which xenomorph?", possible_xenos, theme="hive_status") - if (!selected_xeno || QDELETED(selected_xeno) || selected_xeno == X.observed_xeno || selected_xeno.stat == DEAD || is_admin_level(selected_xeno.z) || !X.check_state(TRUE)) + if (!selected_xeno || QDELETED(selected_xeno) || selected_xeno == X.observed_xeno || selected_xeno.stat == DEAD || should_block_game_interaction(selected_xeno) || !X.check_state(TRUE)) X.overwatch(X.observed_xeno, TRUE) // Cancel OW else if (!isQueen) // Regular Xeno OW vs Queen X.overwatch(selected_xeno) @@ -177,7 +177,7 @@ var/mob/living/carbon/xenomorph/xenoTarget = locate(href_list[XENO_OVERWATCH_TARGET_HREF]) in GLOB.living_xeno_list var/mob/living/carbon/xenomorph/xenoSrc = locate(href_list[XENO_OVERWATCH_SRC_HREF]) in GLOB.living_xeno_list - if(!istype(xenoTarget) || xenoTarget.stat == DEAD || is_admin_level(xenoTarget.z)) + if(!istype(xenoTarget) || xenoTarget.stat == DEAD || should_block_game_interaction(xenoTarget)) return if(!istype(xenoSrc) || xenoSrc.stat == DEAD) diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index d40604e8fdec..08f884d3a69d 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -476,7 +476,7 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE // Only handle free slots if the xeno is not in tdome - if(hive && !is_admin_level(z)) + if(hive && !should_block_game_interaction(src)) var/selected_caste = GLOB.xeno_datum_list[caste_type]?.type hive.used_slots[selected_caste]++ @@ -731,8 +731,6 @@ if(!isliving(AM)) return FALSE var/mob/living/L = AM - if(issynth(L) && L.health < 0) // no pulling critted or dead synths - return FALSE if(L.buckled) return FALSE //to stop xeno from pulling marines on roller beds. if(!L.is_xeno_grabbable()) @@ -1042,7 +1040,7 @@ /mob/living/carbon/xenomorph/ghostize(can_reenter_corpse = TRUE, aghosted = FALSE) . = ..() - if(. && !can_reenter_corpse && stat != DEAD && !QDELETED(src) && !is_admin_level(z)) + if(. && !can_reenter_corpse && stat != DEAD && !QDELETED(src) && !should_block_game_interaction(src)) handle_ghost_message() /mob/living/carbon/xenomorph/proc/handle_ghost_message() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm b/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm index 15797041171f..c4c9b11b37e4 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm @@ -73,7 +73,11 @@ icon_xeno = 'icons/mob/xenos/drone.dmi' icon_xenonid = 'icons/mob/xenonids/drone.dmi' - weed_food_icon = 'icons/mob/xenos/weeds_48x48.dmi' weed_food_states = list("Drone_1","Drone_2","Drone_3") weed_food_states_flipped = list("Drone_1","Drone_2","Drone_3") + +/mob/living/carbon/xenomorph/drone/tutorial + +/mob/living/carbon/xenomorph/drone/tutorial/gib(datum/cause_data/cause = create_cause_data("gibbing", src)) + death(cause, 1) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm index 7416b85a13c4..6d082b327b48 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm @@ -58,7 +58,7 @@ if(hive.living_xeno_queen.hivenumber == hive.hivenumber) continue for(var/mob/living/carbon/xenomorph/queen/Q in GLOB.living_xeno_list) - if(Q.hivenumber == hive.hivenumber && !is_admin_level(Q.z)) + if(Q.hivenumber == hive.hivenumber && !should_block_game_interaction(Q)) hive.living_xeno_queen = Q xeno_message(SPAN_XENOANNOUNCE("A new Queen has risen to lead the Hive! Rejoice!"),3,hive.hivenumber) continue outer_loop @@ -396,7 +396,7 @@ /mob/living/carbon/xenomorph/queen/Initialize() . = ..() SStracking.set_leader("hive_[hivenumber]", src) - if(!is_admin_level(z))//so admins can safely spawn Queens in Thunderdome for tests. + if(!should_block_game_interaction(src))//so admins can safely spawn Queens in Thunderdome for tests. xeno_message(SPAN_XENOANNOUNCE("A new Queen has risen to lead the Hive! Rejoice!"),3,hivenumber) notify_ghosts(header = "New Queen", message = "A new Queen has risen.", source = src, action = NOTIFY_ORBIT) playsound(loc, 'sound/voice/alien_queen_command.ogg', 75, 0) @@ -502,7 +502,7 @@ if(hive && hive.living_xeno_queen == src) var/mob/living/carbon/xenomorph/queen/next_queen = null for(var/mob/living/carbon/xenomorph/queen/queen in hive.totalXenos) - if(!is_admin_level(queen.z) && queen != src && !QDELETED(queen)) + if(!should_block_game_interaction(queen) && queen != src && !QDELETED(queen)) next_queen = queen break hive.set_living_xeno_queen(next_queen) // either null or a queen diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index ea1e674a1faf..503ca11a7631 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -26,7 +26,7 @@ hud_used.alien_plasma_display.icon_state = "power_display_empty" update_icons() - if(!is_admin_level(z)) //so xeno players don't get death messages from admin tests + if(!should_block_game_interaction(src)) //so xeno players don't get death messages from admin tests if(isqueen(src)) var/mob/living/carbon/xenomorph/queen/XQ = src playsound(loc, 'sound/voice/alien_queen_died.ogg', 75, 0) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status.dm b/code/modules/mob/living/carbon/xenomorph/hive_status.dm index 5e444aa211a7..3c8eb51a8155 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_status.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_status.dm @@ -206,7 +206,7 @@ // Can only have one queen. if(isqueen(X)) - if(!living_xeno_queen && !is_admin_level(X.z)) // Don't consider xenos in admin level + if(!living_xeno_queen && !should_block_game_interaction(X)) // Don't consider xenos in admin level set_living_xeno_queen(X) X.hivenumber = hivenumber @@ -218,7 +218,7 @@ X.hud_update() var/area/A = get_area(X) - if(!is_admin_level(X.z) || (A.flags_atom & AREA_ALLOW_XENO_JOIN)) + if(!should_block_game_interaction(X) || (A.flags_atom & AREA_ALLOW_XENO_JOIN)) totalXenos += X if(X.tier == 2) tier_2_xenos += X @@ -241,7 +241,7 @@ if(living_xeno_queen == xeno) var/mob/living/carbon/xenomorph/queen/next_queen = null for(var/mob/living/carbon/xenomorph/queen/queen in totalXenos) - if(!is_admin_level(queen.z) && queen != src && !QDELETED(queen)) + if(!should_block_game_interaction(queen) && queen != src && !QDELETED(queen)) next_queen = queen break @@ -264,7 +264,7 @@ tier_3_xenos -= xeno // Only handle free slots if the xeno is not in tdome - if(!is_admin_level(xeno.z)) + if(!should_block_game_interaction(xeno)) var/selected_caste = GLOB.xeno_datum_list[xeno.caste_type]?.type if(used_slots[selected_caste]) used_slots[selected_caste]-- @@ -408,7 +408,7 @@ for(var/mob/living/carbon/xenomorph/X in totalXenos) //don't show xenos in the thunderdome when admins test stuff. - if(is_admin_level(X.z)) + if(should_block_game_interaction(X)) var/area/A = get_area(X) if(!(A.flags_atom & AREA_ALLOW_XENO_JOIN)) continue @@ -425,7 +425,7 @@ var/list/xenos = list() for(var/mob/living/carbon/xenomorph/X in totalXenos) - if(is_admin_level(X.z)) + if(should_block_game_interaction(X)) var/area/A = get_area(X) if(!(A.flags_atom & AREA_ALLOW_XENO_JOIN)) continue @@ -508,7 +508,7 @@ var/list/xenos = list() for(var/mob/living/carbon/xenomorph/X in totalXenos) - if(is_admin_level(X.z)) + if(should_block_game_interaction(X)) var/area/A = get_area(X) if(!(A.flags_atom & AREA_ALLOW_XENO_JOIN)) continue @@ -539,7 +539,7 @@ var/list/xenos = list() for(var/mob/living/carbon/xenomorph/X in totalXenos) - if(is_admin_level(X.z)) + if(should_block_game_interaction(X)) var/area/A = get_area(X) if(!(A.flags_atom & AREA_ALLOW_XENO_JOIN)) continue diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm b/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm index 0417a7a5977b..4e71b9a2202f 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_status_ui.dm @@ -181,7 +181,7 @@ var/mob/living/carbon/xenomorph/xenoTarget = locate(params["target_ref"]) in GLOB.living_xeno_list var/mob/living/carbon/xenomorph/xenoSrc = ui.user - if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || is_admin_level(xenoTarget.z)) + if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || should_block_game_interaction(xenoTarget)) return if(xenoSrc.stat == DEAD) @@ -194,7 +194,7 @@ var/mob/living/carbon/xenomorph/xenoTarget = locate(params["target_ref"]) in GLOB.living_xeno_list var/mob/living/carbon/xenomorph/xenoSrc = ui.user - if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || is_admin_level(xenoTarget.z)) + if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || should_block_game_interaction(xenoTarget)) return if(xenoSrc.stat == DEAD) @@ -207,7 +207,7 @@ var/mob/living/carbon/xenomorph/xenoTarget = locate(params["target_ref"]) in GLOB.living_xeno_list var/mob/living/carbon/xenomorph/xenoSrc = ui.user - if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || is_admin_level(xenoTarget.z)) + if(QDELETED(xenoTarget) || xenoTarget.stat == DEAD || should_block_game_interaction(xenoTarget)) return if(xenoSrc.stat == DEAD) diff --git a/code/modules/mob/living/carbon/xenomorph/mark_menu.dm b/code/modules/mob/living/carbon/xenomorph/mark_menu.dm index 5f7c1f8bc8c8..dd63f8a4fa70 100644 --- a/code/modules/mob/living/carbon/xenomorph/mark_menu.dm +++ b/code/modules/mob/living/carbon/xenomorph/mark_menu.dm @@ -180,7 +180,7 @@ var/list/possible_xenos = list() possible_xenos |= FunkTownOhyea for(var/mob/living/carbon/xenomorph/T in GLOB.living_xeno_list) - if (T != X && !is_admin_level(T.z) && X.hivenumber == T.hivenumber) + if (T != X && !should_block_game_interaction(T) && X.hivenumber == T.hivenumber) possible_xenos += T var/mob/living/carbon/xenomorph/selected_xeno = tgui_input_list(X, "Target", "Watch which xenomorph?", possible_xenos, theme="hive_status") @@ -195,7 +195,7 @@ . = TRUE update_all_data() return - if (!selected_xeno || QDELETED(selected_xeno) || selected_xeno.stat == DEAD || is_admin_level(selected_xeno.z) || !X.check_state(1)) + if (!selected_xeno || QDELETED(selected_xeno) || selected_xeno.stat == DEAD || should_block_game_interaction(selected_xeno) || !X.check_state(1)) return else selected_xeno.stop_tracking_resin_mark(FALSE, TRUE) diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm index 7ecaab1c3e79..abb044d474e8 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -1,5 +1,3 @@ -#define BORG_CAMERA_BUFFER 5 - //UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. // TURFS @@ -66,10 +64,9 @@ if(src.camera && src.camera.network.len) if(!updating) updating = 1 - spawn(BORG_CAMERA_BUFFER) - if(oldLoc != src.loc) - GLOB.cameranet.updatePortableCamera(src.camera) - updating = 0 + if(oldLoc != src.loc) + GLOB.cameranet.updatePortableCamera(src.camera) + updating = 0 /mob/living/carbon/human/var/updating = 0 @@ -83,10 +80,9 @@ if (updating) continue updating = TRUE - spawn(BORG_CAMERA_BUFFER) - if (oldLoc != loc) - GLOB.cameranet.updatePortableCamera(H.camera) - updating = FALSE + if (oldLoc != loc) + GLOB.cameranet.updatePortableCamera(H.camera) + updating = FALSE // CAMERA @@ -114,4 +110,3 @@ GLOB.cameranet.removeCamera(src) . = ..() -//#undef BORG_CAMERA_BUFFER diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 2ed1ee5e126c..5785197fdcd6 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -463,6 +463,7 @@ /mob/proc/swap_hand() hand = !hand + SEND_SIGNAL(src, COMSIG_MOB_SWAPPED_HAND) //attempt to pull/grab something. Returns true upon success. /mob/proc/start_pulling(atom/movable/AM, lunge, no_msg) @@ -989,6 +990,7 @@ note dizziness decrements automatically in the mob's Life() proc. /// Adds this list to the output to the stat browser /mob/proc/get_status_tab_items() . = list() + SEND_SIGNAL(src, COMSIG_MOB_GET_STATUS_TAB_ITEMS, .) /mob/proc/get_role_name() return @@ -1056,3 +1058,14 @@ note dizziness decrements automatically in the mob's Life() proc. /mob/proc/update_stat() return + +/// Send src back to the lobby as a `/mob/new_player()` +/mob/proc/send_to_lobby() + var/mob/new_player/new_player = new + + if(!mind) + mind_initialize() + + mind.transfer_to(new_player) + + qdel(src) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index f0e5bc48a855..f7f062295778 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -174,7 +174,7 @@ mouse_drag_pointer = MOUSE_ACTIVE_POINTER - var/status_flags = CANKNOCKDOWN|CANPUSH|STATUS_FLAGS_DEBILITATE //bitflags defining which status effects can be inflicted (replaces canweaken, canstun, etc) + var/status_flags = DEFAULT_MOB_STATUS_FLAGS //bitflags defining which status effects can be inflicted (replaces canweaken, canstun, etc) var/area/lastarea = null var/obj/control_object //Used by admins to possess objects. All mobs should have this var diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index e918a00b0984..b9c5dd12a8aa 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -87,6 +87,10 @@ ADD_TRAIT(victim, TRAIT_FLOORED, CHOKEHOLD_TRAIT) /obj/item/grab/proc/progress_passive(mob/living/carbon/human/user, mob/living/victim) + if(SEND_SIGNAL(victim, COMSIG_MOB_AGGRESSIVELY_GRABBED, user) & COMSIG_MOB_AGGRESIVE_GRAB_CANCEL) + to_chat(user, SPAN_WARNING("You can't grab [victim] aggressively!")) + return + user.grab_level = GRAB_AGGRESSIVE playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7) user.visible_message(SPAN_WARNING("[user] has grabbed [victim] aggressively!"), null, null, 5) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 6abe12eee9b1..693eebabcb99 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -308,6 +308,8 @@ GLOBAL_LIST_INIT(limb_types_by_name, list( if(hud_used && hud_used.action_intent) hud_used.action_intent.icon_state = "intent_[intent_text(a_intent)]" + SEND_SIGNAL(src, COMSIG_MOB_INTENT_CHANGE, a_intent) + /mob/proc/is_mob_restrained() return diff --git a/code/modules/mob/mob_verbs.dm b/code/modules/mob/mob_verbs.dm index a941dfc51090..1ba8985d56bd 100644 --- a/code/modules/mob/mob_verbs.dm +++ b/code/modules/mob/mob_verbs.dm @@ -32,7 +32,7 @@ return /mob/verb/view_stats() - set category = "OOC" + set category = "OOC.Records" set name = "View Playtimes" set desc = "View your playtimes." if(!SSentity_manager.ready) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 5e997db240c0..ccf649fb0509 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -42,6 +42,7 @@ var/output = "
Welcome," output +="
[(client.prefs && client.prefs.real_name) ? client.prefs.real_name : client.key]" output +="
[xeno_text]" + output += "

Tutorial

" output += "

Setup Character

" output += "

View Playtimes

" @@ -63,7 +64,7 @@ output += "
" if (refresh) close_browser(src, "playersetup") - show_browser(src, output, null, "playersetup", "size=240x[round_start ? 360 : 460];can_close=0;can_minimize=0") + show_browser(src, output, null, "playersetup", "size=240x[round_start ? 500 : 610];can_close=0;can_minimize=0") return /mob/new_player/Topic(href, href_list[]) @@ -162,6 +163,11 @@ to_chat(src, SPAN_WARNING("Sorry, you cannot late join during [SSticker.mode.name]. You have to start at the beginning of the round. You may observe or try to join as an alien, if possible.")) return + if(client.player_data?.playtime_loaded && (client.get_total_human_playtime() < CONFIG_GET(number/notify_new_player_age)) && !length(client.prefs.completed_tutorials)) + if(tgui_alert(src, "You have little playtime and haven't completed any tutorials. Would you like to go to the tutorial menu?", "Tutorial", list("Yes", "No")) == "Yes") + tutorial_menu() + return + if(client.prefs.species != "Human") if(!is_alien_whitelisted(src, client.prefs.species) && CONFIG_GET(flag/usealienwhitelist)) to_chat(src, "You are currently not whitelisted to play [client.prefs.species].") @@ -224,9 +230,28 @@ AttemptLateSpawn(href_list["job_selected"]) return + if("tutorial") + tutorial_menu() + else new_player_panel() +/mob/new_player/proc/tutorial_menu() + if(SSticker.current_state <= GAME_STATE_SETTING_UP) + to_chat(src, SPAN_WARNING("Please wait for the round to start before entering a tutorial.")) + return + + if(SSticker.current_state == GAME_STATE_FINISHED) + to_chat(src, SPAN_WARNING("The round has ended. Please wait for the next round to enter a tutorial.")) + return + + if(SSticker.tutorial_disabled) + to_chat(src, SPAN_WARNING("Tutorials are currently disabled because something broke, sorry!")) + return + + var/datum/tutorial_menu/menu = new(src) + menu.ui_interact(src) + /mob/new_player/proc/AttemptLateSpawn(rank) var/datum/job/player_rank = GLOB.RoleAuthority.roles_for_mode[rank] if (src != usr) @@ -280,7 +305,7 @@ var/client/client = character.client if(client.player_data && client.player_data.playtime_loaded && length(client.player_data.playtimes) == 0) msg_admin_niche("NEW PLAYER: [key_name(character, 1, 1, 0)]. IP: [character.lastKnownIP], CID: [character.computer_id]") - if(client.player_data && client.player_data.playtime_loaded && ((round(client.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1)) <= 5)) + if(client.player_data && client.player_data.playtime_loaded && ((round(client.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1)) <= CONFIG_GET(number/notify_new_player_age))) msg_sea("NEW PLAYER: [key_name(character, 0, 1, 0)] only has [(round(client.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1))] hours as a human. Current role: [get_actual_job_name(character)] - Current location: [get_area(character)]") character.client.init_verbs() @@ -370,30 +395,8 @@ new_character.lastarea = get_area(loc) - client.prefs.copy_all_to(new_character, job, is_late_join) - - if (client.prefs.be_random_body) - var/datum/preferences/TP = new() - TP.randomize_appearance(new_character) - - if(mind) - mind_initialize() - mind.active = 0 //we wish to transfer the key manually - mind.original = new_character - mind.transfer_to(new_character) //won't transfer key since the mind is not active - mind.setup_human_stats() - - new_character.job = job - new_character.name = real_name - new_character.voice = real_name - - // Update the character icons - // This is done in set_species when the mob is created as well, but - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) - INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_hair)) + setup_human(new_character, src, is_late_join) - new_character.key = key //Manually transfer the key to log them in new_character.client?.change_view(GLOB.world_view_size) return new_character diff --git a/code/modules/organs/limbs.dm b/code/modules/organs/limbs.dm index 8df96650ac50..718aba208f5a 100644 --- a/code/modules/organs/limbs.dm +++ b/code/modules/organs/limbs.dm @@ -547,6 +547,7 @@ This function completely restores a damaged organ to perfect condition. /obj/limb/proc/remove_all_bleeding(external = FALSE, internal = FALSE) + SEND_SIGNAL(src, COMSIG_LIMB_STOP_BLEEDING, external, internal) if(external) for(var/datum/effects/bleeding/external/B in bleeding_effects_list) qdel(B) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index c41a57f53527..3a444e1ad1fc 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -843,6 +843,7 @@ User can be passed as null, (a gun reloading itself for instance), so we need to to_chat(user, SPAN_WARNING("Your reload was interrupted!")) return replace_magazine(user, magazine) + SEND_SIGNAL(user, COMSIG_MOB_RELOADED_GUN, src) else current_mag = magazine magazine.forceMove(src) @@ -1048,6 +1049,7 @@ and you're good to go. user.swap_hand() unload(user, TRUE, drop_to_ground) // We want to quickly autoeject the magazine. This proc does the rest based on magazine type. User can be passed as null. playsound(src, empty_sound, 25, 1) + SEND_SIGNAL(user, COMSIG_MOB_GUN_EMPTY, src) else // Just fired a chambered bullet with no magazine in the gun update_icon() diff --git a/code/modules/projectiles/gun_attachables.dm b/code/modules/projectiles/gun_attachables.dm index 33d28527c8a1..e0dda3203d96 100644 --- a/code/modules/projectiles/gun_attachables.dm +++ b/code/modules/projectiles/gun_attachables.dm @@ -342,6 +342,10 @@ Defined in conflicts.dm of the #defines folder. throw_range = 7 pry_delay = 1 SECONDS +/obj/item/attachable/bayonet/van_bandolier + name = "\improper Fairbairn-Sykes fighting knife" + desc = "This isn't for dressing game or performing camp chores. It's almost certainly not an original. Almost." + /obj/item/attachable/bayonet/co2/update_icon() icon_state = "co2_knife[filled ? "-f" : ""]" attach_icon = "co2_bayonet[filled ? "-f" : ""]_a" diff --git a/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm b/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm index e0d0a80cadc2..51db188826b8 100644 --- a/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm +++ b/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm @@ -29,6 +29,9 @@ updateUsrDialog() if(!do_after(user, 1 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) return + if(!sample) + to_chat(user, SPAN_WARNING("Someone else removed the sample. Make up your mind!")) + return processing = TRUE if(sample.reagents.total_volume < 30 || sample.reagents.reagent_list.len > 1) icon_state = "reagent_analyzer_error" diff --git a/colonialmarines.dme b/colonialmarines.dme index ca8e80ef5067..814674c57f06 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -78,6 +78,7 @@ #include "code\__DEFINES\MC.dm" #include "code\__DEFINES\minimap.dm" #include "code\__DEFINES\misc.dm" +#include "code\__DEFINES\mob.dm" #include "code\__DEFINES\mob_hud.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\mode.dm" @@ -111,6 +112,7 @@ #include "code\__DEFINES\tgui.dm" #include "code\__DEFINES\traits.dm" #include "code\__DEFINES\turf_flags.dm" +#include "code\__DEFINES\tutorial.dm" #include "code\__DEFINES\unit_tests.dm" #include "code\__DEFINES\urls.dm" #include "code\__DEFINES\vehicle.dm" @@ -403,6 +405,7 @@ #include "code\datums\components\rename.dm" #include "code\datums\components\speed_modifier.dm" #include "code\datums\components\toxin_buildup.dm" +#include "code\datums\components\tutorial_status.dm" #include "code\datums\components\weed_damage_reduction.dm" #include "code\datums\components\weed_food.dm" #include "code\datums\components\autofire\_automated_fire.dm" @@ -663,6 +666,15 @@ #include "code\datums\supply_packs\spec_ammo.dm" #include "code\datums\supply_packs\vehicle_ammo.dm" #include "code\datums\supply_packs\weapons.dm" +#include "code\datums\tutorial\_tutorial.dm" +#include "code\datums\tutorial\_tutorial_menu.dm" +#include "code\datums\tutorial\tutorial_example.dm" +#include "code\datums\tutorial\marine\_marine.dm" +#include "code\datums\tutorial\marine\basic_marine.dm" +#include "code\datums\tutorial\marine\medical_basic.dm" +#include "code\datums\tutorial\ss13\_ss13.dm" +#include "code\datums\tutorial\ss13\basic_ss13.dm" +#include "code\datums\tutorial\ss13\intents.dm" #include "code\datums\weather\weather_event.dm" #include "code\datums\weather\weather_map_holder.dm" #include "code\datums\weather\weather_events\big_red.dm" @@ -972,6 +984,7 @@ #include "code\game\machinery\vending\vendor_types\squad_prep\squad_smartgunner.dm" #include "code\game\machinery\vending\vendor_types\squad_prep\squad_specialist.dm" #include "code\game\machinery\vending\vendor_types\squad_prep\squad_tl.dm" +#include "code\game\machinery\vending\vendor_types\squad_prep\tutorial.dm" #include "code\game\objects\empulse.dm" #include "code\game\objects\explosion.dm" #include "code\game\objects\explosion_recursive.dm" diff --git a/html/changelogs/AutoChangeLog-pr-5030.yml b/html/changelogs/AutoChangeLog-pr-5030.yml new file mode 100644 index 000000000000..0cce25ff019a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5030.yml @@ -0,0 +1,4 @@ +author: "Zonespace27" +delete-after: True +changes: + - rscadd: "Added a tutorial system for various roles (and just general information), find it in the lobby screen." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5307.yml b/html/changelogs/AutoChangeLog-pr-5307.yml new file mode 100644 index 000000000000..3047d03d8e82 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5307.yml @@ -0,0 +1,4 @@ +author: "mullenpaul" +delete-after: True +changes: + - refactor: "tgui js components now jsx" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5308.yml b/html/changelogs/AutoChangeLog-pr-5308.yml new file mode 100644 index 000000000000..3adc1465faaf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5308.yml @@ -0,0 +1,4 @@ +author: "cuberound" +delete-after: True +changes: + - bugfix: "m56d can not longer shoot backwards when facing north" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5315.yml b/html/changelogs/AutoChangeLog-pr-5315.yml new file mode 100644 index 000000000000..c5dc61beb308 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5315.yml @@ -0,0 +1,4 @@ +author: "SabreML" +delete-after: True +changes: + - qol: "Made the designation of a tunnel display in chat when a player enters it." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5317.yml b/html/changelogs/AutoChangeLog-pr-5317.yml new file mode 100644 index 000000000000..b5f7cd72accb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5317.yml @@ -0,0 +1,4 @@ +author: "Cthulhu80" +delete-after: True +changes: + - bugfix: "fixes immobilized mobs being able to buckle themselves" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5319.yml b/html/changelogs/AutoChangeLog-pr-5319.yml new file mode 100644 index 000000000000..d9582b58f9bc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5319.yml @@ -0,0 +1,4 @@ +author: "SabreML" +delete-after: True +changes: + - bugfix: "Fixed the CAS laser cannon only setting fire to a single tile, rather a 7x7 range." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5320.yml b/html/changelogs/AutoChangeLog-pr-5320.yml new file mode 100644 index 000000000000..32cd4fc8943d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5320.yml @@ -0,0 +1,4 @@ +author: "Birdtalon" +delete-after: True +changes: + - bugfix: "Runtime in inventory.dm" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5321.yml b/html/changelogs/AutoChangeLog-pr-5321.yml new file mode 100644 index 000000000000..e9e39a2c8c87 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5321.yml @@ -0,0 +1,4 @@ +author: "SabreML" +delete-after: True +changes: + - bugfix: "Fixed the pyro spec's fuel pack sometimes giving weird failure messages when trying to switch fuel." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5323.yml b/html/changelogs/AutoChangeLog-pr-5323.yml new file mode 100644 index 000000000000..1a521533c287 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5323.yml @@ -0,0 +1,5 @@ +author: "InsaneRed" +delete-after: True +changes: + - qol: "\"View Playtime\" is now under the \"Records\" section under OOC" + - qol: "\"Remove Your Splints\" is now under the \"IC\" section." \ No newline at end of file diff --git a/html/changelogs/archive/2023-12.yml b/html/changelogs/archive/2023-12.yml index 43d61e9d7aec..73cd5f8771a1 100644 --- a/html/changelogs/archive/2023-12.yml +++ b/html/changelogs/archive/2023-12.yml @@ -521,3 +521,17 @@ - code_imp: Tweaked the way prayer sends notifications to be more efficient. - admin: Moved the prayer notification sound to a toggle preference, combined with ARES Interface notifications. +2023-12-28: + InsaneRed: + - bugfix: Synths are no longer immune to lunges / dragging while in 'critical state' + since they dont go into crit. + SabreML: + - bugfix: Fixed inserting/removing an item from shoes sometimes acting weirdly. + - refactor: Refactored shoe item storage. + fira: + - bugfix: Fixed XRF Scanner bricking if people were adding and removing vials at + same time. +2023-12-29: + sleepynecrons: + - imageadd: new sprites for predalien, predlarva and weeded corpse + - imageadd: added predalien wound overlays diff --git a/icons/misc/tutorial.dmi b/icons/misc/tutorial.dmi new file mode 100644 index 000000000000..d4a4e65963ba Binary files /dev/null and b/icons/misc/tutorial.dmi differ diff --git a/icons/mob/xenos/predalien.dmi b/icons/mob/xenos/predalien.dmi index 1e3ec5caf806..c6162729b516 100644 Binary files a/icons/mob/xenos/predalien.dmi and b/icons/mob/xenos/predalien.dmi differ diff --git a/icons/mob/xenos/predalien_larva.dmi b/icons/mob/xenos/predalien_larva.dmi index 82786f273980..41eb31a2c809 100644 Binary files a/icons/mob/xenos/predalien_larva.dmi and b/icons/mob/xenos/predalien_larva.dmi differ diff --git a/icons/mob/xenos/weeds_64x64.dmi b/icons/mob/xenos/weeds_64x64.dmi index 26a31eb0fc60..53c971cfe97c 100644 Binary files a/icons/mob/xenos/weeds_64x64.dmi and b/icons/mob/xenos/weeds_64x64.dmi differ diff --git a/icons/mob/xenos/wounds.dmi b/icons/mob/xenos/wounds.dmi index bf7d573b73a9..730e367f43ae 100644 Binary files a/icons/mob/xenos/wounds.dmi and b/icons/mob/xenos/wounds.dmi differ diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi index 8b525fd568d6..c8bf32b00b40 100644 Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ diff --git a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm index b37d42f1a55f..ab98e02cb6e4 100644 --- a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm +++ b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm @@ -31053,7 +31053,7 @@ }, /area/fiorina/station/park) "sRv" = ( -/obj/item/clothing/shoes/marine/upp_knife, +/obj/item/clothing/shoes/marine/upp/knife, /turf/open/floor/prison, /area/fiorina/station/lowsec) "sRE" = ( diff --git a/maps/tutorial/tutorial_12x12.dmm b/maps/tutorial/tutorial_12x12.dmm new file mode 100644 index 000000000000..a682957ea702 --- /dev/null +++ b/maps/tutorial/tutorial_12x12.dmm @@ -0,0 +1,180 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/almayer/outer, +/area/misc/tutorial) +"z" = ( +/turf/open/floor/almayer, +/area/misc/tutorial) +"R" = ( +/obj/effect/landmark/tutorial_bottom_left, +/turf/open/floor/almayer, +/area/misc/tutorial) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +z +z +z +z +z +z +z +z +z +R +a +"} +(3,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(4,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(5,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(6,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(7,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(8,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(9,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(10,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(11,1,1) = {" +a +z +z +z +z +z +z +z +z +z +z +a +"} +(12,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/maps/tutorial/tutorial_7x7.dmm b/maps/tutorial/tutorial_7x7.dmm new file mode 100644 index 000000000000..4297ef72ab8b --- /dev/null +++ b/maps/tutorial/tutorial_7x7.dmm @@ -0,0 +1,75 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/almayer/outer, +/area/misc/tutorial) +"z" = ( +/turf/open/floor/almayer, +/area/misc/tutorial) +"R" = ( +/obj/effect/landmark/tutorial_bottom_left, +/turf/open/floor/almayer, +/area/misc/tutorial) + +(1,1,1) = {" +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +z +z +z +z +R +a +"} +(3,1,1) = {" +a +z +z +z +z +z +a +"} +(4,1,1) = {" +a +z +z +z +z +z +a +"} +(5,1,1) = {" +a +z +z +z +z +z +a +"} +(6,1,1) = {" +a +z +z +z +z +z +a +"} +(7,1,1) = {" +a +a +a +a +a +a +a +"} diff --git a/maps/tutorial/tutorial_8x9.dmm b/maps/tutorial/tutorial_8x9.dmm new file mode 100644 index 000000000000..fc0cdd7a3e48 --- /dev/null +++ b/maps/tutorial/tutorial_8x9.dmm @@ -0,0 +1,100 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/almayer/outer, +/area/misc/tutorial) +"z" = ( +/turf/open/floor/almayer, +/area/misc/tutorial) +"R" = ( +/obj/effect/landmark/tutorial_bottom_left, +/turf/open/floor/almayer, +/area/misc/tutorial) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +z +z +z +z +z +z +R +a +"} +(3,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(4,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(5,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(6,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(7,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(8,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/maps/tutorial/tutorial_8x9_nb.dmm b/maps/tutorial/tutorial_8x9_nb.dmm new file mode 100644 index 000000000000..2e03d5162f65 --- /dev/null +++ b/maps/tutorial/tutorial_8x9_nb.dmm @@ -0,0 +1,100 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/almayer/outer, +/area/misc/tutorial/no_baselight) +"z" = ( +/turf/open/floor/almayer, +/area/misc/tutorial/no_baselight) +"R" = ( +/obj/effect/landmark/tutorial_bottom_left, +/turf/open/floor/almayer, +/area/misc/tutorial/no_baselight) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +z +z +z +z +z +z +R +a +"} +(3,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(4,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(5,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(6,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(7,1,1) = {" +a +z +z +z +z +z +z +z +a +"} +(8,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/tgui/packages/tgui/components/Blink.js b/tgui/packages/tgui/components/Blink.jsx similarity index 100% rename from tgui/packages/tgui/components/Blink.js rename to tgui/packages/tgui/components/Blink.jsx diff --git a/tgui/packages/tgui/components/BlockQuote.js b/tgui/packages/tgui/components/BlockQuote.jsx similarity index 100% rename from tgui/packages/tgui/components/BlockQuote.js rename to tgui/packages/tgui/components/BlockQuote.jsx diff --git a/tgui/packages/tgui/components/Button.js b/tgui/packages/tgui/components/Button.jsx similarity index 100% rename from tgui/packages/tgui/components/Button.js rename to tgui/packages/tgui/components/Button.jsx diff --git a/tgui/packages/tgui/components/ByondUi.js b/tgui/packages/tgui/components/ByondUi.jsx similarity index 100% rename from tgui/packages/tgui/components/ByondUi.js rename to tgui/packages/tgui/components/ByondUi.jsx diff --git a/tgui/packages/tgui/components/Chart.js b/tgui/packages/tgui/components/Chart.jsx similarity index 100% rename from tgui/packages/tgui/components/Chart.js rename to tgui/packages/tgui/components/Chart.jsx diff --git a/tgui/packages/tgui/components/Collapsible.js b/tgui/packages/tgui/components/Collapsible.jsx similarity index 100% rename from tgui/packages/tgui/components/Collapsible.js rename to tgui/packages/tgui/components/Collapsible.jsx diff --git a/tgui/packages/tgui/components/ColorBox.js b/tgui/packages/tgui/components/ColorBox.jsx similarity index 100% rename from tgui/packages/tgui/components/ColorBox.js rename to tgui/packages/tgui/components/ColorBox.jsx diff --git a/tgui/packages/tgui/components/Dimmer.js b/tgui/packages/tgui/components/Dimmer.jsx similarity index 100% rename from tgui/packages/tgui/components/Dimmer.js rename to tgui/packages/tgui/components/Dimmer.jsx diff --git a/tgui/packages/tgui/components/Divider.js b/tgui/packages/tgui/components/Divider.jsx similarity index 100% rename from tgui/packages/tgui/components/Divider.js rename to tgui/packages/tgui/components/Divider.jsx diff --git a/tgui/packages/tgui/components/DraggableControl.js b/tgui/packages/tgui/components/DraggableControl.jsx similarity index 100% rename from tgui/packages/tgui/components/DraggableControl.js rename to tgui/packages/tgui/components/DraggableControl.jsx diff --git a/tgui/packages/tgui/components/Dropdown.js b/tgui/packages/tgui/components/Dropdown.jsx similarity index 100% rename from tgui/packages/tgui/components/Dropdown.js rename to tgui/packages/tgui/components/Dropdown.jsx diff --git a/tgui/packages/tgui/components/Grid.js b/tgui/packages/tgui/components/Grid.jsx similarity index 100% rename from tgui/packages/tgui/components/Grid.js rename to tgui/packages/tgui/components/Grid.jsx diff --git a/tgui/packages/tgui/components/Icon.js b/tgui/packages/tgui/components/Icon.jsx similarity index 100% rename from tgui/packages/tgui/components/Icon.js rename to tgui/packages/tgui/components/Icon.jsx diff --git a/tgui/packages/tgui/components/InfinitePlane.js b/tgui/packages/tgui/components/InfinitePlane.jsx similarity index 100% rename from tgui/packages/tgui/components/InfinitePlane.js rename to tgui/packages/tgui/components/InfinitePlane.jsx diff --git a/tgui/packages/tgui/components/Input.js b/tgui/packages/tgui/components/Input.jsx similarity index 100% rename from tgui/packages/tgui/components/Input.js rename to tgui/packages/tgui/components/Input.jsx diff --git a/tgui/packages/tgui/components/Knob.js b/tgui/packages/tgui/components/Knob.jsx similarity index 100% rename from tgui/packages/tgui/components/Knob.js rename to tgui/packages/tgui/components/Knob.jsx diff --git a/tgui/packages/tgui/components/LabeledControls.js b/tgui/packages/tgui/components/LabeledControls.jsx similarity index 100% rename from tgui/packages/tgui/components/LabeledControls.js rename to tgui/packages/tgui/components/LabeledControls.jsx diff --git a/tgui/packages/tgui/components/Modal.js b/tgui/packages/tgui/components/Modal.jsx similarity index 100% rename from tgui/packages/tgui/components/Modal.js rename to tgui/packages/tgui/components/Modal.jsx diff --git a/tgui/packages/tgui/components/NoticeBox.js b/tgui/packages/tgui/components/NoticeBox.jsx similarity index 100% rename from tgui/packages/tgui/components/NoticeBox.js rename to tgui/packages/tgui/components/NoticeBox.jsx diff --git a/tgui/packages/tgui/components/NumberInput.js b/tgui/packages/tgui/components/NumberInput.jsx similarity index 100% rename from tgui/packages/tgui/components/NumberInput.js rename to tgui/packages/tgui/components/NumberInput.jsx diff --git a/tgui/packages/tgui/components/ProgressBar.js b/tgui/packages/tgui/components/ProgressBar.jsx similarity index 100% rename from tgui/packages/tgui/components/ProgressBar.js rename to tgui/packages/tgui/components/ProgressBar.jsx diff --git a/tgui/packages/tgui/components/RestrictedInput.js b/tgui/packages/tgui/components/RestrictedInput.jsx similarity index 100% rename from tgui/packages/tgui/components/RestrictedInput.js rename to tgui/packages/tgui/components/RestrictedInput.jsx diff --git a/tgui/packages/tgui/components/RoundGauge.js b/tgui/packages/tgui/components/RoundGauge.jsx similarity index 100% rename from tgui/packages/tgui/components/RoundGauge.js rename to tgui/packages/tgui/components/RoundGauge.jsx diff --git a/tgui/packages/tgui/components/Slider.js b/tgui/packages/tgui/components/Slider.jsx similarity index 100% rename from tgui/packages/tgui/components/Slider.js rename to tgui/packages/tgui/components/Slider.jsx diff --git a/tgui/packages/tgui/components/Table.js b/tgui/packages/tgui/components/Table.jsx similarity index 100% rename from tgui/packages/tgui/components/Table.js rename to tgui/packages/tgui/components/Table.jsx diff --git a/tgui/packages/tgui/components/Tabs.js b/tgui/packages/tgui/components/Tabs.jsx similarity index 100% rename from tgui/packages/tgui/components/Tabs.js rename to tgui/packages/tgui/components/Tabs.jsx diff --git a/tgui/packages/tgui/components/TextArea.js b/tgui/packages/tgui/components/TextArea.jsx similarity index 100% rename from tgui/packages/tgui/components/TextArea.js rename to tgui/packages/tgui/components/TextArea.jsx diff --git a/tgui/packages/tgui/components/TimeDisplay.js b/tgui/packages/tgui/components/TimeDisplay.jsx similarity index 100% rename from tgui/packages/tgui/components/TimeDisplay.js rename to tgui/packages/tgui/components/TimeDisplay.jsx diff --git a/tgui/packages/tgui/components/index.js b/tgui/packages/tgui/components/index.jsx similarity index 100% rename from tgui/packages/tgui/components/index.js rename to tgui/packages/tgui/components/index.jsx diff --git a/tgui/packages/tgui/debug/KitchenSink.js b/tgui/packages/tgui/debug/KitchenSink.jsx similarity index 95% rename from tgui/packages/tgui/debug/KitchenSink.js rename to tgui/packages/tgui/debug/KitchenSink.jsx index 246b4f50b478..e25751722c52 100644 --- a/tgui/packages/tgui/debug/KitchenSink.js +++ b/tgui/packages/tgui/debug/KitchenSink.jsx @@ -8,7 +8,7 @@ import { useLocalState } from '../backend'; import { Flex, Section, Tabs } from '../components'; import { Pane, Window } from '../layouts'; -const r = require.context('../stories', false, /\.stories\.js$/); +const r = require.context('../stories', false, /\.stories\.jsx$/); /** * @returns {{ diff --git a/tgui/packages/tgui/interfaces/AcidVest.js b/tgui/packages/tgui/interfaces/AcidVest.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/AcidVest.js rename to tgui/packages/tgui/interfaces/AcidVest.jsx diff --git a/tgui/packages/tgui/interfaces/AlmayerControl.js b/tgui/packages/tgui/interfaces/AlmayerControl.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/AlmayerControl.js rename to tgui/packages/tgui/interfaces/AlmayerControl.jsx diff --git a/tgui/packages/tgui/interfaces/AltitudeControlConsole.js b/tgui/packages/tgui/interfaces/AltitudeControlConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/AltitudeControlConsole.js rename to tgui/packages/tgui/interfaces/AltitudeControlConsole.jsx diff --git a/tgui/packages/tgui/interfaces/AntiAirConsole.js b/tgui/packages/tgui/interfaces/AntiAirConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/AntiAirConsole.js rename to tgui/packages/tgui/interfaces/AntiAirConsole.jsx diff --git a/tgui/packages/tgui/interfaces/Apc.js b/tgui/packages/tgui/interfaces/Apc.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Apc.js rename to tgui/packages/tgui/interfaces/Apc.jsx diff --git a/tgui/packages/tgui/interfaces/AresInterface.js b/tgui/packages/tgui/interfaces/AresInterface.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/AresInterface.js rename to tgui/packages/tgui/interfaces/AresInterface.jsx diff --git a/tgui/packages/tgui/interfaces/Autodispenser.js b/tgui/packages/tgui/interfaces/Autodispenser.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Autodispenser.js rename to tgui/packages/tgui/interfaces/Autodispenser.jsx diff --git a/tgui/packages/tgui/interfaces/Autolathe.js b/tgui/packages/tgui/interfaces/Autolathe.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Autolathe.js rename to tgui/packages/tgui/interfaces/Autolathe.jsx diff --git a/tgui/packages/tgui/interfaces/Binoculars.js b/tgui/packages/tgui/interfaces/Binoculars.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Binoculars.js rename to tgui/packages/tgui/interfaces/Binoculars.jsx diff --git a/tgui/packages/tgui/interfaces/BioSyntheticPrinter.js b/tgui/packages/tgui/interfaces/BioSyntheticPrinter.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/BioSyntheticPrinter.js rename to tgui/packages/tgui/interfaces/BioSyntheticPrinter.jsx diff --git a/tgui/packages/tgui/interfaces/BotanyEditor.js b/tgui/packages/tgui/interfaces/BotanyEditor.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/BotanyEditor.js rename to tgui/packages/tgui/interfaces/BotanyEditor.jsx diff --git a/tgui/packages/tgui/interfaces/BotanyExtractor.js b/tgui/packages/tgui/interfaces/BotanyExtractor.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/BotanyExtractor.js rename to tgui/packages/tgui/interfaces/BotanyExtractor.jsx diff --git a/tgui/packages/tgui/interfaces/BrigCell.js b/tgui/packages/tgui/interfaces/BrigCell.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/BrigCell.js rename to tgui/packages/tgui/interfaces/BrigCell.jsx diff --git a/tgui/packages/tgui/interfaces/CameraConsole.js b/tgui/packages/tgui/interfaces/CameraConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/CameraConsole.js rename to tgui/packages/tgui/interfaces/CameraConsole.jsx diff --git a/tgui/packages/tgui/interfaces/CanvasLayer.js b/tgui/packages/tgui/interfaces/CanvasLayer.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/CanvasLayer.js rename to tgui/packages/tgui/interfaces/CanvasLayer.jsx diff --git a/tgui/packages/tgui/interfaces/CardMod.js b/tgui/packages/tgui/interfaces/CardMod.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/CardMod.js rename to tgui/packages/tgui/interfaces/CardMod.jsx diff --git a/tgui/packages/tgui/interfaces/Centrifuge.js b/tgui/packages/tgui/interfaces/Centrifuge.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Centrifuge.js rename to tgui/packages/tgui/interfaces/Centrifuge.jsx diff --git a/tgui/packages/tgui/interfaces/Changelog.js b/tgui/packages/tgui/interfaces/Changelog.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Changelog.js rename to tgui/packages/tgui/interfaces/Changelog.jsx diff --git a/tgui/packages/tgui/interfaces/ChemDispenser.js b/tgui/packages/tgui/interfaces/ChemDispenser.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ChemDispenser.js rename to tgui/packages/tgui/interfaces/ChemDispenser.jsx diff --git a/tgui/packages/tgui/interfaces/ChooseFruit.js b/tgui/packages/tgui/interfaces/ChooseFruit.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ChooseFruit.js rename to tgui/packages/tgui/interfaces/ChooseFruit.jsx diff --git a/tgui/packages/tgui/interfaces/ChooseResin.js b/tgui/packages/tgui/interfaces/ChooseResin.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ChooseResin.js rename to tgui/packages/tgui/interfaces/ChooseResin.jsx diff --git a/tgui/packages/tgui/interfaces/CommandTablet.js b/tgui/packages/tgui/interfaces/CommandTablet.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/CommandTablet.js rename to tgui/packages/tgui/interfaces/CommandTablet.jsx diff --git a/tgui/packages/tgui/interfaces/CrewConsole.js b/tgui/packages/tgui/interfaces/CrewConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/CrewConsole.js rename to tgui/packages/tgui/interfaces/CrewConsole.jsx diff --git a/tgui/packages/tgui/interfaces/Cryo.js b/tgui/packages/tgui/interfaces/Cryo.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Cryo.js rename to tgui/packages/tgui/interfaces/Cryo.jsx diff --git a/tgui/packages/tgui/interfaces/DemoSim.js b/tgui/packages/tgui/interfaces/DemoSim.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/DemoSim.js rename to tgui/packages/tgui/interfaces/DemoSim.jsx diff --git a/tgui/packages/tgui/interfaces/Disposals.js b/tgui/packages/tgui/interfaces/Disposals.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Disposals.js rename to tgui/packages/tgui/interfaces/Disposals.jsx diff --git a/tgui/packages/tgui/interfaces/DrawnMap.js b/tgui/packages/tgui/interfaces/DrawnMap.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/DrawnMap.js rename to tgui/packages/tgui/interfaces/DrawnMap.jsx diff --git a/tgui/packages/tgui/interfaces/FaxMachine.js b/tgui/packages/tgui/interfaces/FaxMachine.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/FaxMachine.js rename to tgui/packages/tgui/interfaces/FaxMachine.jsx diff --git a/tgui/packages/tgui/interfaces/Filteriffic.js b/tgui/packages/tgui/interfaces/Filteriffic.jsx similarity index 99% rename from tgui/packages/tgui/interfaces/Filteriffic.js rename to tgui/packages/tgui/interfaces/Filteriffic.jsx index a967efafca98..8bda997dff1b 100644 --- a/tgui/packages/tgui/interfaces/Filteriffic.js +++ b/tgui/packages/tgui/interfaces/Filteriffic.jsx @@ -1,6 +1,6 @@ import { map } from 'common/collections'; import { toFixed } from 'common/math'; -import { numberOfDecimalDigits } from '../../common/math'; +import { numberOfDecimalDigits } from 'common/math'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, Collapsible, ColorBox, Dropdown, Input, LabeledList, NoticeBox, NumberInput, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/FiltrationControl.js b/tgui/packages/tgui/interfaces/FiltrationControl.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/FiltrationControl.js rename to tgui/packages/tgui/interfaces/FiltrationControl.jsx diff --git a/tgui/packages/tgui/interfaces/HealthScan.js b/tgui/packages/tgui/interfaces/HealthScan.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/HealthScan.js rename to tgui/packages/tgui/interfaces/HealthScan.jsx diff --git a/tgui/packages/tgui/interfaces/HiveFaction.js b/tgui/packages/tgui/interfaces/HiveFaction.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/HiveFaction.js rename to tgui/packages/tgui/interfaces/HiveFaction.jsx diff --git a/tgui/packages/tgui/interfaces/HiveLeaders.js b/tgui/packages/tgui/interfaces/HiveLeaders.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/HiveLeaders.js rename to tgui/packages/tgui/interfaces/HiveLeaders.jsx diff --git a/tgui/packages/tgui/interfaces/HiveStatus.js b/tgui/packages/tgui/interfaces/HiveStatus.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/HiveStatus.js rename to tgui/packages/tgui/interfaces/HiveStatus.jsx diff --git a/tgui/packages/tgui/interfaces/KeyBinds.js b/tgui/packages/tgui/interfaces/KeyBinds.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/KeyBinds.js rename to tgui/packages/tgui/interfaces/KeyBinds.jsx diff --git a/tgui/packages/tgui/interfaces/KillPanel.js b/tgui/packages/tgui/interfaces/KillPanel.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/KillPanel.js rename to tgui/packages/tgui/interfaces/KillPanel.jsx diff --git a/tgui/packages/tgui/interfaces/LanguageMenu.js b/tgui/packages/tgui/interfaces/LanguageMenu.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/LanguageMenu.js rename to tgui/packages/tgui/interfaces/LanguageMenu.jsx diff --git a/tgui/packages/tgui/interfaces/ListInput.js b/tgui/packages/tgui/interfaces/ListInput.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ListInput.js rename to tgui/packages/tgui/interfaces/ListInput.jsx diff --git a/tgui/packages/tgui/interfaces/MedalsPanel.js b/tgui/packages/tgui/interfaces/MedalsPanel.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/MedalsPanel.js rename to tgui/packages/tgui/interfaces/MedalsPanel.jsx diff --git a/tgui/packages/tgui/interfaces/Mortar.js b/tgui/packages/tgui/interfaces/Mortar.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Mortar.js rename to tgui/packages/tgui/interfaces/Mortar.jsx diff --git a/tgui/packages/tgui/interfaces/NuclearBomb.js b/tgui/packages/tgui/interfaces/NuclearBomb.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/NuclearBomb.js rename to tgui/packages/tgui/interfaces/NuclearBomb.jsx diff --git a/tgui/packages/tgui/interfaces/OrbitalCannonConsole.js b/tgui/packages/tgui/interfaces/OrbitalCannonConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/OrbitalCannonConsole.js rename to tgui/packages/tgui/interfaces/OrbitalCannonConsole.jsx diff --git a/tgui/packages/tgui/interfaces/OverwatchConsole.js b/tgui/packages/tgui/interfaces/OverwatchConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/OverwatchConsole.js rename to tgui/packages/tgui/interfaces/OverwatchConsole.jsx diff --git a/tgui/packages/tgui/interfaces/PartFabricator.js b/tgui/packages/tgui/interfaces/PartFabricator.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/PartFabricator.js rename to tgui/packages/tgui/interfaces/PartFabricator.jsx diff --git a/tgui/packages/tgui/interfaces/PhoneMenu.js b/tgui/packages/tgui/interfaces/PhoneMenu.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/PhoneMenu.js rename to tgui/packages/tgui/interfaces/PhoneMenu.jsx diff --git a/tgui/packages/tgui/interfaces/PlayerPanel.js b/tgui/packages/tgui/interfaces/PlayerPanel.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/PlayerPanel.js rename to tgui/packages/tgui/interfaces/PlayerPanel.jsx diff --git a/tgui/packages/tgui/interfaces/PodLauncher.js b/tgui/packages/tgui/interfaces/PodLauncher.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/PodLauncher.js rename to tgui/packages/tgui/interfaces/PodLauncher.jsx diff --git a/tgui/packages/tgui/interfaces/Proximity.js b/tgui/packages/tgui/interfaces/Proximity.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Proximity.js rename to tgui/packages/tgui/interfaces/Proximity.jsx diff --git a/tgui/packages/tgui/interfaces/Radio.js b/tgui/packages/tgui/interfaces/Radio.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Radio.js rename to tgui/packages/tgui/interfaces/Radio.jsx diff --git a/tgui/packages/tgui/interfaces/ResearchDoorDisplay.js b/tgui/packages/tgui/interfaces/ResearchDoorDisplay.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ResearchDoorDisplay.js rename to tgui/packages/tgui/interfaces/ResearchDoorDisplay.jsx diff --git a/tgui/packages/tgui/interfaces/ResearchMemories.js b/tgui/packages/tgui/interfaces/ResearchMemories.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/ResearchMemories.js rename to tgui/packages/tgui/interfaces/ResearchMemories.jsx diff --git a/tgui/packages/tgui/interfaces/STUI.js b/tgui/packages/tgui/interfaces/STUI.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/STUI.js rename to tgui/packages/tgui/interfaces/STUI.jsx diff --git a/tgui/packages/tgui/interfaces/SelfDestructConsole.js b/tgui/packages/tgui/interfaces/SelfDestructConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/SelfDestructConsole.js rename to tgui/packages/tgui/interfaces/SelfDestructConsole.jsx diff --git a/tgui/packages/tgui/interfaces/Sentencing.js b/tgui/packages/tgui/interfaces/Sentencing.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Sentencing.js rename to tgui/packages/tgui/interfaces/Sentencing.jsx diff --git a/tgui/packages/tgui/interfaces/Signaller.js b/tgui/packages/tgui/interfaces/Signaller.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Signaller.js rename to tgui/packages/tgui/interfaces/Signaller.jsx diff --git a/tgui/packages/tgui/interfaces/SkillsMenu.js b/tgui/packages/tgui/interfaces/SkillsMenu.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/SkillsMenu.js rename to tgui/packages/tgui/interfaces/SkillsMenu.jsx diff --git a/tgui/packages/tgui/interfaces/Sleeper.js b/tgui/packages/tgui/interfaces/Sleeper.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Sleeper.js rename to tgui/packages/tgui/interfaces/Sleeper.jsx diff --git a/tgui/packages/tgui/interfaces/Smes.js b/tgui/packages/tgui/interfaces/Smes.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Smes.js rename to tgui/packages/tgui/interfaces/Smes.jsx diff --git a/tgui/packages/tgui/interfaces/SquadMod.js b/tgui/packages/tgui/interfaces/SquadMod.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/SquadMod.js rename to tgui/packages/tgui/interfaces/SquadMod.jsx diff --git a/tgui/packages/tgui/interfaces/StatbrowserOptions.js b/tgui/packages/tgui/interfaces/StatbrowserOptions.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/StatbrowserOptions.js rename to tgui/packages/tgui/interfaces/StatbrowserOptions.jsx diff --git a/tgui/packages/tgui/interfaces/StationAlertConsole.js b/tgui/packages/tgui/interfaces/StationAlertConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/StationAlertConsole.js rename to tgui/packages/tgui/interfaces/StationAlertConsole.jsx diff --git a/tgui/packages/tgui/interfaces/SupplyDropConsole.js b/tgui/packages/tgui/interfaces/SupplyDropConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/SupplyDropConsole.js rename to tgui/packages/tgui/interfaces/SupplyDropConsole.jsx diff --git a/tgui/packages/tgui/interfaces/TacmapAdminPanel.js b/tgui/packages/tgui/interfaces/TacmapAdminPanel.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/TacmapAdminPanel.js rename to tgui/packages/tgui/interfaces/TacmapAdminPanel.jsx diff --git a/tgui/packages/tgui/interfaces/Tank.js b/tgui/packages/tgui/interfaces/Tank.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Tank.js rename to tgui/packages/tgui/interfaces/Tank.jsx diff --git a/tgui/packages/tgui/interfaces/TechControl.js b/tgui/packages/tgui/interfaces/TechControl.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/TechControl.js rename to tgui/packages/tgui/interfaces/TechControl.jsx diff --git a/tgui/packages/tgui/interfaces/TechMemories.js b/tgui/packages/tgui/interfaces/TechMemories.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/TechMemories.js rename to tgui/packages/tgui/interfaces/TechMemories.jsx diff --git a/tgui/packages/tgui/interfaces/TechNode.js b/tgui/packages/tgui/interfaces/TechNode.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/TechNode.js rename to tgui/packages/tgui/interfaces/TechNode.jsx diff --git a/tgui/packages/tgui/interfaces/TeleporterConsole.js b/tgui/packages/tgui/interfaces/TeleporterConsole.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/TeleporterConsole.js rename to tgui/packages/tgui/interfaces/TeleporterConsole.jsx diff --git a/tgui/packages/tgui/interfaces/Timer.js b/tgui/packages/tgui/interfaces/Timer.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Timer.js rename to tgui/packages/tgui/interfaces/Timer.jsx diff --git a/tgui/packages/tgui/interfaces/TutorialMenu.tsx b/tgui/packages/tgui/interfaces/TutorialMenu.tsx new file mode 100644 index 000000000000..ee22f1a02996 --- /dev/null +++ b/tgui/packages/tgui/interfaces/TutorialMenu.tsx @@ -0,0 +1,149 @@ +import { classes } from 'common/react'; +import { useBackend, useLocalState } from '../backend'; +import { Section, Stack, Box, Divider, Button, Tabs } from '../components'; +import { Window } from '../layouts'; + +type Tutorial = { + name: string; + path: string; + id: string; + description: string; + image: string; +}; + +type TutorialCategory = { + tutorials: Tutorial[]; + name: string; +}; + +type BackendContext = { + tutorial_categories: TutorialCategory[]; + completed_tutorials: string[]; +}; + +export const TutorialMenu = (props, context) => { + const { data, act } = useBackend(context); + const { tutorial_categories, completed_tutorials } = data; + const [chosenTutorial, setTutorial] = useLocalState( + context, + 'tutorial', + null + ); + const [categoryIndex, setCategoryIndex] = useLocalState( + context, + 'category_index', + 'Space Station 13' + ); + return ( + + + + + + + {tutorial_categories.map((item, key) => ( + { + setCategoryIndex(item.name); + }}> + {item.name} + + ))} + + + + + +
+ {tutorial_categories.map( + (tutorial_category) => + tutorial_category.name === categoryIndex && + tutorial_category.tutorials.map((tutorial) => ( +
+ +
+ )) + )} +
+
+ + +
+ {chosenTutorial !== null ? ( + + +
+ + + +
+
+ {chosenTutorial.description} + {completed_tutorials.indexOf(chosenTutorial.id) === -1 ? ( +
+ ) : ( + + Tutorial has been completed. + + )} + +
+
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/VehicleStatus.js b/tgui/packages/tgui/interfaces/VehicleStatus.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/VehicleStatus.js rename to tgui/packages/tgui/interfaces/VehicleStatus.jsx diff --git a/tgui/packages/tgui/interfaces/VoteMenu.js b/tgui/packages/tgui/interfaces/VoteMenu.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/VoteMenu.js rename to tgui/packages/tgui/interfaces/VoteMenu.jsx diff --git a/tgui/packages/tgui/interfaces/VoxPanel.js b/tgui/packages/tgui/interfaces/VoxPanel.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/VoxPanel.js rename to tgui/packages/tgui/interfaces/VoxPanel.jsx diff --git a/tgui/packages/tgui/interfaces/WeaponStats.js b/tgui/packages/tgui/interfaces/WeaponStats.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/WeaponStats.js rename to tgui/packages/tgui/interfaces/WeaponStats.jsx diff --git a/tgui/packages/tgui/interfaces/Wires.js b/tgui/packages/tgui/interfaces/Wires.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/Wires.js rename to tgui/packages/tgui/interfaces/Wires.jsx diff --git a/tgui/packages/tgui/interfaces/WorkingJoe.js b/tgui/packages/tgui/interfaces/WorkingJoe.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/WorkingJoe.js rename to tgui/packages/tgui/interfaces/WorkingJoe.jsx diff --git a/tgui/packages/tgui/interfaces/common/AccessList.js b/tgui/packages/tgui/interfaces/common/AccessList.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/common/AccessList.js rename to tgui/packages/tgui/interfaces/common/AccessList.jsx diff --git a/tgui/packages/tgui/interfaces/common/BeakerContents.js b/tgui/packages/tgui/interfaces/common/BeakerContents.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/common/BeakerContents.js rename to tgui/packages/tgui/interfaces/common/BeakerContents.jsx diff --git a/tgui/packages/tgui/interfaces/common/InterfaceLockNoticeBox.js b/tgui/packages/tgui/interfaces/common/InterfaceLockNoticeBox.jsx similarity index 100% rename from tgui/packages/tgui/interfaces/common/InterfaceLockNoticeBox.js rename to tgui/packages/tgui/interfaces/common/InterfaceLockNoticeBox.jsx diff --git a/tgui/packages/tgui/layouts/Layout.js b/tgui/packages/tgui/layouts/Layout.jsx similarity index 100% rename from tgui/packages/tgui/layouts/Layout.js rename to tgui/packages/tgui/layouts/Layout.jsx diff --git a/tgui/packages/tgui/layouts/NtosWindow.js b/tgui/packages/tgui/layouts/NtosWindow.jsx similarity index 100% rename from tgui/packages/tgui/layouts/NtosWindow.js rename to tgui/packages/tgui/layouts/NtosWindow.jsx diff --git a/tgui/packages/tgui/layouts/Pane.js b/tgui/packages/tgui/layouts/Pane.jsx similarity index 100% rename from tgui/packages/tgui/layouts/Pane.js rename to tgui/packages/tgui/layouts/Pane.jsx diff --git a/tgui/packages/tgui/layouts/Window.js b/tgui/packages/tgui/layouts/Window.jsx similarity index 100% rename from tgui/packages/tgui/layouts/Window.js rename to tgui/packages/tgui/layouts/Window.jsx diff --git a/tgui/packages/tgui/routes.js b/tgui/packages/tgui/routes.jsx similarity index 98% rename from tgui/packages/tgui/routes.js rename to tgui/packages/tgui/routes.jsx index eb4ddff15393..0ad869fc63cb 100644 --- a/tgui/packages/tgui/routes.js +++ b/tgui/packages/tgui/routes.jsx @@ -74,6 +74,7 @@ export const getRoutedComponent = (store) => { const name = config?.interface; const interfacePathBuilders = [ (name) => `./${name}.tsx`, + (name) => `./${name}.jsx`, (name) => `./${name}.js`, (name) => `./${name}/index.tsx`, (name) => `./${name}/index.js`, diff --git a/tgui/packages/tgui/stories/Blink.stories.js b/tgui/packages/tgui/stories/Blink.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Blink.stories.js rename to tgui/packages/tgui/stories/Blink.stories.jsx diff --git a/tgui/packages/tgui/stories/BlockQuote.stories.js b/tgui/packages/tgui/stories/BlockQuote.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/BlockQuote.stories.js rename to tgui/packages/tgui/stories/BlockQuote.stories.jsx diff --git a/tgui/packages/tgui/stories/Box.stories.js b/tgui/packages/tgui/stories/Box.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Box.stories.js rename to tgui/packages/tgui/stories/Box.stories.jsx diff --git a/tgui/packages/tgui/stories/Button.stories.js b/tgui/packages/tgui/stories/Button.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Button.stories.js rename to tgui/packages/tgui/stories/Button.stories.jsx diff --git a/tgui/packages/tgui/stories/ByondUi.stories.js b/tgui/packages/tgui/stories/ByondUi.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/ByondUi.stories.js rename to tgui/packages/tgui/stories/ByondUi.stories.jsx diff --git a/tgui/packages/tgui/stories/Collapsible.stories.js b/tgui/packages/tgui/stories/Collapsible.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Collapsible.stories.js rename to tgui/packages/tgui/stories/Collapsible.stories.jsx diff --git a/tgui/packages/tgui/stories/Flex.stories.js b/tgui/packages/tgui/stories/Flex.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Flex.stories.js rename to tgui/packages/tgui/stories/Flex.stories.jsx diff --git a/tgui/packages/tgui/stories/Input.stories.js b/tgui/packages/tgui/stories/Input.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Input.stories.js rename to tgui/packages/tgui/stories/Input.stories.jsx diff --git a/tgui/packages/tgui/stories/LabeledList.stories.js b/tgui/packages/tgui/stories/LabeledList.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/LabeledList.stories.js rename to tgui/packages/tgui/stories/LabeledList.stories.jsx diff --git a/tgui/packages/tgui/stories/Popper.stories.js b/tgui/packages/tgui/stories/Popper.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Popper.stories.js rename to tgui/packages/tgui/stories/Popper.stories.jsx diff --git a/tgui/packages/tgui/stories/ProgressBar.stories.js b/tgui/packages/tgui/stories/ProgressBar.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/ProgressBar.stories.js rename to tgui/packages/tgui/stories/ProgressBar.stories.jsx diff --git a/tgui/packages/tgui/stories/Stack.stories.js b/tgui/packages/tgui/stories/Stack.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Stack.stories.js rename to tgui/packages/tgui/stories/Stack.stories.jsx diff --git a/tgui/packages/tgui/stories/Storage.stories.js b/tgui/packages/tgui/stories/Storage.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Storage.stories.js rename to tgui/packages/tgui/stories/Storage.stories.jsx diff --git a/tgui/packages/tgui/stories/Tabs.stories.js b/tgui/packages/tgui/stories/Tabs.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Tabs.stories.js rename to tgui/packages/tgui/stories/Tabs.stories.jsx diff --git a/tgui/packages/tgui/stories/Themes.stories.js b/tgui/packages/tgui/stories/Themes.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Themes.stories.js rename to tgui/packages/tgui/stories/Themes.stories.jsx diff --git a/tgui/packages/tgui/stories/Tooltip.stories.js b/tgui/packages/tgui/stories/Tooltip.stories.jsx similarity index 100% rename from tgui/packages/tgui/stories/Tooltip.stories.js rename to tgui/packages/tgui/stories/Tooltip.stories.jsx diff --git a/tgui/packages/tgui/stories/common.js b/tgui/packages/tgui/stories/common.jsx similarity index 100% rename from tgui/packages/tgui/stories/common.js rename to tgui/packages/tgui/stories/common.jsx diff --git a/tgui/webpack.config.js b/tgui/webpack.config.js index 19e2975715fa..f90b80926e44 100644 --- a/tgui/webpack.config.js +++ b/tgui/webpack.config.js @@ -55,13 +55,13 @@ module.exports = (env = {}, argv) => { chunkLoadTimeout: 15000, }, resolve: { - extensions: ['.tsx', '.ts', '.js'], + extensions: ['.jsx', '.tsx', '.ts', '.js'], alias: {}, }, module: { rules: [ { - test: /\.(js|cjs|ts|tsx)$/, + test: /\.(js|jsx|cjs|ts|tsx)$/, use: [ { loader: require.resolve('babel-loader'),