From 5a90dabd3c861065594968802e478e14acbe0d22 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 3 Oct 2023 23:22:57 -0300 Subject: [PATCH 1/3] stuff --- code/__DEFINES/dcs/signals/signals_global.dm | 2 + .../signals/signals_mob/signals_mob_main.dm | 2 + code/__HELPERS/pronouns.dm | 15 +++ code/datums/components/riding.dm | 9 ++ code/datums/elements/mob_holder.dm | 75 +++++++----- code/game/objects/buckling.dm | 25 +++- code/game/objects/items.dm | 12 ++ code/game/objects/items/cigs_lighters.dm | 1 + .../structures/beds_chairs/alien_nest.dm | 2 +- code/game/objects/structures/kitchen_spike.dm | 2 +- code/game/objects/structures/manned_turret.dm | 2 +- code/game/objects/structures/morgue.dm | 11 ++ code/game/objects/structures/tables_racks.dm | 34 +++++- .../clock_structures/traps/brass_skewer.dm | 2 +- .../antagonists/devil/true_devil/inventory.dm | 2 +- code/modules/mob/inventory.dm | 16 ++- .../living/carbon/alien/larva/inventory.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 109 +++++++++--------- .../simple_animal/guardian/types/dextrous.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- .../mob/living/simple_animal/slime/slime.dm | 2 +- code/modules/power/singularity/emitter.dm | 2 +- tgstation.dme | 2 + 23 files changed, 228 insertions(+), 105 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/signals_global.dm create mode 100644 code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm new file mode 100644 index 0000000000..3e0e1d2296 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -0,0 +1,2 @@ +/// a person somewhere has thrown something : (mob/living/carbon/carbon_thrower, target) +#define COMSIG_GLOB_CARBON_THROW_THING "!throw_thing" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm new file mode 100644 index 0000000000..e6c3464ff7 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -0,0 +1,2 @@ +/// from mob/proc/dropItemToGround() +#define COMSIG_MOB_DROPPING_ITEM "mob_dropping_item" diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index bfe09ba370..fd15c05c64 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -39,6 +39,21 @@ /datum/proc/p_es(temp_gender) . = "es" +/datum/proc/plural_s(pluralize) + switch(copytext_char(pluralize, -2)) + if ("ss") + return "es" + if ("sh") + return "es" + if ("ch") + return "es" + else + switch(copytext_char(pluralize, -1)) + if("s", "x", "z") + return "es" + else + return "s" + //like clients, which do have gender. /client/p_they(capitalized, temp_gender) if(!temp_gender) diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index a074fe6f5f..49b8f7f7f0 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -392,3 +392,12 @@ if(rider in AM.buckled_mobs) AM.unbuckle_mob(rider) . = ..() + +/obj/item/riding_offhand/on_thrown(mob/living/carbon/user, atom/target) + if(rider == user) + return //Piggyback user. + user.unbuckle_mob(rider) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, span_notice("You gently let go of [rider].")) + return + return rider diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 5f57b4fce3..82f42d69b3 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -61,7 +61,7 @@ return FALSE source.visible_message("[user] starts picking up [source].", \ "[user] starts picking you up!") - if(!do_after(user, 20, target = source) || source.buckled) + if(!do_after(user, 2 SECONDS, target = source) || source.buckled) return FALSE source.visible_message("[user] picks up [source]!", \ @@ -95,6 +95,7 @@ dynamic_hair_suffix = "" var/mob/living/held_mob var/escape_on_find + var/destroying = FALSE /obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE) . = ..() @@ -134,45 +135,54 @@ w_class = WEIGHT_CLASS_HUGE /obj/item/clothing/head/mob_holder/Destroy() + destroying = TRUE if(held_mob) - release() + release(FALSE) return ..() /obj/item/clothing/head/mob_holder/examine(mob/user) return held_mob?.examine(user) || ..() -/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc) - . = ..() - if(AM == held_mob) - held_mob.reset_perspective() - held_mob = null - QDEL_IN(src, 1) //To avoid a qdel loop. +/obj/item/clothing/head/mob_holder/on_thrown(mob/living/carbon/user, atom/target) + if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP)) + return + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, span_notice("You set [src] down gently on the ground.")) + release() + return -/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc) - . = ..() - if(AM != held_mob) - var/destination = loc - if(isliving(loc)) //the mob is held or worn, drop things on the floor - destination = get_turf(loc) - AM.forceMove(destination) + var/mob/living/throw_mob = held_mob + release() + return throw_mob /obj/item/clothing/head/mob_holder/dropped(mob/user) . = ..() - if(held_mob && !ismob(loc) && !istype(loc,/obj/item/storage))//don't release on soft-drops + if(held_mob && isturf(loc)) release() -/obj/item/clothing/head/mob_holder/proc/release() - if(held_mob) - var/mob/living/L = held_mob - held_mob = null - L.forceMove(get_turf(L)) - L.reset_perspective() - L.setDir(SOUTH) - if(!QDELETED(src)) +/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE, display_messages = TRUE) + if(!held_mob) + if(del_on_release && !destroying) + qdel(src) + return FALSE + var/mob/living/released_mob = held_mob + held_mob = null // stops the held mob from being release()'d twice. + if(isliving(loc)) + var/mob/living/L = loc + if(display_messages) + to_chat(L, span_warning("[released_mob] wriggles free!")) + L.dropItemToGround(src) + released_mob.forceMove(drop_location()) + released_mob.reset_perspective() + released_mob.setDir(SOUTH) + if(display_messages) + released_mob.visible_message(span_warning("[released_mob] uncurls!")) + if(del_on_release && !destroying) qdel(src) + return TRUE -/obj/item/clothing/head/mob_holder/relaymove(mob/user) - return +/obj/item/clothing/head/mob_holder/relaymove(mob/living/user, direction) + container_resist() /obj/item/clothing/head/mob_holder/container_resist() if(isliving(loc)) @@ -180,6 +190,11 @@ L.visible_message("[held_mob] escapes from [L]!", "[held_mob] escapes your grip!") release() +/obj/item/clothing/head/mob_holder/Exited(atom/movable/gone, direction) + . = ..() + if(held_mob && held_mob == gone) + release() + /obj/item/clothing/head/mob_holder/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self) if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys... return FALSE @@ -232,7 +247,9 @@ return location.transfer_air(taker, ratio) // escape when found if applicable -/obj/item/clothing/head/mob_holder/on_found(mob/living/finder) +/obj/item/clothing/head/mob_holder/on_found(mob/finder) if(escape_on_find) - finder.visible_message("[finder] accidentally releases the [held_mob]!") - release() + to_chat(finder, span_warning("\A [held_mob.name] pops out! ")) + finder.visible_message(span_warning("\A [held_mob.name] pops out of the container [finder] is opening!"), ignored_mobs = finder) + release(TRUE, FALSE) + return diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index afc4312779..aae6cbaa5c 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -25,11 +25,32 @@ if(user_unbuckle_mob(buckled_mobs[1],user)) return 1 +/atom/movable/attackby(obj/item/attacking_item, mob/user, params) + if(!can_buckle || !istype(attacking_item, /obj/item/riding_offhand) || !user.Adjacent(src)) + return ..() + + var/obj/item/riding_offhand/riding_item = attacking_item + var/mob/living/carried_mob = riding_item.rider + if(carried_mob == user) //Piggyback user. + return + user.unbuckle_mob(carried_mob) + carried_mob.forceMove(get_turf(src)) + return mouse_buckle_handling(carried_mob, user) + /atom/movable/MouseDrop_T(mob/living/M, mob/living/user) . = ..() + return mouse_buckle_handling(M, user) + +/** + * Does some typechecks and then calls user_buckle_mob + * + * Arguments: + * M - The mob being buckled to src + * user - The mob buckling M to src + */ +/atom/movable/proc/mouse_buckle_handling(mob/living/M, mob/living/user) if(can_buckle && istype(M) && istype(user)) - if(user_buckle_mob(M, user)) - return 1 + return user_buckle_mob(M, user, check_loc = FALSE) /atom/movable/proc/has_buckled_mobs() if(!buckled_mobs) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 7a953089a5..e63f809a5e 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -177,6 +177,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/canMouseDown = FALSE + /// Used if we want to have a custom verb text for throwing. "John Spaceman flicks the ciggerate" for example. + var/throw_verb /obj/item/Initialize(mapload) @@ -1116,6 +1118,16 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb QDEL_NULL(src) return TRUE +///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else. +/obj/item/proc/on_thrown(mob/living/carbon/user, atom/target) + if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP)) + return + user.dropItemToGround(src, silent = TRUE) + if(throwforce && HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, span_notice("You set [src] down gently on the ground.")) + return + return src + /** diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 518772c771..a52bbb75f3 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -108,6 +108,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM w_class = WEIGHT_CLASS_TINY body_parts_covered = null grind_results = list() + throw_verb = "flick" var/lit = FALSE var/starts_lit = FALSE var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm index 77b3279517..eafacf4456 100644 --- a/code/game/objects/structures/beds_chairs/alien_nest.dm +++ b/code/game/objects/structures/beds_chairs/alien_nest.dm @@ -48,7 +48,7 @@ unbuckle_mob(M) add_fingerprint(user) -/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/user) +/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/user, check_loc) if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.incapacitated() || M.buckled ) return diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index a37797045f..8c2655dd64 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -97,7 +97,7 @@ -/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking +/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user, check_loc) //Don't want them getting put on the rack other than by spiking return /obj/structure/kitchenspike/user_unbuckle_mob(mob/living/buckled_mob, mob/living/carbon/human/user) diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index f70510e173..3f1cb5f4c1 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -43,7 +43,7 @@ . = ..() STOP_PROCESSING(SSfastprocess, src) -/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) +/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc) if(user.incapacitated() || !istype(user)) return M.forceMove(get_turf(src)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 69206f0d08..c39b3f64b1 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -330,6 +330,17 @@ GLOBAL_LIST_EMPTY(crematoriums) else to_chat(user, "That's not connected to anything!") +/obj/structure/tray/attackby(obj/P, mob/user, params) + if(!istype(P, /obj/item/riding_offhand)) + return ..() + + var/obj/item/riding_offhand/riding_item = P + var/mob/living/carried_mob = riding_item.rider + if(carried_mob == user) //Piggyback user. + return + user.unbuckle_mob(carried_mob) + MouseDrop_T(carried_mob, user) + /obj/structure/tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user) if(!ismovable(O) || O.anchored || !Adjacent(user) || !user.Adjacent(O) || O.loc == user) return diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index b7642f4658..12799b4370 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -124,11 +124,11 @@ . = . || (caller.pass_flags & PASSTABLE) /obj/structure/table/proc/tableplace(mob/living/user, mob/living/pushed_mob) - pushed_mob.forceMove(src.loc) - pushed_mob.set_resting(TRUE, FALSE) - pushed_mob.visible_message("[user] places [pushed_mob] onto [src].", \ - "[user] places [pushed_mob] onto [src].") - log_combat(user, pushed_mob, "placed") + pushed_mob.forceMove(loc) + pushed_mob.set_resting(TRUE, TRUE) + pushed_mob.visible_message(span_notice("[user] places [pushed_mob] onto [src]."), \ + span_notice("[user] places [pushed_mob] onto [src].")) + log_combat(user, pushed_mob, "places", null, "onto [src]") /obj/structure/table/proc/tablepush(mob/living/user, mob/living/pushed_mob) if(HAS_TRAIT(user, TRAIT_PACIFISM)) @@ -205,6 +205,30 @@ return // If the tray IS empty, continue on (tray will be placed on the table like other items) + if(istype(I, /obj/item/riding_offhand)) + var/obj/item/riding_offhand/riding_item = I + var/mob/living/carried_mob = riding_item.rider + if(carried_mob == user) //Piggyback user. + return + if(user.a_intent == INTENT_HARM) + user.unbuckle_mob(carried_mob) + tablelimbsmash(user, carried_mob) + else + var/tableplace_delay = 3.5 SECONDS + var/skills_space = "" + if(HAS_TRAIT(user, TRAIT_QUICKER_CARRY)) + tableplace_delay = 2 SECONDS + skills_space = " expertly" + else if(HAS_TRAIT(user, TRAIT_QUICK_CARRY)) + tableplace_delay = 2.75 SECONDS + skills_space = " quickly" + carried_mob.visible_message(span_notice("[user] begins to[skills_space] place [carried_mob] onto [src]..."), + span_userdanger("[user] begins to[skills_space] place [carried_mob] onto [src]...")) + if(do_after(user, tableplace_delay, target = carried_mob)) + user.unbuckle_mob(carried_mob) + tableplace(user, carried_mob) + return TRUE + if(user.a_intent != INTENT_HARM && !(I.item_flags & ABSTRACT)) if(user.transferItemToLoc(I, drop_location())) var/list/click_params = params2list(params) diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm index a7c1f81f06..ac8dc0bffb 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm @@ -81,7 +81,7 @@ density = TRUE //Skewers are one-use only desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember? -/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob() +/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob(check_loc) return /obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L) diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm index e98cb5ca72..8856838a34 100644 --- a/code/modules/antagonists/devil/true_devil/inventory.dm +++ b/code/modules/antagonists/devil/true_devil/inventory.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, silent = FALSE) +/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, invdrop, silent = FALSE) if(..()) update_inv_hands() return 1 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 51659a2904..79a0ccda77 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -292,10 +292,18 @@ //The following functions are the same save for one small difference -//for when you want the item to end up on the ground -//will force move the item to the ground and call the turf's Entered -/mob/proc/dropItemToGround(obj/item/I, force = FALSE) - return doUnEquip(I, force, drop_location(), FALSE) +/** + * Used to drop an item (if it exists) to the ground. + * * Will pass as TRUE is successfully dropped, or if there is no item to drop. + * * Will pass FALSE if the item can not be dropped due to TRAIT_NODROP via doUnEquip() + * If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called. +*/ +/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE) + if (isnull(I)) + return TRUE + + SEND_SIGNAL(src, COMSIG_MOB_DROPPING_ITEM) + . = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent) //for when the item will be immediately placed in a loc other than the ground /mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE) diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index b07bd180f6..5b49c3abb0 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,3 +1,3 @@ //can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, silent = FALSE) +/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, invdrop, silent = FALSE) return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 404ca1df8d..504f903d5e 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -141,26 +141,28 @@ /mob/living/carbon/proc/throw_mode_off() - in_throw_mode = 0 + in_throw_mode = FALSE if(client && hud_used) hud_used.throw_icon.icon_state = "act_throw_off" /mob/living/carbon/proc/throw_mode_on() - in_throw_mode = 1 + in_throw_mode = TRUE if(client && hud_used) hud_used.throw_icon.icon_state = "act_throw_on" /mob/proc/throw_item(atom/target) SEND_SIGNAL(src, COMSIG_MOB_THROW, target) - return + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CARBON_THROW_THING, src, target) + return TRUE /mob/living/carbon/throw_item(atom/target) + . = ..() throw_mode_off() if(!target || !isturf(loc)) - return + return FALSE if(istype(target, /atom/movable/screen)) - return + return FALSE //CIT CHANGES - makes it impossible to throw while in stamina softcrit if(IS_STAMCRIT(src)) @@ -170,59 +172,56 @@ var/random_turn = a_intent == INTENT_HARM //END OF CIT CHANGES - var/obj/item/I = get_active_held_item() - var/atom/movable/thrown_thing - var/mob/living/throwable_mob + var/obj/item/held_item = get_active_held_item() + var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling") + if(prob(0.5)) + verb_text = "yeet" - if(istype(I, /obj/item/clothing/head/mob_holder)) - var/obj/item/clothing/head/mob_holder/holder = I - if(holder.held_mob) - throwable_mob = holder.held_mob - holder.release() - - if(!I || throwable_mob) - if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) - throwable_mob = pulling - - if(throwable_mob && !throwable_mob.buckled) - thrown_thing = throwable_mob - if(pulling) + var/neckgrab_throw = FALSE + if(!held_item) + if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) + var/mob/living/throwable_mob = pulling + if(!throwable_mob.buckled) + thrown_thing = throwable_mob + if(grab_state >= GRAB_NECK) + neckgrab_throw = TRUE stop_pulling() - if(HAS_TRAIT(src, TRAIT_PACIFISM)) - to_chat(src, "You gently let go of [throwable_mob].") - return - if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE)) - return - var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors - var/turf/end_T = get_turf(target) - if(start_T && end_T) - log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") - - else if(!(I.item_flags & ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP)) - thrown_thing = I - dropItemToGround(I) - - if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce) - to_chat(src, "You set [I] down gently on the ground.") - return - - if(!UseStaminaBuffer(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST), warn = TRUE)) - return - - if(thrown_thing) - var/power_throw = 0 - if(HAS_TRAIT(src, TRAIT_HULK)) - power_throw++ - if(pulling && grab_state >= GRAB_NECK) - power_throw++ - visible_message("[src] throws [thrown_thing][power_throw ? " really hard!" : "."]", \ - "You throw [thrown_thing][power_throw ? " really hard!" : "."]") - log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK) - do_attack_animation(target, no_effect = 1) - playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) - newtonian_move(get_dir(target, src)) - thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn) + if(HAS_TRAIT(src, TRAIT_PACIFISM)) + to_chat(src, span_notice("You gently let go of [throwable_mob].")) + return FALSE + if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE)) + return FALSE + else + thrown_thing = held_item.on_thrown(src, target) + if(!thrown_thing) + return FALSE + if(isliving(thrown_thing)) + var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors + var/turf/end_T = get_turf(target) + if(start_T && end_T) + log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") + var/power_throw = 0 + if(HAS_TRAIT(src, TRAIT_HULK)) + power_throw++ + if(HAS_TRAIT(src, TRAIT_DWARF)) + power_throw-- + if(HAS_TRAIT(thrown_thing, TRAIT_DWARF)) + power_throw++ + if(neckgrab_throw) + power_throw++ + if(isitem(thrown_thing)) + var/obj/item/thrown_item = thrown_thing + if(thrown_item.throw_verb) + verb_text = thrown_item.throw_verb + visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw ? " really hard!" : "."]"), \ + span_danger("You [verb_text] [thrown_thing][power_throw ? " really hard!" : "."]")) + log_message("has thrown [thrown_thing] [power_throw > 0 ? "really hard" : ""]", LOG_ATTACK) + do_attack_animation(target, no_effect = 1) + var/extra_throw_range = 0 // HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0 + playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) + newtonian_move(get_dir(target, src)) + thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force, random_turn) /mob/living/carbon/restrained(ignore_grab) . = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index 1fd1e623db..4e57aa1562 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -41,7 +41,7 @@ ..() //lose items, then return //SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE -/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, silent = FALSE) +/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, invdrop, silent = FALSE) if(..()) update_inv_hands() if(I == internal_storage) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f226a911d8..151cc70a27 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -587,7 +587,7 @@ //ANIMAL RIDING -/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user) +/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user, check_loc) var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding) if(riding_datum) if(user.incapacitated()) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index dc9d6ff6a3..2b267c4d01 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -252,7 +252,7 @@ Feedon(Food) return ..() -/mob/living/simple_animal/slime/doUnEquip(obj/item/W, silent = FALSE) +/mob/living/simple_animal/slime/doUnEquip(obj/item/W, invdrop, silent = FALSE) return /mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 8f9a7805c6..be03e8a9c9 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -383,7 +383,7 @@ auto.Remove(buckled_mob) . = ..() -/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user) +/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc) if(user.incapacitated() || !istype(user)) return for(var/atom/movable/A in get_turf(src)) diff --git a/tgstation.dme b/tgstation.dme index 48fe8ae6eb..babe77f4be 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -160,6 +160,7 @@ #include "code\__DEFINES\dcs\flags.dm" #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\signals.dm" +#include "code\__DEFINES\dcs\signals\signals_global.dm" #include "code\__DEFINES\dcs\signals\signals_hud.dm" #include "code\__DEFINES\dcs\signals\signals_medical.dm" #include "code\__DEFINES\dcs\signals\signals_mod.dm" @@ -169,6 +170,7 @@ #include "code\__DEFINES\dcs\signals\signals_subsystem.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm" +#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm" #include "code\__DEFINES\mapping\maploader.dm" #include "code\__DEFINES\material\worth.dm" #include "code\__DEFINES\mobs\innate_abilities.dm" From d4ea14c4efbe862d6f59e42f0e00261705e92c7a Mon Sep 17 00:00:00 2001 From: SandPoot Date: Mon, 9 Oct 2023 16:15:49 -0300 Subject: [PATCH 2/3] push --- code/__DEFINES/DNA.dm | 5 + code/__DEFINES/loadout.dm | 21 +- code/_globalvars/lists/loadout_categories.dm | 2 +- code/_onclick/hud/new_player.dm | 2 +- code/modules/arousal/genitals.dm | 3 +- code/modules/client/preferences.dm | 1807 +++++++++-------- .../mob/dead/new_player/preferences_setup.dm | 28 +- 7 files changed, 985 insertions(+), 883 deletions(-) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 9cae56645f..a057d3cf41 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -200,3 +200,8 @@ #define G_FEMALE 2 #define G_PLURAL 3 #define G_NEUTER 4 + +#define PREVIEW_PREF_JOB "Job" +#define PREVIEW_PREF_LOADOUT "Loadout" +#define PREVIEW_PREF_NAKED "Naked" +#define PREVIEW_PREF_NAKED_AROUSED "Naked - Aroused" diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 4a52d25fb3..0b1db1ecc6 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -88,12 +88,21 @@ //the names of the customization tabs #define SETTINGS_TAB 0 -#define GAME_PREFERENCES_TAB 1 -#define APPEARANCE_TAB 2 -#define SPEECH_TAB 3 -#define LOADOUT_TAB 4 -#define CONTENT_PREFERENCES_TAB 5 -#define KEYBINDINGS_TAB 6 +#define PREFERENCES_TAB 1 +#define KEYBINDINGS_TAB 2 + +//subtabs for the character settings tab +#define GENERAL_CHAR_TAB 0 +#define BACKGROUND_CHAR_TAB 1 +#define APPEARANCE_CHAR_TAB 2 +#define MARKINGS_CHAR_TAB 3 +#define SPEECH_CHAR_TAB 4 +#define LOADOUT_CHAR_TAB 5 + +//subtabs for preferences tab +#define GAME_PREFS_TAB 0 +#define OOC_PREFS_TAB 1 +#define CONTENT_PREFS_TAB 2 //quirks #define QUIRK_POSITIVE "Positive" diff --git a/code/_globalvars/lists/loadout_categories.dm b/code/_globalvars/lists/loadout_categories.dm index 4ddb451f19..37e6145e47 100644 --- a/code/_globalvars/lists/loadout_categories.dm +++ b/code/_globalvars/lists/loadout_categories.dm @@ -1,10 +1,10 @@ GLOBAL_LIST_INIT(loadout_categories, list( - LOADOUT_CATEGORY_ACCESSORY = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_TOYS), LOADOUT_CATEGORY_NECK = list(LOADOUT_SUBCATEGORY_NECK_GENERAL, LOADOUT_SUBCATEGORY_NECK_TIE, LOADOUT_SUBCATEGORY_NECK_SCARVES), LOADOUT_CATEGORY_MASK = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_HANDS = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_UNIFORM = list(LOADOUT_SUBCATEGORY_UNIFORM_GENERAL, LOADOUT_SUBCATEGORY_UNIFORM_JOBS, LOADOUT_SUBCATEGORY_UNIFORM_SUITS, LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS, LOADOUT_SUBCATEGORY_UNIFORM_DRESSES, LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS, LOADOUT_SUBCATEGORY_UNIFORM_PANTS, LOADOUT_SUBCATEGORY_UNIFORM_SHORTS), + LOADOUT_CATEGORY_ACCESSORY = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_SUIT = list(LOADOUT_SUBCATEGORY_SUIT_GENERAL, LOADOUT_SUBCATEGORY_SUIT_COATS, LOADOUT_SUBCATEGORY_SUIT_JACKETS, LOADOUT_SUBCATEGORY_SUIT_JOBS), LOADOUT_CATEGORY_HEAD = list(LOADOUT_SUBCATEGORY_HEAD_GENERAL, LOADOUT_SUBCATEGORY_HEAD_JOBS), LOADOUT_CATEGORY_SHOES = LOADOUT_SUBCATEGORIES_NONE, diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 4eff9cd7e6..b01199c6c2 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -280,7 +280,7 @@ if(!.) return - hud.mymob.client.prefs.current_tab = GAME_PREFERENCES_TAB + hud.mymob.client.prefs.current_tab = PREFERENCES_TAB hud.mymob.client.prefs.ShowChoices(hud.mymob) /atom/movable/screen/lobby/button/bottom/changelog_button diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index 3e16a46526..e9fe56cadf 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -41,7 +41,8 @@ return FALSE if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state)) aroused_state = new_state - owner.log_message("[src]'s arousal was [new_state ? "enabled" : "disabled"] due to [cause]", LOG_EMOTE) + if(cause) + owner.log_message("[src]'s arousal was [new_state ? "enabled" : "disabled"] due to [cause]", LOG_EMOTE) return aroused_state /obj/item/organ/genital/proc/update() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index b03ac81842..8ec0731613 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -221,6 +221,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/show_mismatched_markings = FALSE //determines whether or not the markings lists should show markings that don't match the currently selected species. Intentionally left unsaved. + var/character_settings_tab = GENERAL_CHAR_TAB + var/preferences_tab = GAME_PREFS_TAB + var/preview_pref = PREVIEW_PREF_JOB + var/no_tetris_storage = FALSE ///loadout stuff @@ -300,11 +304,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/list/dat = list("
") dat += "Character Settings" - dat += "Character Appearance" - dat += "Character Speech" - dat += "Loadout" - dat += "Game Preferences" - dat += "Content Preferences" + dat += "Preferences" dat += "Keybindings" if(!path) @@ -334,854 +334,930 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "[name] " dat += "
" - dat += "

