Skip to content

Commit

Permalink
Merge Upstream 31.01.2025 (#1110)
Browse files Browse the repository at this point in the history
This pull request merges upstream/master. Resolve possible conflicts
manually and make sure all the changes are applied correctly.

## Changelog
:cl: tgstation
qol: Консоль снабжения получила небольшой редизайн, а также возможность
видеть, что может находиться внутри заказа. <!-- Supply console got
little redesign, and ability to see what can be inside a order.
(www.github.com/tgstation/tgstation/pull/89198) -->
code: Консоль снабжения и экспресс-консоль снабжения теперь используют
единую методику получения данных. <!-- Supply console and express supply
console, now use a unified method of acquiring data
(www.github.com/tgstation/tgstation/pull/89198) -->
fix: Теперь невозможно обойти свою клятву чести, начав операцию на
ком-то. <!-- You can no longer circumvent your honorbound oath by
starting a surgery on someone.
(www.github.com/tgstation/tgstation/pull/89151) -->
/:cl:

## Summary by Sourcery

Update the supply console interface to allow viewing the contents of an
order. Unify the data acquisition methods for the supply console and
express supply console. Prevent honorbound characters from bypassing
their oath by starting surgery on someone.

New Features:
- Add the ability to view the contents of a supply order.

Tests:
- Add tests for the new supply console functionality.
  • Loading branch information
Gaxeer authored Jan 31, 2025
2 parents 2a02005 + f1e6e71 commit f64245f
Show file tree
Hide file tree
Showing 31 changed files with 601 additions and 396 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
/code/controllers/master.dm @LemonInTheDark
/code/controllers/subsystem.dm @LemonInTheDark
/code/controllers/subsystem/air.dm @LemonInTheDark
/code/controllers/subsystem/timer.dm @MrStonedOne
/code/controllers/subsystem/timer.dm @LemonInTheDark

# Mothblocks

Expand Down
4 changes: 3 additions & 1 deletion code/__DEFINES/dcs/signals/signals_object.dm
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,11 @@

// /obj/item/gun signals

///called in /obj/item/gun/try_fire_gun (user, src, target, flag, params)
#define COMSIG_MOB_TRYING_TO_FIRE_GUN "mob_trying_to_fire_gun"
///called in /obj/item/gun/fire_gun (user, target, flag, params)
#define COMSIG_GUN_TRY_FIRE "gun_try_fire"
#define COMPONENT_CANCEL_GUN_FIRE (1<<0)
#define COMPONENT_CANCEL_GUN_FIRE (1<<0) /// Also returned to cancel COMSIG_MOB_TRYING_TO_FIRE_GUN
///called in /obj/item/gun/process_fire (src, target, params, zone_override, bonus_spread_values)
#define COMSIG_MOB_FIRED_GUN "mob_fired_gun"
#define MIN_BONUS_SPREAD_INDEX 1
Expand Down
2 changes: 0 additions & 2 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -479,8 +479,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_PRESERVE_UI_WITHOUT_CLIENT "preserve_ui_without_client"
/// This mob overrides certain SSlag_switch measures with this special trait
#define TRAIT_BYPASS_MEASURES "bypass_lagswitch_measures"
/// Someone can safely be attacked with honorbound with ONLY a combat mode check, the trait is assuring holding a weapon and hitting won't hurt them..
#define TRAIT_ALLOWED_HONORBOUND_ATTACK "allowed_honorbound_attack"
/// The user is sparring
#define TRAIT_SPARRING "sparring"
/// The user is currently challenging an elite mining mob. Prevents him from challenging another until he's either lost or won.
Expand Down
1 change: 0 additions & 1 deletion code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_AIRLOCK_SHOCKIMMUNE" = TRAIT_AIRLOCK_SHOCKIMMUNE,
"TRAIT_AI_BAGATTACK" = TRAIT_AI_BAGATTACK,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
"TRAIT_ALLOWED_HONORBOUND_ATTACK" = TRAIT_ALLOWED_HONORBOUND_ATTACK,
"TRAIT_ALLOW_HERETIC_CASTING" = TRAIT_ALLOW_HERETIC_CASTING,
"TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED,
"TRAIT_ANALGESIA" = TRAIT_ANALGESIA,
Expand Down
3 changes: 0 additions & 3 deletions code/datums/components/surgery_initiator.dm
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@

if(the_surgery.status == 1)
patient.surgeries -= the_surgery
REMOVE_TRAIT(patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, type)
user.visible_message(
span_notice("[capitalize(user.declent_ru(NOMINATIVE))] снимает [parent.declent_ru(ACCUSATIVE)] с [patient.parse_zone_with_bodypart(selected_zone, declent = GENITIVE)] у [patient.declent_ru(GENITIVE)]."),
span_notice("Вы снимаете [parent.declent_ru(ACCUSATIVE)] с [patient.parse_zone_with_bodypart(selected_zone, declent = GENITIVE)] у [patient.declent_ru(GENITIVE)]."),
Expand All @@ -142,7 +141,6 @@
the_surgery.operated_bodypart.adjustBleedStacks(-5)

patient.surgeries -= the_surgery
REMOVE_TRAIT(patient, TRAIT_ALLOWED_HONORBOUND_ATTACK, ELEMENT_TRAIT(type))

user.visible_message(
span_notice("[capitalize(user.declent_ru(NOMINATIVE))] закрывает [patient.parse_zone_with_bodypart(selected_zone)] у [patient.declent_ru(GENITIVE)], используя [close_tool.declent_ru(ACCUSATIVE)] и снимая [parent.declent_ru(ACCUSATIVE)]."),
Expand Down Expand Up @@ -307,7 +305,6 @@
ui_close()

var/datum/surgery/procedure = new surgery.type(target, selected_zone, affecting_limb)
ADD_TRAIT(target, TRAIT_ALLOWED_HONORBOUND_ATTACK, type)

target.balloon_alert(user, "начинается \"[LOWER_TEXT(procedure.name)]\"")

Expand Down
1 change: 1 addition & 0 deletions code/datums/mutations/touch.dm
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,4 @@
icon_state = "greyscale"
color = COLOR_VERY_PALE_LIME_GREEN
inhand_icon_state = "greyscale"
item_flags = parent_type::item_flags & ~NEEDS_PERMIT
33 changes: 12 additions & 21 deletions code/modules/cargo/expressconsole.dm
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,17 @@

/obj/machinery/computer/cargo/express/proc/packin_up(forced = FALSE) // oh shit, I'm sorry
meme_pack_data = list() // sorry for what?
if (!forced && !SSshuttle.initialized) // Subsystem is still sleeping, add ourselves to its buffer and abort
SSshuttle.express_consoles += src
return
for(var/pack in SSshuttle.supply_packs) // our quartermaster taught us not to be ashamed of our supply packs
var/datum/supply_pack/P = SSshuttle.supply_packs[pack] // specially since they're such a good price and all
if(!meme_pack_data[P.group]) // yeah, I see that, your quartermaster gave you good advice
meme_pack_data[P.group] = list( // it gets cheaper when I return it
"name" = P.group, // mmhm
"packs" = list() // sometimes, I return it so much, I rip the manifest
) // see, my quartermaster taught me a few things too
if((P.hidden) || (P.special)) // like, how not to rip the manifest
continue// by using someone else's crate
if(P.contraband && !contraband) // will you show me?
continue // i'd be right happy to
meme_pack_data[P.group]["packs"] += list(list(
"name" = P.name,
"cost" = P.get_cost() * get_discount(),
"id" = pack,
"desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name.
))
if(!forced && !SSshuttle.initialized) // our quartermaster taught us not to be ashamed of our supply packs
SSshuttle.express_consoles += src // specially since they're such a good price and all
return // yeah, I see that, your quartermaster gave you good advice
// it gets cheaper when I return it
for(var/pack_id in SSshuttle.supply_packs) // mmhm
var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id] // sometimes, I return it so much, I rip the manifest
if(!meme_pack_data[pack.group]) // see, my quartermaster taught me a few things too
meme_pack_data[pack.group] = list( // like, how not to rip the manifest
"name" = pack.group, // by using someone else's crate
"packs" = get_packs_data(pack.group, express = TRUE), // will you show me?
) // i'd be right happy to

/obj/machinery/computer/cargo/express/ui_data(mob/user)
var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location?
Expand Down Expand Up @@ -146,7 +137,7 @@
data["supplies"] = meme_pack_data
return data

/obj/machinery/computer/cargo/express/proc/get_discount()
/obj/machinery/computer/cargo/express/get_discount()
return (obj_flags & EMAGGED) ? EXPRESS_EMAG_DISCOUNT : 1

/obj/machinery/computer/cargo/express/ui_act(action, params, datum/tgui/ui)
Expand Down
90 changes: 71 additions & 19 deletions code/modules/cargo/orderconsole.dm
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@
var/list/data = list()
data["department"] = "Cargo" // Hardcoded here, for customization in budgetordering.dm AKA NT IRN
data["location"] = SSshuttle.supply.getStatusText()
var/datum/bank_account/D = SSeconomy.get_dep_account(cargo_account)
if(D)
data["points"] = D.account_balance
var/datum/bank_account/bank = SSeconomy.get_dep_account(cargo_account)
if(bank)
data["points"] = bank.account_balance
data["grocery"] = SSshuttle.chef_groceries.len
data["away"] = SSshuttle.supply.getDockedId() == docking_away
data["self_paid"] = self_paid
Expand Down Expand Up @@ -162,25 +162,77 @@
var/list/data = list()
data["max_order"] = CARGO_MAX_ORDER
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
if(!data["supplies"][P.group])
data["supplies"][P.group] = list(
"name" = P.group,
"packs" = list()

for(var/pack_id in SSshuttle.supply_packs)
var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id]
if(!data["supplies"][pack.group])
data["supplies"][pack.group] = list(
"name" = pack.group,
"packs" = get_packs_data(pack.group),
)
if((P.hidden && !(obj_flags & EMAGGED)) || (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.drop_pod_only)

return data

/**
* returns a list of supply packs for a certain group
* * group - the group of packs to return
* * express - if this is an express console
*/
/obj/machinery/computer/cargo/proc/get_packs_data(group, express = FALSE)
var/list/packs = list()
for(var/pack_id in SSshuttle.supply_packs)
var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id]
if(pack.group != group)
continue

// Express console packs check
if(express && (pack.hidden || pack.special))
continue

if(!express && ((pack.hidden && !(obj_flags & EMAGGED)) || (pack.special && !pack.special_enabled) || pack.drop_pod_only))
continue

if(pack.contraband && !contraband)
continue
data["supplies"][P.group]["packs"] += list(list(
"name" = P.name,
"cost" = P.get_cost(),
"id" = pack,
"desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
"goody" = P.goody,
"access" = P.access,
"contraband" = P.contraband,

var/obj/item/first_item = length(pack.contains) > 0 ? pack.contains[1] : null
packs += list(list(
"name" = pack.name,
"cost" = pack.get_cost() * get_discount(),
"id" = pack_id,
"desc" = pack.desc || pack.name, // If there is a description, use it. Otherwise use the pack's name.
"first_item_icon" = first_item?.icon,
"first_item_icon_state" = first_item?.icon_state,
"goody" = pack.goody,
"access" = pack.access,
"contraband" = pack.contraband,
"contains" = get_pack_contains(pack),
))
return data

return packs

/**
* returns a list of the contents of a supply pack
* * pack - the pack to get the contents of
*/
/obj/machinery/computer/cargo/proc/get_pack_contains(datum/supply_pack/pack)
var/list/contains = list()
for(var/obj/item/item as anything in pack.contains)
contains += list(list(
"name" = item.name,
"icon" = item.greyscale_config ? null : item.icon,
"icon_state" = item.greyscale_config ? null : item.icon_state,
"amount" = pack.contains[item]
))

return contains

/**
* returns the discount multiplier applied to all supply packs,
* the discount is calculated as follows: pack_cost * get_discount()
*/
/obj/machinery/computer/cargo/proc/get_discount()
return 1

/**
* adds an supply pack to the checkout cart
Expand Down
4 changes: 4 additions & 0 deletions code/modules/projectiles/gun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@
return
if(firing_burst)
return

if(SEND_SIGNAL(user, COMSIG_MOB_TRYING_TO_FIRE_GUN, src, target, flag, params) & COMPONENT_CANCEL_GUN_FIRE)
return

if(SEND_SIGNAL(src, COMSIG_GUN_TRY_FIRE, user, target, flag, params) & COMPONENT_CANCEL_GUN_FIRE)
return
if(flag) //It's adjacent, is the user, or is on the user's person
Expand Down
68 changes: 51 additions & 17 deletions code/modules/religion/honorbound/honorbound_trauma.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,77 @@
RegisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked))

//signal that checks for dishonorable attacks
RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(attack_honor))
RegisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(unarmed_attack_honor))
RegisterSignal(owner, COMSIG_MOB_ITEM_ATTACK, PROC_REF(attack_honor))
RegisterSignal(owner, COMSIG_MOB_TRYING_TO_FIRE_GUN, PROC_REF(fire_gun_honor))
var/datum/action/cooldown/spell/pointed/declare_evil/declare = new(owner)
declare.Grant(owner)
return ..()

/datum/brain_trauma/special/honorbound/on_lose(silent)
owner.clear_mood_event("honorbound")
UnregisterSignal(owner, list(
COMSIG_ATOM_WAS_ATTACKED,
COMSIG_MOB_CLICKON,
COMSIG_LIVING_EARLY_UNARMED_ATTACK,
COMSIG_MOB_ITEM_ATTACK,
COMSIG_MOB_TRYING_TO_FIRE_GUN,
COMSIG_MOB_CAST_SPELL,
COMSIG_MOB_FIRED_GUN,
))
return ..()

/// Signal to see if the trauma allows us to attack a target
/datum/brain_trauma/special/honorbound/proc/attack_honor(mob/living/carbon/human/honorbound, atom/clickingon, list/modifiers)
/datum/brain_trauma/special/honorbound/proc/unarmed_attack_honor(mob/living/carbon/human/honorbound, atom/target, proximity_flag, modifiers)
SIGNAL_HANDLER

if(modifiers[ALT_CLICK] || modifiers[SHIFT_CLICK] || modifiers[CTRL_CLICK] || modifiers[MIDDLE_CLICK])
return
if(!isliving(clickingon))

if(!proximity_flag || !isliving(target))
return NONE

var/mob/living/punched_mob = target

if(!(punched_mob in guilty))
check_visible_guilt(punched_mob)

if((honorbound.combat_mode || modifiers[RIGHT_CLICK]) && !is_honorable(honorbound, punched_mob))
return COMPONENT_CANCEL_ATTACK_CHAIN

/// Signal to see if the trauma allows us to attack a target with a weapon
/datum/brain_trauma/special/honorbound/proc/attack_honor(mob/living/honorbound, atom/attacked, params)
SIGNAL_HANDLER

if(!isliving(attacked))
return

var/mob/living/clicked_mob = clickingon
var/mob/living/attacked_mob = attacked
var/obj/item/weapon = honorbound.get_active_held_item()

if(!honorbound.DirectAccess(clicked_mob) && !isgun(weapon))
return
if(weapon?.item_flags & NOBLUDGEON)
return
if(!honorbound.combat_mode && (HAS_TRAIT(clicked_mob, TRAIT_ALLOWED_HONORBOUND_ATTACK) || ((!weapon || !weapon.force) && !LAZYACCESS(modifiers, RIGHT_CLICK))))

if(!(attacked_mob in guilty))
check_visible_guilt(attacked_mob)

if(((weapon?.item_flags & NEEDS_PERMIT) || honorbound.combat_mode || weapon?.force > 0) && !is_honorable(honorbound, attacked_mob))
return COMPONENT_CANCEL_ATTACK_CHAIN

/// Signal to see if we're targeting a mob that is guilty or not.
/datum/brain_trauma/special/honorbound/proc/fire_gun_honor(mob/living/honorbound, obj/item/gun/the_gun_in_question, atom/target, flag, params)
SIGNAL_HANDLER

if(istype(the_gun_in_question, /obj/item/gun/magic))
return
if(!(clicked_mob in guilty))
check_visible_guilt(clicked_mob)
if(!is_honorable(honorbound, clicked_mob))
return (COMSIG_MOB_CANCEL_CLICKON)

if(!isliving(target)) //No shooting an innocent you weren't aiming at to get around this. Aim true or go home, honor-dork
return COMPONENT_CANCEL_GUN_FIRE

var/mob/living/shot_mob = target

if(!(shot_mob in guilty))
check_visible_guilt(shot_mob)

if(!is_honorable(honorbound, shot_mob))
return COMPONENT_CANCEL_GUN_FIRE

/// Checks a mob for any obvious signs of evil, and applies a guilty reason for each.
/datum/brain_trauma/special/honorbound/proc/check_visible_guilt(mob/living/attacked_mob)
Expand All @@ -74,7 +108,7 @@
if(HAS_TRAIT(attacked_mob, TRAIT_CULT_HALO))
guilty(attacked_mob, "for blasphemous worship!")
if(HAS_TRAIT(attacked_mob, TRAIT_EVIL))
guilty(attacked_mob, "an almost fanatical commitment to EEEEVIL!")
guilty(attacked_mob, "for an almost fanatical commitment to EEEEVIL!")
if(attacked_mob.mind)
var/datum/mind/guilty_conscience = attacked_mob.mind
if(guilty_conscience.has_antag_datum(/datum/antagonist/abductor))
Expand Down Expand Up @@ -167,7 +201,7 @@
*/
/datum/brain_trauma/special/honorbound/proc/punishment(mob/living/carbon/human/user, school)
switch(school)
if(SCHOOL_UNSET, SCHOOL_HOLY, SCHOOL_MIME, SCHOOL_RESTORATION, SCHOOL_PSYCHIC)
if(SCHOOL_HOLY, SCHOOL_MIME, SCHOOL_RESTORATION, SCHOOL_PSYCHIC)
return
if(SCHOOL_NECROMANCY, SCHOOL_FORBIDDEN, SCHOOL_SANGUINE)
to_chat(user, span_userdanger("[GLOB.deity] is enraged by your use of forbidden magic!"))
Expand All @@ -177,7 +211,7 @@
owner.add_mood_event("honorbound", /datum/mood_event/banished) //add mood event after we already cleared our events
to_chat(user, span_userdanger("You have been excommunicated! You are no longer holy!"))
else
to_chat(user, span_userdanger("[GLOB.deity] is angered by your use of [school] magic!"))
to_chat(user, span_userdanger("[GLOB.deity] is angered by your use of [school == SCHOOL_UNSET ? "strange" : school] magic!"))
lightningbolt(user)
owner.add_mood_event("honorbound", /datum/mood_event/holy_smite)//permanently lose your moodlet after this

Expand Down
6 changes: 0 additions & 6 deletions html/changelogs/AutoChangeLog-pr-88716.yml

This file was deleted.

4 changes: 0 additions & 4 deletions html/changelogs/AutoChangeLog-pr-89032.yml

This file was deleted.

4 changes: 0 additions & 4 deletions html/changelogs/AutoChangeLog-pr-89086.yml

This file was deleted.

4 changes: 0 additions & 4 deletions html/changelogs/AutoChangeLog-pr-89136.yml

This file was deleted.

4 changes: 0 additions & 4 deletions html/changelogs/AutoChangeLog-pr-89225.yml

This file was deleted.

4 changes: 0 additions & 4 deletions html/changelogs/AutoChangeLog-pr-89269.yml

This file was deleted.

5 changes: 0 additions & 5 deletions html/changelogs/AutoChangeLog-pr-89270.yml

This file was deleted.

Loading

0 comments on commit f64245f

Please sign in to comment.