From 49eab491b403e071a195467b13f736309b781134 Mon Sep 17 00:00:00 2001 From: spookydonut Date: Thu, 5 Mar 2020 20:06:33 +0800 Subject: [PATCH] Gamer skill (#49618) * gaming.dm added * initial changes * gamer god trait * finalization after testing * spellcheck + flavortext * phone gamer support * incorporates review suggestions * tiny flavor change in pwr game desc * more trait-related touchups and minor fluff * adds and removes ?s where needed Co-authored-by: spookydonut --- code/__DEFINES/skills.dm | 4 +- code/__DEFINES/traits.dm | 1 + code/datums/mind.dm | 4 +- code/datums/skills/_skill.dm | 18 ++++ code/datums/skills/gaming.dm | 15 +++ code/game/machinery/computer/arcade.dm | 94 ++++++++++++------- code/modules/food_and_drinks/drinks/drinks.dm | 2 +- .../file_system/programs/arcade.dm | 19 ++-- .../chemistry/reagents/drink_reagents.dm | 9 ++ tgstation.dme | 1 + 10 files changed, 123 insertions(+), 44 deletions(-) create mode 100644 code/datums/skills/gaming.dm diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index e61cb51ab77..c757af43b21 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -17,7 +17,9 @@ #define SKILL_EXP_LEGENDARY 2500 //Skill modifier types -#define SKILL_SPEED_MODIFIER "skill_speed_modifier" +#define SKILL_SPEED_MODIFIER "skill_speed_modifier"//ideally added/subtracted in speed calculations to make you do stuff faster +#define SKILL_PROBS_MODIFIER "skill_probability_modifier"//ideally added/subtracted where beneficial in prob(x) calls +#define SKILL_RANDS_MODIFIER "skill_randomness_modifier"//ideally added/subtracted where beneficial in rand(x,y) calls // Gets the reference for the skill type that was given diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index afda9ad877b..09584eb27e5 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -166,6 +166,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_PRIMITIVE "primitive" #define TRAIT_GUNFLIP "gunflip" #define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat" +#define TRAIT_GAMERGOD "gamer-god" //double arcade prizes //non-mob traits #define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 118b691345c..f6fc597446c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -149,9 +149,9 @@ if(silent) return if(known_skills[S] >= old_level) - to_chat(current, "I feel like I've become more proficient at [S.name]!") + S.level_gained(src, known_skills[S], old_level) else - to_chat(current, "I feel like I've become worse at [S.name]!") + S.level_lost(src, known_skills[S], old_level) ///Gets the skill's singleton and returns the result of its get_skill_modifier /datum/mind/proc/get_skill_modifier(skill, modifier) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index 52d4f3e62ad..ca38b812c11 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -5,3 +5,21 @@ /datum/skill/proc/get_skill_modifier(modifier, level) return modifiers[modifier][level+1] //+1 because lists start at 1 + +/** + * level_gained: Gives skill levelup messages to the user + * + * Only fires if the xp gain isn't silent, so only really useful for messages. + * Arguments: + * * mind - The mind that you'll want to send messages + * * new_level - The newly gained level. Can check the actual level to give different messages at different levels, see defines in skills.dm + * * old_level - Similar to the above, but the level you had before levelling up. + */ +/datum/skill/proc/level_gained(var/datum/mind/mind, new_level, old_level)//just for announcements (doesn't go off if the xp gain is silent) + to_chat(mind.current, "I feel like I've become more proficient at [name]!") + +/** + * level_lost: See level_gained, same idea but fires on skill level-down + */ +/datum/skill/proc/level_lost(var/datum/mind/mind, new_level, old_level) + to_chat(mind.current, "I feel like I've become worse at [name]!") diff --git a/code/datums/skills/gaming.dm b/code/datums/skills/gaming.dm new file mode 100644 index 00000000000..5a8e098fda0 --- /dev/null +++ b/code/datums/skills/gaming.dm @@ -0,0 +1,15 @@ +/datum/skill/gaming + name = "Gaming" + desc = "My proficiency as a gamer. This helps me beat bosses with ease, powergame in Orion Trail, and makes me wanna slam some gamer fuel." + modifiers = list(SKILL_PROBS_MODIFIER = list(0, 5, 10, 15, 15, 20, 25), + SKILL_RANDS_MODIFIER = list(0, 1, 2, 3, 4, 5, 7)) + +/datum/skill/gaming/level_gained(var/datum/mind/mind, new_level, old_level) + switch(new_level) + if(SKILL_LEVEL_JOURNEYMAN)//gives slight extra perks outside roll modifiers + to_chat(mind.current, "I'm starting to pick up the meta of these arcade games. \ + If I were to minmax the optimal strat and accentuate my playstyle around well-refined tech...") + if(SKILL_LEVEL_LEGENDARY)//leads to a mysterious power... + to_chat(mind.current, "Maybe gamerfuel actually would help me play better...") + else + to_chat(mind.current, "I'm getting better at these arcade games!") diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 846a1deaa4c..27f0354aaf9 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -77,22 +77,28 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return INITIALIZE_HINT_QDEL Reset() -/obj/machinery/computer/arcade/proc/prizevend(mob/user) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade) - if(prob(0.0001)) //1 in a million - new /obj/item/gun/energy/pulse/prize(src) - visible_message("[src] dispenses.. woah, a gun! Way past cool.", "You hear a chime and a shot.") - user.client.give_award(/datum/award/achievement/misc/pulse, user) - return +/obj/machinery/computer/arcade/proc/prizevend(mob/user, prizes = 1) + if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD)) + visible_message("[user] inputs an intense cheat code!",\ + "You hear a flurry of buttons being pressed.") + say("CODE ACTIVATED: EXTRA PRIZES.") + prizes *= 2 + for(var/i = 0, i < prizes, i++) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade) + if(prob(0.0001)) //1 in a million + new /obj/item/gun/energy/pulse/prize(src) + visible_message("[src] dispenses.. woah, a gun! Way past cool.", "You hear a chime and a shot.") + user.client.give_award(/datum/award/achievement/misc/pulse, user) + return - var/prizeselect - if(prize_override) - prizeselect = pickweight(prize_override) - else - prizeselect = pickweight(GLOB.arcade_prize_pool) - var/atom/movable/the_prize = new prizeselect(get_turf(src)) - playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) - visible_message("[src] dispenses [the_prize]!", "You hear a chime and a clunk.") + var/prizeselect + if(prize_override) + prizeselect = pickweight(prize_override) + else + prizeselect = pickweight(GLOB.arcade_prize_pool) + var/atom/movable/the_prize = new prizeselect(get_turf(src)) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + visible_message("[src] dispenses [the_prize]!", "You hear a chime and a clunk.") /obj/machinery/computer/arcade/emp_act(severity) . = ..() @@ -206,9 +212,11 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return if (!blocked && !gameover) + var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming) + var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) if (href_list["attack"]) blocked = TRUE - var/attackamt = rand(2,6) + var/attackamt = rand(2,6) + rand(0, gamerSkill) var/weapon = pick(weapons) temp = "You attack with a [weapon] for [attackamt] damage!" playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -222,8 +230,11 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( else if (href_list["heal"]) blocked = TRUE - var/pointamt = rand(1,3) - var/healamt = rand(6,8) + var/maxPointCost = 3 + if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN) + maxPointCost = 2 + var/pointamt = rand(1, maxPointCost) + var/healamt = rand(6,8) + rand(0, gamerSkill) temp = "You use [pointamt] magic to heal for [healamt] damage!" playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10) updateUsrDialog() @@ -238,7 +249,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( else if (href_list["charge"]) blocked = TRUE - var/chargeamt = rand(4,7) + var/chargeamt = rand(4,7) + rand(0, gamerSkill) temp = "You regain [chargeamt] points." playsound(loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10) player_mp += chargeamt @@ -271,6 +282,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return /obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user) + var/xp_gained = 0 if ((enemy_mp <= 0) || (enemy_hp <= 0)) if(!gameover) gameover = TRUE @@ -284,8 +296,10 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.") Reset() obj_flags &= ~EMAGGED + xp_gained += 100 else prizevend(user) + xp_gained += 50 SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal"))) @@ -327,10 +341,12 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( gameover = TRUE temp = "You have been crushed! GAME OVER" playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10) + xp_gained += 10//pity points if(obj_flags & EMAGGED) usr.gib() SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal"))) + user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP blocked = FALSE return @@ -512,6 +528,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( gamers[gamer] = -1 gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation + gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better if(!isnull(GLOB.data_core.general)) for(var/datum/data/record/R in GLOB.data_core.general) @@ -553,6 +570,8 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( desc = "Learn how our ancestors got to Orion, and have fun in the process!" dat += "

May They Rest In Peace

" + user?.mind?.adjust_experience(/datum/skill/gaming, 10)//learning from your mistakes is the first rule of roguelikes + else if(event) dat = eventdat else if(gameStatus == ORION_STATUS_NORMAL) @@ -592,20 +611,25 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return busy = TRUE + var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming) + var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_PROBS_MODIFIER) + var/gamerSkillRands = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) + var/xp_gained = 0 if (href_list["continue"]) //Continue your travels if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7) if(turns >= ORION_TRAIL_WINTURN) win(usr) + xp_gained += 34 else food -= (alive+lings_aboard)*2 fuel -= 5 - if(turns == 2 && prob(30)) + if(turns == 2 && prob(30-gamerSkill)) event = ORION_TRAIL_COLLISION event() - else if(prob(75)) + else if(prob(75-gamerSkill)) event = pickweight(events) if(lings_aboard) - if(event == ORION_TRAIL_LING || prob(55)) + if(event == ORION_TRAIL_LING || prob(55-gamerSkill)) event = ORION_TRAIL_LING_ATTACK event() turns += 1 @@ -613,7 +637,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( var/mob/living/carbon/M = usr //for some vars switch(event) if(ORION_TRAIL_RAIDERS) - if(prob(50)) + if(prob(50-gamerSkill)) to_chat(usr, "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?") M.hallucination += 30 else @@ -621,7 +645,10 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( M.take_bodypart_damage(30) playsound(loc, 'sound/weapons/genhit2.ogg', 100, TRUE) if(ORION_TRAIL_ILLNESS) - var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS + var/maxSeverity = 3 + if(gamerSkillLevel >= SKILL_LEVEL_EXPERT) + maxSeverity = 2 //part of gitting gud is rng mitigation + var/severity = rand(1,maxSeverity) //pray to RNGesus. PRAY, PIGS if(severity == 1) to_chat(M, "You suddenly feel slightly nauseated." ) if(severity == 2) @@ -633,7 +660,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( sleep(30) M.vomit(10, distance = 5) if(ORION_TRAIL_FLUX) - if(prob(75)) + if(prob(75-gamerSkill)) M.Paralyze(60) say("A sudden gust of powerful wind slams [M] into the floor!") M.take_bodypart_damage(25) @@ -641,7 +668,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( else to_chat(M, "A violent gale blows past you, and you barely manage to stay standing!") if(ORION_TRAIL_COLLISION) //by far the most damaging event - if(prob(90)) + if(prob(90-gamerSkill)) playsound(loc, 'sound/effects/bang.ogg', 100, TRUE) var/turf/open/floor/F for(F in orange(1, src)) @@ -724,7 +751,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( event = null else if(href_list["blackhole"]) //keep speed past a black hole if(turns == 7) - if(prob(75)) + if(prob(75-gamerSkill)) event = ORION_TRAIL_BLACKHOLE event() if(obj_flags & EMAGGED) @@ -805,15 +832,16 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( else if(href_list["raid_spaceport"]) if(gameStatus == ORION_STATUS_MARKET) if(!spaceport_raided) - var/success = min(15 * alive,100) //default crew (4) have a 60% chance + var/success = min(15 * alive + gamerSkill,100) //default crew (4) have a 60% chance spaceport_raided = 1 var/FU = 0 var/FO = 0 if(prob(success)) - FU = rand(5,15) - FO = rand(5,15) + FU = rand(5 + gamerSkillRands,15 + gamerSkillRands) + FO = rand(5 + gamerSkillRands,15 + gamerSkillRands) last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)" + xp_gained += 10 else FU = rand(-5,-15) FO = rand(-5,-15) @@ -872,7 +900,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( add_fingerprint(usr) updateUsrDialog() busy = FALSE - return + usr?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1) /obj/machinery/computer/arcade/orion_trail/proc/event() @@ -1273,9 +1301,9 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand) chopchop.dismember() qdel(chopchop) + user.mind?.adjust_experience(/datum/skill/gaming, 100) playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10) - for(var/i=1; i<=rand(3,5); i++) - prizevend(user) + prizevend(user, rand(3,5)) else to_chat(c_user, "You (wisely) decide against putting your hand in the machine.") diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 5f331e5df74..520115b1f03 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -704,7 +704,7 @@ /obj/item/reagent_containers/food/drinks/soda_cans/pwr_game name = "Pwr Game" - desc = "The only drink with the PWR that true gamers crave." + desc = "The only drink with the PWR that true gamers crave. When a gamer talks about gamerfuel, this is what they're literally referring to." icon_state = "purple_can" list_reagents = list(/datum/reagent/consumable/pwr_game = 30) diff --git a/code/modules/modular_computers/file_system/programs/arcade.dm b/code/modules/modular_computers/file_system/programs/arcade.dm index 17db77381a2..ca19c80a9f2 100644 --- a/code/modules/modular_computers/file_system/programs/arcade.dm +++ b/code/modules/modular_computers/file_system/programs/arcade.dm @@ -27,6 +27,7 @@ /datum/computer_file/program/arcade/proc/game_check(mob/user) sleep(5) + user?.mind?.adjust_experience(/datum/skill/gaming, 1) if(boss_hp <= 0) heads_up = "You have crushed [boss_name]! Rejoice!" playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -35,8 +36,8 @@ if(istype(computer)) computer.update_icon() ticket_count += 1 + user?.mind?.adjust_experience(/datum/skill/gaming, 50) sleep(10) - return else if(player_hp <= 0 || player_mp <= 0) heads_up = "You have been defeated... how will the station survive?" playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -44,9 +45,8 @@ program_icon_state = "arcade_off" if(istype(computer)) computer.update_icon() + user?.mind?.adjust_experience(/datum/skill/gaming, 10) sleep(10) - return - return /datum/computer_file/program/arcade/proc/enemy_check(mob/user) var/boss_attackamt = 0 //Spam protection from boss attacks as well. @@ -101,11 +101,13 @@ if(computer) printer = computer.all_components[MC_PRINT] + var/gamerSkillLevel = user.mind?.get_skill_level(/datum/skill/gaming) + var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) switch(action) if("Attack") var/attackamt = 0 //Spam prevention. if(pause_state == FALSE) - attackamt = rand(2,6) + attackamt = rand(2,6) + rand(0, gamerSkill) pause_state = TRUE heads_up = "You attack for [attackamt] damage." playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -118,8 +120,11 @@ var/healamt = 0 //More Spam Prevention. var/healcost = 0 if(pause_state == FALSE) - healamt = rand(6,8) - healcost = rand(1,3) + healamt = rand(6,8) + rand(0, gamerSkill) + var/maxPointCost = 3 + if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN) + maxPointCost = 2 + healcost = rand(1, maxPointCost) pause_state = TRUE heads_up = "You heal for [healamt] damage." playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -132,7 +137,7 @@ if("Recharge_Power") var/rechargeamt = 0 //As above. if(pause_state == FALSE) - rechargeamt = rand(4,7) + rechargeamt = rand(4,7) + rand(0, gamerSkill) pause_state = TRUE heads_up = "You regain [rechargeamt] magic power." playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 55d0c5c207a..5754b2f7c5a 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -487,8 +487,17 @@ glass_name = "glass of Pwr Game" glass_desc = "Goes well with a Vlad's salad." +/datum/reagent/consumable/pwr_game/reaction_mob(mob/living/C, method=TOUCH, reac_volume) + ..() + if(C?.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && method==INGEST && !HAS_TRAIT(C, TRAIT_GAMERGOD)) + ADD_TRAIT(C, TRAIT_GAMERGOD, "pwr_game") + to_chat(C, "As you imbibe the Pwr Game, your gamer third eye opens... \ + You feel as though a great secret of the universe has been made known to you...") + /datum/reagent/consumable/pwr_game/on_mob_life(mob/living/carbon/M) M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, M.get_body_temp_normal()) + if(prob(10)) + M?.mind.adjust_experience(/datum/skill/gaming, 5) ..() /datum/reagent/consumable/shamblers diff --git a/tgstation.dme b/tgstation.dme index 394c10cbc08..241f3be62b4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -592,6 +592,7 @@ #include "code\datums\ruins\space.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\cleaning.dm" +#include "code\datums\skills\gaming.dm" #include "code\datums\skills\medical.dm" #include "code\datums\skills\mining.dm" #include "code\datums\status_effects\buffs.dm"