Occupation Choices

" - dat += "Set Occupation Preferences
" - if(CONFIG_GET(flag/roundstart_traits)) - dat += "

Quirk Setup

" - dat += "Configure Quirks
" - dat += "
Current Quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" - dat += "

Identity

" - dat += "" - dat += "
Records
" - dat += "
Security Records
" - if(length_char(security_records) <= 40) - if(!length(security_records)) - dat += "\[...\]" + dat += "
" + dat += "
" + dat += "
" - if(jobban_isbanned(user, "appearance")) - dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" - dat += "Random Name " - dat += "Always Random Name:[be_random_name ? "Yes" : "No"]
" + dat += "
" - dat += "[nameless ? "Default designation" : "Name"]:" - dat += "[real_name]
" - dat += "Be nameless: [nameless ? "Yes" : "No"]
" + dat += "
" + dat += "General" + dat += "Background" + dat += "Appearance" + dat += "Markings" + dat += "Speech" + dat += "Loadout" //If you change the index of this tab, change all the logic regarding tab + dat += "
" - dat += "Gender: [gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" - dat += "Age: [age]
" - - dat += "Special Names:
" - var/old_group - for(var/custom_name_id in GLOB.preferences_custom_names) - var/namedata = GLOB.preferences_custom_names[custom_name_id] - if(!old_group) - old_group = namedata["group"] - else if(old_group != namedata["group"]) - old_group = namedata["group"] - dat += "
" - dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " - dat += "

" - - dat += "Custom job preferences:
" - dat += "Preferred AI Core Display: [preferred_ai_core_display]
" - dat += "Preferred Security Department: [prefered_security_department]
" + dat += "" + dat += "" + if(character_settings_tab == LOADOUT_CHAR_TAB) //if loadout + //calculate your gear points from the chosen item + gear_points = CONFIG_GET(number/initial_gear_points) + var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"] + if(chosen_gear) + for(var/loadout_item in chosen_gear) + var/loadout_item_path = loadout_item[LOADOUT_ITEM] + if(loadout_item_path) + var/datum/gear/loadout_gear = text2path(loadout_item_path) + if(loadout_gear) + gear_points -= initial(loadout_gear.cost) else - dat += "[security_records]" + chosen_gear = list() + + dat += "" else - dat += "[TextPreview(security_records)]...
" + dat += "" - dat += "
Medical Records
" - if(length_char(medical_records) <= 40) - if(!length(medical_records)) - dat += "\[...\]
" - else - dat += "[medical_records]" - else - dat += "[TextPreview(medical_records)]...
" - dat += "
Hide ckey: [hide_ckey ? "Enabled" : "Disabled"]
" - dat += "
" + dat += "
Preview:

