From 6b84c4b75436389211a10858811cf3843fa8a43a Mon Sep 17 00:00:00 2001 From: Tsurupeta <41485301+Tsurupeta@users.noreply.github.com> Date: Wed, 24 Apr 2024 21:31:31 +0200 Subject: [PATCH] S.P.E.C.I.A.L. pt. 2 (#97) --- code/__DEFINES/jobs.dm | 1 + code/__DEFINES/special.dm | 6 + code/__DEFINES/traits.dm | 2 + code/_globalvars/traits.dm | 2 + code/_onclick/item_attack.dm | 20 ++- code/controllers/subsystem/job.dm | 13 ++ code/modules/client/preferences.dm | 71 +++++++--- code/modules/client/preferences_savefile.dm | 21 +-- code/modules/jobs/job_types/_job.dm | 60 +++++++++ code/modules/jobs/job_types/bos.dm | 12 ++ code/modules/jobs/job_types/legion.dm | 16 +++ code/modules/jobs/job_types/ncr.dm | 12 ++ .../modules/mob/dead/new_player/new_player.dm | 5 +- .../mob/living/carbon/human/species.dm | 4 + code/modules/mob/living/say.dm | 17 ++- code/modules/mob/mob_helpers.dm | 20 +++ code/modules/mob/special_stats.dm | 85 +++++++++--- code/modules/projectiles/gun.dm | 4 + fallout/obj/stack/f13Cash.dm | 122 +++++++----------- fallout/obj/trash_stack.dm | 7 +- hailmary.dme | 1 + 21 files changed, 362 insertions(+), 139 deletions(-) create mode 100644 code/__DEFINES/special.dm diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 3134f59c3ed..eac863962db 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -220,6 +220,7 @@ #define JOB_UNAVAILABLE_SLOTFULL 5 #define JOB_UNAVAILABLE_SPECIESLOCK 6 #define JOB_UNAVAILABLE_WHITELIST 7 +#define JOB_UNAVAILABLE_SPECIAL 8 #define DEFAULT_RELIGION "Christianity" #define DEFAULT_DEITY "Space Jesus" diff --git a/code/__DEFINES/special.dm b/code/__DEFINES/special.dm new file mode 100644 index 00000000000..0c5ec2e973d --- /dev/null +++ b/code/__DEFINES/special.dm @@ -0,0 +1,6 @@ +#define SPECIAL_MAX_POINT_SUM_CAP 38 +#define SPECIAL_MIN_ATTR_VALUE 1 +#define SPECIAL_DEFAULT_ATTR_VALUE 5 +#define SPECIAL_MAX_ATTR_VALUE 10 + +#define SPECIAL_MIN_INT_CRAFTING_REQUIREMENT 3 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 1d75692464b..5fe0346d075 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -173,6 +173,8 @@ #define TRAIT_PARALYSIS_R_LEG "para-r-leg" #define TRAIT_DISK_VERIFIER "disk-verifier" #define TRAIT_UNINTELLIGIBLE_SPEECH "unintelligible-speech" +#define TRAIT_SAY_STUTTERING "say-stuttering" +#define TRAIT_SAY_LISPING "say-lisping" #define TRAIT_SOOTHED_THROAT "soothed-throat" #define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism" #define TRAIT_QUICK_CARRY "quick-carry" diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index a3f0c3093c9..fc1a0c72700 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -91,6 +91,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SOOTHED_THROAT" = TRAIT_SOOTHED_THROAT, "TRAIT_LAW_ENFORCEMENT_METABOLISM" = TRAIT_LAW_ENFORCEMENT_METABOLISM, "TRAIT_UNINTELLIGIBLE_SPEECH" = TRAIT_UNINTELLIGIBLE_SPEECH, + "TRAIT_SAY_STUTTERING" = TRAIT_SAY_STUTTERING, + "TRAIT_SAY_LISPING " = TRAIT_SAY_LISPING, "TRAIT_UNSTABLE" = TRAIT_UNSTABLE, "TRAIT_COLDBLOODED" = TRAIT_COLDBLOODED, "TRAIT_NONATURALHEAL" = TRAIT_NONATURALHEAL, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 9f6f08575e0..7b4c728f07f 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -82,9 +82,10 @@ * * damage_multiplier - what to multiply the damage by */ /obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) - if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK) + var/mob/living/target = M + if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, target, user) & COMPONENT_ITEM_NO_ATTACK) return - SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target, user) if(item_flags & NOBLUDGEON) return if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM)) @@ -124,13 +125,18 @@ else if(hitsound) playsound(loc, hitsound, get_clamped_volume(), 1, -1) - M.lastattacker = user.real_name - M.lastattackerckey = user.ckey + target.lastattacker = user.real_name + target.lastattackerckey = user.ckey - user.do_attack_animation(M) - M.attacked_by(src, user, attackchain_flags, damage_multiplier, damage_addition = force_modifier) + user.do_attack_animation(target) - log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + if(prob(user.get_luck_critfail_chance())) //S.P.E.C.I.A.L. + target = user + user.visible_message(span_warning("Critical fail! [user] tries to attack [M], but hits [user.p_them()]self instead!")) + + log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])[M != target ? "(Critfail: hit [target] instead)" : ""]") + + target.attacked_by(src, user, attackchain_flags, damage_multiplier, damage_addition = force_modifier) add_fingerprint(user) //the equivalent of the standard version of attack() but for object targets. diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index d939e993f7f..31c89b56a09 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -104,6 +104,8 @@ SUBSYSTEM_DEF(job) var/datum/job/job = GetJob(rank) if(!job) return FALSE + if(job.special_stat_check(player.client?.prefs)) + return FALSE if(jobban_isbanned(player, rank) || QDELETED(player)) return FALSE if(!job.player_old_enough(player.client)) @@ -126,6 +128,9 @@ SUBSYSTEM_DEF(job) JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]") var/list/candidates = list() for(var/mob/dead/new_player/player in unassigned) + if(job.special_stat_check(player.client?.prefs)) + JobDebug("FOC special stat failed, player: [player]") + continue if(jobban_isbanned(player, job.title) || QDELETED(player)) JobDebug("FOC isbanned failed, Player: [player]") continue @@ -165,6 +170,10 @@ SUBSYSTEM_DEF(job) if((job.title in GLOB.faction_whitelist_positions) && (CONFIG_GET(flag/use_role_whitelist))) //If you want a whitelist position, get a whitelist and choose it. continue + if(job.special_stat_check(player.client?.prefs)) + JobDebug("GRJ special stat failed, player: [player]") + continue + if(jobban_isbanned(player, job.title) || QDELETED(player)) if(QDELETED(player)) JobDebug("GRJ isbanned failed, Player deleted") @@ -346,6 +355,10 @@ SUBSYSTEM_DEF(job) if(!job) continue + if(job.special_stat_check(player.client?.prefs)) + JobDebug("DO special stat failed, player: [player]") + continue + if(jobban_isbanned(player, job.title)) JobDebug("DO isbanned failed, Player: [player], Job:[job.title]") continue diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index fdfb884b582..9844724508c 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -205,13 +205,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/hide_ckey = FALSE //pref for hiding if your ckey shows round-end or not - var/special_s = 5 - var/special_p = 5 - var/special_e = 5 - var/special_c = 5 - var/special_i = 5 - var/special_a = 5 - var/special_l = 5 + var/special_s = SPECIAL_DEFAULT_ATTR_VALUE + var/special_p = SPECIAL_DEFAULT_ATTR_VALUE + var/special_e = SPECIAL_DEFAULT_ATTR_VALUE + var/special_c = SPECIAL_DEFAULT_ATTR_VALUE + var/special_i = SPECIAL_DEFAULT_ATTR_VALUE + var/special_a = SPECIAL_DEFAULT_ATTR_VALUE + var/special_l = SPECIAL_DEFAULT_ATTR_VALUE /// Associative list: matchmaking_prefs[/datum/matchmaking_pref subtype] -> number of desired matches var/list/matchmaking_prefs = list() @@ -929,6 +929,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(jobban_isbanned(user, rank)) HTML += "[rank] BANNED" continue + if(job.special_stat_check(src)) + HTML += "[rank]\[SPECIAL [job.special_stat_check(src)]\]" + continue var/required_playtime_remaining = job.required_playtime_remaining(user.client) if(required_playtime_remaining) HTML += "[rank] \[ [get_exp_format(required_playtime_remaining)] as [job.get_exp_req_type()] \] " @@ -1150,21 +1153,28 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
Allocate points
" dat += "
Note: SPECIAL is functional here. These points have an effect on gameplay.

" - dat += "
[total] out of 35 possible

" + dat += "
[total] out of [SPECIAL_MAX_POINT_SUM_CAP] possible

" dat += "Strength : [special_s]
" + dat += "Strength affects the amount of melee damage you dish out.
" dat += "Perception : [special_p]
" + dat += "Perception affects how well you can fire ranged weapons.
" dat += "Endurance : [special_e]
" + dat += "Endurance affects your maximum health & resistance to fire and poisons.
" dat += "Charisma : [special_c]
" + dat += "Charisma determines your character's examine text, leadership & ability to manipulate others.
" dat += "Intelligence: [special_i]
" + dat += "Intelligence is necessary for being able to craft various recipes, as well as the operation of energy weapons.
" dat += "Agility : [special_a]
" + dat += "Agility determines your move speed and how much stamina you use while sprinting.
" dat += "Luck : [special_l]
" - if (total>35) + dat += "Luck does stuff!
" + if (total > SPECIAL_MAX_POINT_SUM_CAP) dat += "
Maximum exceeded, please change until your total is at or below 35
" else dat += "
Done
" user << browse(null, "window=preferences") - var/datum/browser/popup = new(user, "mob_occupation", "
S.P.E.C.I.A.L
", 300, 400) //no reason not to reuse the occupation window, as it's cleaner that way + var/datum/browser/popup = new(user, "mob_occupation", "
S.P.E.C.I.A.L
", 400, 550) //no reason not to reuse the occupation window, as it's cleaner that way popup.set_window_options("can_close=0") popup.set_content(dat.Join()) popup.open(0) @@ -1347,43 +1357,43 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("special_s") var/new_point = input(user, "Choose Amount(1-10)", "Strength") as num|null if(new_point) - special_s = max(min(round(text2num(new_point)), 10),1) + special_s = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_p") var/new_point = input(user, "Choose Amount(1-10)", "Perception") as num|null if(new_point) - special_p = max(min(round(text2num(new_point)), 10),1) + special_p = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_e") var/new_point = input(user, "Choose Amount(1-10)", "Endurance") as num|null if(new_point) - special_e = max(min(round(text2num(new_point)), 10),1) + special_e = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_c") var/new_point = input(user, "Choose Amount(1-10)", "Charisma") as num|null if(new_point) - special_c = max(min(round(text2num(new_point)), 10),1) + special_c = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_i") var/new_point = input(user, "Choose Amount(1-10)", "Intelligence") as num|null if(new_point) - special_i = max(min(round(text2num(new_point)), 10),1) + special_i = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_a") var/new_point = input(user, "Choose Amount(1-10)", "Agility") as num|null if(new_point) - special_a = max(min(round(text2num(new_point)), 10),1) + special_a = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("special_l") var/new_point = input(user, "Choose Amount(1-10)", "Luck") as num|null if(new_point) - special_l = max(min(round(text2num(new_point)), 10),1) + special_l = clamp(round(new_point), SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) SetSpecial(user) return 1 if("ghostform") @@ -2127,7 +2137,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.gender = gender character.age = age - //special stuff + //S.P.E.C.I.A.L. + fix_special_values() character.special_s = special_s character.special_p = special_p character.special_e = special_e @@ -2348,6 +2359,30 @@ GLOBAL_LIST_EMPTY(preferences_datums) else to_chat(parent, span_userdanger("Something went wrong! Your quirks have been reset, and you'll need to set up your quirks again.")) +/datum/preferences/proc/clamp_special_values() // S.P.E.C.I.A.L. + special_s = clamp(special_s, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_p = clamp(special_p, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_e = clamp(special_e, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_c = clamp(special_c, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_i = clamp(special_i, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_a = clamp(special_a, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + special_l = clamp(special_l, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + +/datum/preferences/proc/reset_special_values() // S.P.E.C.I.A.L. + special_s = SPECIAL_DEFAULT_ATTR_VALUE + special_p = SPECIAL_DEFAULT_ATTR_VALUE + special_e = SPECIAL_DEFAULT_ATTR_VALUE + special_c = SPECIAL_DEFAULT_ATTR_VALUE + special_i = SPECIAL_DEFAULT_ATTR_VALUE + special_a = SPECIAL_DEFAULT_ATTR_VALUE + special_l = SPECIAL_DEFAULT_ATTR_VALUE + +/datum/preferences/proc/fix_special_values() // S.P.E.C.I.A.L. + clamp_special_values() + var/sum = special_s + special_p + special_e + special_c + special_i + special_a + special_l + if(sum > SPECIAL_MAX_POINT_SUM_CAP) + reset_special_values() + #undef DEFAULT_SLOT_AMT #undef HANDS_SLOT_AMT diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index a96b80e2471..167c6109bc2 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -519,7 +519,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car loadout_data = safe_json_decode(S["loadout"]) else loadout_data = list() - //special + + //S.P.E.C.I.A.L. S["special_s"] >> special_s S["special_p"] >> special_p S["special_e"] >> special_e @@ -567,13 +568,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car socks = sanitize_inlist(socks, GLOB.socks_list) socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color)) age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) - special_s = sanitize_integer(special_s, 1, 10, initial(special_s)) - special_p = sanitize_integer(special_p, 1, 10, initial(special_p)) - special_e = sanitize_integer(special_e, 1, 10, initial(special_e)) - special_c = sanitize_integer(special_c, 1, 10, initial(special_c)) - special_i = sanitize_integer(special_i, 1, 10, initial(special_i)) - special_a = sanitize_integer(special_a, 1, 10, initial(special_a)) - special_l = sanitize_integer(special_l, 1, 10, initial(special_l)) + special_s = sanitize_integer(special_s, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_s)) + special_p = sanitize_integer(special_p, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_p)) + special_e = sanitize_integer(special_e, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_e)) + special_c = sanitize_integer(special_c, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_c)) + special_i = sanitize_integer(special_i, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_i)) + special_a = sanitize_integer(special_a, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_a)) + special_l = sanitize_integer(special_l, SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE, initial(special_l)) + fix_special_values() hair_color = sanitize_hexcolor(hair_color, 6, FALSE) facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE) @@ -705,7 +707,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_taste"], features["taste"]) - //special + //S.P.E.C.I.A.L. + fix_special_values() WRITE_FILE(S["special_s"] ,special_s) WRITE_FILE(S["special_p"] ,special_p) WRITE_FILE(S["special_e"] ,special_e) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index d582c1dc816..90893f0dccb 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -100,6 +100,33 @@ /// the value should be something like "strings/names/cow.txt" var/whitelist_path + var/list/min_required_special + + /* //!Template for pasting into job defines, leave only needed fields: + min_required_special = list( + "special_s" = 0, + "special_p" = 0, + "special_e" = 0, + "special_c" = 0, + "special_i" = 0, + "special_a" = 0, + "special_l" = 0, + ) + */ + + var/list/modify_special + + /* //!Template for pasting into job defines, leave only needed fields: + modify_special = list( + "special_s" = 0, + "special_p" = 0, + "special_e" = 0, + "special_c" = 0, + "special_i" = 0, + "special_a" = 0, + "special_l" = 0, + ) + */ /datum/job/proc/after_spawn(mob/living/spawner, mob/client_holder, latejoin = FALSE) SHOULD_CALL_PARENT(TRUE) @@ -170,6 +197,15 @@ //Equip the rest of the gear H.dna.species.before_equip_job(src, H, visualsOnly) + if(islist(modify_special)) + H.special_s = clamp(H.special_s + modify_special["special_s"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_p = clamp(H.special_p + modify_special["special_p"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_e = clamp(H.special_e + modify_special["special_e"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_c = clamp(H.special_c + modify_special["special_c"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_i = clamp(H.special_i + modify_special["special_i"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_a = clamp(H.special_a + modify_special["special_a"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_l = clamp(H.special_l + modify_special["special_l"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + var/datum/outfit/job/O = outfit_override || outfit if(O) H.equipOutfit(O, visualsOnly, preference_source) //mob doesn't have a client yet. @@ -383,3 +419,27 @@ if(CONFIG_GET(flag/security_has_maint_access)) return list(ACCESS_MAINT_TUNNELS) return list() + +/datum/job/proc/special_stat_check(datum/preferences/prefs) + var/output = "" + var/sum = prefs.special_s + prefs.special_p + prefs.special_e + prefs.special_c + prefs.special_i + prefs.special_a + prefs.special_l + if(sum > SPECIAL_MAX_POINT_SUM_CAP) + return "\[SPECIAL CAP\]" + if(islist(min_required_special)) + if(min_required_special["special_s"] && min_required_special["special_s"] > prefs.special_s) + output += "S: [min_required_special["special_s"]], " + if(min_required_special["special_p"] && min_required_special["special_p"] > prefs.special_p) + output += "P: [min_required_special["special_p"]], " + if(min_required_special["special_e"] && min_required_special["special_e"] > prefs.special_e) + output += "E: [min_required_special["special_e"]], " + if(min_required_special["special_c"] && min_required_special["special_c"] > prefs.special_c) + output += "C: [min_required_special["special_c"]], " + if(min_required_special["special_i"] && min_required_special["special_i"] > prefs.special_i) + output += "I: [min_required_special["special_i"]], " + if(min_required_special["special_a"] && min_required_special["special_a"] > prefs.special_a) + output += "A: [min_required_special["special_a"]], " + if(min_required_special["special_l"] && min_required_special["special_l"] > prefs.special_l) + output += "L: [min_required_special["special_l"]], " + if(length(output)) + output = copytext_char(output, 1, length(output) - 1) + return output diff --git a/code/modules/jobs/job_types/bos.dm b/code/modules/jobs/job_types/bos.dm index 9ebd1cd295e..92323cfc067 100644 --- a/code/modules/jobs/job_types/bos.dm +++ b/code/modules/jobs/job_types/bos.dm @@ -173,6 +173,10 @@ Paladin Commander /datum/outfit/loadout/sentmini //Minigun ) + min_required_special = list( + "special_c" = 4, + ) + access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_CHANGE_IDS) minimal_access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_CHANGE_IDS) @@ -328,6 +332,10 @@ Knight-Captain access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_ARMORY, ACCESS_BRIG, ACCESS_CHANGE_IDS) minimal_access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_ARMORY, ACCESS_BRIG, ACCESS_CHANGE_IDS) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/bos/f13knightcap/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -462,6 +470,10 @@ Paladin ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/bos/f13paladin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/jobs/job_types/legion.dm b/code/modules/jobs/job_types/legion.dm index e2a00095466..bc1b670b319 100644 --- a/code/modules/jobs/job_types/legion.dm +++ b/code/modules/jobs/job_types/legion.dm @@ -211,6 +211,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al /datum/outfit/loadout/centurion, // 14mm Pistol + Unique Lever-Action ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13centurion/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -304,6 +308,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al /datum/outfit/loadout/decvetbrave, // Lever-action Shotgun, 44 revolver, ballistic fist ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decanvet/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() @@ -409,6 +417,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decan/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -500,6 +512,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decanrec/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/jobs/job_types/ncr.dm b/code/modules/jobs/job_types/ncr.dm index 03baab73c79..7acc497a010 100644 --- a/code/modules/jobs/job_types/ncr.dm +++ b/code/modules/jobs/job_types/ncr.dm @@ -156,6 +156,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. /datum/outfit/loadout/captainfrontline, // AR Service Rifle ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13captain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -236,6 +240,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13lieutenant // AR Service Rifle, Binoculars, Bayonet, M1911 custom name = "NCR Lieutenant" jobtype = /datum/job/ncr/f13lieutenant @@ -536,6 +544,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. /datum/outfit/loadout/vrcqc // 2 x .45 Long colt revolvers ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13vetranger/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 7a912937859..c1c3e4b742a 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -405,6 +405,8 @@ return "Your species cannot play as a [jobtitle]." if(JOB_UNAVAILABLE_WHITELIST) return "[jobtitle] requires a whitelist." + if(JOB_UNAVAILABLE_SPECIAL) + return "[jobtitle] requires certain SPECIAL stats high enough." return "Error: Unknown job availability." /mob/dead/new_player/proc/IsJobUnavailable(rank, latejoin = FALSE) @@ -422,6 +424,8 @@ return JOB_UNAVAILABLE_SLOTFULL if(jobban_isbanned(src,rank)) return JOB_UNAVAILABLE_BANNED + if(job.special_stat_check(client?.prefs)) + return JOB_UNAVAILABLE_SPECIAL if(QDELETED(src)) return JOB_UNAVAILABLE_GENERIC if(!job.player_old_enough(client)) @@ -717,4 +721,3 @@ // Add verb for re-opening the interview panel, and re-init the verbs for the stat panel add_verb(src, /mob/dead/new_player/proc/open_interview) - diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index c9deed02029..00b196460f0 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1395,6 +1395,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) target_message = span_warning("[target] blocks your attack!")) return FALSE + if(prob(user.get_luck_critfail_chance())) //S.P.E.C.I.A.L. + user.visible_message(span_warning("Critical fail! [user] tries to attack [target], but hits [user.p_them()]self instead!")) + target = user + if(!(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)) if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount user.adjustStaminaLossBuffered(1.5) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 3ea764984ec..86aa15f698e 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -22,12 +22,12 @@ /mob/living/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, just_chat) /* var/static/list/crit_allowed_modes = list( - MODE_WHISPER = TRUE, - MODE_CUSTOM_SAY = TRUE, - MODE_SING = TRUE, - MODE_HEADSET = TRUE, - MODE_ROBOT = TRUE, - MODE_CHANGELING = TRUE, + MODE_WHISPER = TRUE, + MODE_CUSTOM_SAY = TRUE, + MODE_SING = TRUE, + MODE_HEADSET = TRUE, + MODE_ROBOT = TRUE, + MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE ) */ var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE) @@ -316,7 +316,7 @@ if(derpspeech) message = derpspeech(message, stuttering) - if(stuttering) + if(stuttering || HAS_TRAIT(src, TRAIT_SAY_STUTTERING)) message = stutter(message) if(slurring) @@ -328,6 +328,9 @@ if(clockcultslurring) message = CLOCK_CULT_SLUR(message) + if(HAS_TRAIT(src, TRAIT_SAY_LISPING)) + message = lisp_replace(message) + var/end_char = copytext(message, length(message), length(message) + 1) if(!(end_char in list(".", "?", "!", "-", "~", ",", "_", "+", "|", "*"))) message += "." diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index ad353c1fb20..16dc963488c 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -210,6 +210,26 @@ . += letter return sanitize(.) +/proc/lisp_replace(message) + var/static/regex/replace_s = new("s+h?h?", "g") + var/static/regex/replace_S = new("S+H?H?", "g") + var/static/regex/replace_z = new("z+h?h?", "g") + var/static/regex/replace_Z = new("Z+H?H?", "g") + var/static/regex/replace_x = new("x+h?h?", "g") + var/static/regex/replace_X = new("X+H?H?", "g") + var/static/regex/replace_ceci = new("ceh?|cih?", "g") + var/static/regex/replace_CECI = new("CEH?|CIH?", "g") + if(message[1] != "*") + message = replace_s.Replace(message, "th") + message = replace_S.Replace(message, "TH") + message = replace_z.Replace(message, "th") + message = replace_Z.Replace(message, "TH") + message = replace_ceci.Replace(message, "th") + message = replace_CECI.Replace(message, "TH") + message = replace_x.Replace(message, "ckth") + message = replace_X.Replace(message, "CKTH") + return message + /* The difference with stutter is that this proc can stutter more than 1 letter The issue here is that anything that does not have a space is treated as one word (in many instances). For instance, "LOOKING," is a word, including the comma. diff --git a/code/modules/mob/special_stats.dm b/code/modules/mob/special_stats.dm index 3eab666f135..5727860e98a 100644 --- a/code/modules/mob/special_stats.dm +++ b/code/modules/mob/special_stats.dm @@ -1,18 +1,12 @@ -////////////////////////////////////////////////////// -////////////////////SUBTLE COMMAND//////////////////// -////////////////////////////////////////////////////// - -#define DEFAULT_SPECIAL_ATTR_VALUE 5 -#define MIN_INT_CRAFTING_REQUIREMENT 3 /mob var/flavor_text = "" //tired of fucking double checking this - var/special_s = DEFAULT_SPECIAL_ATTR_VALUE // +/-2 dmg in melee for each level above/below 5 ST - var/special_p = DEFAULT_SPECIAL_ATTR_VALUE // +/- 5 degrees of innate gun spread for each level below/above 5 PR - var/special_e = DEFAULT_SPECIAL_ATTR_VALUE // +/-5 maxHealth for each level above/below 5 END - var/special_c = DEFAULT_SPECIAL_ATTR_VALUE // Desc message + moodlets - var/special_i = DEFAULT_SPECIAL_ATTR_VALUE // Can't craft with INT under MIN_INT_CRAFTING_REQUIREMENT, certain recipes can be INT locked, certain guns can be INT locked - var/special_a = DEFAULT_SPECIAL_ATTR_VALUE // +/- 10% Sprint stamina usage modifier -/+ 0.05 movespeed modifier per lvl below/above 5 AGI - var/special_l = DEFAULT_SPECIAL_ATTR_VALUE // Currently nothing + var/special_s = SPECIAL_DEFAULT_ATTR_VALUE // +/-2 dmg in melee for each level above/below 5 ST + var/special_p = SPECIAL_DEFAULT_ATTR_VALUE // +/- 5 degrees of innate gun spread for each level below/above 5 PR + var/special_e = SPECIAL_DEFAULT_ATTR_VALUE // +/-5 maxHealth for each level above/below 5 END + var/special_c = SPECIAL_DEFAULT_ATTR_VALUE // Desc message + moodlets + var/special_i = SPECIAL_DEFAULT_ATTR_VALUE // Can't craft with INT under SPECIAL_MIN_INT_CRAFTING_REQUIREMENT, certain recipes can be INT locked, certain guns can be INT locked + var/special_a = SPECIAL_DEFAULT_ATTR_VALUE // +/- 10% Sprint stamina usage modifier -/+ 0.05 movespeed modifier per lvl below/above 5 AGI + var/special_l = SPECIAL_DEFAULT_ATTR_VALUE // Currently nothing /mob/proc/get_top_level_mob() if(istype(src.loc,/mob)&&src.loc!=src) @@ -61,20 +55,20 @@ proc/get_top_level_mob(mob/S) /// STRENGTH /obj/item/proc/calc_melee_dam_mod_from_special(mob/living/user) - return ((user.special_s - DEFAULT_SPECIAL_ATTR_VALUE) * 2) + return ((user.special_s - SPECIAL_DEFAULT_ATTR_VALUE) * 2) /datum/species/proc/calc_unarmed_dam_mod_from_special(mob/living/user) - return ((user.special_s - DEFAULT_SPECIAL_ATTR_VALUE) * 2) + return ((user.special_s - SPECIAL_DEFAULT_ATTR_VALUE) * 2) /// PERCEPTION /obj/item/ammo_casing/proc/calc_bullet_spread_mod_from_special(mob/living/user) - return ((user.special_p - DEFAULT_SPECIAL_ATTR_VALUE) * 5) // +/- 5 degrees of innate spread per lvl + return ((user.special_p - SPECIAL_DEFAULT_ATTR_VALUE) * 5) // +/- 5 degrees of innate spread per lvl /// ENDURANCE /mob/living/carbon/human/initialize_special_endurance() - maxHealth = initial(maxHealth) + ((special_e - DEFAULT_SPECIAL_ATTR_VALUE) * 5) + maxHealth = initial(maxHealth) + ((special_e - SPECIAL_DEFAULT_ATTR_VALUE) * 5) health = maxHealth /datum/species/proc/get_special_burn_resist_multiplier(mob/living/user) @@ -130,12 +124,27 @@ proc/get_top_level_mob(mob/S) /mob/living/carbon/human/initialize_special_charisma() RegisterSignal(src, COMSIG_PARENT_EXAMINE, PROC_REF(handle_special_charisma_examine_moodlet), TRUE) + initialize_charisma_traits(src) /mob/living/carbon/human/Destroy() UnregisterSignal(src, COMSIG_PARENT_EXAMINE) return ..() +/mob/proc/initialize_charisma_traits(mob/living/carbon/user) + if(HAS_TRAIT_FROM(user, TRAIT_SAY_STUTTERING, "charisma")) + REMOVE_TRAIT(user, TRAIT_SAY_STUTTERING, "charisma") + if(HAS_TRAIT_FROM(user, TRAIT_SAY_LISPING, "charisma")) + REMOVE_TRAIT(user, TRAIT_SAY_LISPING, "charisma") + switch(special_c) + if(3) + ADD_TRAIT(user, TRAIT_SAY_STUTTERING, "charisma") + if(2) + ADD_TRAIT(user, TRAIT_SAY_LISPING, "charisma") + if(1) + ADD_TRAIT(user, TRAIT_SAY_STUTTERING, "charisma") + ADD_TRAIT(user, TRAIT_SAY_LISPING, "charisma") + /mob/proc/handle_special_charisma_examine_moodlet(mob/living/examinee, mob/living/examiner, text) if(!istype(examiner)) return @@ -182,7 +191,7 @@ proc/get_top_level_mob(mob/S) /datum/component/personal_crafting/proc/special_crafting_check(mob/living/user) if(!istype(user)) return FALSE - if(user.special_i <= MIN_INT_CRAFTING_REQUIREMENT) + if(user.special_i <= SPECIAL_MIN_INT_CRAFTING_REQUIREMENT) to_chat(user, "Your brain is too dumb to craft items.") return FALSE return TRUE @@ -199,13 +208,49 @@ proc/get_top_level_mob(mob/S) return /mob/living/carbon/calc_sprint_stamina_mod_from_special() - return (1 - ((special_a - DEFAULT_SPECIAL_ATTR_VALUE) * 0.1)) + return (1 - ((special_a - SPECIAL_DEFAULT_ATTR_VALUE) * 0.1)) /mob/proc/calc_movespeed_mod_from_special() - return -((special_a - DEFAULT_SPECIAL_ATTR_VALUE) * 0.05) + return -((special_a - SPECIAL_DEFAULT_ATTR_VALUE) * 0.05) /// LUCK +/// Currently affects only money from trashpiles +/mob/proc/get_luck_loot_amt_multiplier() + switch(special_l) + if(1) + return 0.5 + if(2) + return 0.625 + if(3) + return 0.750 + if(4) + return 0.875 + if(5) + return 1 + if(6) + return 1.1 + if(7) + return 1.2 + if(8) + return 1.3 + if(9) + return 1.4 + if(10) + return 1.5 + return 1 + + +/// Chance to drop a gun or hit yourself in melee +/mob/proc/get_luck_critfail_chance() + switch(special_l) + if(1) + return 10 + if(2) + return 4 + if(3) + return 1 + return 0 diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 3973012fe2f..ed44788dedd 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -564,6 +564,10 @@ ATTACHMENTS if(time_till_draw) to_chat(user, "You're still drawing your [src]! It'll take another [time_till_draw*0.1] seconds until it's ready!") return + if(prob(user.get_luck_critfail_chance())) + user.drop_all_held_items() + user.visible_message(span_warning("Critical fail! [user] accidentally drops [p_their()] gun!")) + return if(pre_fire(user, target, params, zone_override, stam_cost)) return TRUE // pre_fire will handle what comes next~ (like firing at your mouse cursor after a delay) firing = TRUE diff --git a/fallout/obj/stack/f13Cash.dm b/fallout/obj/stack/f13Cash.dm index 36d43882256..d591ea02b61 100644 --- a/fallout/obj/stack/f13Cash.dm +++ b/fallout/obj/stack/f13Cash.dm @@ -9,31 +9,24 @@ /* value of coins to spawn, use as-is for caps */ /* LOW_MIN / AUR = amount in AUR */ -// A low value cash spawn is on average worth 25 -#define LOW_MIN 7 -#define LOW_MAX 19 +/// Average amount of caps spawned from trash pile +#define AVG_BASE 13 / CASH_CAP -// A medium value cash spawn is on average worth 60ish -#define MED_MIN 20 -#define MED_MAX 35 +// A low value cash spawn +#define CASH_MULT_LOW 1 +// A medium value cash spawn +#define CASH_MULT_MED 2.1 -// A high value cash spawn is on average worth 280 -#define HIGH_MIN 36 -#define HIGH_MAX 45 +// A high value cash spawn +#define CASH_MULT_HIGH 3.1 - -// Bad Pebbles fix to NCR money fudgery -#define TEMP3_MIN 0 -#define TEMP3_MAX 0 -#define TEMP_MIN 0 -#define TEMP_MAX 0 -#define TEMP2_MIN 0 -#define TEMP2_MAX 0 +/// round(AVG * CASH_MULT) +- AVG_SPREAD +#define AVG_SPEAD 6 / CASH_CAP // The Bankers Vault-Stash, done like this make it so it only spawns on his person to stop metarushing. Average 8500. -#define BANKER_MIN 2000 -#define BANKER_MAX 15000 +#define AVG_BANKER 8500 / CASH_CAP +#define BANKER_SPREAD 6500 / CASH_CAP /obj/item/stack/f13Cash //DO NOT USE THIS name = "bottle cap" @@ -141,20 +134,25 @@ /obj/item/stack/f13Cash/random var/money_type = /obj/item/stack/f13Cash/caps - var/min_qty = LOW_MIN - var/max_qty = LOW_MAX + var/average_qty = AVG_BASE + var/average_spread = AVG_SPEAD + var/average_mult = CASH_MULT_LOW var/spawn_nothing_chance = 0 //chance no money at all spawns -/obj/item/stack/f13Cash/random/Initialize() +/obj/item/stack/f13Cash/random/Initialize(mapload, new_amount, merge = TRUE, amt_multiplier = 0) //S.P.E.C.I.A.L. ..() + amt_multiplier = max(amt_multiplier, 0) + if(amt_multiplier) + average_mult *= amt_multiplier if(!prob(spawn_nothing_chance)) spawn_money() return INITIALIZE_HINT_QDEL /obj/item/stack/f13Cash/random/proc/spawn_money() + var/spawn_amount = round(average_qty * average_mult) var/obj/item/stack/f13Cash/stack = new money_type stack.loc = loc - stack.amount = round(rand(min_qty, max_qty)) + stack.amount = round(rand(round(spawn_amount - average_spread), round(spawn_amount + average_spread))) stack.update_icon() /* we have 6 icons, so we will use our own, instead of stack's */ @@ -174,8 +172,7 @@ icon_state = "[initial(icon_state)]6" /obj/item/stack/f13Cash/random/low - min_qty = LOW_MIN / CASH_CAP - max_qty = LOW_MAX / CASH_CAP + average_mult = CASH_MULT_LOW /obj/item/stack/f13Cash/random/low/lowchance spawn_nothing_chance = 75 @@ -184,16 +181,14 @@ spawn_nothing_chance = 50 /obj/item/stack/f13Cash/random/med - min_qty = MED_MIN / CASH_CAP - max_qty = MED_MAX / CASH_CAP + average_mult = CASH_MULT_MED /obj/item/stack/f13Cash/random/high - min_qty = HIGH_MIN / CASH_CAP - max_qty = HIGH_MAX / CASH_CAP + average_mult = CASH_MULT_HIGH /obj/item/stack/f13Cash/random/banker - min_qty = BANKER_MIN / CASH_CAP - max_qty = BANKER_MAX / CASH_CAP + average_qty = AVG_BANKER + average_spread = BANKER_SPREAD /obj/item/stack/f13Cash/denarius name = "Denarius" @@ -208,31 +203,27 @@ merge_type = /obj/item/stack/f13Cash/denarius /obj/item/stack/f13Cash/random/denarius + average_qty = AVG_BASE / CASH_DEN + average_spread = AVG_SPEAD / CASH_DEN money_type = /obj/item/stack/f13Cash/denarius /obj/item/stack/f13Cash/random/denarius/low - min_qty = LOW_MIN / CASH_DEN - max_qty = LOW_MAX / CASH_DEN + average_mult = CASH_MULT_LOW /obj/item/stack/f13Cash/random/denarius/med - min_qty = MED_MIN / CASH_DEN - max_qty = MED_MAX / CASH_DEN + average_mult = CASH_MULT_MED /obj/item/stack/f13Cash/random/denarius/high - min_qty = HIGH_MIN / CASH_DEN - max_qty = HIGH_MAX / CASH_DEN + average_mult = CASH_MULT_HIGH /obj/item/stack/f13Cash/random/denarius/legionpay_basic - min_qty = LOW_MIN / CASH_DEN - max_qty = LOW_MAX / CASH_DEN + average_mult = CASH_MULT_LOW /obj/item/stack/f13Cash/random/denarius/legionpay_veteran - min_qty = MED_MIN / CASH_DEN - max_qty = MED_MAX / CASH_DEN + average_mult = CASH_MULT_MED /obj/item/stack/f13Cash/random/denarius/legionpay_officer - min_qty = HIGH_MIN / CASH_DEN - max_qty = HIGH_MAX / CASH_DEN + average_mult = CASH_MULT_HIGH /obj/item/stack/f13Cash/aureus name = "Aureus" @@ -247,19 +238,15 @@ merge_type = /obj/item/stack/f13Cash/aureus /obj/item/stack/f13Cash/random/aureus + average_qty = 0 + average_spread = 0 money_type = /obj/item/stack/f13Cash/aureus /obj/item/stack/f13Cash/random/aureus/low - min_qty = 0 - max_qty = 0 /obj/item/stack/f13Cash/random/aureus/med - min_qty = 0 - max_qty = 0 /obj/item/stack/f13Cash/random/aureus/high - min_qty = 0 - max_qty = 0 //uses flat values because aurei are worth so much /obj/item/stack/f13Cash/ncr name = "NCR Dollar" @@ -290,30 +277,29 @@ /obj/item/stack/f13Cash/random/ncr money_type = /obj/item/stack/f13Cash/ncr + average_qty = AVG_BASE / CASH_NCR + average_spread = AVG_SPEAD / CASH_NCR /obj/item/stack/f13Cash/random/ncr/low - min_qty = TEMP3_MIN / CASH_NCR - max_qty = TEMP3_MAX / CASH_NCR + average_qty = 0 + average_spread = 0 /obj/item/stack/f13Cash/random/ncr/med - min_qty = TEMP_MIN / CASH_NCR - max_qty = TEMP_MAX / CASH_NCR + average_qty = 0 + average_spread = 0 /obj/item/stack/f13Cash/random/ncr/high - min_qty = TEMP2_MIN / CASH_NCR - max_qty = TEMP2_MAX / CASH_NCR + average_qty = 0 + average_spread = 0 /obj/item/stack/f13Cash/random/ncr/ncrpay_basic - min_qty = LOW_MIN / CASH_NCR - max_qty = LOW_MAX / CASH_NCR + average_mult = CASH_MULT_LOW /obj/item/stack/f13Cash/random/ncr/ncrpay_veteran - min_qty = MED_MIN / CASH_NCR - max_qty = MED_MAX / CASH_NCR + average_mult = CASH_MULT_MED /obj/item/stack/f13Cash/random/ncr/ncrpay_officer - min_qty = HIGH_MIN / CASH_NCR - max_qty = HIGH_MAX / CASH_NCR + average_mult = CASH_MULT_HIGH #undef maxCoinIcon @@ -321,17 +307,3 @@ #undef CASH_AUR #undef CASH_DEN #undef CASH_NCR -#undef LOW_MIN -#undef LOW_MAX -#undef MED_MIN -#undef MED_MAX -#undef HIGH_MIN -#undef HIGH_MAX -#undef BANKER_MIN -#undef BANKER_MAX -#undef TEMP3_MIN -#undef TEMP3_MAX -#undef TEMP_MIN -#undef TEMP_MAX -#undef TEMP2_MIN -#undef TEMP2_MAX diff --git a/fallout/obj/trash_stack.dm b/fallout/obj/trash_stack.dm index 502eda862ee..fa64a5956f5 100644 --- a/fallout/obj/trash_stack.dm +++ b/fallout/obj/trash_stack.dm @@ -38,7 +38,11 @@ //var/itemtypebonus= pickweight(lootable_trash) if(itemtype) to_chat(user, span_notice("You scavenge through [src].")) - var/atom/newthing = new itemtype(ST) + var/atom/newthing + if(ispath(itemtype, /obj/item/stack/f13Cash/random)) // SHITCODE TIME (I can't imagine any clever solution right now at 2 AM) ~Tsuru + newthing = new itemtype(ST, null, TRUE, user.get_luck_loot_amt_multiplier()) + else + newthing = new itemtype(ST) //if (prob(10+(user.special_l*3.5)))//SPECIAL Integration // to_chat(user, span_notice("You get lucky and find even more loot!")) // var/obj/item/bonusitem = new itemtypebonus(ST) @@ -113,4 +117,3 @@ for(var/i in garbage_list) for(var/ii in i) lootable_trash += ii - diff --git a/hailmary.dme b/hailmary.dme index 70bab8a3920..9d10ff0b136 100644 --- a/hailmary.dme +++ b/hailmary.dme @@ -118,6 +118,7 @@ #include "code\__DEFINES\sound.dm" #include "code\__DEFINES\spaceman_dmm.dm" #include "code\__DEFINES\span.dm" +#include "code\__DEFINES\special.dm" #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\stat_tracking.dm" #include "code\__DEFINES\statpanel.dm"