Add Work Hard, Party Harder quirk (#32290)

* Add Work Hard, Party Harder quirk

* Update conflicts and whitespace.

* Run Prettier.

* Build TGUI.

* Actually prevent selecting conflicting quirks.

* Apply fixes from @warriorstar-orion. Thanks!

* Run Prettier.

* app

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

---------

Signed-off-by: Alan <alfalfascout@users.noreply.github.com>
Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
This commit is contained in:
Alan
2026-08-28 23:40:38 +00:00
committed by GitHub
co-authored by CRUNCH
parent c8dfcdac13
commit 4045c8177d
9 changed files with 42 additions and 7 deletions
+2 -1
View File
@@ -127,7 +127,8 @@
"name" = quirk.name,
"desc" = quirk.desc,
"cost" = quirk.cost,
"path" = quirk.type
"path" = quirk.type,
"conflicts" = quirk.conflicting_quirks,
)
GLOB.quirk_paths[quirk.name] = quirk.type // This will let us get the datum of a quirk with just the name later.
GLOB.quirk_tgui_info += list(data)
+1
View File
@@ -300,6 +300,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_AI_DISABLE_PLANNING "TRAIT_AI_DISABLE_PLANNING"
#define TRAIT_TEMPERATE_PARTIER "temperate_partier" // Mob won't wake up drunk in a random department
#define TRAIT_WORK_HARD_PARTY_HARDER "work_hard_party_harder" // Mob will wake up drunk somewhere random even if nobody else does
/// This mob's speech is heard through walls by dead players/observers even if it has no client. Idk a better name
#define TRAIT_IMPORTANT_SPEAKER "important_speaker"
/// Ignores line of sight for the purposes of send_speech()
+1
View File
@@ -129,6 +129,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
"TRAIT_BOOTS_OF_JUMPING" = TRAIT_BOOTS_OF_JUMPING,
"TRAIT_TEMPERATE_PARTIER" = TRAIT_TEMPERATE_PARTIER,
"TRAIT_WORK_HARD_PARTY_HARDER" = TRAIT_WORK_HARD_PARTY_HARDER,
),
/datum/mind = list(
+4 -3
View File
@@ -163,12 +163,13 @@ SUBSYSTEM_DEF(jobs)
var/turf/T = null
var/obj/S = null
var/list/landmarks = GLOB.landmarks_list
if(drunken_spawning && !HAS_TRAIT(H, TRAIT_TEMPERATE_PARTIER))
if((drunken_spawning && !HAS_TRAIT(H, TRAIT_TEMPERATE_PARTIER)) || HAS_TRAIT(H, TRAIT_WORK_HARD_PARTY_HARDER))
landmarks = shuffle(landmarks) //Shuffle it so it's random
for(var/obj/effect/landmark/start/sloc in landmarks)
if(sloc.name != rank && !(drunken_spawning && !HAS_TRAIT(H, TRAIT_TEMPERATE_PARTIER)))
continue
if(!(sloc.name in list("Assistant", "Chef", "Bartender", "Clown", "Mime", "Coroner")) || !HAS_TRAIT(H, TRAIT_WORK_HARD_PARTY_HARDER))
continue
if(locate(/mob/living) in sloc.loc)
continue
if(drunken_spawning && sloc.name == "AI")
@@ -224,7 +225,7 @@ SUBSYSTEM_DEF(jobs)
return H
if(late_arrivals_spawning)
H.forceMove(pick(GLOB.latejoin))
if(drunken_spawning && !HAS_TRAIT(H, TRAIT_TEMPERATE_PARTIER))
if((drunken_spawning && !HAS_TRAIT(H, TRAIT_TEMPERATE_PARTIER)) || HAS_TRAIT(H, TRAIT_WORK_HARD_PARTY_HARDER))
var/obj/item/organ/internal/liver/L
var/liver_multiplier = 1
L = H.get_int_organ(/obj/item/organ/internal/liver)
@@ -151,3 +151,10 @@
cost = -1
trait_to_apply = TRAIT_NEARSIGHT
species_flags = QUIRK_SLIME_INCOMPATIBLE
/datum/quirk/work_hard_party_harder
name = "Work Hard, Party Harder"
desc = "You party like there's no tomorrow every day, the consequences are a problem for future you! When the shift starts, you will always wake up in a random part of the station, drunk."
cost = -1
trait_to_apply = TRAIT_WORK_HARD_PARTY_HARDER
conflicting_quirks = list(/datum/quirk/temperate_partier)
@@ -202,3 +202,4 @@
desc = "You never wake up drunk in an unrelated department. You know better than to drink like that on a work night."
cost = 1
trait_to_apply = TRAIT_TEMPERATE_PARTIER
conflicting_quirks = list(/datum/quirk/work_hard_party_harder)
@@ -26,6 +26,8 @@ GLOBAL_LIST_EMPTY(quirk_paths)
var/organ_slot_to_remove
/// If the quirk should spawn a mob with the player.
var/mob_to_spawn
/// What quirks cannot be taken with this quirk.
var/list/conflicting_quirks
/datum/quirk/Destroy(force, ...)
remove_quirk_effects()
@@ -115,6 +117,11 @@ GLOBAL_LIST_EMPTY(quirk_paths)
if((to_add.species_flags & QUIRK_PLASMAMAN_INCOMPATIBLE) && (active_character.species == "Plasmaman")) //If someone can figure out how to only let plasmaman with a secondary language take this feel free to do that
to_chat(src.client, SPAN_WARNING("You can't put that quirk on a plasmaman, you have no species language!"))
return FALSE
if(to_add.conflicting_quirks)
for(var/datum/quirk/existing_quirk in active_character.quirks)
if(existing_quirk.type in to_add.conflicting_quirks)
to_chat(src.client, SPAN_WARNING("You can't take that quirk at the same time as [existing_quirk::name]!"))
return FALSE
active_character.quirks += to_add
return TRUE
+18 -2
View File
@@ -3,7 +3,7 @@ import { Box, Button, Divider, Icon, LabeledList, Section, Stack } from 'tgui-co
import { useBackend } from '../backend';
import { Window } from '../layouts';
type Quirk = { name: string; cost: number; desc: string; path: string };
type Quirk = { name: string; cost: number; desc: string; path: string; conflicts: string[] };
type Data = { selected_quirks: string[]; all_quirks: Quirk[] };
// Helper to calculate the balance for a given set of selected quirk names
@@ -29,6 +29,17 @@ export const QuirkMenu = () => {
const canAfford = (q: Quirk) => q.cost <= 0 || balance >= q.cost;
// Track quirk conflicts.
const hasConflicts = (q: Quirk) => {
for (const quirkName of selectedSet) {
const selectedQuirk = data.all_quirks.filter((quirk) => quirk.name === quirkName)[0];
if (q.conflicts && q.conflicts.includes(selectedQuirk.path)) {
return true;
}
}
return false;
};
const toggle = (q: Quirk) => {
const isChosen = selectedSet.has(q.name);
@@ -41,7 +52,7 @@ export const QuirkMenu = () => {
}
} else {
// Logic for ADDING a quirk
if (q.cost > 0 && !canAfford(q)) {
if ((q.cost > 0 && !canAfford(q)) || hasConflicts(q)) {
return;
}
}
@@ -78,6 +89,11 @@ export const QuirkMenu = () => {
buttonContent = 'Locked';
buttonColor = 'average';
}
if (hasConflicts(q)) {
disabled = true;
buttonContent = 'Locked (Conflict)';
buttonColor = 'average';
}
} else {
const remainingQuirks = selected.filter((n) => n !== q.name);
const remainingBalance = calculateBalance(remainingQuirks, data.all_quirks);
File diff suppressed because one or more lines are too long