" + dat += "
" + dat += "[PREVIEW_PREF_JOB]" + dat += "[PREVIEW_PREF_LOADOUT]" + dat += "[PREVIEW_PREF_NAKED]" + dat += "
" + dat += "[PREVIEW_PREF_NAKED_AROUSED]" + dat += "
" + dat += "
" + dat += "
[gear_points] loadout point[gear_points == 1 ? "" : "s"] remaining

" + dat += "
Clear Loadout
" + dat += "
" + dat += "
Mismatched parts:

" + dat += "
[(show_mismatched_markings) ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "" + dat += "
Advanced colors:

" + dat += "
[(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) ? "Enabled" : "Disabled"]
" + dat += "" - //Character Appearance - if(APPEARANCE_TAB) - if(path) - var/savefile/S = new /savefile(path) - if(S) - dat += "
" - var/name - var/unspaced_slots = 0 - for(var/i=1, i<=max_save_slots, i++) - unspaced_slots++ - if(unspaced_slots > 4) - dat += "
" - unspaced_slots = 0 - S.cd = "/character[i]" - S["real_name"] >> name - if(!name) - name = "Character[i]" - dat += "[name] " - dat += "
" + dat += "" + dat += "" + dat += "" + dat += "
" + switch(character_settings_tab) + //General + if(GENERAL_CHAR_TAB) + dat += "

Occupation Choices

" + dat += "Set Occupation Preferences
" + if(CONFIG_GET(flag/roundstart_traits)) + dat += "

Quirk Setup

" + dat += "Configure Quirks
" + dat += "
Current Quirks: [all_quirks.len ? all_quirks.Join(", ") : "None"]
" + dat += "

Identity

" + dat += "" - var/matrixed_sections = accessory.matrixed_sections - if(accessory.color_src == MATRIXED && !matrixed_sections) - message_admins("Sprite Accessory Failure (customization): Accessory [accessory.type] is a matrixed item without any matrixed sections set!") - continue - else if(accessory.color_src == MATRIXED) - switch(matrixed_sections) - if(MATRIX_GREEN) //only composed of a green section - primary_feature = secondary_feature //swap primary for secondary, so it properly assigns the second colour, reserved for the green section - if(MATRIX_BLUE) - primary_feature = tertiary_feature //same as above, but the tertiary feature is for the blue section - if(MATRIX_RED_BLUE) //composed of a red and blue section - secondary_feature = tertiary_feature //swap secondary for tertiary, as blue should always be tertiary - if(MATRIX_GREEN_BLUE) //composed of a green and blue section - primary_feature = secondary_feature //swap primary for secondary, as first option is green, which is linked to the secondary - secondary_feature = tertiary_feature //swap secondary for tertiary, as second option is blue, which is linked to the tertiary - dat += "Primary Color
" - dat += "   Change
" - if((accessory.color_src == MATRIXED && (matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)) || (accessory.extra && (accessory.extra_color_src == MUTCOLORS || accessory.extra_color_src == MUTCOLORS2 || accessory.extra_color_src == MUTCOLORS3))) - dat += "Secondary Color
" - dat += "   Change
" - if((accessory.color_src == MATRIXED && matrixed_sections == MATRIX_ALL) || (accessory.extra2 && (accessory.extra2_color_src == MUTCOLORS || accessory.extra2_color_src == MUTCOLORS2 || accessory.extra2_color_src == MUTCOLORS3))) - dat += "Tertiary Color
" - dat += "   Change
" + dat += "
" + if(jobban_isbanned(user, "appearance")) + dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" - dat += "" - else - dat += "

Left Eye Color

" - dat += "   Change" - dat += "

Right Eye Color

" - dat += "   Change
" - dat += "" - else if(use_skintones || mutant_colors) + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + dat += "Age:[age]
" + dat += "Hide ckey: [hide_ckey ? "Enabled" : "Disabled"]
" dat += "" - if(HAIR in pref_species.species_traits) + dat += "
" - dat += "

Flavor Text

" - dat += "Set Examine Text
" - if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) - if(!length(features["flavor_text"])) - dat += "\[...\]" - else - dat += "[features["flavor_text"]]" - else - dat += "[TextPreview(features["flavor_text"])]...
" - dat += "

Silicon Flavor Text

" - dat += "Set Silicon Examine Text
" - if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) - if(!length(features["silicon_flavor_text"])) - dat += "\[...\]" - else - dat += "[features["silicon_flavor_text"]]" - else - dat += "[TextPreview(features["silicon_flavor_text"])]...
" - dat += "

OOC notes

" - dat += "Set OOC notes
" - var/ooc_notes_len = length(features["ooc_notes"]) - if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN) - if(!ooc_notes_len) - dat += "\[...\]" - else - dat += "[features["ooc_notes"]]" - else - dat += "[TextPreview(features["ooc_notes"])]...
" - dat += "

Body

" - dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" - if(gender != NEUTER && pref_species.sexes) - dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
" - dat += "Limb Modification:
" - dat += "Modify Limbs
" - for(var/modification in modified_limbs) - if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) - dat += "[modification]: [modified_limbs[modification][2]]
" - else - dat += "[modification]: [modified_limbs[modification][1]]
" - dat += "
" - dat += "Species:[pref_species.name]
" - dat += "Custom Species Name:[custom_species ? custom_species : "None"]
" - dat += "Random Body:Randomize!
" - dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
" - dat += "
Cycle background:[bgstate]
" - var/use_skintones = pref_species.use_skintones - if(use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN + dat += "[nameless ? "Default designation" : "Name"]:
" + dat += "[real_name]
" + dat += "Random Name
" + dat += "Be nameless: [nameless ? "Yes" : "No"]
" + dat += "Always Random Name:[be_random_name ? "Yes" : "No"]
" - dat += "

Skin Tone

" - - dat += "[use_custom_skin_tone ? "custom:    " : skin_tone]
" - - var/mutant_colors - if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits)) - if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

Advanced Coloring

" - dat += "[(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) ? "Enabled" : "Disabled"]" - - dat += "

Body Colors

" - - dat += "Primary Color:
" - dat += "    Change
" - - dat += "Secondary Color:
" - dat += "    Change
" - - dat += "Tertiary Color:
" - dat += "    Change
" - mutant_colors = TRUE - - dat += "Sprite Size: [features["body_size"]*100]%
" - - if(!(NOEYES in pref_species.species_traits)) - dat += "

Eye Type

" - dat += "[eye_type]
" - if((EYECOLOR in pref_species.species_traits)) - if(!use_skintones && !mutant_colors) - dat += APPEARANCE_CATEGORY_COLUMN - if(left_eye_color != right_eye_color) - split_eye_colors = TRUE - dat += "

Heterochromia

" - dat += "[split_eye_colors ? "Enabled" : "Disabled"]" - if(!split_eye_colors) - dat += "

Eye Color

" - dat += "    Change" - dat += "
" + dat += "Special Names:
" + var/old_group + for(var/custom_name_id in GLOB.preferences_custom_names) + var/namedata = GLOB.preferences_custom_names[custom_name_id] + if(!old_group) + old_group = namedata["group"] + else if(old_group != namedata["group"]) + old_group = namedata["group"] + dat += "
" + dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " + dat += "

" - dat += APPEARANCE_CATEGORY_COLUMN + dat += "Custom job preferences:
" + dat += "Preferred AI Core Display: [preferred_ai_core_display]
" + dat += "Preferred Security Department: [prefered_security_department]
" - dat += "

Hair Style

" + dat += "
" + //Character background + if(BACKGROUND_CHAR_TAB) + dat += "" - //Mutant stuff - var/mutant_category = 0 - - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Show mismatched markings

" - dat += "[show_mismatched_markings ? "Yes" : "No"]" - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) //just in case someone sets the max rows to 1 or something dumb like that - dat += "" - mutant_category = 0 - - // rp marking selection - // assume you can only have mam markings or regular markings or none, never both - var/marking_type - if(parent.can_have_part("mam_body_markings")) - marking_type = "mam_body_markings" - if(marking_type) - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

[GLOB.all_mutant_parts[marking_type]]

" // give it the appropriate title for the type of marking - dat += "Add marking" - // list out the current markings you have - if(length(features[marking_type])) - dat += "
" - dat += "[hair_style]" - dat += "< >
" - dat += "    Change
" - - dat += "

Facial Hair Style

" - - dat += "[facial_hair_style]" - dat += "< >
" - dat += "    Change
" - - dat += "

Hair Gradient

" - - dat += "[grad_style]" - dat += "< >
" - dat += "    Change
" - - dat += "
" - var/list/markings = features[marking_type] - if(!islist(markings)) - // something went terribly wrong - markings = list() - var/list/reverse_markings = reverseList(markings) - for(var/list/marking_list in reverse_markings) - var/marking_index = markings.Find(marking_list) // consider changing loop to go through indexes over lists instead of using Find here - var/limb_value = marking_list[1] - var/actual_name = GLOB.bodypart_names[num2text(limb_value)] // get the actual name from the bitflag representing the part the marking is applied to - var/color_marking_dat = "" - var/number_colors = 1 - var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] - var/matrixed_sections = S.covered_limbs[actual_name] - if(S && matrixed_sections) - // if it has nothing initialize it to white - if(length(marking_list) == 2) - var/first = "#FFFFFF" - var/second = "#FFFFFF" - var/third = "#FFFFFF" - if(features["mcolor"]) - first = "#[features["mcolor"]]" - if(features["mcolor2"]) - second = "#[features["mcolor2"]]" - if(features["mcolor3"]) - third = "#[features["mcolor3"]]" - marking_list += list(list(first, second, third)) // just assume its 3 colours if it isnt it doesnt matter we just wont use the other values - // index magic - var/primary_index = 1 - var/secondary_index = 2 - var/tertiary_index = 3 - switch(matrixed_sections) - if(MATRIX_GREEN) - primary_index = 2 - if(MATRIX_BLUE) - primary_index = 3 - if(MATRIX_RED_BLUE) - secondary_index = 2 - if(MATRIX_GREEN_BLUE) - primary_index = 2 - secondary_index = 3 - - // we know it has one matrixed section at minimum - color_marking_dat += "   " - // if it has a second section, add it - if(matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL) - color_marking_dat += "   " - number_colors = 2 - // if it has a third section, add it - if(matrixed_sections == MATRIX_ALL) - color_marking_dat += "   " - number_colors = 3 - color_marking_dat += " Change
" - dat += "" - dat += "
[marking_list[2]] - [actual_name] ˄ ˅ X [color_marking_dat]
" - - for(var/mutant_part in GLOB.all_mutant_parts) - if(mutant_part == "mam_body_markings") - continue - if(parent.can_have_part(mutant_part)) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

[GLOB.all_mutant_parts[mutant_part]]

" - dat += "[features[mutant_part]]" - var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button - if(color_type) - dat += "    Change
" + dat += "

Flavor Text

" + dat += "Set Examine Text
" + if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["flavor_text"])) + dat += "\[...\]" + else + dat += "[features["flavor_text"]]" else - if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) //advanced individual part colouring system - //is it matrixed or does it have extra parts to be coloured? - var/find_part = features[mutant_part] || pref_species.mutant_bodyparts[mutant_part] - var/find_part_list = GLOB.mutant_reference_list[mutant_part] - if(find_part && find_part != "None" && find_part_list) - var/datum/sprite_accessory/accessory = find_part_list[find_part] - if(accessory) - if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future - var/mutant_string = accessory.mutant_part_string - var/primary_feature = "[mutant_string]_primary" - var/secondary_feature = "[mutant_string]_secondary" - var/tertiary_feature = "[mutant_string]_tertiary" - if(!features[primary_feature]) - features[primary_feature] = features["mcolor"] - if(!features[secondary_feature]) - features[secondary_feature] = features["mcolor2"] - if(!features[tertiary_feature]) - features[tertiary_feature] = features["mcolor3"] + dat += "[TextPreview(features["flavor_text"])]..." + dat += "

Silicon Flavor Text

" + dat += "Set Silicon Examine Text
" + if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["silicon_flavor_text"])) + dat += "\[...\]" + else + dat += "[features["silicon_flavor_text"]]" + else + dat += "[TextPreview(features["silicon_flavor_text"])]..." + dat += "

OOC notes

" + dat += "Set OOC notes
" + var/ooc_notes_len = length(features["ooc_notes"]) + if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN) + if(!ooc_notes_len) + dat += "\[...\]" + else + dat += "[features["ooc_notes"]]" + else + dat += "[TextPreview(features["ooc_notes"])]..." + dat += "
" + dat += "

Records

" + dat += "Security Records
" + if(length_char(security_records) <= 40) + if(!length(security_records)) + dat += "\[...\]" + else + dat += "[security_records]" + else + dat += "[TextPreview(security_records)]..." - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) + dat += "
Medical Records
" + if(length_char(medical_records) <= 40) + if(!length(medical_records)) + dat += "\[...\]" + else + dat += "[medical_records]" + else + dat += "[TextPreview(medical_records)]..." + dat += "
" + //Character Appearance + if(APPEARANCE_CHAR_TAB) + dat += "" + + var/use_skintones = pref_species.use_skintones + if(use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Skin Tone

" + + dat += "[use_custom_skin_tone ? "custom: [skin_tone]" : skin_tone]
" + + var/mutant_colors + if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits)) + if(!use_skintones) + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Body Colors

" + + dat += "Primary Color:
" + dat += "#[features["mcolor"]]Change
" + + dat += "Secondary Color:
" + dat += "#[features["mcolor2"]]Change
" + + dat += "Tertiary Color:
" + dat += "#[features["mcolor3"]]Change
" + mutant_colors = TRUE + + dat += "Sprite Size:[features["body_size"]*100]%
" + + if(!(NOEYES in pref_species.species_traits)) + dat += "

Eye Type

" + dat += "[eye_type]
" + if((EYECOLOR in pref_species.species_traits)) + if(!use_skintones && !mutant_colors) + dat += APPEARANCE_CATEGORY_COLUMN + if(left_eye_color != right_eye_color) + split_eye_colors = TRUE + dat += "

Heterochromia

" + dat += "[split_eye_colors ? "Enabled" : "Disabled"]" + if(!split_eye_colors) + dat += "

Eye Color

" + dat += "#[left_eye_color]Change" + else + dat += "

Left Eye Color

" + dat += "#[left_eye_color]Change" + dat += "

Right Eye Color

" + dat += "#[right_eye_color]Change
" + + if(HAIR in pref_species.species_traits) + + dat += APPEARANCE_CATEGORY_COLUMN + + dat += "

Hair Style

" + + dat += "[hair_style]" + dat += "<>
" + dat += "#[hair_color]Change
" + + dat += "

Facial Hair Style

" + + dat += "[facial_hair_style]" + dat += "<>
" + dat += "#[facial_hair_color]Change
" + + dat += "

Hair Gradient

" + + dat += "[grad_style]" + dat += "<>
" + dat += "#[grad_color]Change
" + + dat += "" + + //Mutant stuff + var/mutant_category = 0 + + for(var/mutant_part in GLOB.all_mutant_parts) + if(mutant_part == "mam_body_markings") + continue + if(parent.can_have_part(mutant_part)) + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

[GLOB.all_mutant_parts[mutant_part]]

" + dat += "[features[mutant_part]]" + var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button + if(color_type) + dat += "#[features[color_type]]Change
" + else + if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) //advanced individual part colouring system + //is it matrixed or does it have extra parts to be coloured? + var/find_part = features[mutant_part] || pref_species.mutant_bodyparts[mutant_part] + var/find_part_list = GLOB.mutant_reference_list[mutant_part] + if(find_part && find_part != "None" && find_part_list) + var/datum/sprite_accessory/accessory = find_part_list[find_part] + if(accessory) + if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future + var/mutant_string = accessory.mutant_part_string + var/primary_feature = "[mutant_string]_primary" + var/secondary_feature = "[mutant_string]_secondary" + var/tertiary_feature = "[mutant_string]_tertiary" + if(!features[primary_feature]) + features[primary_feature] = features["mcolor"] + if(!features[secondary_feature]) + features[secondary_feature] = features["mcolor2"] + if(!features[tertiary_feature]) + features[tertiary_feature] = features["mcolor3"] + + var/matrixed_sections = accessory.matrixed_sections + if(accessory.color_src == MATRIXED && !matrixed_sections) + message_admins("Sprite Accessory Failure (customization): Accessory [accessory.type] is a matrixed item without any matrixed sections set!") + continue + else if(accessory.color_src == MATRIXED) + switch(matrixed_sections) + if(MATRIX_GREEN) //only composed of a green section + primary_feature = secondary_feature //swap primary for secondary, so it properly assigns the second colour, reserved for the green section + if(MATRIX_BLUE) + primary_feature = tertiary_feature //same as above, but the tertiary feature is for the blue section + if(MATRIX_RED_BLUE) //composed of a red and blue section + secondary_feature = tertiary_feature //swap secondary for tertiary, as blue should always be tertiary + if(MATRIX_GREEN_BLUE) //composed of a green and blue section + primary_feature = secondary_feature //swap primary for secondary, as first option is green, which is linked to the secondary + secondary_feature = tertiary_feature //swap secondary for tertiary, as second option is blue, which is linked to the tertiary + dat += "Primary Color
" + dat += "#[features[primary_feature]]Change
" + if((accessory.color_src == MATRIXED && (matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)) || (accessory.extra && (accessory.extra_color_src == MUTCOLORS || accessory.extra_color_src == MUTCOLORS2 || accessory.extra_color_src == MUTCOLORS3))) + dat += "Secondary Color
" + dat += "#[features[secondary_feature]]Change
" + if((accessory.color_src == MATRIXED && matrixed_sections == MATRIX_ALL) || (accessory.extra2 && (accessory.extra2_color_src == MUTCOLORS || accessory.extra2_color_src == MUTCOLORS2 || accessory.extra2_color_src == MUTCOLORS3))) + dat += "Tertiary Color
" + dat += "#[features[tertiary_feature]]Change
" + + mutant_category++ + if(mutant_category >= MAX_MUTANT_ROWS) + dat += "" + mutant_category = 0 + + if(length(pref_species.allowed_limb_ids)) + if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids)) + chosen_limb_id = pref_species.limbs_id || pref_species.id + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Body sprite

" + dat += "[chosen_limb_id]" + + if(mutant_category) dat += "" mutant_category = 0 - if(length(pref_species.allowed_limb_ids)) - if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids)) - chosen_limb_id = pref_species.limbs_id || pref_species.id - dat += "

Body sprite

" - dat += "[chosen_limb_id]" + dat += "
" + + dat += "

Body

" + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + if(gender != NEUTER && pref_species.sexes) + dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
" + dat += "Limb Modification:
" + dat += "Modify Limbs
" + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + dat += "[modification]: [modified_limbs[modification][2]]
" + else + dat += "[modification]: [modified_limbs[modification][1]]
" + dat += "
" + dat += "Species:[pref_species.name]
" + dat += "Custom Species Name:[custom_species ? custom_species : "None"]
" + dat += "Random Body:Randomize!
" + dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
" + dat += "
Cycle background:[bgstate]
" + + dat += "
" - if(mutant_category) - dat += "" - mutant_category = 0 + dat += "" + dat += "" - dat += "
" + dat += "

Clothing & Equipment

" + dat += "Underwear:[underwear]" + if(GLOB.underwear_list[underwear]?.has_color) + dat += "Underwear Color: #[undie_color] Change
" + dat += "Undershirt:[undershirt]" + if(GLOB.undershirt_list[undershirt]?.has_color) + dat += "Undershirt Color: #[shirt_color] Change
" + dat += "Socks:[socks]" + if(GLOB.socks_list[socks]?.has_color) + dat += "Socks Color: #[socks_color] Change
" + dat += "Backpack:[backbag]" + dat += "Jumpsuit:
[jumpsuit_style]
" + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) + dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" + dat += "Clear scar slots" + dat += "Uplink Location:[uplink_spawn_loc]" + dat += "
" + dat += APPEARANCE_CATEGORY_COLUMN - dat += "" - dat += "" - - dat +="" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Breasts

" - dat += "[features["has_breasts"] == TRUE ? "Yes" : "No"]" - if(features["has_breasts"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Color:
" - dat += "   Change
" - dat += "Cup Size:[features["breasts_size"]]" - dat += "Breasts Shape:[features["breasts_shape"]]" - dat += "Breasts Visibility:[features["breasts_visibility"]]" - dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]" - dat += "" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Butt

" - dat += "[features["has_butt"] == TRUE ? "Yes" : "No"]" - if(features["has_butt"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Color:
" - dat += "   Change
" - dat += "Butt Size:[features["butt_size"]]" - dat += "Butt Visibility:[features["butt_visibility"]]" - dat += "" - dat += "" - dat += "
" - dat += "

Clothing & Equipment

" - dat += "Underwear:[underwear]" - if(GLOB.underwear_list[underwear]?.has_color) - dat += "Underwear Color:     Change
" - dat += "Undershirt:[undershirt]" - if(GLOB.undershirt_list[undershirt]?.has_color) - dat += "Undershirt Color:     Change
" - dat += "Socks:[socks]" - if(GLOB.socks_list[socks]?.has_color) - dat += "Socks Color:     Change
" - dat += "Backpack:[backbag]" - dat += "Jumpsuit:
[jumpsuit_style]
" - if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) - dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" - dat += "Clear scar slots" - dat += "Uplink Location:[uplink_spawn_loc]" - dat += "
" - if(NOGENITALS in pref_species.species_traits) - dat += "Your species ([pref_species.name]) does not support genitals!
" - else - if(pref_species.use_skintones) - dat += "Genitals use skintone:[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]" - dat += "

Penis

" - dat += "[features["has_cock"] == TRUE ? "Yes" : "No"]" - if(features["has_cock"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Penis Color:
" - dat += "   (Skin tone overriding)
" + if(NOGENITALS in pref_species.species_traits) + dat += "Your species ([pref_species.name]) does not support genitals!
" else - dat += "Penis Color:
" - dat += "    Change
" - var/tauric_shape = FALSE - if(features["cock_taur"]) - var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]] - if(P.taur_icon && parent.can_have_part("taur")) - var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] - if(T.taur_mode & P.accepted_taurs) - tauric_shape = TRUE - dat += "Penis Shape: [features["cock_shape"]][tauric_shape ? " (Taur)" : ""]" - dat += "Penis Length: [features["cock_length"]] inch(es)" - dat += "Penis Visibility:[features["cock_visibility"]]" - dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" - if(features["has_balls"]) - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Testicles Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Testicles Color:
" - dat += "    Change
" - dat += "Testicles Shape: [features["balls_shape"]]" - dat += "Testicles Visibility:[features["balls_visibility"]]" - dat += APPEARANCE_CATEGORY_COLUMN - dat += "

Vagina

" - dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]" - if(features["has_vag"]) - dat += "Vagina Type: [features["vag_shape"]]" - if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Vagina Color:
" - dat += "   (Skin tone overriding)
" - else - dat += "Vagina Color:
" - dat += "    Change
" - dat += "Vagina Visibility:[features["vag_visibility"]]" - dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" - dat += "
" - - if(SPEECH_TAB) - if(path) - var/savefile/S = new /savefile(path) - if(S) - dat += "
" - var/name - var/unspaced_slots = 0 - for(var/i=1, i<=max_save_slots, i++) - unspaced_slots++ - if(unspaced_slots > 4) - dat += "
" - unspaced_slots = 0 - S.cd = "/character[i]" - S["real_name"] >> name - if(!name) - name = "Character[i]" - dat += "[name] " - dat += "
" - - dat += "" - dat += "" - dat += "
" - dat += "

Speech preferences

" - dat += "Custom Speech Verb:
" - dat += "[custom_speech_verb]
" - dat += "Custom Tongue:
" - dat += "[custom_tongue]
" - dat += "Additional Language
" - dat += "[additional_language]
" - dat += "
" - dat += "

Vocal Bark preferences

" - var/datum/bark/B = GLOB.bark_list[bark_id] - dat += "Vocal Bark Sound:
" - dat += "[B ? initial(B.name) : "INVALID"]
" - dat += "Vocal Bark Speed: [bark_speed]
" - dat += "Vocal Bark Pitch: [bark_pitch]
" - dat += "Vocal Bark Variance: [bark_variance]
" - dat += "
Preview Bark
" - dat += "
" - - if(GAME_PREFERENCES_TAB) // Game Preferences - dat += "" - if(user.client.holder) - dat +="" - - dat +="" - dat += "
" - dat += "

General Settings

" - dat += "UI Style: [UI_style]
" - dat += "Outline: [outline_enabled ? "Enabled" : "Disabled"]
" - dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"]    Change
" - dat += "Screentip: [screentip_pref]
" - dat += "Screentip Color:     Change
" - dat += "\ - Screentip context with images: [screentip_images ? "Allowed" : "Disallowed"]
" - dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
" - dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
" - dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" - dat += "Runechat message char limit: [max_chat_length]
" - dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" - dat += "
" - dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" - dat += "
" - dat += "PDA Color:     Change
" - dat += "PDA Style: [pda_style]
" - dat += "PDA Reskin: [pda_skin]
" - dat += "
" - dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" - dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" - dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" - dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"]
" - dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
" - dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]
" - dat += "
" - dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
" - dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
" - dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
" - dat += "
" - if(user.client) - if(unlock_content) - dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" - if(unlock_content || check_rights_for(user.client, R_ADMIN)) - dat += "OOC Color:     Change
" - dat += "Antag OOC Color:     Change
" - - dat += "
" - dat += "

