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"