diff --git a/code/__DEFINES/~doppler_defines/TESHARI_WAR_defines.dm b/code/__DEFINES/~doppler_defines/TESHARI_WAR_defines.dm new file mode 100644 index 00000000000000..bfca153ed5734c --- /dev/null +++ b/code/__DEFINES/~doppler_defines/TESHARI_WAR_defines.dm @@ -0,0 +1,5 @@ +// Factions +#define WAR_FACTION_TIZIRA "Tizira" +#define WAR_FACTION_TESHARI "Teshari Soverignty" +#define WAR_FACTION_ISOLATIONIST "4CA Isolationist" +#define WAR_FACTION_NEUTRAL "Neutral" diff --git a/code/game/objects/effects/posters/poster.dm b/code/game/objects/effects/posters/poster.dm index ebfc3a791bb2f1..8e6859a4840291 100644 --- a/code/game/objects/effects/posters/poster.dm +++ b/code/game/objects/effects/posters/poster.dm @@ -155,6 +155,7 @@ poster_item_desc = initial(selected.poster_item_desc) poster_item_icon_state = initial(selected.poster_item_icon_state) ruined = initial(selected.ruined) + randomise_further(selected) // DOPPLER EDIT ADDITIION - War posters if(length(GLOB.holidays) && prob(30)) // its the holidays! lets get festive apply_holiday() update_appearance() diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index ed65563b02ca36..920297e42d3622 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -8,6 +8,7 @@ /obj/structure/closet/crate/large, /obj/structure/closet/crate/mail, /obj/structure/closet/crate/wooden, + /obj/structure/closet/crate/donation, // DOPPLER EDIT ADDITION - Dono crates are in loadout and are craftable... do not want infinite money glitch ) /datum/export/large/crate/total_printout(datum/export_report/ex, notes = TRUE) // That's why a goddamn metal crate costs that much. diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm index d5984da9ec9828..c4b3cd16752a32 100644 --- a/code/modules/cargo/orderconsole.dm +++ b/code/modules/cargo/orderconsole.dm @@ -189,6 +189,7 @@ packs += list(list( "name" = pack.name, "cost" = pack.get_cost() * get_discount(), + "shortagemult" = pack.get_shortage_price_mult(), // DOPPLER EDIT ADDITION - TESHARI_WAR STORY MODULE "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, diff --git a/code/modules/modular_computers/file_system/programs/dept_order.dm b/code/modules/modular_computers/file_system/programs/dept_order.dm index e640d5ecb3710c..f0952e5b151e73 100644 --- a/code/modules/modular_computers/file_system/programs/dept_order.dm +++ b/code/modules/modular_computers/file_system/programs/dept_order.dm @@ -85,9 +85,18 @@ GLOBAL_VAR(department_cd_override) if(!islist(supply_data[pack.group]) || !can_see_pack(pack)) continue + // DOPPLER EDIT ADDITION BEGIN - TESHARI_WAR STORY MODULE + var/shortage_text = "" + if (pack.is_unavailable()) + shortage_text = " (Shortages: Unavailable!)" + else if (pack.get_shortage_price_mult() != 1) + shortage_text = " (Shortages: [pack.get_shortage_price_mult()]x cooldown)" + // DOPPLER EDIT ADDITION END UNTYPED_LIST_ADD(supply_data[pack.group], list( "name" = pack.name, "cost" = pack.get_cost(), + "unavailable" = pack.is_unavailable(), // DOPPLER EDIT ADDITION - TESHARI_WAR STORY MODULE + "shortage_text" = shortage_text, // DOPPLER EDIT ADDITION - TESHARI_WAR STORY MODULE "id" = pack.id, "desc" = pack.desc || pack.name, // If there is a description, use it. Otherwise use the pack's name. )) diff --git a/config/config.txt b/config/config.txt index 35b7e9a352d176..ebf61685b778a5 100644 --- a/config/config.txt +++ b/config/config.txt @@ -3,6 +3,7 @@ $include game_options.txt $include dbconfig.txt $include doppler/config_doppler.txt +$include doppler/STORY_SUPPLY_SHORTAGE.txt $include comms.txt $include logging.txt $include resources.txt diff --git a/config/doppler/STORY_SUPPLY_SHORTAGE.txt b/config/doppler/STORY_SUPPLY_SHORTAGE.txt new file mode 100644 index 00000000000000..dfbc7ba520b870 --- /dev/null +++ b/config/doppler/STORY_SUPPLY_SHORTAGE.txt @@ -0,0 +1,10 @@ +## Instructions - write SUPPLY_SHORTAGES, followed by this format: SUPPLYPACKTYPEPATH,MULT to change the price of +## a supply pack. +## 1 has no effect. +## -1 will make the item completely unavailable. +## Mults below 1, including 0, are possible, but highly inadvisable. + +## Examples: +#SUPPLY_SHORTAGES /datum/supply_pack/goody/laser_single,1.5 +#SUPPLY_SHORTAGES /datum/supply_pack/security/armory/laser,-1 +#SUPPLY_SHORTAGES /datum/supply_pack/security/stingpack,4 diff --git a/modular_doppler/STORY_teshari_war/config.dm b/modular_doppler/STORY_teshari_war/config.dm new file mode 100644 index 00000000000000..58caf63c53739d --- /dev/null +++ b/modular_doppler/STORY_teshari_war/config.dm @@ -0,0 +1,11 @@ +/datum/config_entry/keyed_list/supply_shortages + key_mode = KEY_MODE_TYPE + value_mode = VALUE_MODE_NUM + splitter = "," + +/datum/config_entry/keyed_list/supply_shortages/validate_config_key(key) + var/type = text2path(key) + if (type in get_usable_supply_packs()) + return key + log_config("ERROR: [key] is not a valid supply pack typepath.") + return null diff --git a/modular_doppler/STORY_teshari_war/mind.dm b/modular_doppler/STORY_teshari_war/mind.dm new file mode 100644 index 00000000000000..e1c852097cf25c --- /dev/null +++ b/modular_doppler/STORY_teshari_war/mind.dm @@ -0,0 +1,3 @@ +/datum/mind + /// The stance this mind takes on the tizira/teshari war. By default, they dont care at all. + var/war_faction = WAR_FACTION_NEUTRAL // i just wanna grill diff --git a/modular_doppler/STORY_teshari_war/preferences.dm b/modular_doppler/STORY_teshari_war/preferences.dm new file mode 100644 index 00000000000000..9d27c79c4753a6 --- /dev/null +++ b/modular_doppler/STORY_teshari_war/preferences.dm @@ -0,0 +1,30 @@ +GLOBAL_LIST_INIT(teshari_war_factions, list( + WAR_FACTION_TIZIRA, + WAR_FACTION_TESHARI, + WAR_FACTION_ISOLATIONIST, + WAR_FACTION_NEUTRAL +)) + +/datum/preference/choiced/doppler_war_faction + savefile_key = "doppler_war_faction" + main_feature_name = "War Alignment" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/choiced/doppler_war_faction/init_possible_values() + return GLOB.teshari_war_factions + +/datum/preference/choiced/doppler_war_faction/create_default_value() + return WAR_FACTION_NEUTRAL + +/datum/preference/choiced/doppler_war_faction/apply_to_human(mob/living/carbon/human/target, value) + RegisterSignal(target, COMSIG_MOB_MIND_INITIALIZED, PROC_REF(apply_mind_variable)) + return + +/datum/preference/choiced/doppler_war_faction/proc/apply_mind_variable(mob/living/carbon/human/target, datum/mind/new_mind) + SIGNAL_HANDLER + + new_mind.war_faction = target.client.prefs.read_preference(/datum/preference/choiced/doppler_war_faction) + UnregisterSignal(target, COMSIG_MOB_MIND_INITIALIZED) + diff --git a/modular_doppler/STORY_teshari_war/readme.md b/modular_doppler/STORY_teshari_war/readme.md new file mode 100644 index 00000000000000..9b3f2eb3793b17 --- /dev/null +++ b/modular_doppler/STORY_teshari_war/readme.md @@ -0,0 +1,35 @@ +## Title: Teshari/Tizira war + +MODULE ID: TESHARI_WAR + +### Description: + +TEMPORARY STORY MODULE. WILL BE REVERTED WHEN THE ARC ENDS. + +### TG Proc Changes: + +code/modules/cargo/orderconsole.dm - L192, added "shortagemult" = pack.get_shortage_price_mult(), +code/modules/modular_computers/file_system/programs/dept_order.dm - L88 - L99 + +tgui/packages/tgui/interfaces/NtosDeptOrder.tsx - L31-L32, L211-213, L223 +tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx - L201-L204, L221-L223, L241-L245 +tgui/packages/tgui/interfaces/Cargo/types.ts - L42 + +config/config.txt - L6 + +### Defines: + +code\_\_DEFINES\~doppler_defines\TESHARI_WAR_defines.dm + +### Master file additions + +N/A + +### Included files that are not contained in this module: + +config/doppler/STORY_SUPPLY_SHORTAGE.txt +tgui\packages\tgui\interfaces\PreferencesMenu\preferences\features\dopplershift_preferences\war_faction.tsx + +### Credits: + +Niko diff --git a/modular_doppler/STORY_teshari_war/supply_pack.dm b/modular_doppler/STORY_teshari_war/supply_pack.dm new file mode 100644 index 00000000000000..01426caef5fd8a --- /dev/null +++ b/modular_doppler/STORY_teshari_war/supply_pack.dm @@ -0,0 +1,32 @@ +/// Returns a list of non-abstract supply packs. +/proc/get_usable_supply_packs() + RETURN_TYPE(/list) + var/list/packs = list() + for (var/datum/supply_pack/iter_path as anything in subtypesof(/datum/supply_pack)) + if (iter_path::abstract_type == iter_path) + continue + packs += iter_path + return packs + +/// Returns the assoc list of stringified supply pack typepaths to their price mult. +/proc/get_price_mults() + RETURN_TYPE(/list) + return CONFIG_GET(keyed_list/supply_shortages) + +// If this proc returns -1, the item is wholly unavailable. +/// Returns the actual price mult of the supply pack. If -1, the item is completely unavailable. Use get_cost() for actual price calculations. +/datum/supply_pack/proc/get_shortage_price_mult() + var/mult = get_price_mults()["[type]"] + if (isnull(mult)) + return 1 + return mult + +/// Returns TRUE if our shortage price mult is -1. +/datum/supply_pack/proc/is_unavailable() + return get_shortage_price_mult() == -1 + +/datum/supply_pack/get_cost() + . = ..() + + if (!is_unavailable()) + . *= get_shortage_price_mult() diff --git a/modular_doppler/donation_box/donation_box.dm b/modular_doppler/donation_box/donation_box.dm new file mode 100644 index 00000000000000..4cfd8fd1897488 --- /dev/null +++ b/modular_doppler/donation_box/donation_box.dm @@ -0,0 +1,59 @@ +/obj/structure/closet/crate/donation + name = "donation box" + desc = "A steel crate, modified into a donation box via a small slot on the top. Allows insertion of items without allowing removal." + icon = 'modular_doppler/donation_box/icons/donation_box.dmi' + icon_state = "donation_box" + base_icon_state = "donation_box" + +/obj/structure/closet/crate/donation/secure + name = "secure donation box" + desc = "A steel crate, modified into a donation box via a small slot on the top. Allows insertion of items without allowing removal." + icon = 'modular_doppler/donation_box/icons/donation_box.dmi' + icon_state = "securedonation_box" + base_icon_state = "securedonation_box" + secure = TRUE + card_reader_installed = TRUE + +/obj/structure/closet/crate/donation/examine(mob/user) + . = ..() + + . += span_smallnotice("When closed, you can [EXAMINE_HINT("Right-Click")] with an item to place it in the box, if able.") + +/obj/structure/closet/crate/donation/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if (opened) + return NONE + if (user.combat_mode) + return NONE + if (!LAZYACCESS(modifiers, RIGHT_CLICK)) + return NONE + if (!insertion_allowed(tool)) + balloon_alert(user, "can't fit it in!") + return NONE + + user.balloon_alert_to_viewers("inserts [tool]", "inserted [tool]") + user.visible_message( + span_notice("[user] inserts [tool] into the small slot on [src]."), + span_notice("You insert [tool] into the small slot on [src].") + ) + + if (insert(tool)) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/donation_box_kit + icon = 'icons/obj/storage/box.dmi' + icon_state = "plasticbox" + name = "donation kit" + desc = "Contains a folded donation box, with an access lock and a few tools inside." + +/obj/item/donation_box_kit/attack_self(mob/user, modifiers) + user.balloon_alert_to_viewers("deploying...") + if (!do_after(user, 3 SECONDS, src)) + return FALSE + var/obj/structure/closet/crate/donation/secure/box = new /obj/structure/closet/crate/donation/secure(get_turf(user)) + new /obj/item/hand_labeler(box) + playsound(src, 'sound/machines/terminal/terminal_eject.ogg', 70, TRUE) + qdel(src) + + return TRUE + diff --git a/modular_doppler/donation_box/icons/donation_box.dmi b/modular_doppler/donation_box/icons/donation_box.dmi new file mode 100644 index 00000000000000..757eb8ffa64287 Binary files /dev/null and b/modular_doppler/donation_box/icons/donation_box.dmi differ diff --git a/modular_doppler/donation_box/loadout.dm b/modular_doppler/donation_box/loadout.dm new file mode 100644 index 00000000000000..ae6eb4e8a82617 --- /dev/null +++ b/modular_doppler/donation_box/loadout.dm @@ -0,0 +1,3 @@ +/datum/loadout_item/pocket_items/equipment/donation_kit + name = "Donation Kit" + item_path = /obj/item/donation_box_kit diff --git a/modular_doppler/modular_crafting/code/sheet_types.dm b/modular_doppler/modular_crafting/code/sheet_types.dm index 6f546d20248b44..5978e0041c4997 100644 --- a/modular_doppler/modular_crafting/code/sheet_types.dm +++ b/modular_doppler/modular_crafting/code/sheet_types.dm @@ -25,6 +25,7 @@ GLOBAL_LIST_INIT(doppler_metal_recipes, list( new/datum/stack_recipe("forge", /obj/structure/reagent_forge, 10, time = 2 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_TOOLS), new/datum/stack_recipe("throwing wheel", /obj/structure/throwing_wheel, 10, time = 2 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_TOOLS), new/datum/stack_recipe("metal shelf", /obj/structure/shelf, 1, time = 2 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_STRUCTURE), + new/datum/stack_recipe("donation box", /obj/structure/closet/crate/donation, 10, time = 3 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_CONTAINERS), )) GLOBAL_LIST_INIT(doppler_metal_airlock_recipes, list( diff --git a/modular_doppler/war_posters/code/loadout.dm b/modular_doppler/war_posters/code/loadout.dm new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/modular_doppler/war_posters/code/mood.dm b/modular_doppler/war_posters/code/mood.dm new file mode 100644 index 00000000000000..87d7c4fe71985f --- /dev/null +++ b/modular_doppler/war_posters/code/mood.dm @@ -0,0 +1,13 @@ +#define WAR_POSTER_MOOD_CAT "poster_mood" + +/datum/mood_event/war_poster_sympathy + description = "I saw a poster that reinforces my beliefs. It's good to have like-minded people around." + mood_change = 2 + category = WAR_POSTER_MOOD_CAT + +/datum/mood_event/war_poster_wrong + description = "I saw a poster that really pissed me off! How can people like that be allowed to work here?!" + mood_change = -4 + category = WAR_POSTER_MOOD_CAT + +#undef WAR_POSTER_MOOD_CAT diff --git a/modular_doppler/war_posters/code/posters.dm b/modular_doppler/war_posters/code/posters.dm new file mode 100644 index 00000000000000..7908ebb8b53f70 --- /dev/null +++ b/modular_doppler/war_posters/code/posters.dm @@ -0,0 +1,141 @@ +#define WAR_POSTER_MOOD "war_poster" +#define WAR_POSTER_RANGE 7 + +/obj/structure/sign/poster/proc/randomise_further(obj/structure/sign/poster/selected_path) + return + +/obj/structure/sign/poster/doppler_war + name = "abstract war poster" + desc = "Surely, if this was coded correctly, you would be angry." + abstract_type = /obj/structure/sign/poster/doppler_war + icon = 'modular_doppler/war_posters/icons/posters.dmi' + icon_state = "tesh_unity" + + /// Those of our aligned faction recieve a small mood buff when seeing this poster - other factions get a debuff. Neutral doesn't care at all. + var/aligned_faction = WAR_FACTION_NEUTRAL + /// Assoc list of (WAR_FACTION -> list(/datum/war_demoralisation_reaction, chance)). Used in pickweight to determine what people think when they see the poster, depending on + var/list/faction_reactions = list() + var/list/faction_moods = list() + /// Proximity sensor for the above vars + var/datum/proximity_monitor/advanced/war_demoraliser/demoraliser + +/obj/structure/sign/poster/doppler_war/randomise_further(obj/structure/sign/poster/doppler_war/selected_path) + . = ..() + + faction_reactions = selected_path::faction_reactions + faction_moods = selected_path::faction_moods + +/obj/structure/sign/poster/doppler_war/on_placed_poster() + demoraliser = new(src, WAR_POSTER_RANGE, TRUE, aligned_faction, WAR_POSTER_MOOD, faction_reactions, faction_moods, READING_CHECK_LIGHT) + return ..() + +/obj/item/poster/random_teshari + name = "random teshari poster" + poster_type = /obj/structure/sign/poster/doppler_war/teshari/random + icon = 'modular_doppler/war_posters/icons/posters.dmi' + icon_state = "rolled_tesh" + +/obj/structure/sign/poster/doppler_war/teshari + name = "teshari war poster" + poster_item_name = "teshari war poster" + poster_item_desc = "A pro-teshari propoganda poster, espousing the evils of the Talunan empire and the virtue of Sirsiai's defense. Aisi Tarischi." + poster_item_icon_state = "rolled_tesh" + printable = TRUE + aligned_faction = WAR_FACTION_TESHARI + abstract_type = /obj/structure/sign/poster/doppler_war/teshari + +/obj/structure/sign/poster/doppler_war/teshari/random + name = "random teshari poster" + random_basetype = /obj/structure/sign/poster/doppler_war/teshari + icon_state = "tesh_unity" + never_random = TRUE + +/obj/structure/sign/poster/doppler_war/teshari/unity + name = "Ilisime. (Unity.)" + desc = "A poster encouraging the teshari diaspora - from stars, from sea, from earth, from dust - to unite in defense of their shattered homeworld, Sirisai." + icon_state = "tesh_unity" + faction_reactions = list( + WAR_FACTION_TESHARI = list( + "All for Sirisai. Aisi Tarischi!" = 10, + "Sophonts in arms, we can save Teshari kind." = 10, + "Unity...? I'm not alone here." = 8 + ), + WAR_FACTION_TIZIRA = list( + + ), + WAR_FACTION_ISOLATIONIST = list( + "Ugh! More propoganda!" = 10, + "Keep your war posters out of my workspace." = 10 + ) + ) + faction_moods = list( + WAR_FACTION_TESHARI = /datum/mood_event/war_poster_sympathy, + WAR_FACTION_TIZIRA = /datum/mood_event/war_poster_wrong, + WAR_FACTION_ISOLATIONIST = /datum/mood_event/war_poster_wrong + ) + +/obj/structure/sign/poster/doppler_war/teshari/execution + name = "Schatara Shitilushu. (Our Execution.)" + desc = "A kneeled teshari is presented for execution by a Tiziran blade. You could be next on the block. Act now!" + icon_state = "tesh_warn" + faction_reactions = list( + WAR_FACTION_TESHARI = list( + "We will shatter their Tiziran steel with our resolve..." = 10, + "I won't be next. Noone will. We can stop the Tizirans here and now." = 10, + ), + WAR_FACTION_TIZIRA = list( + + ), + WAR_FACTION_ISOLATIONIST = list( + "Seriously? An execution on a poster? That's just tasteless." = 10, + "They're so desparate to get the 4CA involved, they post fake executions on our walls?" = 10 + ) + ) + faction_moods = list( + WAR_FACTION_TESHARI = /datum/mood_event/war_poster_sympathy, + WAR_FACTION_TIZIRA = /datum/mood_event/war_poster_wrong, + WAR_FACTION_ISOLATIONIST = /datum/mood_event/war_poster_wrong + ) + +/obj/structure/sign/poster/doppler_war/tiziran + name = "tiziran war poster" + poster_item_name = "tiziran war poster" + poster_item_desc = "A pro-tizira propoganda poster, generally encouraging enlistment and patriotism." + poster_item_icon_state = "rolled_tizira" + printable = TRUE + abstract_type = /obj/structure/sign/poster/doppler_war/tiziran + aligned_faction = WAR_FACTION_TIZIRA + +/obj/structure/sign/poster/doppler_war/tiziran/enlist + name = "Za'Haious Rar! (Enlist!)" + desc = "While many Tizirans face obligate military service, few reach professional status. This poster encourages the reader to fully commit themselves to the Talunan ranks, and earn their prestige in white." + icon_state = "tizira_enlist" + faction_reactions = list( + WAR_FACTION_TESHARI = list( + "We will shatter their Tiziran steel with our resolve..." = 10, + "I won't be next. Noone will. We can stop the Tizirans here and now." = 10, + ), + WAR_FACTION_TIZIRA = list( + + ), + WAR_FACTION_ISOLATIONIST = list( + "Ugh! More propoganda!" = 10, + "Keep your war posters out of my workspace." = 10 + ) + ) + faction_moods = list( + WAR_FACTION_TESHARI = /datum/mood_event/war_poster_wrong, + WAR_FACTION_TIZIRA = /datum/mood_event/war_poster_sympathy, + WAR_FACTION_ISOLATIONIST = /datum/mood_event/war_poster_wrong + ) + +/obj/structure/sign/poster/doppler_war/isolationist + name = "isolationist war poster" + poster_item_name = "isolationist war poster" + poster_item_desc = "An isolationist propoganda poster, condeming the 4CA for its attempted involvement in the tizira/teshari war." + poster_item_icon_state = "rolled_iso" + abstract_type = /obj/structure/sign/poster/doppler_war/isolationist + aligned_faction = WAR_FACTION_ISOLATIONIST + +#undef WAR_POSTER_MOOD +#undef WAR_POSTER_RANGE diff --git a/modular_doppler/war_posters/code/war_moralisation.dm b/modular_doppler/war_posters/code/war_moralisation.dm new file mode 100644 index 00000000000000..32b19430e8c4b1 --- /dev/null +++ b/modular_doppler/war_posters/code/war_moralisation.dm @@ -0,0 +1,83 @@ +/datum/proximity_monitor/advanced/war_demoraliser + /// The faction, using defines from TESHARI_WAR_defines.dm. Do NOT use neutral. + var/faction + /// Mood category to apply to moods + var/mood_category + /// Assoc list of (WAR_FACTION -> list(/datum/war_demoralisation_reaction, chance)). Used in pickweight to determine what people think when they see the poster, depending on + var/list/faction_reactions = list() + var/list/faction_moods = list() + /// For literacy checks + var/reading_requirements = READING_CHECK_LIGHT + +/datum/proximity_monitor/advanced/war_demoraliser/New(atom/_host, range, _ignore_if_not_on_turf = TRUE, faction, mood_category, list/faction_reactions, list/faction_moods, reading_requirements) + . = ..() + + if (faction == WAR_FACTION_NEUTRAL) + CRASH("War demoralizers should not be neutral. That's like, their entire point. They're propoganda.") + RegisterSignal(host, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + + src.faction = faction + src.mood_category = mood_category + src.faction_reactions = faction_reactions + src.faction_moods = faction_moods + src.reading_requirements = reading_requirements + +/datum/proximity_monitor/advanced/war_demoraliser/field_turf_crossed(atom/movable/crossed, turf/old_location, turf/new_location) + if (!isliving(crossed)) + return + if (!can_see(crossed, host, current_range)) + return + on_seen(crossed) + +/* + * Signal proc for [COMSIG_ATOM_EXAMINE]. + * Immediately tries to apply a mood to the examiner, ignoring the proximity check. + * If someone wants to make themselves sad through a camera that's their choice I guess. + */ +/datum/proximity_monitor/advanced/war_demoraliser/proc/on_examine(datum/source, mob/examiner) + SIGNAL_HANDLER + if (isliving(examiner)) + on_seen(examiner) + +/** + * Called when someone is looking at a war-related demoralizer. + * Applies a mood if they are conscious and don't already have it. + * Different moods are applied based on their faction. + * + * Arguments + * * viewer - Whoever is looking at this. + */ +/datum/proximity_monitor/advanced/war_demoraliser/proc/on_seen(mob/living/viewer) + if (!viewer.mind) + return + // If you're not conscious you're too busy or dead to look at propaganda + if (viewer.stat != CONSCIOUS) + return + if(viewer.is_blind()) + return + if (!should_demoralise(viewer)) + return + if(!viewer.can_read(host, reading_requirements, TRUE)) //if it's a text based demoralization datum, make sure the mob has the capability to read. if it's only an image, make sure it's just bright enough for them to see it. + return + + var/target_faction = viewer.mind.war_faction + var/datum/mood_event/mood = faction_moods[target_faction] + if (isnull(mood)) + return + viewer.add_mood_event(mood_category, mood) + var/reaction = faction_reactions[target_faction] + if (isnull(reaction)) + return + to_chat(viewer, span_notice(reaction)) + +/** + * Returns true if user is capable of experiencing moods and doesn't already have the one relevant to this datum, false otherwise. + * + * Arguments + * * viewer - Whoever just saw the parent. + */ +/datum/proximity_monitor/advanced/war_demoraliser/proc/should_demoralise(mob/living/viewer) + if (!viewer.mob_mood) + return FALSE + + return !viewer.mob_mood.has_mood_of_category(mood_category) diff --git a/modular_doppler/war_posters/icons/posters.dmi b/modular_doppler/war_posters/icons/posters.dmi new file mode 100644 index 00000000000000..6aa0fc62d5976d Binary files /dev/null and b/modular_doppler/war_posters/icons/posters.dmi differ diff --git a/tgstation.dme b/tgstation.dme index fd750de46c9da8..9241c8b1965ba4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -464,6 +464,7 @@ #include "code\__DEFINES\~doppler_defines\species_clothing_paths.dm" #include "code\__DEFINES\~doppler_defines\speech_channels.dm" #include "code\__DEFINES\~doppler_defines\strippable.dm" +#include "code\__DEFINES\~doppler_defines\TESHARI_WAR_defines.dm" #include "code\__DEFINES\~doppler_defines\text.dm" #include "code\__DEFINES\~doppler_defines\traits.dm" #include "code\__DEFINES\~doppler_defines\vehicles.dm" @@ -6934,6 +6935,8 @@ #include "modular_doppler\deforest_medical_items\code\vulnerable_status_effect.dm" #include "modular_doppler\deforest_medical_items\code\chemicals\demoneye.dm" #include "modular_doppler\disable_suicide\config_entries.dm" +#include "modular_doppler\donation_box\donation_box.dm" +#include "modular_doppler\donation_box\loadout.dm" #include "modular_doppler\doppler_command_uniforms\hop\overrides.dm" #include "modular_doppler\emotes\code\emotes.dm" #include "modular_doppler\emotes\code\hologram.dm" @@ -7720,6 +7723,10 @@ #include "modular_doppler\starter_resources\ore_vent.dm" #include "modular_doppler\stone\code\ore_veins.dm" #include "modular_doppler\stone\code\stone.dm" +#include "modular_doppler\STORY_teshari_war\config.dm" +#include "modular_doppler\STORY_teshari_war\mind.dm" +#include "modular_doppler\STORY_teshari_war\supply_pack.dm" +#include "modular_doppler\STORY_teshari_war\preferences.dm" #include "modular_doppler\super_glasses\code\glasses_stats_thief.dm" #include "modular_doppler\super_glasses\code\techno_visors.dm" #include "modular_doppler\suuuper_trustworthy_item_orders\code\chem_containers.dm" @@ -7767,6 +7774,10 @@ #include "modular_doppler\verbs\code\preferences.dm" #include "modular_doppler\verbs\code\say.dm" #include "modular_doppler\verbs\code\subtle.dm" +#include "modular_doppler\war_posters\code\loadout.dm" +#include "modular_doppler\war_posters\code\mood.dm" +#include "modular_doppler\war_posters\code\posters.dm" +#include "modular_doppler\war_posters\code\war_moralisation.dm" #include "modular_doppler\wargaming\code\game_kit.dm" #include "modular_doppler\wargaming\code\holograms.dm" #include "modular_doppler\wargaming\code\projectors.dm" diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx index dbc019cacf081b..f20f13a1392bcc 100644 --- a/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx +++ b/tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx @@ -198,6 +198,10 @@ function CatalogList(props: CatalogListProps) { } const privateBuy = (self_paid && !pack.goody) || app_cost; + const unavailable = pack.shortagemult === -1; + const shortageString = unavailable + ? 'UNAVAILABLE!' + : `${pack.shortagemult}x cost`; const tooltipIcon = (content: string, icon: string, color: string) => ( @@ -214,7 +218,9 @@ function CatalogList(props: CatalogListProps) { dmIconState={pack.first_item_icon_state} imageSize={32} color={color} - disabled={(amount_by_name[pack.name] || 0) >= max_order} + disabled={ + (amount_by_name[pack.name] || 0) >= max_order || unavailable + } buttonsAlt={ diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/war_faction.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/war_faction.tsx new file mode 100644 index 00000000000000..595ee790bd93fc --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/war_faction.tsx @@ -0,0 +1,13 @@ +import { FeatureChoiced, FeatureValueProps, FeatureChoicedServerData } from "../base"; +import { FeatureDropdownInput } from "../dropdowns"; + +export const doppler_war_faction: FeatureChoiced = { + name: 'War Alignment', + description: + 'The stance your character takes on the Tizira/Teshari war.', + component: ( + props: FeatureValueProps, + ) => { + return ; + }, +};