diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 86a3bd4c31dd..9d0031a80790 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -132,6 +132,7 @@ #define VV_HK_MAKE_ALIEN "human_alienify" #define VV_HK_SET_SPECIES "setspecies" #define VV_HK_PURRBATION "purrbation" +#define VV_HK_APPLY_PREFS "applyprefs" // misc #define VV_HK_SPACEVINE_PURGE "spacevine_purge" diff --git a/code/datums/changelog/changelog.dm b/code/datums/changelog/changelog.dm index 3ce51c60344c..1b7c76232536 100644 --- a/code/datums/changelog/changelog.dm +++ b/code/datums/changelog/changelog.dm @@ -25,7 +25,7 @@ var/list/data = list( "dates" = list() ) var/regex/ymlRegex = regex(@"\.yml", "g") - for(var/archive_file in flist("[global.config.directory]/../html/changelogs/archive/")) + for(var/archive_file in sort_list(flist("html/changelogs/archive/"))) var/archive_date = ymlRegex.Replace(archive_file, "") data["dates"] = list(archive_date) + data["dates"] diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ae7e94b213ff..dd18f38d571e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -740,6 +740,7 @@ VV_DROPDOWN_OPTION(VV_HK_MAKE_ALIEN, "Make Alien") VV_DROPDOWN_OPTION(VV_HK_SET_SPECIES, "Set Species") VV_DROPDOWN_OPTION(VV_HK_PURRBATION, "Toggle Purrbation") + VV_DROPDOWN_OPTION(VV_HK_APPLY_PREFS, "Apply preferences") /mob/living/carbon/human/vv_do_topic(list/href_list) . = ..() @@ -801,6 +802,34 @@ var/msg = "[key_name_admin(usr)] has removed [key_name(src)] from purrbation." message_admins(msg) admin_ticket_log(src, msg) + if(href_list[VV_HK_APPLY_PREFS]) + if(!check_rights(R_SPAWN)) + return + if(!client) + var/bigtext = {"This action requires a client, if you need to do anything special, follow this short guide: +
+Mark this mob, then navigate to the preferences of the client you desire and call copy_to() with one argument, when it asks for the argument, browse to the bottom of the list and select marked datum, if you've followed this guide correctly, the mob will be turned into the character from the preferences you used. +
+ "} + to_chat(usr, bigtext) + return + + var/datum/preferences/copying_this_one = client.prefs // turns out that prefs always exist if the client leaves, i'm not checking for client again + var/is_this_guy_trolling_the_admin = copying_this_one.default_slot + + if(alert(usr, "Confirm reapply preferences?", "", "I'm sure", "Cancel") != "I'm sure") + return + + if(is_this_guy_trolling_the_admin != copying_this_one.default_slot) // why would you do this, broooo + if(alert(usr, "The user changed their character slot while you were deciding, are you sure you want to do this? They might change their mind again and i will not protect again this time", "Uh oh", "I'm sure", "They did what?") != "I'm sure") + return + + copying_this_one.copy_to(src) + var/change_text = "reapplied [key_name(src, TRUE)]'s preferences, [(is_this_guy_trolling_the_admin != copying_this_one.default_slot) ? "changing their character" : "resetting their character"]." + to_chat(usr, capitalize(change_text)) + log_admin("[key_name(usr)] has [change_text]") + message_admins(span_notice("[key_name_admin(usr)] has [change_text]")) + admin_ticket_log(src, span_notice("[key_name_admin(usr, FALSE)] has [change_text]")) // In case they complained in an ahelp, we'll let them know anything happened /mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user) var/GS_needed = istype(target, /mob/living/silicon/pai)? GRAB_PASSIVE : GRAB_AGGRESSIVE diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm index c00357245a7a..9ed9f9b03735 100644 --- a/code/modules/vehicles/_vehicle.dm +++ b/code/modules/vehicles/_vehicle.dm @@ -8,23 +8,41 @@ density = TRUE anchored = FALSE COOLDOWN_DECLARE(cooldown_vehicle_move) - var/list/mob/occupants //mob = bitflags of their control level. + /// mob = bitflags of their control level. + var/list/mob/occupants var/max_occupants = 1 + /// Maximum amount of drivers var/max_drivers = 1 var/movedelay = 2 var/lastmove = 0 + /** + * If the driver needs a certain item in hand (or inserted, for vehicles) to drive this. For vehicles, this must be duplicated on their riding component subtype + * [/datum/component/riding/var/keytype] variable because only a few specific checks are handled here with this var, and the majority of it is on the riding component + * Eventually the remaining checks should be moved to the component and this var removed. + */ var/key_type + /// The inserted key, needed on some vehicles to start the engine var/obj/item/key/inserted_key - var/key_type_exact = TRUE //can subtypes work + /// Can subtypes of this key work + var/key_type_exact = TRUE + /// Whether the vehicle is currently able to move var/canmove = TRUE - var/emulate_door_bumps = TRUE //when bumping a door try to make occupants bump them to open them. - var/default_driver_move = TRUE //handle driver movement instead of letting something else do it like riding datums. - var/enclosed = FALSE // is the rider protected from bullets? assume no - var/list/autogrant_actions_passenger = list() //plain list of typepaths - var/list/autogrant_actions_controller = list() //assoc list "[bitflag]" = list(typepaths) - var/list/mob/occupant_actions = list() //assoc list mob = list(type = action datum assigned to mob) + /// When bumping a door try to make occupants bump them to open them. + var/emulate_door_bumps = TRUE + /// Handle driver movement instead of letting something else do it like riding datums. + var/default_driver_move = TRUE + /// Is the rider protected from bullets? assume no + var/enclosed = FALSE + /// Plain list of typepaths + var/list/autogrant_actions_passenger = list() + /// Assoc list "[bitflag]" = list(typepaths) + var/list/autogrant_actions_controller = list() + /// Assoc list mob = list(type = action datum assigned to mob) + var/list/mob/occupant_actions = list() + /// This vehicle will follow us when we move (like atrailer duh) var/obj/vehicle/trailer - var/mouse_pointer //do we have a special mouse + /// Do we have a special mouse + var/mouse_pointer /obj/vehicle/Initialize(mapload) . = ..() @@ -33,18 +51,29 @@ /obj/vehicle/examine(mob/user) . = ..() if(resistance_flags & ON_FIRE) - . += "It's on fire!" - var/healthpercent = obj_integrity/max_integrity * 100 - switch(healthpercent) + . += span_warning("It's on fire!") + . += generate_integrity_message() + +/// Returns a readable string of the vehicle's health for examining. Overridden by subtypes who want to be more verbose with their health messages. +/obj/vehicle/proc/generate_integrity_message() + var/examine_text = "" + var/integrity = obj_integrity/max_integrity * 100 + switch(integrity) if(50 to 99) - . += "It looks slightly damaged." + examine_text = "It looks slightly damaged." if(25 to 50) - . += "It appears heavily damaged." + examine_text = "It appears heavily damaged." if(0 to 25) - . += "It's falling apart!" + examine_text = span_warning("It's falling apart!") -/obj/vehicle/proc/is_key(obj/item/I) - return I? (key_type_exact? (I.type == key_type) : istype(I, key_type)) : FALSE + return examine_text + +/obj/vehicle/proc/is_key(obj/item/possible_key) + if(possible_key) + if(key_type_exact) + return possible_key.type == key_type + return istype(possible_key, key_type) + return FALSE /obj/vehicle/proc/return_occupants() return occupants @@ -75,7 +104,7 @@ return is_occupant(M) && occupants[M] & VEHICLE_CONTROL_DRIVE /obj/vehicle/proc/is_occupant(mob/M) - return !isnull(occupants?[M]) + return !isnull(LAZYACCESS(occupants, M)) /obj/vehicle/proc/add_occupant(mob/M, control_flags) if(!istype(M) || is_occupant(M)) @@ -95,6 +124,7 @@ add_control_flags(M, VEHICLE_CONTROL_DRIVE) /obj/vehicle/proc/remove_occupant(mob/M) + SHOULD_CALL_PARENT(TRUE) if(!istype(M)) return FALSE remove_control_flags(M, ALL) @@ -107,13 +137,15 @@ /obj/vehicle/proc/after_remove_occupant(mob/M) /obj/vehicle/relaymove(mob/user, direction) + if(!canmove) + return FALSE if(is_driver(user)) return driver_move(user, direction) return FALSE /obj/vehicle/proc/driver_move(mob/user, direction) if(key_type && !is_key(inserted_key)) - to_chat(user, "[src] has no key inserted!") + to_chat(user, span_warning("[src] has no key inserted!")) return FALSE if(!default_driver_move) return @@ -123,15 +155,15 @@ if(!COOLDOWN_FINISHED(src, cooldown_vehicle_move)) return FALSE COOLDOWN_START(src, cooldown_vehicle_move, movedelay) + if(trailer) var/dir_to_move = get_dir(trailer.loc, loc) var/did_move = step(src, direction) if(did_move) step(trailer, dir_to_move) return did_move - else - after_move(direction) - return step(src, direction) + after_move(direction) + return step(src, direction) /obj/vehicle/proc/after_move(direction) return @@ -161,10 +193,24 @@ for(var/m in occupants) M.Bumped(m) +/// To add a trailer to the vehicle in a manner that allows safe qdels +/obj/vehicle/proc/add_trailer(obj/vehicle/added_vehicle) + trailer = added_vehicle + RegisterSignal(trailer, COMSIG_PARENT_QDELETING, PROC_REF(remove_trailer)) + +/// To remove a trailer from the vehicle in a manner that allows safe qdels +/obj/vehicle/proc/remove_trailer() + SIGNAL_HANDLER + UnregisterSignal(trailer, COMSIG_PARENT_QDELETING) + trailer = null + /obj/vehicle/Move(newloc, dir) + // It is unfortunate, but this is the way to make it not mess up + var/atom/old_loc = loc + // When we do this, it will set the loc to the new loc . = ..() if(trailer && .) - var/dir_to_move = get_dir(trailer.loc, newloc) + var/dir_to_move = get_dir(trailer.loc, old_loc) step(trailer, dir_to_move) /obj/vehicle/bullet_act(obj/item/projectile/Proj) //wrapper diff --git a/html/changelogs/archive/2024-07.yml b/html/changelogs/archive/2024-07.yml index 0dcae1cda1e2..12510c4e0081 100644 --- a/html/changelogs/archive/2024-07.yml +++ b/html/changelogs/archive/2024-07.yml @@ -10,3 +10,6 @@ - rscadd: Added K4T cyborgs. I think it's just tall, buff cat? - tweak: Changes some default MEKA sprites. Few were kept with ported ones being alternative. +2024-07-05: + SandPoot: + - bugfix: Fixed runtimes on hugbot. diff --git a/icons/obj/dice.dmi b/icons/obj/dice.dmi index aecdbde71c61..fa5c5abc5fef 100644 Binary files a/icons/obj/dice.dmi and b/icons/obj/dice.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index 6089a1c30dd7..5a8cf5ae001d 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -85,7 +85,7 @@ if(!GLOB.changelog_tgui) GLOB.changelog_tgui = new /datum/changelog() - GLOB.changelog_tgui.ui_interact(usr) + GLOB.changelog_tgui.ui_interact(mob) if(prefs.lastchangelog != GLOB.changelog_hash) prefs.lastchangelog = GLOB.changelog_hash prefs.save_preferences() diff --git a/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm b/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm index 2d949b5297ec..43e7e79f4904 100644 --- a/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm +++ b/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm @@ -294,10 +294,10 @@ return if(patient && path.len == 0 && (get_dist(src,patient) > 1)) - path = get_path_to(src, get_turf(patient), 0, 30,id=access_card) + path = get_path_to(src, patient, 30, id=access_card) mode = BOT_MOVING if(!path.len) //try to get closer if you can't reach the patient directly - path = get_path_to(src, get_turf(patient), 0, 30,1,id=access_card) + path = get_path_to(src, patient, 30, 1, id=access_card) if(!path.len) //Do not chase a patient we cannot reach. soft_reset()