Admin Settings

" - dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]
" - dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"]
" - dat += "
" - dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"]
" - dat += "
" - - //deadmin - dat += "

Deadmin While Playing

" - if(CONFIG_GET(flag/auto_deadmin_players)) - dat += "Always Deadmin: FORCED
" - else - dat += "Always Deadmin: [(deadmin & DEADMIN_ALWAYS)?"Enabled":"Disabled"]
" - if(!(deadmin & DEADMIN_ALWAYS)) - dat += "
" - if(!CONFIG_GET(flag/auto_deadmin_antagonists)) - dat += "As Antag: [(deadmin & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"]
" - else - dat += "As Antag: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_heads)) - dat += "As Command: [(deadmin & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"]
" - else - dat += "As Command: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_security)) - dat += "As Security: [(deadmin & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"]
" - else - dat += "As Security: FORCED
" - - if(!CONFIG_GET(flag/auto_deadmin_silicons)) - dat += "As Silicon: [(deadmin & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"]
" - else - dat += "As Silicon: FORCED
" - dat += "
" - dat += "

Citadel Preferences

" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. - dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]
" - dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"]
" - dat += "Auto stand: [autostand ? "Enabled" : "Disabled"]
" - dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"]
" - dat += "Force Slot Storage HUD: [no_tetris_storage ? "Enabled" : "Disabled"]
" - dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]
" - if (user && user.client && !user.client.prefs.screenshake==0) - dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]
" - dat += "Recoil Screen Push: [(recoil_screenshake==100) ? "Full" : ((recoil_screenshake==0) ? "None" : "[screenshake]")]
" - var/p_chaos - if (!preferred_chaos) - p_chaos = "No preference" - else - p_chaos = preferred_chaos - dat += "Preferred Chaos Amount: [p_chaos]
" - dat += "
" - dat += "
" - if(unlock_content) - dat += "Ghost Form: [ghost_form]
" - dat += "Ghost Orbit: [ghost_orbit]
" - var/button_name = "If you see this something went wrong." - switch(ghost_accs) - if(GHOST_ACCS_FULL) - button_name = GHOST_ACCS_FULL_NAME - if(GHOST_ACCS_DIR) - button_name = GHOST_ACCS_DIR_NAME - if(GHOST_ACCS_NONE) - button_name = GHOST_ACCS_NONE_NAME - - dat += "Ghost Accessories: [button_name]
" - switch(ghost_others) - if(GHOST_OTHERS_THEIR_SETTING) - button_name = GHOST_OTHERS_THEIR_SETTING_NAME - if(GHOST_OTHERS_DEFAULT_SPRITE) - button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME - if(GHOST_OTHERS_SIMPLE) - button_name = GHOST_OTHERS_SIMPLE_NAME - - dat += "Ghosts of Others: [button_name]
" - dat += "
" - - dat += "FPS: [clientfps]
" - - dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" - dat += "
" - - dat += "Parallax (Fancy Space): " - switch (parallax) - if (PARALLAX_LOW) - dat += "Low" - if (PARALLAX_MED) - dat += "Medium" - if (PARALLAX_INSANE) - dat += "Insane" - if (PARALLAX_DISABLE) - dat += "Disabled" - else - dat += "High" - dat += "
" - dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"]
" - dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"]
" - dat += "HUD Button Flashes: [hud_toggle_flash ? "Enabled" : "Disabled"]
" - dat += "HUD Button Flash Color:     Change
" - -/* CITADEL EDIT - We're using top menu instead - button_name = pixel_size - dat += "Pixel Scaling: [(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"]
" - - switch(scaling_method) - if(SCALING_METHOD_NORMAL) - button_name = "Nearest Neighbor" - if(SCALING_METHOD_DISTORT) - button_name = "Point Sampling" - if(SCALING_METHOD_BLUR) - button_name = "Bilinear" - dat += "Scaling Method: [button_name]
" -*/ - - if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation)) - var/p_map = preferred_map - if (!p_map) - p_map = "Default" - if (config.defaultmap) - p_map += " ([config.defaultmap.map_name])" - else - if (p_map in config.maplist) - var/datum/map_config/VM = config.maplist[p_map] - if (!VM) - p_map += " (No longer exists)" - else - p_map = VM.map_name - else - p_map += " (No longer exists)" - if(CONFIG_GET(flag/allow_map_voting)) - dat += "Preferred Map: [p_map]
" - - dat += "" - - dat += "

Special Role Settings

" - - if(jobban_isbanned(user, ROLE_SYNDICATE)) - dat += "You are banned from antagonist roles." - src.be_special = list() - - dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]
" - - for (var/i in GLOB.special_roles) - if(jobban_isbanned(user, i)) - dat += "Be [capitalize(i)]: BANNED
" - else - var/days_remaining = null - if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age - var/mode_path = GLOB.special_roles[i] - var/datum/game_mode/temp_mode = new mode_path - days_remaining = temp_mode.get_remaining_days(user.client) - - if(days_remaining) - dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
" - else - var/enabled_text = "" - if(i in be_special) - if(be_special[i] >= 1) - enabled_text = "Enabled" + if(pref_species.use_skintones) + dat += "Genitals use skintone:[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]" + dat += "

Penis

" + dat += "[features["has_cock"] == TRUE ? "Yes" : "No"]" + if(features["has_cock"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Penis Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" else - enabled_text = "Low" - else - enabled_text = "Disabled" - dat += "Be [capitalize(i)]: [enabled_text]
" - dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" - - dat += "
" - - if(LOADOUT_TAB) - //calculate your gear points from the chosen item - gear_points = CONFIG_GET(number/initial_gear_points) - var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"] - if(chosen_gear) - for(var/loadout_item in chosen_gear) - var/loadout_item_path = loadout_item[LOADOUT_ITEM] - if(loadout_item_path) - var/datum/gear/loadout_gear = text2path(loadout_item_path) - if(loadout_gear) - gear_points -= initial(loadout_gear.cost) - else - chosen_gear = list() - - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - - dat += "" - - dat += "" - dat += "" - dat += "" - dat += "" - for(var/name in GLOB.loadout_items[gear_category][gear_subcategory]) - var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name] - var/donoritem = gear.donoritem - if(donoritem && !gear.donator_ckey_check(user.ckey)) - continue - var/class_link = "" - var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]") - var/extra_loadout_data = "" - if(loadout_item) - class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'" - if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) - extra_loadout_data += "
Color" - for(var/loadout_color in loadout_item[LOADOUT_COLOR]) - extra_loadout_data += "   " - else - var/loadout_color_non_poly = "#FFFFFF" - if(length(loadout_item[LOADOUT_COLOR])) - loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1] - extra_loadout_data += "
Color" - extra_loadout_data += "   " - if(gear.loadout_flags & LOADOUT_CAN_NAME) - extra_loadout_data += "
Name [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]" - if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION) - extra_loadout_data += "
Description" - else if((gear_points - gear.cost) < 0) - class_link = "style='white-space:normal;' class='linkOff'" - else if(donoritem) - class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" - else if(!istype(gear, /datum/gear/unlockable) || can_use_unlockable(gear)) - class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" - else - class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'" - dat += "" - dat += "" - else - //we add the user's progress to the description assuming they have progress - var/datum/gear/unlockable/unlockable = gear - var/progress_made = unlockable_loadout_data[unlockable.progress_key] - if(!progress_made) - progress_made = 0 - dat += "" + dat += "Testicles Color:
" + dat += "#[features["balls_color"]]Change
" + dat += "Testicles Shape:[features["balls_shape"]]" + dat += "Testicles Visibility:[features["balls_visibility"]]" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Vagina

" + dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]" + if(features["has_vag"]) + dat += "Vagina Type:[features["vag_shape"]]" + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Vagina Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Vagina Color:
" + dat += "#[features["vag_color"]]Change
" + dat += "Vagina Visibility:[features["vag_visibility"]]" + dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" + dat += "" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Breasts

" + dat += "[features["has_breasts"] == TRUE ? "Yes" : "No"]" + if(features["has_breasts"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Color:
" + dat += "#[features["breasts_color"]]Change
" + dat += "Cup Size:[features["breasts_size"]]" + dat += "Breasts Shape:[features["breasts_shape"]]" + dat += "Breasts Visibility:[features["breasts_visibility"]]" + dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]" + dat += "" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

Butt

" + dat += "[features["has_butt"] == TRUE ? "Yes" : "No"]" + if(features["has_butt"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" + else + dat += "Color:
" + dat += "#[features["butt_color"]]Change
" + dat += "Butt Size:[features["butt_size"]]" + dat += "Butt Visibility:[features["butt_visibility"]]" + dat += "" + dat += "" + dat += "
[gear_points] loadout points remaining. \[Clear Loadout\]
You can only choose one item per category, unless it's an item that spawns in your backpack or hands.
" - - if(!length(GLOB.loadout_items)) - dat += "
ERROR: No loadout categories - something is horribly wrong!" - else - if(!GLOB.loadout_categories[gear_category]) - gear_category = GLOB.loadout_categories[1] - var/firstcat = TRUE - for(var/category in GLOB.loadout_categories) - if(firstcat) - firstcat = FALSE - else - dat += " |" - if(category == gear_category) - dat += " [category] " - else - dat += " [category] " - - dat += "

" - - if(!length(GLOB.loadout_categories[gear_category])) - dat += "No subcategories detected. Something is horribly wrong!" - else - var/list/subcategories = GLOB.loadout_categories[gear_category] - if(!subcategories.Find(gear_subcategory)) - gear_subcategory = subcategories[1] - - var/firstsubcat = TRUE - for(var/subcategory in subcategories) - if(firstsubcat) - firstsubcat = FALSE - else - dat += " |" - if(gear_subcategory == subcategory) - dat += " [subcategory] " - else - dat += " [subcategory] " - dat += "
NameCostRestrictionsDescription
[name][extra_loadout_data][gear.cost]" - if(islist(gear.restricted_roles)) - if(gear.restricted_roles.len) - if(gear.restricted_desc) - dat += "" - dat += gear.restricted_desc - dat += "" + dat += "Penis Color:
" + dat += "#[features["cock_color"]] Change
" + var/tauric_shape = FALSE + if(features["cock_taur"]) + var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]] + if(P.taur_icon && parent.can_have_part("taur")) + var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] + if(T.taur_mode & P.accepted_taurs) + tauric_shape = TRUE + dat += "Penis Shape: [features["cock_shape"]][tauric_shape ? " (Taur)" : ""]" + dat += "Penis Length: [features["cock_length"]] inch(es)" + dat += "Penis Visibility:[features["cock_visibility"]]" + dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" + if(features["has_balls"]) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Testicles Color:
" + dat += "[SKINTONE2HEX(skin_tone)](Skin tone overriding)
" else - dat += "" - dat += gear.restricted_roles.Join(";") - dat += "" - if(!istype(gear, /datum/gear/unlockable)) - // the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description" - dat += "
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]
" + //Markings + if(MARKINGS_CHAR_TAB) + var/iterated_markings = 0 + var/total_pages = 0 + // rp marking selection + // assume you can only have mam markings or regular markings or none, never both + var/marking_type + if(parent.can_have_part("mam_body_markings")) + marking_type = "mam_body_markings" + if(marking_type) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "
" + dat += "

[GLOB.all_mutant_parts[marking_type]]

" // give it the appropriate title for the type of marking + dat += "Add marking" + dat += "
" + dat += "" + + for(var/limb in GLOB.bodypart_values) + if(length(GLOB.bodypart_values) % 3 != 0) + continue + total_pages++ + + for(var/limb in GLOB.bodypart_values) + if(!iterated_markings) + dat += "" + iterated_markings = 0 + dat += "
" + dat += "

[limb]

" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + // list out the current markings you have + if(length(features[marking_type])) + var/list/markings = features[marking_type] + if(!islist(markings)) + // something went terribly wrong + markings = list() + + for(var/list/marking_list in markings) + var/marking_index = markings.Find(marking_list) // consider changing loop to go through indexes over lists instead of using Find here + var/limb_value = marking_list[1] + var/actual_name = GLOB.bodypart_names[num2text(limb_value)] // get the actual name from the bitflag representing the part the marking is applied to + if(actual_name != limb) + continue + var/color_marking_dat = "" + var/number_colors = 1 + var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] + var/matrixed_sections = S.covered_limbs[actual_name] + if(S && matrixed_sections) + // if it has nothing initialize it to white + if(length(marking_list) == 2) + var/first = "#FFFFFF" + var/second = "#FFFFFF" + var/third = "#FFFFFF" + if(features["mcolor"]) + first = "#[features["mcolor"]]" + if(features["mcolor2"]) + second = "#[features["mcolor2"]]" + if(features["mcolor3"]) + third = "#[features["mcolor3"]]" + marking_list += list(list(first, second, third)) // just assume its 3 colours if it isnt it doesnt matter we just wont use the other values + // index magic + var/primary_index = 1 + var/secondary_index = 2 + var/tertiary_index = 3 + switch(matrixed_sections) + if(MATRIX_GREEN) + primary_index = 2 + if(MATRIX_BLUE) + primary_index = 3 + if(MATRIX_RED_BLUE) + secondary_index = 2 + if(MATRIX_GREEN_BLUE) + primary_index = 2 + secondary_index = 3 + + // we know it has one matrixed section at minimum + color_marking_dat += "[marking_list[3][primary_index]]" + // if it has a second section, add it + if(matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL) + number_colors = 2 + color_marking_dat += "[marking_list[3][secondary_index]]" + // if it has a third section, add it + if(matrixed_sections == MATRIX_ALL) + number_colors = 3 + color_marking_dat += "[marking_list[3][tertiary_index]]" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + else + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "
[marking_index]˅˄[marking_list[2]][color_marking_dat]X
" + + iterated_markings++ + if(iterated_markings >= 3) + dat += "
" + + if(SPEECH_CHAR_TAB) + dat += "" + dat += "" + dat += "
" + dat += "

Speech preferences

" + dat += "Custom Speech Verb:
" + dat += "[custom_speech_verb]
" + dat += "Custom Tongue:
" + dat += "[custom_tongue]
" + dat += "Additional Language
" + dat += "[additional_language]
" + dat += "
" + dat += "

Vocal Bark preferences

" + var/datum/bark/B = GLOB.bark_list[bark_id] + dat += "Vocal Bark Sound:
" + dat += "[B ? initial(B.name) : "INVALID"]
" + dat += "Vocal Bark Speed: [bark_speed]
" + dat += "Vocal Bark Pitch: [bark_pitch]
" + dat += "Vocal Bark Variance: [bark_variance]
" + dat += "
Preview Bark
" + dat += "
" + if(LOADOUT_CHAR_TAB) + dat += "" + dat += "" + dat += "" + dat += "" + + dat += "" + + dat += "
You can only choose one item per category, unless it's an item that spawns in your backpack or hands.
" + + if(!length(GLOB.loadout_items)) + dat += "
ERROR: No loadout categories - something is horribly wrong!" + else + if(!GLOB.loadout_categories[gear_category]) + gear_category = GLOB.loadout_categories[1] + var/firstcat = TRUE + for(var/category in GLOB.loadout_categories) + if(firstcat) + firstcat = FALSE + else + dat += " |" + if(category == gear_category) + dat += " [category] " + else + dat += " [category] " + + dat += "

" + + if(!length(GLOB.loadout_categories[gear_category])) + dat += "No subcategories detected. Something is horribly wrong!" + else + var/list/subcategories = GLOB.loadout_categories[gear_category] + if(!subcategories.Find(gear_subcategory)) + gear_subcategory = subcategories[1] + + var/firstsubcat = TRUE + for(var/subcategory in subcategories) + if(firstsubcat) + firstsubcat = FALSE + else + dat += " |" + if(gear_subcategory == subcategory) + dat += " [subcategory] " + else + dat += " [subcategory] " + dat += "
" + dat += "
" + dat += "
" + dat += "" + dat += "" + dat += "" + dat += "" + + var/even = FALSE + for(var/name in GLOB.loadout_items[gear_category][gear_subcategory]) + var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name] + var/donoritem = gear.donoritem + if(donoritem && !gear.donator_ckey_check(user.ckey)) + continue + var/background_cl = "#23273C" + if(even) + background_cl = "#17191C" + even = !even + var/class_link = "" + var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]") + var/extra_loadout_data = "" + if(loadout_item) + class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'" + if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC) + extra_loadout_data += "
Color" + for(var/loadout_color in loadout_item[LOADOUT_COLOR]) + extra_loadout_data += "[loadout_color]" + else + var/loadout_color_non_poly = "#FFFFFF" + if(length(loadout_item[LOADOUT_COLOR])) + loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1] + extra_loadout_data += "
Color" + extra_loadout_data += "[loadout_color_non_poly]" + if(gear.loadout_flags & LOADOUT_CAN_NAME) + extra_loadout_data += "
Name [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]" + if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION) + extra_loadout_data += "
Description" + else if((gear_points - gear.cost) < 0) + class_link = "style='white-space:normal;' class='linkOff'" + else if(donoritem) + class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + else if(!istype(gear, /datum/gear/unlockable) || can_use_unlockable(gear)) + class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + else + class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'" + dat += "" + dat += "" + else + //we add the user's progress to the description assuming they have progress + var/datum/gear/unlockable/unlockable = gear + var/progress_made = unlockable_loadout_data[unlockable.progress_key] + if(!progress_made) + progress_made = 0 + dat += "" + dat += "
NameCostRestrictionsDescription
[name][extra_loadout_data][gear.cost]" + if(islist(gear.restricted_roles)) + if(gear.restricted_roles.len) + if(gear.restricted_desc) + dat += "" + dat += gear.restricted_desc + dat += "" + else + dat += "" + dat += gear.restricted_roles.Join(";") + dat += "" + if(!istype(gear, /datum/gear/unlockable)) + // the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description" + dat += "[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]
[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]
" dat += "" - if(CONTENT_PREFERENCES_TAB) // Content preferences - dat += "" - dat +="
" - dat += "

Fetish content prefs

" - dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
" - dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"]
" - dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"]
" - dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
" - dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
" - dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
" - dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]
" - dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
" - dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
" - dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
" - dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"]
" - dat += "
" - dat += "

Other content prefs

" - dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Butt Enlargement: [(cit_toggles & BUTT_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" - dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
" - dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
" - dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" - dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]
" - dat += "
" - dat += "
" + if(PREFERENCES_TAB) // Game Preferences + dat += "
" + dat += "General" + dat += "OOC" + dat += "Content" + dat += "
" + + dat += "
" + + switch(preferences_tab) + if(GAME_PREFS_TAB) + dat += "" + + dat += "
" + dat += "

General Settings

" + dat += "UI Style: [UI_style]
" + dat += "Outline: [outline_enabled ? "Enabled" : "Disabled"]
" + dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"][outline_color] Change
" + dat += "Screentip: [screentip_pref ? "Enabled" : "Disabled"]
" + dat += "Screentip Color: [screentip_color] Change
" + dat += "\ + Screentip context with images: [screentip_images ? "Allowed" : "Disallowed"]
" + dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
" + dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
" + dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"]
" + dat += "Runechat message char limit: [max_chat_length]
" + dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"]
" + dat += "
" + dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" + dat += "
" + dat += "PDA Color: [pda_color] Change
" + dat += "PDA Style: [pda_style]
" + dat += "PDA Reskin: [pda_skin]
" + dat += "
" + dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" + dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
" + dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"]
" + dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
" + + dat += "
" + + dat += "

Special Role Settings

" + + if(jobban_isbanned(user, ROLE_SYNDICATE)) + dat += "You are banned from antagonist roles." + src.be_special = list() + + dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]
" + + for (var/i in GLOB.special_roles) + if(jobban_isbanned(user, i)) + dat += "Be [capitalize(i)]: BANNED
" + else + var/days_remaining = null + if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age + var/mode_path = GLOB.special_roles[i] + var/datum/game_mode/temp_mode = new mode_path + days_remaining = temp_mode.get_remaining_days(user.client) + + if(days_remaining) + dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS\]
" + else + var/enabled_text = "" + if(i in be_special) + if(be_special[i] >= 1) + enabled_text = "Enabled" + else + enabled_text = "Low" + else + enabled_text = "Disabled" + dat += "Be [capitalize(i)]: [enabled_text]
" + dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" + + dat += "
" + + if(OOC_PREFS_TAB) + dat += "" + dat += "" + + dat += "
" + dat += "

OOC Settings

" + dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]
" + dat += "
" + dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"]
" + dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
" + dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
" + dat += "
" + if(user.client) + if(unlock_content) + dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" + if(unlock_content || check_rights_for(user.client, R_ADMIN)) + dat += "OOC Color: [ooccolor ? ooccolor : GLOB.normal_ooc_colour] Change
" + dat += "Antag OOC Color: [aooccolor ? aooccolor : GLOB.normal_aooc_colour] Change
" + + if(user.client.holder) + dat += "

Admin Settings

" + dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]
" + dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"]
" + dat += "
" + dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"]
" + + //deadmin + dat += "

Deadmin While Playing

" + if(CONFIG_GET(flag/auto_deadmin_players)) + dat += "Always Deadmin: FORCED
" + else + dat += "Always Deadmin: [(deadmin & DEADMIN_ALWAYS)?"Enabled":"Disabled"]
" + if(!(deadmin & DEADMIN_ALWAYS)) + dat += "
" + if(!CONFIG_GET(flag/auto_deadmin_antagonists)) + dat += "As Antag: [(deadmin & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"]
" + else + dat += "As Antag: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_heads)) + dat += "As Command: [(deadmin & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"]
" + else + dat += "As Command: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_security)) + dat += "As Security: [(deadmin & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"]
" + else + dat += "As Security: FORCED
" + + if(!CONFIG_GET(flag/auto_deadmin_silicons)) + dat += "As Silicon: [(deadmin & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"]
" + else + dat += "As Silicon: FORCED
" + + dat += "
" + + dat += "

Citadel Preferences

" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. + dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]
" + dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"]
" + dat += "Auto stand: [autostand ? "Enabled" : "Disabled"]
" + dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"]
" + dat += "Force Slot Storage HUD: [no_tetris_storage ? "Enabled" : "Disabled"]
" + dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]
" + if (user && user.client && !user.client.prefs.screenshake==0) + dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]
" + dat += "Recoil Screen Push: [(recoil_screenshake==100) ? "Full" : ((recoil_screenshake==0) ? "None" : "[screenshake]")]
" + var/p_chaos + if (!preferred_chaos) + p_chaos = "No preference" + else + p_chaos = preferred_chaos + dat += "Preferred Chaos Amount: [p_chaos]
" + dat += "
" + + if(unlock_content) + dat += "Ghost Form: [ghost_form]
" + dat += "Ghost Orbit: [ghost_orbit]
" + var/button_name = "If you see this something went wrong." + switch(ghost_accs) + if(GHOST_ACCS_FULL) + button_name = GHOST_ACCS_FULL_NAME + if(GHOST_ACCS_DIR) + button_name = GHOST_ACCS_DIR_NAME + if(GHOST_ACCS_NONE) + button_name = GHOST_ACCS_NONE_NAME + + dat += "Ghost Accessories: [button_name]
" + switch(ghost_others) + if(GHOST_OTHERS_THEIR_SETTING) + button_name = GHOST_OTHERS_THEIR_SETTING_NAME + if(GHOST_OTHERS_DEFAULT_SPRITE) + button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME + if(GHOST_OTHERS_SIMPLE) + button_name = GHOST_OTHERS_SIMPLE_NAME + + dat += "Ghosts of Others: [button_name]
" + dat += "
" + + dat += "FPS: [clientfps]
" + + dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" + dat += "
" + + dat += "Parallax (Fancy Space): " + switch (parallax) + if (PARALLAX_LOW) + dat += "Low" + if (PARALLAX_MED) + dat += "Medium" + if (PARALLAX_INSANE) + dat += "Insane" + if (PARALLAX_DISABLE) + dat += "Disabled" + else + dat += "High" + dat += "
" + dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"]
" + dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"]
" + dat += "HUD Button Flashes: [hud_toggle_flash ? "Enabled" : "Disabled"]
" + dat += "HUD Button Flash Color: [hud_toggle_color] Change
" + + + if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation)) + var/p_map = preferred_map + if (!p_map) + p_map = "Default" + if (config.defaultmap) + p_map += " ([config.defaultmap.map_name])" + else + if (p_map in config.maplist) + var/datum/map_config/VM = config.maplist[p_map] + if (!VM) + p_map += " (No longer exists)" + else + p_map = VM.map_name + else + p_map += " (No longer exists)" + if(CONFIG_GET(flag/allow_map_voting)) + dat += "Preferred Map: [p_map]
" + + dat += "
" + + if(CONTENT_PREFS_TAB) + dat += "" + dat +="
" + dat += "

Fetish content prefs

" + dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
" + dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"]
" + dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"]
" + dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
" + dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
" + dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
" + dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]
" + dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
" + dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
" + dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
" + dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"]
" + dat += "
" + dat += "

Other content prefs

" + dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Butt Enlargement: [(cit_toggles & BUTT_ENLARGEMENT) ? "Allowed" : "Disallowed"]
" + dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
" + dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
" + dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" + dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]
" + dat += "
" + if(KEYBINDINGS_TAB) // Custom keybindings dat += "Keybindings: [(hotkeys) ? "Hotkeys" : "Input"]
" dat += "Keybindings mode controls how the game behaves with tab and map/input focus.
If it is on Hotkeys, the game will always attempt to force you to map focus, meaning keypresses are sent \ @@ -2565,7 +2641,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) gender = chosengender if("body_size") - var/new_body_size = input(user, "Choose your desired sprite size: (90-125%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null + var/new_body_size = input(user, "Choose your desired sprite size: ([CONFIG_GET(number/body_size_min)]-[CONFIG_GET(number/body_size_max)]%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null if(new_body_size) features["body_size"] = clamp(new_body_size * 0.01, CONFIG_GET(number/body_size_min), CONFIG_GET(number/body_size_max)) @@ -2689,47 +2765,36 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/limb_value = text2num(GLOB.bodypart_values[limb]) features[marking_type] += list(list(limb_value, selected_marking)) - if("marking_color") + if("marking_color_specific") var/index = text2num(href_list["marking_index"]) var/marking_type = href_list["marking_type"] - if(index && marking_type && features[marking_type]) - // work out the input options to show the user - var/list/options = list("Primary") - var/number_colors = text2num(href_list["number_colors"]) - var/color_number = 1 // 1-3 which color are we editing - if(number_colors >= 2) - options += "Secondary" - if(number_colors == 3) - options += "Tertiary" - var/color_option = input(user, "Select the colour you wish to edit") as null|anything in options - if(color_option) - if(color_option == "Secondary") color_number = 2 - if(color_option == "Tertiary") color_number = 3 - // perform some magic on the color number - var/list/marking_list = features[marking_type][index] - var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] - var/matrixed_sections = S.covered_limbs[GLOB.bodypart_names[num2text(marking_list[1])]] - if(color_number == 1) - switch(matrixed_sections) - if(MATRIX_GREEN) - color_number = 2 - if(MATRIX_BLUE) - color_number = 3 - else if(color_number == 2) - switch(matrixed_sections) - if(MATRIX_RED_BLUE) - color_number = 3 - if(MATRIX_GREEN_BLUE) - color_number = 3 + var/color_number = text2num(href_list["number_color"]) + if(index && marking_type && color_number && features[marking_type]) + // perform some magic on the color number + var/list/marking_list = features[marking_type][index] + var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]] + var/matrixed_sections = S.covered_limbs[GLOB.bodypart_names[num2text(marking_list[1])]] + if(color_number == 1) + switch(matrixed_sections) + if(MATRIX_GREEN) + color_number = 2 + if(MATRIX_BLUE) + color_number = 3 + else if(color_number == 2) + switch(matrixed_sections) + if(MATRIX_RED_BLUE) + color_number = 3 + if(MATRIX_GREEN_BLUE) + color_number = 3 - var/color_list = features[marking_type][index][3] - var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null - if(new_marking_color) - var/temp_hsv = RGBtoHSV(new_marking_color) - if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin - color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]" - else - to_chat(user, "Invalid color. Your color is not bright enough.") + var/color_list = features[marking_type][index][3] + var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null + if(new_marking_color) + var/temp_hsv = RGBtoHSV(new_marking_color) + if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin + color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]" + else + to_chat(user, "Invalid color. Your color is not bright enough.") else switch(href_list["preference"]) //CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj @@ -3130,6 +3195,18 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("tab") if(href_list["tab"]) current_tab = text2num(href_list["tab"]) + + if("character_preview") + preview_pref = href_list["tab"] + + if("character_tab") + if(href_list["tab"]) + character_settings_tab = text2num(href_list["tab"]) + + if("preferences_tab") + if(href_list["tab"]) + preferences_tab = text2num(href_list["tab"]) + if(href_list["preference"] == "gear") if(href_list["clear_loadout"]) loadout_data["SAVE_[loadout_slot]"] = list() diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm index dd3d5186de..a978e541bf 100644 --- a/code/modules/mob/dead/new_player/preferences_setup.dm +++ b/code/modules/mob/dead/new_player/preferences_setup.dm @@ -30,7 +30,6 @@ age = rand(AGE_MIN,AGE_MAX) /datum/preferences/proc/update_preview_icon(current_tab) - var/equip_job = (current_tab != APPEARANCE_TAB) // Determine what job is marked as 'High' priority, and dress them up as such. var/datum/job/previewJob = get_highest_job() @@ -49,14 +48,25 @@ mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER)) copy_to(mannequin, initial_spawn = TRUE) - if(current_tab == LOADOUT_TAB) - //give it its loadout if not on the appearance tab - SSjob.equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) - SSjob.post_equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) - else - if(previewJob && equip_job) - mannequin.job = previewJob.title - previewJob.equip(mannequin, TRUE, preference_source = parent) + switch(preview_pref) + if(PREVIEW_PREF_JOB) + if(previewJob) + mannequin.job = previewJob.title + previewJob.equip(mannequin, TRUE, preference_source = parent) + if(PREVIEW_PREF_LOADOUT) + SSjob.equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) + SSjob.post_equip_loadout(parent.mob, mannequin, bypass_prereqs = TRUE, can_drop = FALSE) + if(PREVIEW_PREF_NAKED) + mannequin.hidden_underwear = TRUE + mannequin.hidden_undershirt = TRUE + mannequin.hidden_socks = TRUE + if(PREVIEW_PREF_NAKED_AROUSED) + mannequin.hidden_underwear = TRUE + mannequin.hidden_undershirt = TRUE + mannequin.hidden_socks = TRUE + for(var/obj/item/organ/genital/genital in mannequin.internal_organs) + if(genital.genital_flags & GENITAL_CAN_AROUSE) + genital.set_aroused_state(TRUE, null) mannequin.regenerate_icons() From def4b38a467e3595416db66c42b30512be69fabf Mon Sep 17 00:00:00 2001 From: BlueWildrose <57083662+BlueWildrose@users.noreply.github.com> Date: Wed, 11 Oct 2023 13:52:03 -0600 Subject: [PATCH 3/3] Revert "[DNM] Updates firemanning, throwing stuff" --- code/__DEFINES/dcs/signals/signals_global.dm | 2 - .../signals/signals_mob/signals_mob_main.dm | 2 - code/__HELPERS/pronouns.dm | 15 --- code/datums/components/riding.dm | 9 -- code/datums/elements/mob_holder.dm | 75 +++++------- code/game/objects/buckling.dm | 25 +--- code/game/objects/items.dm | 12 -- code/game/objects/items/cigs_lighters.dm | 1 - .../structures/beds_chairs/alien_nest.dm | 2 +- code/game/objects/structures/kitchen_spike.dm | 2 +- code/game/objects/structures/manned_turret.dm | 2 +- code/game/objects/structures/morgue.dm | 11 -- code/game/objects/structures/tables_racks.dm | 34 +----- .../clock_structures/traps/brass_skewer.dm | 2 +- .../antagonists/devil/true_devil/inventory.dm | 2 +- code/modules/mob/inventory.dm | 16 +-- .../living/carbon/alien/larva/inventory.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 111 +++++++++--------- .../simple_animal/guardian/types/dextrous.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- .../mob/living/simple_animal/slime/slime.dm | 2 +- code/modules/power/singularity/emitter.dm | 2 +- tgstation.dme | 2 - 23 files changed, 106 insertions(+), 229 deletions(-) delete mode 100644 code/__DEFINES/dcs/signals/signals_global.dm delete mode 100644 code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm deleted file mode 100644 index 3e0e1d2296..0000000000 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ /dev/null @@ -1,2 +0,0 @@ -/// a person somewhere has thrown something : (mob/living/carbon/carbon_thrower, target) -#define COMSIG_GLOB_CARBON_THROW_THING "!throw_thing" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm deleted file mode 100644 index e6c3464ff7..0000000000 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ /dev/null @@ -1,2 +0,0 @@ -/// from mob/proc/dropItemToGround() -#define COMSIG_MOB_DROPPING_ITEM "mob_dropping_item" diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index fd15c05c64..bfe09ba370 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -39,21 +39,6 @@ /datum/proc/p_es(temp_gender) . = "es" -/datum/proc/plural_s(pluralize) - switch(copytext_char(pluralize, -2)) - if ("ss") - return "es" - if ("sh") - return "es" - if ("ch") - return "es" - else - switch(copytext_char(pluralize, -1)) - if("s", "x", "z") - return "es" - else - return "s" - //like clients, which do have gender. /client/p_they(capitalized, temp_gender) if(!temp_gender) diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 49b8f7f7f0..a074fe6f5f 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -392,12 +392,3 @@ if(rider in AM.buckled_mobs) AM.unbuckle_mob(rider) . = ..() - -/obj/item/riding_offhand/on_thrown(mob/living/carbon/user, atom/target) - if(rider == user) - return //Piggyback user. - user.unbuckle_mob(rider) - if(HAS_TRAIT(user, TRAIT_PACIFISM)) - to_chat(user, span_notice("You gently let go of [rider].")) - return - return rider diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 82f42d69b3..5f57b4fce3 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -61,7 +61,7 @@ return FALSE source.visible_message("[user] starts picking up [source].", \ "[user] starts picking you up!") - if(!do_after(user, 2 SECONDS, target = source) || source.buckled) + if(!do_after(user, 20, target = source) || source.buckled) return FALSE source.visible_message("[user] picks up [source]!", \ @@ -95,7 +95,6 @@ dynamic_hair_suffix = "" var/mob/living/held_mob var/escape_on_find - var/destroying = FALSE /obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE) . = ..() @@ -135,54 +134,45 @@ w_class = WEIGHT_CLASS_HUGE /obj/item/clothing/head/mob_holder/Destroy() - destroying = TRUE if(held_mob) - release(FALSE) + release() return ..() /obj/item/clothing/head/mob_holder/examine(mob/user) return held_mob?.examine(user) || ..() -/obj/item/clothing/head/mob_holder/on_thrown(mob/living/carbon/user, atom/target) - if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP)) - return - if(HAS_TRAIT(user, TRAIT_PACIFISM)) - to_chat(user, span_notice("You set [src] down gently on the ground.")) - release() - return +/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc) + . = ..() + if(AM == held_mob) + held_mob.reset_perspective() + held_mob = null + QDEL_IN(src, 1) //To avoid a qdel loop. - var/mob/living/throw_mob = held_mob - release() - return throw_mob +/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc) + . = ..() + if(AM != held_mob) + var/destination = loc + if(isliving(loc)) //the mob is held or worn, drop things on the floor + destination = get_turf(loc) + AM.forceMove(destination) /obj/item/clothing/head/mob_holder/dropped(mob/user) . = ..() - if(held_mob && isturf(loc)) + if(held_mob && !ismob(loc) && !istype(loc,/obj/item/storage))//don't release on soft-drops release() -/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE, display_messages = TRUE) - if(!held_mob) - if(del_on_release && !destroying) - qdel(src) - return FALSE - var/mob/living/released_mob = held_mob - held_mob = null // stops the held mob from being release()'d twice. - if(isliving(loc)) - var/mob/living/L = loc - if(display_messages) - to_chat(L, span_warning("[released_mob] wriggles free!")) - L.dropItemToGround(src) - released_mob.forceMove(drop_location()) - released_mob.reset_perspective() - released_mob.setDir(SOUTH) - if(display_messages) - released_mob.visible_message(span_warning("[released_mob] uncurls!")) - if(del_on_release && !destroying) +/obj/item/clothing/head/mob_holder/proc/release() + if(held_mob) + var/mob/living/L = held_mob + held_mob = null + L.forceMove(get_turf(L)) + L.reset_perspective() + L.setDir(SOUTH) + if(!QDELETED(src)) qdel(src) - return TRUE -/obj/item/clothing/head/mob_holder/relaymove(mob/living/user, direction) - container_resist() +/obj/item/clothing/head/mob_holder/relaymove(mob/user) + return /obj/item/clothing/head/mob_holder/container_resist() if(isliving(loc)) @@ -190,11 +180,6 @@ L.visible_message("[held_mob] escapes from [L]!", "[held_mob] escapes your grip!") release() -/obj/item/clothing/head/mob_holder/Exited(atom/movable/gone, direction) - . = ..() - if(held_mob && held_mob == gone) - release() - /obj/item/clothing/head/mob_holder/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self) if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys... return FALSE @@ -247,9 +232,7 @@ return location.transfer_air(taker, ratio) // escape when found if applicable -/obj/item/clothing/head/mob_holder/on_found(mob/finder) +/obj/item/clothing/head/mob_holder/on_found(mob/living/finder) if(escape_on_find) - to_chat(finder, span_warning("\A [held_mob.name] pops out! ")) - finder.visible_message(span_warning("\A [held_mob.name] pops out of the container [finder] is opening!"), ignored_mobs = finder) - release(TRUE, FALSE) - return + finder.visible_message("[finder] accidentally releases the [held_mob]!") + release() diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index aae6cbaa5c..afc4312779 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -25,32 +25,11 @@ if(user_unbuckle_mob(buckled_mobs[1],user)) return 1 -/atom/movable/attackby(obj/item/attacking_item, mob/user, params) - if(!can_buckle || !istype(attacking_item, /obj/item/riding_offhand) || !user.Adjacent(src)) - return ..() - - var/obj/item/riding_offhand/riding_item = attacking_item - var/mob/living/carried_mob = riding_item.rider - if(carried_mob == user) //Piggyback user. - return - user.unbuckle_mob(carried_mob) - carried_mob.forceMove(get_turf(src)) - return mouse_buckle_handling(carried_mob, user) - /atom/movable/MouseDrop_T(mob/living/M, mob/living/user) . = ..() - return mouse_buckle_handling(M, user) - -/** - * Does some typechecks and then calls user_buckle_mob - * - * Arguments: - * M - The mob being buckled to src - * user - The mob buckling M to src - */ -/atom/movable/proc/mouse_buckle_handling(mob/living/M, mob/living/user) if(can_buckle && istype(M) && istype(user)) - return user_buckle_mob(M, user, check_loc = FALSE) + if(user_buckle_mob(M, user)) + return 1 /atom/movable/proc/has_buckled_mobs() if(!buckled_mobs) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e63f809a5e..7a953089a5 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -177,8 +177,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/canMouseDown = FALSE - /// Used if we want to have a custom verb text for throwing. "John Spaceman flicks the ciggerate" for example. - var/throw_verb /obj/item/Initialize(mapload) @@ -1118,16 +1116,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb QDEL_NULL(src) return TRUE -///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else. -/obj/item/proc/on_thrown(mob/living/carbon/user, atom/target) - if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP)) - return - user.dropItemToGround(src, silent = TRUE) - if(throwforce && HAS_TRAIT(user, TRAIT_PACIFISM)) - to_chat(user, span_notice("You set [src] down gently on the ground.")) - return - return src - /** diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index a52bbb75f3..518772c771 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -108,7 +108,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM w_class = WEIGHT_CLASS_TINY body_parts_covered = null grind_results = list() - throw_verb = "flick" var/lit = FALSE var/starts_lit = FALSE var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm index 762331c40e..eff87d3955 100644 --- a/code/game/objects/structures/beds_chairs/alien_nest.dm +++ b/code/game/objects/structures/beds_chairs/alien_nest.dm @@ -48,7 +48,7 @@ unbuckle_mob(M) add_fingerprint(user) -/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc) +/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/carbon/user) if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || !user.cuff_resist_check() || M.buckled ) return diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 8c2655dd64..a37797045f 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -97,7 +97,7 @@ -/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user, check_loc) //Don't want them getting put on the rack other than by spiking +/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking return /obj/structure/kitchenspike/user_unbuckle_mob(mob/living/buckled_mob, mob/living/carbon/human/user) diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index 3f1cb5f4c1..f70510e173 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -43,7 +43,7 @@ . = ..() STOP_PROCESSING(SSfastprocess, src) -/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc) +/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) if(user.incapacitated() || !istype(user)) return M.forceMove(get_turf(src)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index c39b3f64b1..69206f0d08 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -330,17 +330,6 @@ GLOBAL_LIST_EMPTY(crematoriums) else to_chat(user, "That's not connected to anything!") -/obj/structure/tray/attackby(obj/P, mob/user, params) - if(!istype(P, /obj/item/riding_offhand)) - return ..() - - var/obj/item/riding_offhand/riding_item = P - var/mob/living/carried_mob = riding_item.rider - if(carried_mob == user) //Piggyback user. - return - user.unbuckle_mob(carried_mob) - MouseDrop_T(carried_mob, user) - /obj/structure/tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user) if(!ismovable(O) || O.anchored || !Adjacent(user) || !user.Adjacent(O) || O.loc == user) return diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 12799b4370..b7642f4658 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -124,11 +124,11 @@ . = . || (caller.pass_flags & PASSTABLE) /obj/structure/table/proc/tableplace(mob/living/user, mob/living/pushed_mob) - pushed_mob.forceMove(loc) - pushed_mob.set_resting(TRUE, TRUE) - pushed_mob.visible_message(span_notice("[user] places [pushed_mob] onto [src]."), \ - span_notice("[user] places [pushed_mob] onto [src].")) - log_combat(user, pushed_mob, "places", null, "onto [src]") + pushed_mob.forceMove(src.loc) + pushed_mob.set_resting(TRUE, FALSE) + pushed_mob.visible_message("[user] places [pushed_mob] onto [src].", \ + "[user] places [pushed_mob] onto [src].") + log_combat(user, pushed_mob, "placed") /obj/structure/table/proc/tablepush(mob/living/user, mob/living/pushed_mob) if(HAS_TRAIT(user, TRAIT_PACIFISM)) @@ -205,30 +205,6 @@ return // If the tray IS empty, continue on (tray will be placed on the table like other items) - if(istype(I, /obj/item/riding_offhand)) - var/obj/item/riding_offhand/riding_item = I - var/mob/living/carried_mob = riding_item.rider - if(carried_mob == user) //Piggyback user. - return - if(user.a_intent == INTENT_HARM) - user.unbuckle_mob(carried_mob) - tablelimbsmash(user, carried_mob) - else - var/tableplace_delay = 3.5 SECONDS - var/skills_space = "" - if(HAS_TRAIT(user, TRAIT_QUICKER_CARRY)) - tableplace_delay = 2 SECONDS - skills_space = " expertly" - else if(HAS_TRAIT(user, TRAIT_QUICK_CARRY)) - tableplace_delay = 2.75 SECONDS - skills_space = " quickly" - carried_mob.visible_message(span_notice("[user] begins to[skills_space] place [carried_mob] onto [src]..."), - span_userdanger("[user] begins to[skills_space] place [carried_mob] onto [src]...")) - if(do_after(user, tableplace_delay, target = carried_mob)) - user.unbuckle_mob(carried_mob) - tableplace(user, carried_mob) - return TRUE - if(user.a_intent != INTENT_HARM && !(I.item_flags & ABSTRACT)) if(user.transferItemToLoc(I, drop_location())) var/list/click_params = params2list(params) diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm index ac8dc0bffb..a7c1f81f06 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm @@ -81,7 +81,7 @@ density = TRUE //Skewers are one-use only desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember? -/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob(check_loc) +/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob() return /obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L) diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm index 8856838a34..e98cb5ca72 100644 --- a/code/modules/antagonists/devil/true_devil/inventory.dm +++ b/code/modules/antagonists/devil/true_devil/inventory.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, invdrop, silent = FALSE) +/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, silent = FALSE) if(..()) update_inv_hands() return 1 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 79a0ccda77..51659a2904 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -292,18 +292,10 @@ //The following functions are the same save for one small difference -/** - * Used to drop an item (if it exists) to the ground. - * * Will pass as TRUE is successfully dropped, or if there is no item to drop. - * * Will pass FALSE if the item can not be dropped due to TRAIT_NODROP via doUnEquip() - * If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called. -*/ -/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE) - if (isnull(I)) - return TRUE - - SEND_SIGNAL(src, COMSIG_MOB_DROPPING_ITEM) - . = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent) +//for when you want the item to end up on the ground +//will force move the item to the ground and call the turf's Entered +/mob/proc/dropItemToGround(obj/item/I, force = FALSE) + return doUnEquip(I, force, drop_location(), FALSE) //for when the item will be immediately placed in a loc other than the ground /mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE) diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index 5b49c3abb0..b07bd180f6 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,3 +1,3 @@ //can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, invdrop, silent = FALSE) +/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, silent = FALSE) return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e9f4f61556..419a75eff2 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -141,28 +141,26 @@ /mob/living/carbon/proc/throw_mode_off() - in_throw_mode = FALSE + in_throw_mode = 0 if(client && hud_used) hud_used.throw_icon.icon_state = "act_throw_off" /mob/living/carbon/proc/throw_mode_on() - in_throw_mode = TRUE + in_throw_mode = 1 if(client && hud_used) hud_used.throw_icon.icon_state = "act_throw_on" /mob/proc/throw_item(atom/target) SEND_SIGNAL(src, COMSIG_MOB_THROW, target) - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CARBON_THROW_THING, src, target) - return TRUE + return /mob/living/carbon/throw_item(atom/target) - . = ..() throw_mode_off() if(!target || !isturf(loc)) - return FALSE + return if(istype(target, /atom/movable/screen)) - return FALSE + return //CIT CHANGES - makes it impossible to throw while in stamina softcrit if(IS_STAMCRIT(src)) @@ -172,56 +170,59 @@ var/random_turn = a_intent == INTENT_HARM //END OF CIT CHANGES - var/atom/movable/thrown_thing - var/obj/item/held_item = get_active_held_item() - var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling") - if(prob(0.5)) - verb_text = "yeet" + var/obj/item/I = get_active_held_item() - var/neckgrab_throw = FALSE - if(!held_item) - if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) - var/mob/living/throwable_mob = pulling - if(!throwable_mob.buckled) - thrown_thing = throwable_mob - if(grab_state >= GRAB_NECK) - neckgrab_throw = TRUE + var/atom/movable/thrown_thing + var/mob/living/throwable_mob + + if(istype(I, /obj/item/clothing/head/mob_holder)) + var/obj/item/clothing/head/mob_holder/holder = I + if(holder.held_mob) + throwable_mob = holder.held_mob + holder.release() + + if(!I || throwable_mob) + if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) + throwable_mob = pulling + + if(throwable_mob && !throwable_mob.buckled) + thrown_thing = throwable_mob + if(pulling) stop_pulling() - if(HAS_TRAIT(src, TRAIT_PACIFISM)) - to_chat(src, span_notice("You gently let go of [throwable_mob].")) - return FALSE - if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE)) - return FALSE - else - thrown_thing = held_item.on_thrown(src, target) - if(!thrown_thing) - return FALSE - if(isliving(thrown_thing)) - var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors - var/turf/end_T = get_turf(target) - if(start_T && end_T) - log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") - var/power_throw = 0 - if(HAS_TRAIT(src, TRAIT_HULK)) - power_throw++ - if(HAS_TRAIT(src, TRAIT_DWARF)) - power_throw-- - if(HAS_TRAIT(thrown_thing, TRAIT_DWARF)) - power_throw++ - if(neckgrab_throw) - power_throw++ - if(isitem(thrown_thing)) - var/obj/item/thrown_item = thrown_thing - if(thrown_item.throw_verb) - verb_text = thrown_item.throw_verb - visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw ? " really hard!" : "."]"), \ - span_danger("You [verb_text] [thrown_thing][power_throw ? " really hard!" : "."]")) - log_message("has thrown [thrown_thing] [power_throw > 0 ? "really hard" : ""]", LOG_ATTACK) - do_attack_animation(target, no_effect = 1) - var/extra_throw_range = 0 // HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0 - playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) - newtonian_move(get_dir(target, src)) - thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force, random_turn) + if(HAS_TRAIT(src, TRAIT_PACIFISM)) + to_chat(src, "You gently let go of [throwable_mob].") + return + if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE)) + return + var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors + var/turf/end_T = get_turf(target) + if(start_T && end_T) + log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") + + else if(!(I.item_flags & ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP)) + thrown_thing = I + dropItemToGround(I) + + if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce) + to_chat(src, "You set [I] down gently on the ground.") + return + + if(!UseStaminaBuffer(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST), warn = TRUE)) + return + + if(thrown_thing) + var/power_throw = 0 + if(HAS_TRAIT(src, TRAIT_HULK)) + power_throw++ + if(pulling && grab_state >= GRAB_NECK) + power_throw++ + visible_message("[src] throws [thrown_thing][power_throw ? " really hard!" : "."]", \ + "You throw [thrown_thing][power_throw ? " really hard!" : "."]") + log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK) + do_attack_animation(target, no_effect = 1) + playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) + newtonian_move(get_dir(target, src)) + thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn) /mob/living/carbon/restrained(ignore_grab) . = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index 4e57aa1562..1fd1e623db 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -41,7 +41,7 @@ ..() //lose items, then return //SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE -/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, invdrop, silent = FALSE) +/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, silent = FALSE) if(..()) update_inv_hands() if(I == internal_storage) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 151cc70a27..f226a911d8 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -587,7 +587,7 @@ //ANIMAL RIDING -/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user, check_loc) +/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user) var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding) if(riding_datum) if(user.incapacitated()) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 2b267c4d01..dc9d6ff6a3 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -252,7 +252,7 @@ Feedon(Food) return ..() -/mob/living/simple_animal/slime/doUnEquip(obj/item/W, invdrop, silent = FALSE) +/mob/living/simple_animal/slime/doUnEquip(obj/item/W, silent = FALSE) return /mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index be03e8a9c9..8f9a7805c6 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -383,7 +383,7 @@ auto.Remove(buckled_mob) . = ..() -/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc) +/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user) if(user.incapacitated() || !istype(user)) return for(var/atom/movable/A in get_turf(src)) diff --git a/tgstation.dme b/tgstation.dme index 15028c7f40..54a485b1a3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -160,7 +160,6 @@ #include "code\__DEFINES\dcs\flags.dm" #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\signals.dm" -#include "code\__DEFINES\dcs\signals\signals_global.dm" #include "code\__DEFINES\dcs\signals\signals_hud.dm" #include "code\__DEFINES\dcs\signals\signals_medical.dm" #include "code\__DEFINES\dcs\signals\signals_mod.dm" @@ -170,7 +169,6 @@ #include "code\__DEFINES\dcs\signals\signals_subsystem.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm" -#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm" #include "code\__DEFINES\mapping\maploader.dm" #include "code\__DEFINES\material\worth.dm" #include "code\__DEFINES\mobs\innate_abilities.dm"