diff --git a/Amnesia.dll b/Amnesia.dll index c14454d..13f683e 100644 Binary files a/Amnesia.dll and b/Amnesia.dll differ diff --git a/CHANGELOG.md b/CHANGELOG.md index 35d0622..d3b6788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.0] - 2023-01-03 + +- add fragile memory state +- add retroactive refund for hardened memory +- disable near death trauma/xp debt for mem loss +- remove client-side-only respawn window info +- remove non-time text from buffs for cleanliness +- remove references to lives in positive outlook +- update journal entry to reflect new flow +- update memory boosters to cure fragile memory +- update memory loss to start at ltm level +- update to add fragile memory on death +- update to lose memory if fragile on death + ## [1.0.0] - 2022-12-23 - add admin configurable xp boosts for zombie kills diff --git a/Config/Localization.txt b/Config/Localization.txt index 670e807..acaf17b 100644 --- a/Config/Localization.txt +++ b/Config/Localization.txt @@ -1,27 +1,29 @@ Key,File,Type,english -amnesiaJournalTip,Journal Tip,,"Survivors are reporting strange occurrences of Amnesia when experiencing severe trauma...\n\n[ff8000]Becoming incapacitated after level[-] [007fff]{cvar(amnesiaLongTermMemoryLevel)}[-] will result in [ff8000]Memory Loss[-], causing you to forget certain experiences on this server.\n\n[007fff]What Can Cause Memory Loss?[-]\nDying will trigger memory loss, but there are a few exceptions. You will [00ff80]NOT[-] lose memory if:\n- [00ff80]another player kills you[-]\n- [00ff80]you die during Blood Moon for any reason[-]\n\n[ff007f]What Will I Forget?[-]\nYou will forget your level, learned skills, and unspent skill points (you'll be reset back to level [007fff]{cvar(amnesiaLongTermMemoryLevel)}[-] and can reallocate all skillpoints).\n\n[00ff80]What Will I Remember?[-]\nYou will not forget schematics, books, items/equipment (backpack is dropped on ground, but not deleted), vehicles, map, waypoints, land claims, bedroll location, quests, trader relationships.\n\n[007fff]How Can I Protect My Memory?[-]\nAll traders sell a new item called [007fff]Trader Jen's Memory Booster[-] in limited quantities, which you can use to protect your memory against the next time you experience severe trauma. This item is quite expensive, so you probably won't be able to afford it right away.\n\n[007fff]Anything Else?[-]\nYes; defeating certain powerful zombies will lift your spirits, providing a timed boost of double xp for you and everyone else on the server! Try to take these challenging enemies down for the benefit and relief of the entire community." +amnesiaJournalTip,Journal Tip,,"Survivors are reporting strange occurrences of Amnesia when experiencing severe trauma... At level [007fff]{cvar(amnesiaLongTermMemoryLevel)}[-] and beyond, becoming incapacitated will result in a [ff8000]Fragile Memory[-]. This [ff8000]Fragile Memory[-] will cause full-blown [ff007f]Memory Loss[-] if you were to become incapacitated once more.\n\n[ff8000]This Happens Every Time I Die?[-]\nDying will impact memory, but there are a few exceptions: if [00ff80]another player kills you[-], or if [00ff80]you die during Blood Moon for any reason[-].\n\n[ff8000]What Would I Forget Due to Memory Loss?[-]\nYou will forget your level, learned skills, and unspent skill points (you'll be reset back to level [007fff]{cvar(amnesiaLongTermMemoryLevel)}[-] and can reallocate the skillpoints you would've had at that level).\n\n[ff8000]Will I Remember Anything After Memory Loss?[-]\nYou will never forget schematics, books, items/equipment (backpack is dropped on ground, but not deleted), vehicles, map, waypoints, land claims, bedroll location, quests, trader relationships.\n\n[ff8000]How Can I Recover From a Fragile Memory?[-]\nYou'll find that all traders sell a new item called [007fff]Trader Jen's Memory Boosters[-] in limited quantities, which you can use to recover from a [ff8000]Fragile Memory[-]. This will give you a buffer against memory loss, but the sale price is also quite high; you probably won't be able to afford it right away.\n\n[ff8000]Anything Else I Should Know?[-]\nDefeating certain powerful zombies will lift your spirits, providing a timed boost of double xp for you and everyone else on the server! Try to take these challenging enemies down for the benefit and relief of the entire community." amnesiaJournalTip_title,Journal Tip,,"Amnesia [ff8000][MOD]" -amnesiaRespawnMessage,UI,Respawn Window,"This server runs the Amnesia mod.\nAfter reaching a certain level, [ff8000]dying will cause memory loss[-]!\nUse [007fff]Trader Jen's Memory Booster[-] to harden your memory against traumatic situations like this.\nTo learn more about Amnesia, [ff8000]take a look at your Journal[-]." +buffAmnesiaFragileMemoryName,buffs,Buffs,"Fragile Memory" +buffAmnesiaFragileMemoryDesc,buffs,Buffs,"You now have a [ff8000]Fragile Memory[-] due to being incapacitated. \n\nIf you become incapacitated again, you will experience [ff007f]Memory Loss[-].\n\n[007fff]Trader Jen's Memory Boosters[-] can be purchased from any trader to cure your [ff8000]Fragile Memory[-], which will provide a buffer against [ff007f]Memory Loss[-]." +buffAmnesiaFragileMemoryStartTooltip,buffs,Buffs,"You now have a [ff8000]Fragile Memory[-] due to being incapacitated" +buffAmnesiaFragileMemoryRemoveTooltip,buffs,Buffs,"You no longer have a [ff8000]Fragile Memory[-], thanks to [007fff]Trader Jen's Memory Boosters[-]" -buffAmnesiaHardenedMemoryName,buffs,Buffs,"Hardened Memory" -buffAmnesiaHardenedMemoryDesc,buffs,Buffs,"Your Memory is currently reinforced and able to withstand 1 episode of extreme trauma." -buffAmnesiaHardenedMemoryTooltipAdd,buffs,Buffs,"Memory Hardened: You will withstand your next episode of extreme trauma!" -buffAmnesiaHardenedMemoryTooltipRemove,buffs,Buffs,"Memory Loss Prevented! Boost again to protect against future trauma." +buffAmnesiaHardenedMemoryRemoveTooltip,buffs,Buffs,"[007fff]Memory Boosters[-] you previously used [00ff80]are being given back to you[-]; see Amnesia entry in [ff8000]Journal[-] for more info." buffAmnesiaMemoryLossName,buffs,Buffs,"Memory Loss" -buffAmnesiaMemoryLossDesc,buffs,Buffs,"You feel a sense that mistakes were made, but perhaps can find a more effective method of survival this time around." -buffAmnesiaMemoryLossTooltip,buffs,Buffs,"Memory Loss: Extreme Trauma has caused memory loss. You barely recall who you once were..." +buffAmnesiaMemoryLossDesc,buffs,Buffs,"You feel a sense that mistakes were made, but perhaps can find a more effective method of survival this time around.\n\n[007fff]Trader Jen's Memory Boosters[-] can be purchased from any trader to cure your [ff8000]Fragile Memory[-], which will provide a buffer against [ff007f]Memory Loss[-]." +buffAmnesiaMemoryLossTooltip,buffs,Buffs,"You experienced [ff007f]Memory Loss[-] due to being incapacitated" buffAmnesiaPositiveOutlookName,buffs,Buffs,"Positive Outlook" buffAmnesiaPositiveOutlookDesc,buffs,Buffs,"You're feeling especially positive about your situation and the future.\n\nSure, the world has gone to hell, but that doesn't mean your attitude needs to!\n\n[00FF00]XP Gain is Doubled!" buffAmnesiaPositiveOutlookTooltip,buffs,Buffs,"Positive Outlook: [00FF00]XP Gain Doubled!" buffAmnesiaBloodmoonLifeProtectionName,buffs,Buffs,"Blood Moon Life Protection" -buffAmnesiaBloodmoonLifeProtectionDesc,buffs,Buffs,"You feel something in the air that seems to provide you with a sense of peace and clarity of thought... perhaps this is the same 'something' causing the zombies to go wild.\n\n[00ff80]You WILL NOT lose any lives if you die during this event[-].\n\n... but still, try to play it safe." -buffAmnesiaBloodmoonLifeProtectionTooltip,buffs,Buffs,"You [00ff80]WILL NOT[-] lose any lives during this event when/if you die" -buffAmnesiaBloodmoonLifeProtectionEndTooltip,buffs,Buffs,"Blood Moon Protection [ff007f]HAS ENDED[-] - dying will result in lives lost again" +buffAmnesiaBloodmoonLifeProtectionDesc,buffs,Buffs,"You feel something in the air that seems to provide you with a sense of peace and clarity of thought... perhaps this is the same 'something' causing the zombies to go wild.\n\n[00ff80]You [00ff80]CANNOT[-] lose memory during or otherwise experience harm to your memory if you die during this event[-].\n\n... but still, try to play it safe." +buffAmnesiaBloodmoonLifeProtectionTooltip,buffs,Buffs,"You [00ff80]CANNOT[-] lose memory if you die during this event" +buffAmnesiaBloodmoonLifeProtectionEndTooltip,buffs,Buffs,"Blood Moon Memory Protection [ff007f]HAS ENDED[-]" -drugAmnesiaMemoryBooster,items,Medical,"Trader Jen's Memory Booster" -drugAmnesiaMemoryBoosterDesc,items,Medical,"Ingesting this special drug/vitamin cocktail will prevent the loss of memory typically caused by severe trauma.\n\nTo use this medicine:\n1. [007fff]you must exceed level {cvar(amnesiaLongTermMemoryLevel:0)}[-]\n2. [007fff]you must not already have a Hardened Memory[-]\n\n[ff8000]Don't Forget, Get BOOSTED![-]\n - Trader Jen's Experimental Pharmaceuticals" +drugAmnesiaMemoryBoosters,items,Medical,"Trader Jen's Memory Boosters" +drugAmnesiaMemoryBoostersDesc,items,Medical,"Ingesting this special drug/vitamin cocktail loaded with omega-3 fatty acids will stabilize a [ff8000]Fragile Memory[-].\n\n[007fff]Don't Forget, Get BOOSTED![-]\n - Trader Jen's Experimental Pharmaceuticals" + +statStopsFragileMemory,ui_display,Item stat,"Cure Fragile Memory" \ No newline at end of file diff --git a/Config/XUi_Menu/windows.xml b/Config/XUi_Menu/windows.xml deleted file mode 100644 index 2176a56..0000000 --- a/Config/XUi_Menu/windows.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Config/buffs.xml b/Config/buffs.xml index 147553e..4aa1e7d 100644 --- a/Config/buffs.xml +++ b/Config/buffs.xml @@ -5,29 +5,43 @@ + @amnesiaLongTermMemoryLevel @amnesiaLongTermMemoryLevel - + + + + - - - + + + - - - + + + + + + + @@ -37,6 +51,7 @@ + @@ -54,9 +69,8 @@ - - + @@ -67,6 +81,7 @@ + diff --git a/Config/items.xml b/Config/items.xml index 2fb6357..20f6401 100644 --- a/Config/items.xml +++ b/Config/items.xml @@ -1,9 +1,10 @@  - + - + + @@ -24,12 +25,12 @@ - - + - + + diff --git a/Config/traders.xml b/Config/traders.xml index d1461ac..7f0827b 100644 --- a/Config/traders.xml +++ b/Config/traders.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/Config/ui_display.xml b/Config/ui_display.xml new file mode 100644 index 0000000..dff76b3 --- /dev/null +++ b/Config/ui_display.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ModInfo.xml b/ModInfo.xml index fd90d4d..b16d974 100644 --- a/ModInfo.xml +++ b/ModInfo.xml @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index aa4c4e5..8624d20 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ - [Amnesia](#amnesia) - [Summary](#summary) + - [Flow](#flow) - [Admin Configuration](#admin-configuration) - [Experimental/Volatile Options](#experimentalvolatile-options) - [File Example](#file-example) @@ -19,13 +20,31 @@ As you may have guessed, this mod adds a Roguelike element to 7 Days to Die in a > :mag: This mod *only* runs on a dedicated server which you can technically run locally and will need to connect to. If you're only looking for a client-side/single-player experience, consider [Mostly Dead](https://7daystodiemods.com/mostly-dead/) by [Khzmusik](https://7daystodiemods.com/tag/khzmusik/). -Each time a player dies (after a configurable level), that player's "Memory" will be reset in various, configurable ways (see [Admin Configuration](#admin-configuration)). Memory can be hardened with the help of `Trader Jen's Memory Booster` (non-craftable, but often purchasable from traders for a very high price... i.e. it will require effort to save up for). +After reaching an admin-configurable level (which defaults to 1), a player will receive the debuff `Fragile Memory` upon death, along with `Near Death Trauma` and an XP Debt to work off. -The Goal: improve long-term engagement for various kinds of players and take a step toward 'evergreen' servers by reducing how often map wipes need to occur. +Dying with the `Fragile Memory` debuff will cause a player to **Lose Memory**, resulting in *no* XP Debt or the `Near Death Trauma` debuff, but will trigger a series of admin-configurable changes to the player: levels being reset, forgetting books/schematics, even forgetting kill stats for pvp, death, and zombies. More details on settings and defaults are listed in the [Admin Configuration](#admin-configuration) section. -The Effect: support a heavier risk/reward play style meant to be a balance for servers with a higher XP boost. Fast player growth with the risk of dynamic, configurable player reset. +Players can recover from `Fragile Memory` with the help of `Trader Jen's Memory Booster`: a non-craftable item that all traders sell for a very high price... so it will require effort to save up for. -> 💭 Regular xp growth can be used as well for a more hardcore experience. This is definitely something worth discussing with your community if you want to try to keep the server engaging for all players past 3-4 months (your mileage may vary) +The Primary Goal is to improve long-term engagement by introducing a *far* heavier risk/reward play style that should mix well with a post-apocalyptic survival experience. + +The Secondary Goal is to take a meaningful step toward 'evergreen' servers by reducing how often map wipes need to occur due to total exhaustion of all challenge to the players (i.e. when most players have reached max level and no longer feel they have anything exciting to work towards). While it is the case that other reasons for wiping a map may be unavoidable, Amnesia is meant to help with player engagement/boredom/challenge/etc. + +> 💭 Higher XP growth is recommended; possibly 2x or 3x. Regular xp growth can be used, but may be very challenging. This is definitely something worth discussing with your community if you want to try to keep the server engaging for all players past 3-4 months (your mileage may vary). + +## Flow + +```mermaid +flowchart LR + alive[[Alive]]-->incap[[Incapacitated]] + incap-->|not fragile|fragile[[Fragile Memory]] + incap-->|fragile|amnesia[Lose Memory, Reset to Level 50] + + amnesia-->fragile + fragile-->incap + + fragile-->|use memory booster|alive +``` ## Admin Configuration diff --git a/src/Commands/ConsoleCmdAmnesia.cs b/src/Commands/ConsoleCmdAmnesia.cs index 5ec11d4..ada7fe8 100644 --- a/src/Commands/ConsoleCmdAmnesia.cs +++ b/src/Commands/ConsoleCmdAmnesia.cs @@ -79,7 +79,7 @@ private void HandleShowPlayers() { SdtdConsole.Instance.Output("No players are currently online."); } foreach (var player in players) { - SdtdConsole.Instance.Output($"{player.entityId}. {Values.HardenedMemoryBuff}: {player.Buffs.HasBuff(Values.HardenedMemoryBuff)}, {Values.PositiveOutlookRemTimeCVar}: {player.GetCVar(Values.PositiveOutlookRemTimeCVar)} ({player.GetDebugName()})"); + SdtdConsole.Instance.Output($"{player.entityId}. {Values.BuffHardenedMemory}: {player.Buffs.HasBuff(Values.BuffHardenedMemory)}, {Values.CVarPositiveOutlookRemTime}: {player.GetCVar(Values.CVarPositiveOutlookRemTime)} ({player.GetDebugName()})"); } } @@ -122,7 +122,7 @@ private void RouteListRequest(List @params) { SdtdConsole.Instance.Output($"Unable to parse command value; expecting 'add', 'rem', or 'clear'.\n{string.Join(", ", @params)}"); return; } - if (Values.PositiveOutlookTimeOnKillName.EqualsCaseInsensitive(@params[1])) { + if (Values.NamePositiveOutlookTimeOnKill.EqualsCaseInsensitive(@params[1])) { UpdatePositiveOutlookOnKill(@params); return; } @@ -163,7 +163,7 @@ private void UpdatePositiveOutlookOnKill(List @params) { } return; } - SdtdConsole.Instance.Output($"Invald request; run '{Commands[0]} set {Values.PositiveOutlookTimeOnKillName}' to see a list of options."); + SdtdConsole.Instance.Output($"Invald request; run '{Commands[0]} set {Values.NamePositiveOutlookTimeOnKill}' to see a list of options."); return; } @@ -172,55 +172,55 @@ private void RouteSetRequest(List @params) { SdtdConsole.Instance.Output(Values.SingleValueFieldNamesAndDescriptions); return; } - if (Values.LongTermMemoryLevelName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameLongTermMemoryLevel.EqualsCaseInsensitive(@params[1])) { UpdateLongTermMemoryLevel(@params); return; } - if (Values.PositiveOutlookMaxTimeName.EqualsCaseInsensitive(@params[1])) { + if (Values.NamePositiveOutlookMaxTime.EqualsCaseInsensitive(@params[1])) { UpdatePositiveOutlookMaxTime(@params); return; } - if (Values.PositiveOutlookTimeOnFirstJoinName.EqualsCaseInsensitive(@params[1])) { + if (Values.NamePositiveOutlookTimeOnFirstJoin.EqualsCaseInsensitive(@params[1])) { UpdatePositiveOutlookTimeOnFirstJoin(@params); return; } - if (Values.PositiveOutlookTimeOnMemoryLossName.EqualsCaseInsensitive(@params[1])) { + if (Values.NamePositiveOutlookTimeOnMemoryLoss.EqualsCaseInsensitive(@params[1])) { UpdatePositiveOutlookTimeOnMemoryLoss(@params); return; } - if (Values.ProtectMemoryDuringBloodmoonName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameProtectMemoryDuringBloodmoon.EqualsCaseInsensitive(@params[1])) { UpdateProtectMemoryDuringBloodmoon(@params); return; } - if (Values.ProtectMemoryDuringPvpName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameProtectMemoryDuringPvp.EqualsCaseInsensitive(@params[1])) { UpdateProtectMemoryDuringPvp(@params); return; } - if (Values.ForgetLevelsAndSkillsName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetLevelsAndSkills.EqualsCaseInsensitive(@params[1])) { UpdateForgetLevelsAndSkills(@params); return; } - if (Values.ForgetBooksName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetBooks.EqualsCaseInsensitive(@params[1])) { UpdateForgetBooks(@params); return; } - if (Values.ForgetSchematicsName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetSchematics.EqualsCaseInsensitive(@params[1])) { UpdateForgetSchematics(@params); return; } - if (Values.ForgetKdrName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetKdr.EqualsCaseInsensitive(@params[1])) { UpdateForgetKdr(@params); return; } - if (Values.ForgetActiveQuestsName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetActiveQuests.EqualsCaseInsensitive(@params[1])) { UpdateForgetActiveQuests(@params); return; } - if (Values.ForgetInactiveQuestsName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetInactiveQuests.EqualsCaseInsensitive(@params[1])) { UpdateForgetInactiveQuests(@params); return; } - if (Values.ForgetIntroQuestsName.EqualsCaseInsensitive(@params[1])) { + if (Values.NameForgetIntroQuests.EqualsCaseInsensitive(@params[1])) { UpdateForgetIntroQuests(@params); return; } @@ -229,8 +229,8 @@ private void RouteSetRequest(List @params) { private void UpdateLongTermMemoryLevel(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.LongTermMemoryLevelName]} -{Commands[0]} set {Values.LongTermMemoryLevelName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameLongTermMemoryLevel]} +{Commands[0]} set {Values.NameLongTermMemoryLevel} "); return; } if (!int.TryParse(@params[2], out var value)) { @@ -242,8 +242,8 @@ private void UpdateLongTermMemoryLevel(List @params) { private void UpdatePositiveOutlookMaxTime(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.PositiveOutlookMaxTimeName]} -{Commands[0]} set {Values.PositiveOutlookMaxTimeName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NamePositiveOutlookMaxTime]} +{Commands[0]} set {Values.NamePositiveOutlookMaxTime} "); return; } if (!int.TryParse(@params[2], out var value)) { @@ -255,8 +255,8 @@ private void UpdatePositiveOutlookMaxTime(List @params) { private void UpdatePositiveOutlookTimeOnFirstJoin(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.PositiveOutlookTimeOnFirstJoinName]} -{Commands[0]} set {Values.PositiveOutlookTimeOnFirstJoinName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NamePositiveOutlookTimeOnFirstJoin]} +{Commands[0]} set {Values.NamePositiveOutlookTimeOnFirstJoin} "); return; } if (!int.TryParse(@params[2], out var value)) { @@ -268,8 +268,8 @@ private void UpdatePositiveOutlookTimeOnFirstJoin(List @params) { private void UpdatePositiveOutlookTimeOnMemoryLoss(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.PositiveOutlookTimeOnMemoryLossName]} -{Commands[0]} set {Values.PositiveOutlookTimeOnMemoryLossName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NamePositiveOutlookTimeOnMemoryLoss]} +{Commands[0]} set {Values.NamePositiveOutlookTimeOnMemoryLoss} "); return; } if (!int.TryParse(@params[2], out var value)) { @@ -281,8 +281,8 @@ private void UpdatePositiveOutlookTimeOnMemoryLoss(List @params) { private void UpdateProtectMemoryDuringBloodmoon(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ProtectMemoryDuringBloodmoonName]} -{Commands[0]} set {Values.ProtectMemoryDuringBloodmoonName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameProtectMemoryDuringBloodmoon]} +{Commands[0]} set {Values.NameProtectMemoryDuringBloodmoon} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -294,8 +294,8 @@ private void UpdateProtectMemoryDuringBloodmoon(List @params) { private void UpdateProtectMemoryDuringPvp(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ProtectMemoryDuringPvpName]} -{Commands[0]} set {Values.ProtectMemoryDuringPvpName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameProtectMemoryDuringPvp]} +{Commands[0]} set {Values.NameProtectMemoryDuringPvp} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -307,8 +307,8 @@ private void UpdateProtectMemoryDuringPvp(List @params) { private void UpdateForgetLevelsAndSkills(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetLevelsAndSkillsName]} -{Commands[0]} set {Values.ForgetLevelsAndSkillsName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetLevelsAndSkills]} +{Commands[0]} set {Values.NameForgetLevelsAndSkills} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -320,8 +320,8 @@ private void UpdateForgetLevelsAndSkills(List @params) { private void UpdateForgetBooks(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetBooksName]} -{Commands[0]} set {Values.ForgetBooksName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetBooks]} +{Commands[0]} set {Values.NameForgetBooks} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -333,8 +333,8 @@ private void UpdateForgetBooks(List @params) { private void UpdateForgetSchematics(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetSchematicsName]} -{Commands[0]} set {Values.ForgetSchematicsName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetSchematics]} +{Commands[0]} set {Values.NameForgetSchematics} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -346,8 +346,8 @@ private void UpdateForgetSchematics(List @params) { private void UpdateForgetKdr(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetKdrName]} -{Commands[0]} set {Values.ForgetKdrName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetKdr]} +{Commands[0]} set {Values.NameForgetKdr} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -359,8 +359,8 @@ private void UpdateForgetKdr(List @params) { private void UpdateForgetActiveQuests(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetActiveQuestsName]} -{Commands[0]} set {Values.ForgetActiveQuestsName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetActiveQuests]} +{Commands[0]} set {Values.NameForgetActiveQuests} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -372,8 +372,8 @@ private void UpdateForgetActiveQuests(List @params) { private void UpdateForgetInactiveQuests(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetInactiveQuestsName]} -{Commands[0]} set {Values.ForgetInactiveQuestsName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetInactiveQuests]} +{Commands[0]} set {Values.NameForgetInactiveQuests} "); return; } if (!bool.TryParse(@params[2], out var value)) { @@ -385,8 +385,8 @@ private void UpdateForgetInactiveQuests(List @params) { private void UpdateForgetIntroQuests(List @params) { if (@params.Count == 2) { - SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.ForgetIntroQuestsName]} -{Commands[0]} set {Values.ForgetInactiveQuestsName} "); + SdtdConsole.Instance.Output($@"{Values.SingleValueNamesAndDescriptionsDict[Values.NameForgetIntroQuests]} +{Commands[0]} set {Values.NameForgetInactiveQuests} "); return; } if (!bool.TryParse(@params[2], out var value)) { diff --git a/src/Data/Config.cs b/src/Data/Config.cs index 15eefdd..09411a3 100644 --- a/src/Data/Config.cs +++ b/src/Data/Config.cs @@ -30,13 +30,9 @@ public struct TimeOnKill { public string caption; public int value; - public override string ToString() { - return ToString("name", "caption", "value"); - } + public override string ToString() => ToString("name", "caption", "value"); - public string ToString(string nameDisplay, string captionDisplay, string valueDisplay, bool hideName = false) { - return $"{{ {(hideName ? "" : nameDisplay + ": " + name + ", ")}{captionDisplay}: {caption}, {valueDisplay}: {value} }}"; - } + public string ToString(string nameDisplay, string captionDisplay, string valueDisplay, bool hideName = false) => $"{{ {(hideName ? "" : nameDisplay + ": " + name + ", ")}{captionDisplay}: {caption}, {valueDisplay}: {value} }}"; }; /// Whether to prevent memory loss during blood moon. @@ -61,26 +57,26 @@ public string ToString(string nameDisplay, string captionDisplay, string valueDi public static bool ForgetIntroQuests { get; private set; } = false; public static string PrintPositiveOutlookTimeOnMemoryLoss() => PositiveOutlookTimeOnKill.Count == 0 ? "None" : "[\n " + string.Join(",\n ", PositiveOutlookTimeOnKill.Select(kvp => kvp.Value.ToString("entityName", "displayName", "bonusTimeInSeconds")).ToArray()) + "\n]"; - public static string AsString() => $@"=== Amnesia Configuration === -{Values.LongTermMemoryLevelName}: {LongTermMemoryLevel} + public static string AsString() => $@"=== Amnesia Configuration === +{Values.NameLongTermMemoryLevel}: {LongTermMemoryLevel} -{Values.PositiveOutlookMaxTimeName}: {PositiveOutlookMaxTime} -{Values.PositiveOutlookTimeOnFirstJoinName}: {PositiveOutlookTimeOnFirstJoin} -{Values.PositiveOutlookTimeOnMemoryLossName}: {PositiveOutlookTimeOnMemoryLoss} -{Values.PositiveOutlookTimeOnKillName}: {PrintPositiveOutlookTimeOnMemoryLoss()} +{Values.NamePositiveOutlookMaxTime}: {PositiveOutlookMaxTime} +{Values.NamePositiveOutlookTimeOnFirstJoin}: {PositiveOutlookTimeOnFirstJoin} +{Values.NamePositiveOutlookTimeOnMemoryLoss}: {PositiveOutlookTimeOnMemoryLoss} +{Values.NamePositiveOutlookTimeOnKill}: {PrintPositiveOutlookTimeOnMemoryLoss()} -{Values.ProtectMemoryDuringBloodmoonName}: {ProtectMemoryDuringBloodmoon} -{Values.ProtectMemoryDuringPvpName}: {ProtectMemoryDuringPvp} +{Values.NameProtectMemoryDuringBloodmoon}: {ProtectMemoryDuringBloodmoon} +{Values.NameProtectMemoryDuringPvp}: {ProtectMemoryDuringPvp} -{Values.ForgetLevelsAndSkillsName}: {ForgetLevelsAndSkills} -{Values.ForgetBooksName}: {ForgetBooks} -{Values.ForgetSchematicsName}: {ForgetSchematics} -{Values.ForgetKdrName}: {ForgetKdr} +{Values.NameForgetLevelsAndSkills}: {ForgetLevelsAndSkills} +{Values.NameForgetBooks}: {ForgetBooks} +{Values.NameForgetSchematics}: {ForgetSchematics} +{Values.NameForgetKdr}: {ForgetKdr} == Experimental Features (require player disconnection on final death) == -{Values.ForgetActiveQuestsName}: {ForgetActiveQuests} -{Values.ForgetInactiveQuestsName}: {ForgetInactiveQuests} -{Values.ForgetIntroQuestsName}: {ForgetIntroQuests}"; +{Values.NameForgetActiveQuests}: {ForgetActiveQuests} +{Values.NameForgetInactiveQuests}: {ForgetInactiveQuests} +{Values.NameForgetIntroQuests}: {ForgetIntroQuests}"; /// /// Update the long term memory level. This will determine when Amnesia activates and the level players will be reset to on death. @@ -93,14 +89,14 @@ public static void SetLongTermMemoryLevel(int value) { LongTermMemoryLevel = Math.Max(1, value); _ = Save(); foreach (var player in GameManager.Instance.World.Players.list) { - player.SetCVar(Values.LongTermMemoryLevelCVar, LongTermMemoryLevel); + player.SetCVar(Values.CVarLongTermMemoryLevel, LongTermMemoryLevel); if (player.Progression.Level <= LongTermMemoryLevel) { - if (!player.Buffs.HasBuff(Values.NewbieCoatBuff)) { - _ = player.Buffs.AddBuff(Values.NewbieCoatBuff); + if (!player.Buffs.HasBuff(Values.BuffNewbieCoat)) { + _ = player.Buffs.AddBuff(Values.BuffNewbieCoat); } - if (player.Buffs.HasBuff(Values.HardenedMemoryBuff)) { - player.Buffs.RemoveBuff(Values.HardenedMemoryBuff); - PlayerHelper.GiveItem(player, Values.MemoryBoosterItemName); + if (player.Buffs.HasBuff(Values.BuffHardenedMemory)) { + player.Buffs.RemoveBuff(Values.BuffHardenedMemory); + PlayerHelper.GiveItem(player, Values.NameMemoryBoosters); } } } @@ -117,16 +113,16 @@ public static void SetPositiveOutlookMaxTime(int timeInSeconds) { PositiveOutlookMaxTime = Math.Max(0, timeInSeconds); _ = Save(); foreach (var player in GameManager.Instance.World.Players.list) { - var playerRemTime = player.GetCVar(Values.PositiveOutlookRemTimeCVar); + var playerRemTime = player.GetCVar(Values.CVarPositiveOutlookRemTime); if (playerRemTime > 0) { - var playerMaxTime = player.GetCVar(Values.PositiveOutlookMaxTimeCVar); + var playerMaxTime = player.GetCVar(Values.CVarPositiveOutlookMaxTime); if (playerMaxTime < PositiveOutlookMaxTime) { - player.SetCVar(Values.PositiveOutlookRemTimeCVar, PositiveOutlookMaxTime - playerMaxTime + playerRemTime); + player.SetCVar(Values.CVarPositiveOutlookRemTime, PositiveOutlookMaxTime - playerMaxTime + playerRemTime); } else if (playerMaxTime > PositiveOutlookMaxTime) { - player.SetCVar(Values.PositiveOutlookRemTimeCVar, PositiveOutlookMaxTime); + player.SetCVar(Values.CVarPositiveOutlookRemTime, PositiveOutlookMaxTime); } } - player.SetCVar(Values.PositiveOutlookMaxTimeCVar, PositiveOutlookMaxTime); + player.SetCVar(Values.CVarPositiveOutlookMaxTime, PositiveOutlookMaxTime); } } @@ -220,12 +216,12 @@ public static void SetProtectMemoryDuringBloodmoon(bool value) { _ = Save(); if (ProtectMemoryDuringBloodmoon && GameManager.Instance.World.aiDirector.BloodMoonComponent.BloodMoonActive) { foreach (var player in GameManager.Instance.World.Players.list) { - _ = player.Buffs.AddBuff(Values.BloodmoonLifeProtectionBuff); + _ = player.Buffs.AddBuff(Values.BuffBloodmoonLifeProtection); } } else { foreach (var player in GameManager.Instance.World.Players.list) { - player.Buffs.RemoveBuff(Values.BloodmoonLifeProtectionBuff); - player.Buffs.RemoveBuff(Values.PostBloodmoonLifeProtectionBuff); + player.Buffs.RemoveBuff(Values.BuffBloodmoonLifeProtection); + player.Buffs.RemoveBuff(Values.BuffPostBloodmoonLifeProtection); } } } @@ -328,7 +324,7 @@ public static void SetForgetInactiveQuests(bool value) { public static bool Save() { try { - var timeOnKillElement = new XElement(Values.PositiveOutlookTimeOnKillName); + var timeOnKillElement = new XElement(Values.NamePositiveOutlookTimeOnKill); foreach (var kvp in PositiveOutlookTimeOnKill) { timeOnKillElement.Add(new XElement("entry", new XAttribute("name", kvp.Value.name), @@ -337,24 +333,24 @@ public static bool Save() { } new XElement("config", - new XElement(Values.LongTermMemoryLevelName, LongTermMemoryLevel), + new XElement(Values.NameLongTermMemoryLevel, LongTermMemoryLevel), - new XElement(Values.PositiveOutlookMaxTimeName, PositiveOutlookMaxTime), - new XElement(Values.PositiveOutlookTimeOnFirstJoinName, PositiveOutlookTimeOnFirstJoin), - new XElement(Values.PositiveOutlookTimeOnMemoryLossName, PositiveOutlookTimeOnMemoryLoss), + new XElement(Values.NamePositiveOutlookMaxTime, PositiveOutlookMaxTime), + new XElement(Values.NamePositiveOutlookTimeOnFirstJoin, PositiveOutlookTimeOnFirstJoin), + new XElement(Values.NamePositiveOutlookTimeOnMemoryLoss, PositiveOutlookTimeOnMemoryLoss), timeOnKillElement, - new XElement(Values.ProtectMemoryDuringBloodmoonName, ProtectMemoryDuringBloodmoon), - new XElement(Values.ProtectMemoryDuringPvpName, ProtectMemoryDuringPvp), + new XElement(Values.NameProtectMemoryDuringBloodmoon, ProtectMemoryDuringBloodmoon), + new XElement(Values.NameProtectMemoryDuringPvp, ProtectMemoryDuringPvp), - new XElement(Values.ForgetLevelsAndSkillsName, ForgetLevelsAndSkills), - new XElement(Values.ForgetBooksName, ForgetBooks), - new XElement(Values.ForgetSchematicsName, ForgetSchematics), - new XElement(Values.ForgetKdrName, ForgetKdr), + new XElement(Values.NameForgetLevelsAndSkills, ForgetLevelsAndSkills), + new XElement(Values.NameForgetBooks, ForgetBooks), + new XElement(Values.NameForgetSchematics, ForgetSchematics), + new XElement(Values.NameForgetKdr, ForgetKdr), - new XElement(Values.ForgetActiveQuestsName, ForgetActiveQuests), - new XElement(Values.ForgetInactiveQuestsName, ForgetInactiveQuests), - new XElement(Values.ForgetIntroQuestsName, ForgetIntroQuests) + new XElement(Values.NameForgetActiveQuests, ForgetActiveQuests), + new XElement(Values.NameForgetInactiveQuests, ForgetInactiveQuests), + new XElement(Values.NameForgetIntroQuests, ForgetIntroQuests) ).Save(filename); log.Info($"Successfully saved {filename}"); return true; @@ -367,14 +363,14 @@ public static bool Save() { public static void Load() { try { var config = XElement.Load(filename); - LongTermMemoryLevel = ParseInt(config, Values.LongTermMemoryLevelName, LongTermMemoryLevel); + LongTermMemoryLevel = ParseInt(config, Values.NameLongTermMemoryLevel, LongTermMemoryLevel); - PositiveOutlookMaxTime = ParseInt(config, Values.PositiveOutlookMaxTimeName, PositiveOutlookMaxTime); - PositiveOutlookTimeOnFirstJoin = ParseInt(config, Values.PositiveOutlookTimeOnFirstJoinName, PositiveOutlookTimeOnFirstJoin); - PositiveOutlookTimeOnMemoryLoss = ParseInt(config, Values.PositiveOutlookTimeOnMemoryLossName, PositiveOutlookTimeOnMemoryLoss); + PositiveOutlookMaxTime = ParseInt(config, Values.NamePositiveOutlookMaxTime, PositiveOutlookMaxTime); + PositiveOutlookTimeOnFirstJoin = ParseInt(config, Values.NamePositiveOutlookTimeOnFirstJoin, PositiveOutlookTimeOnFirstJoin); + PositiveOutlookTimeOnMemoryLoss = ParseInt(config, Values.NamePositiveOutlookTimeOnMemoryLoss, PositiveOutlookTimeOnMemoryLoss); PositiveOutlookTimeOnKill.Clear(); - foreach (var entry in config.Descendants(Values.PositiveOutlookTimeOnKillName).First().Descendants("entry")) { + foreach (var entry in config.Descendants(Values.NamePositiveOutlookTimeOnKill).First().Descendants("entry")) { if (!int.TryParse(entry.Attribute("value").Value, out var intValue)) { log.Error($"Unable to parse value; expecting int"); return; @@ -386,17 +382,17 @@ public static void Load() { }); } - ProtectMemoryDuringBloodmoon = ParseBool(config, Values.ProtectMemoryDuringBloodmoonName, ProtectMemoryDuringBloodmoon); - ProtectMemoryDuringPvp = ParseBool(config, Values.ProtectMemoryDuringPvpName, ProtectMemoryDuringPvp); + ProtectMemoryDuringBloodmoon = ParseBool(config, Values.NameProtectMemoryDuringBloodmoon, ProtectMemoryDuringBloodmoon); + ProtectMemoryDuringPvp = ParseBool(config, Values.NameProtectMemoryDuringPvp, ProtectMemoryDuringPvp); - ForgetLevelsAndSkills = ParseBool(config, Values.ForgetLevelsAndSkillsName, ForgetLevelsAndSkills); - ForgetBooks = ParseBool(config, Values.ForgetBooksName, ForgetBooks); - ForgetSchematics = ParseBool(config, Values.ForgetSchematicsName, ForgetSchematics); - ForgetKdr = ParseBool(config, Values.ForgetKdrName, ForgetKdr); + ForgetLevelsAndSkills = ParseBool(config, Values.NameForgetLevelsAndSkills, ForgetLevelsAndSkills); + ForgetBooks = ParseBool(config, Values.NameForgetBooks, ForgetBooks); + ForgetSchematics = ParseBool(config, Values.NameForgetSchematics, ForgetSchematics); + ForgetKdr = ParseBool(config, Values.NameForgetKdr, ForgetKdr); - ForgetActiveQuests = ParseBool(config, Values.ForgetActiveQuestsName, ForgetActiveQuests); - ForgetInactiveQuests = ParseBool(config, Values.ForgetInactiveQuestsName, ForgetInactiveQuests); - ForgetIntroQuests = ParseBool(config, Values.ForgetIntroQuestsName, ForgetIntroQuests); + ForgetActiveQuests = ParseBool(config, Values.NameForgetActiveQuests, ForgetActiveQuests); + ForgetInactiveQuests = ParseBool(config, Values.NameForgetInactiveQuests, ForgetInactiveQuests); + ForgetIntroQuests = ParseBool(config, Values.NameForgetIntroQuests, ForgetIntroQuests); log.Info($"Successfully loaded {filename}"); Loaded = true; } catch (FileNotFoundException) { diff --git a/src/Data/Values.cs b/src/Data/Values.cs index 26aecb3..a6694a8 100644 --- a/src/Data/Values.cs +++ b/src/Data/Values.cs @@ -5,63 +5,65 @@ namespace Amnesia.Data { internal class Values { // cvars - public const string LongTermMemoryLevelCVar = "amnesiaLongTermMemoryLevel"; - public const string PositiveOutlookMaxTimeCVar = "amnesiaPositiveOutlookMaxTime"; - public const string PositiveOutlookRemTimeCVar = "amnesiaPositiveOutlookRemTime"; + public const string CVarLongTermMemoryLevel = "amnesiaLongTermMemoryLevel"; + public const string CVarPositiveOutlookMaxTime = "amnesiaPositiveOutlookMaxTime"; + public const string CVarPositiveOutlookRemTime = "amnesiaPositiveOutlookRemTime"; // buffs - public const string PositiveOutlookBuff = "buffAmnesiaPositiveOutlook"; - public const string BloodmoonLifeProtectionBuff = "buffAmnesiaBloodmoonLifeProtection"; - public const string PostBloodmoonLifeProtectionBuff = "buffAmnesiaPostBloodmoonLifeProtection"; - public const string HardenedMemoryBuff = "buffAmnesiaHardenedMemory"; - public const string NewbieCoatBuff = "buffNewbieCoat"; - public const string MemoryLossNotificationBuff = "buffAmnesiaMemoryLoss"; + public const string BuffPositiveOutlook = "buffAmnesiaPositiveOutlook"; + public const string BuffBloodmoonLifeProtection = "buffAmnesiaBloodmoonLifeProtection"; + public const string BuffPostBloodmoonLifeProtection = "buffAmnesiaPostBloodmoonLifeProtection"; + public const string BuffHardenedMemory = "buffAmnesiaHardenedMemory"; + public const string BuffFragileMemory = "buffAmnesiaFragileMemory"; + public const string BuffMemoryLoss = "buffAmnesiaMemoryLoss"; + public const string BuffNewbieCoat = "buffNewbieCoat"; + public const string BuffNearDeathTrauma = "buffNearDeathTrauma"; // items - public const string MemoryBoosterItemName = "drugAmnesiaMemoryBooster"; + public const string NameMemoryBoosters = "drugAmnesiaMemoryBoosters"; // names - public const string LongTermMemoryLevelName = "LongTermMemoryLevel"; - public const string PositiveOutlookMaxTimeName = "PositiveOutlookMaxTime"; - public const string PositiveOutlookTimeOnFirstJoinName = "PositiveOutlookTimeOnFirstJoin"; - public const string PositiveOutlookTimeOnMemoryLossName = "PositiveOutlookTimeOnMemoryLoss"; - public const string PositiveOutlookTimeOnKillName = "PositiveOutlookTimeOnKill"; - public const string ProtectMemoryDuringBloodmoonName = "ProtectMemoryDuringBloodmoon"; - public const string ProtectMemoryDuringPvpName = "ProtectMemoryDuringPvp"; - public const string ForgetLevelsAndSkillsName = "ForgetLevelsAndSkills"; - public const string ForgetBooksName = "ForgetBooks"; - public const string ForgetSchematicsName = "ForgetSchematics"; - public const string ForgetKdrName = "ForgetKdr"; - public const string ForgetActiveQuestsName = "ForgetActiveQuests"; - public const string ForgetInactiveQuestsName = "ForgetInactiveQuests"; - public const string ForgetIntroQuestsName = "ForgetIntroQuests"; + public const string NameLongTermMemoryLevel = "LongTermMemoryLevel"; + public const string NamePositiveOutlookMaxTime = "PositiveOutlookMaxTime"; + public const string NamePositiveOutlookTimeOnFirstJoin = "PositiveOutlookTimeOnFirstJoin"; + public const string NamePositiveOutlookTimeOnMemoryLoss = "PositiveOutlookTimeOnMemoryLoss"; + public const string NamePositiveOutlookTimeOnKill = "PositiveOutlookTimeOnKill"; + public const string NameProtectMemoryDuringBloodmoon = "ProtectMemoryDuringBloodmoon"; + public const string NameProtectMemoryDuringPvp = "ProtectMemoryDuringPvp"; + public const string NameForgetLevelsAndSkills = "ForgetLevelsAndSkills"; + public const string NameForgetBooks = "ForgetBooks"; + public const string NameForgetSchematics = "ForgetSchematics"; + public const string NameForgetKdr = "ForgetKdr"; + public const string NameForgetActiveQuests = "ForgetActiveQuests"; + public const string NameForgetInactiveQuests = "ForgetInactiveQuests"; + public const string NameForgetIntroQuests = "ForgetIntroQuests"; - public const string DisconnectionWarning = "\n - [!] SYSTEM WILL DISCONNECT PLAYER ON FINAL DEATH IF ENABLED!"; - public const string ExperimentalWarning = "\n - [!] EXPERIMENTAL FEATURE - USE AT YOUR OWN RISK..."; + private const string DisconnectionWarning = "\n - [!] SYSTEM WILL DISCONNECT PLAYER ON FINAL DEATH IF ENABLED!"; + private const string ExperimentalWarning = "\n - [!] EXPERIMENTAL FEATURE - USE AT YOUR OWN RISK..."; public static readonly Dictionary SingleValueNamesAndDescriptionsDict = new Dictionary { - { LongTermMemoryLevelName, "the level players will be reset to on memory loss and the level at which losing memory on death starts" }, + { NameLongTermMemoryLevel, "the level players will be reset to on memory loss and the level at which losing memory on death starts" }, - { PositiveOutlookMaxTimeName, "maximum length of time allowed for buff that boost xp growth" }, - { PositiveOutlookTimeOnFirstJoinName, "length of time for buff that boosts xp growth at first-time server join" }, - { PositiveOutlookTimeOnMemoryLossName, "length of time for buff that boosts xp growth on memory loss" }, + { NamePositiveOutlookMaxTime, "maximum length of time allowed for buff that boost xp growth" }, + { NamePositiveOutlookTimeOnFirstJoin, "length of time for buff that boosts xp growth at first-time server join" }, + { NamePositiveOutlookTimeOnMemoryLoss, "length of time for buff that boosts xp growth on memory loss" }, - { ProtectMemoryDuringBloodmoonName, "whether deaths during bloodmoon will cost lives" }, - { ProtectMemoryDuringPvpName, "whether to prevent memory when defeated in pvp" }, + { NameProtectMemoryDuringBloodmoon, "whether deaths during bloodmoon will harm memory" }, + { NameProtectMemoryDuringPvp, "whether to prevent harm to memory when defeated in pvp" }, - { ForgetLevelsAndSkillsName, $"whether to forget levels, skills, and skill points on memory loss (note that players will reset back to the level configured in {LongTermMemoryLevelName}" }, - { ForgetBooksName, "whether books should be forgotten on memory loss" }, - { ForgetSchematicsName, "whether schematics should be forgotten on memory loss" }, - { ForgetKdrName, "whether players/zombies killed and times died should be forgotten on memory loss" }, + { NameForgetLevelsAndSkills, $"whether to forget levels, skills, and skill points on memory loss (note that players will reset back to the level configured in {NameLongTermMemoryLevel}" }, + { NameForgetBooks, "whether books should be forgotten on memory loss" }, + { NameForgetSchematics, "whether schematics should be forgotten on memory loss" }, + { NameForgetKdr, "whether players/zombies killed and times died should be forgotten on memory loss" }, - { ForgetActiveQuestsName, $"whether ongoing quests should be forgotten on memory loss{DisconnectionWarning}{ExperimentalWarning}" }, - { ForgetInactiveQuestsName, $"whether completed quests (AND TRADER TIER LEVELS) should be forgotten on memory loss{DisconnectionWarning}{ExperimentalWarning}" }, - { ForgetIntroQuestsName, $"whether the intro quests should be forgotten/reset on memory loss{DisconnectionWarning}{ExperimentalWarning}" } + { NameForgetActiveQuests, $"whether ongoing quests should be forgotten on memory loss{DisconnectionWarning}{ExperimentalWarning}" }, + { NameForgetInactiveQuests, $"whether completed quests (AND TRADER TIER LEVELS) should be forgotten on memory loss{DisconnectionWarning}{ExperimentalWarning}" }, + { NameForgetIntroQuests, $"whether the intro quests should be forgotten/reset on memory loss{DisconnectionWarning}{ExperimentalWarning}" } }; public static List SingleValueFieldNames { get; private set; } = SingleValueNamesAndDescriptionsDict.Keys.ToList(); public static string SingleValueFieldNamesAndDescriptions { get; private set; } = " - " + string.Join("\n - ", SingleValueNamesAndDescriptionsDict.Select(kvp => kvp.Key + ": " + kvp.Value)); public static readonly Dictionary KeyValueNamesAndDescriptionsDict = new Dictionary { - { PositiveOutlookTimeOnKillName, "length of time awarded to all online players when any player defeats an entity of the given type (name is case sensitive)" }, + { NamePositiveOutlookTimeOnKill, "length of time awarded to all online players when any player defeats an entity of the given type (name is case sensitive)" }, }; public static string KeyValueFieldNamesAndDescriptions { get; private set; } = " - " + string.Join("\n - ", KeyValueNamesAndDescriptionsDict.Select(kvp => kvp.Key + ": " + kvp.Value)); } diff --git a/src/Handlers/GameMessage.cs b/src/Handlers/GameMessage.cs index 99a8732..39a064f 100644 --- a/src/Handlers/GameMessage.cs +++ b/src/Handlers/GameMessage.cs @@ -9,38 +9,36 @@ internal class GameMessage { public static bool Handle(ClientInfo clientInfo, EnumGameMessages messageType, string message, string mainName, bool localizeMain, string secondaryName, bool localizeSecondary) { if (!Config.Loaded) { return true; } // do not interrupt other mods from processing event try { - switch (messageType) { - case EnumGameMessages.EntityWasKilled: - if (!GameManager.Instance.World.Players.dict.TryGetValue(clientInfo.entityId, out var player)) { - return true; // player not present; skip - } + if (EnumGameMessages.EntityWasKilled != messageType) { + return true; // only focus on entity killed messages + } + + if (!GameManager.Instance.World.Players.dict.TryGetValue(clientInfo.entityId, out var player)) { + return true; // player not present; skip + } - if (player.Buffs.HasBuff(Values.BloodmoonLifeProtectionBuff) || player.Buffs.HasBuff(Values.PostBloodmoonLifeProtectionBuff)) { - log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died but had bloodmoon life protection."); - return true; // player had protection - } else { - log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died and did not have bloodmoon life protection."); - } + if (player.Buffs.HasBuff(Values.BuffBloodmoonLifeProtection) || player.Buffs.HasBuff(Values.BuffPostBloodmoonLifeProtection)) { + log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died but had bloodmoon memory protection."); + return true; // player had protection + } else { + log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died and did not have bloodmoon memory protection."); + } - if (mainName != secondaryName) { - var killerClient = ConnectionManager.Instance.Clients.GetForNameOrId(secondaryName); - if (killerClient != null) { - if (Config.ProtectMemoryDuringPvp) { - log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) was killed by {secondaryName} but this server has pvp deaths set to not remove lives."); - return true; // being killed in pvp doesn't count against player - } - } - } + if (Config.ProtectMemoryDuringPvp && mainName != secondaryName) { + var killerClient = ConnectionManager.Instance.Clients.GetForNameOrId(secondaryName); + if (killerClient != null) { + log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) was killed by {secondaryName} but this server has pvp deaths set to not harm memory."); + return true; // being killed in pvp doesn't count against player + } + } - if (player.Progression.Level <= Config.LongTermMemoryLevel) { - log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died but did not exceed the configured LongTermMemoryLevel of {Config.LongTermMemoryLevel}"); - return true; - } + if (player.Progression.Level < Config.LongTermMemoryLevel) { + log.Trace($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died but had not yet reached the configured LongTermMemoryLevel of {Config.LongTermMemoryLevel}"); + return true; + } - if (!ModApi.Obituary.ContainsKey(clientInfo.entityId)) { - ModApi.Obituary.Add(clientInfo.entityId, true); - } - break; + if (!ModApi.Obituary.ContainsKey(clientInfo.entityId)) { + ModApi.Obituary.Add(clientInfo.entityId, true); } } catch (Exception e) { log.Error("Failed to handle GameMessage event.", e); diff --git a/src/Handlers/GameUpdate.cs b/src/Handlers/GameUpdate.cs index e663816..876317a 100644 --- a/src/Handlers/GameUpdate.cs +++ b/src/Handlers/GameUpdate.cs @@ -23,6 +23,7 @@ internal static void Handle() { } private static void HandleBloodMoon() { + // TODO: this should probably be injected into triggers when bloodmoon starts and ends, honestly try { if (isBloodmoon == GameManager.Instance.World.aiDirector.BloodMoonComponent.BloodMoonActive) { return; @@ -32,12 +33,12 @@ private static void HandleBloodMoon() { var players = GameManager.Instance.World.Players.list; if (isBloodmoon) { for (var i = 0; i < players.Count; i++) { - _ = players[i].Buffs.AddBuff(Values.BloodmoonLifeProtectionBuff); + _ = players[i].Buffs.AddBuff(Values.BuffBloodmoonLifeProtection); } } else { for (var i = 0; i < players.Count; i++) { - _ = players[i].Buffs.AddBuff(Values.PostBloodmoonLifeProtectionBuff); - players[i].Buffs.RemoveBuff(Values.BloodmoonLifeProtectionBuff); + _ = players[i].Buffs.AddBuff(Values.BuffPostBloodmoonLifeProtection); + players[i].Buffs.RemoveBuff(Values.BuffBloodmoonLifeProtection); } } } catch (Exception e) { diff --git a/src/Handlers/PlayerSpawnedInWorld.cs b/src/Handlers/PlayerSpawnedInWorld.cs index f54b5ef..5c37160 100644 --- a/src/Handlers/PlayerSpawnedInWorld.cs +++ b/src/Handlers/PlayerSpawnedInWorld.cs @@ -22,11 +22,13 @@ public static void Handle(ClientInfo clientInfo, RespawnType respawnType, Vector switch (respawnType) { case RespawnType.EnterMultiplayer: // first-time login for new player _ = PlayerHelper.AddPositiveOutlookTime(player, Config.PositiveOutlookTimeOnFirstJoin); + RefundHardenedMemory(clientInfo, player); HandleStandardRespawnSteps(player); break; case RespawnType.JoinMultiplayer: // existing player rejoining // grace period should continue only so long as you don't disconnect - player.Buffs.RemoveBuff(Values.PostBloodmoonLifeProtectionBuff); + player.Buffs.RemoveBuff(Values.BuffPostBloodmoonLifeProtection); + RefundHardenedMemory(clientInfo, player); HandleStandardRespawnSteps(player); break; case RespawnType.Died: // existing player returned from death @@ -38,7 +40,7 @@ public static void Handle(ClientInfo clientInfo, RespawnType respawnType, Vector log.Error("Failed to handle PlayerSpawnedInWorld event.", e); } } - + /// /// Process steps common to enter/join/death. /// @@ -47,27 +49,38 @@ public static void Handle(ClientInfo clientInfo, RespawnType respawnType, Vector private static void HandleStandardRespawnSteps(EntityPlayer player) { // Ensure joining/respawning players have their constants updated - if (player.GetCVar(Values.LongTermMemoryLevelCVar) != Config.LongTermMemoryLevel) { - player.SetCVar(Values.LongTermMemoryLevelCVar, Config.LongTermMemoryLevel); + if (player.GetCVar(Values.CVarLongTermMemoryLevel) != Config.LongTermMemoryLevel) { + player.SetCVar(Values.CVarLongTermMemoryLevel, Config.LongTermMemoryLevel); } // Remove Positive Outlook if admin disabled it since player's last login - if (Config.PositiveOutlookTimeOnMemoryLoss == 0 && player.Buffs.HasBuff(Values.PositiveOutlookBuff)) { - player.Buffs.RemoveBuff(Values.PositiveOutlookBuff); + if (Config.PositiveOutlookTimeOnMemoryLoss == 0 && player.Buffs.HasBuff(Values.BuffPositiveOutlook)) { + player.Buffs.RemoveBuff(Values.BuffPositiveOutlook); } // Apply/Remove memory protection based on configuration if (Config.ProtectMemoryDuringBloodmoon) { // add or remove protection based on whether BM is active if (GameManager.Instance.World.aiDirector.BloodMoonComponent.BloodMoonActive) { - _ = player.Buffs.AddBuff(Values.BloodmoonLifeProtectionBuff); + _ = player.Buffs.AddBuff(Values.BuffBloodmoonLifeProtection); } else { - player.Buffs.RemoveBuff(Values.BloodmoonLifeProtectionBuff); + player.Buffs.RemoveBuff(Values.BuffBloodmoonLifeProtection); } } else { // remove/clean up since protection is inactive - player.Buffs.RemoveBuff(Values.BloodmoonLifeProtectionBuff); - player.Buffs.RemoveBuff(Values.PostBloodmoonLifeProtectionBuff); + player.Buffs.RemoveBuff(Values.BuffBloodmoonLifeProtection); + player.Buffs.RemoveBuff(Values.BuffPostBloodmoonLifeProtection); + } + } + + /// + /// Temporary method to automatically refund any players with the Hardened Memory buff from version 1.0.0. + /// + /// EntityPlayer to check buffs for and refund if hardened. + private static void RefundHardenedMemory(ClientInfo clientInfo, EntityPlayer player) { + if (player.Buffs.HasBuff(Values.BuffHardenedMemory)) { + PlayerHelper.GiveItem(clientInfo, player, Values.NameMemoryBoosters); + player.Buffs.RemoveBuff(Values.BuffHardenedMemory); } } } diff --git a/src/Handlers/SavePlayerData.cs b/src/Handlers/SavePlayerData.cs index da26e7f..f0b929e 100644 --- a/src/Handlers/SavePlayerData.cs +++ b/src/Handlers/SavePlayerData.cs @@ -21,10 +21,10 @@ public static void Handle(ClientInfo clientInfo, PlayerDataFile playerDataFile) return; // exit early, do not interrupt other mods from processing event } - if (player.Buffs.HasBuff(Values.HardenedMemoryBuff)) { - player.Buffs.RemoveBuff(Values.HardenedMemoryBuff); - log.Info($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died but will not be reset, thanks to Hardened Memory (which has now expired)."); - return; + if (!player.Buffs.HasBuff(Values.BuffFragileMemory)) { + _ = player.Buffs.AddBuff(Values.BuffFragileMemory); + log.Info($"{clientInfo.InternalId.CombinedString} ({player.GetDebugName()}) died and will not be reset, but now has a Fragile Memory."); + return; // let player know it's time for memory boosters } if ((Config.ForgetActiveQuests || Config.ForgetInactiveQuests) && QuestHelper.ResetQuests(player)) { diff --git a/src/Utilities/MessagingSystem.cs b/src/Utilities/MessagingSystem.cs index 9f3e21b..1145a22 100644 --- a/src/Utilities/MessagingSystem.cs +++ b/src/Utilities/MessagingSystem.cs @@ -31,7 +31,7 @@ public static void Broadcast(string message) { } Send(EChatType.Global, message, entityIds); } - + /// /// Send a message to all players who match the given condition. /// diff --git a/src/Utilities/PlayerHelper.cs b/src/Utilities/PlayerHelper.cs index ea5c962..ed2021a 100644 --- a/src/Utilities/PlayerHelper.cs +++ b/src/Utilities/PlayerHelper.cs @@ -33,10 +33,6 @@ public static void ResetPlayer(EntityPlayer player) { player.Progression.ExpToNextLevel = player.Progression.GetExpForNextLevel(); player.Progression.SkillPoints = Config.LongTermMemoryLevel - 1; - // Zero out xp debt; the reset has caused enough suffering ;) - player.Progression.ExpDeficit = 0; - player.SetCVar("_expdeficit", 0); - // Return all skill points rewarded from completed quest; should cover vanilla quest_BasicSurvival8, for example if (!Config.ForgetIntroQuests) { try { @@ -76,11 +72,11 @@ public static void ResetPlayer(EntityPlayer player) { ConnectionManager.Instance.SendPackage(NetPackageManager.GetPackage().Setup(player), false, player.entityId); } - _ = player.Buffs.AddBuff(Values.MemoryLossNotificationBuff); + _ = player.Buffs.AddBuff(Values.BuffMemoryLoss); if (Config.PositiveOutlookTimeOnMemoryLoss > 0) { log.Trace($"{player.GetDebugName()} will receive the Positive Outlook buff."); - player.SetCVar(Values.PositiveOutlookRemTimeCVar, Config.PositiveOutlookTimeOnMemoryLoss); - _ = player.Buffs.AddBuff(Values.PositiveOutlookBuff); + player.SetCVar(Values.CVarPositiveOutlookRemTime, Config.PositiveOutlookTimeOnMemoryLoss); + _ = player.Buffs.AddBuff(Values.BuffPositiveOutlook); } } @@ -88,11 +84,11 @@ public static float AddPositiveOutlookTime(EntityPlayer player, int valueToAdd) if (valueToAdd == 0) { return 0; } - var playerRemTime = Math.Max(0, player.GetCVar(Values.PositiveOutlookRemTimeCVar)); + var playerRemTime = Math.Max(0, player.GetCVar(Values.CVarPositiveOutlookRemTime)); var targetValue = Math.Min(playerRemTime + valueToAdd, Config.PositiveOutlookMaxTime); - player.SetCVar(Values.PositiveOutlookRemTimeCVar, targetValue); - if (!player.Buffs.HasBuff(Values.PositiveOutlookBuff)) { - _ = player.Buffs.AddBuff(Values.PositiveOutlookBuff); + player.SetCVar(Values.CVarPositiveOutlookRemTime, targetValue); + if (!player.Buffs.HasBuff(Values.BuffPositiveOutlook)) { + _ = player.Buffs.AddBuff(Values.BuffPositiveOutlook); } return targetValue; } @@ -109,6 +105,18 @@ public static void GiveItem(EntityPlayer player, string itemName, int count = 1) GiveItemStack(clientInfo, player.GetBlockPosition(), itemStack); } + /// + /// Give an item to the player, placing it in the player's inventory if possible. + /// + /// ClientInfo for player to send the network package to. + /// EntityPlayer to give item to. + /// Name of the item to give the player. + /// Number of items to give within a single stack (only works with stackable items). + public static void GiveItem(ClientInfo clientInfo, EntityPlayer player, string itemName, int count = 1) { + var itemStack = new ItemStack(ItemClass.GetItem(itemName, true), count); + GiveItemStack(clientInfo, player.GetBlockPosition(), itemStack); + } + internal static void GiveItemStack(ClientInfo clientInfo, Vector3i pos, ItemStack itemStack) { var entityId = EntityFactory.nextEntityID++; GameManager.Instance.World.SpawnEntityInWorld((EntityItem)EntityFactory.CreateEntity(new EntityCreationData { @@ -123,7 +131,5 @@ internal static void GiveItemStack(ClientInfo clientInfo, Vector3i pos, ItemStac clientInfo.SendPackage(NetPackageManager.GetPackage().Setup(entityId, clientInfo.entityId)); _ = GameManager.Instance.World.RemoveEntity(entityId, EnumRemoveEntityReason.Despawned); } - - internal static void GiveItem(EntityPlayer player, object memoryBoosterItemName) => throw new NotImplementedException(); } } diff --git a/src/Utilities/QuestHelper.cs b/src/Utilities/QuestHelper.cs index 5c03368..7584a86 100644 --- a/src/Utilities/QuestHelper.cs +++ b/src/Utilities/QuestHelper.cs @@ -76,7 +76,7 @@ private static bool RemoveActiveQuest(EntityPlayer player, Quest quest) { } return true; } - + /// /// Server-safe version of quest.HandleUnlockPOI. /// @@ -156,7 +156,7 @@ private static void RemoveFetchItems(EntityPlayer player, Quest quest, BaseObjec _ = player.bag.DecItem(expectedItem, 1, false); } - + /// /// Server-safe version of QuestJournal.HandlePartyRemoveQuest. ///