From bdb7f80ca6f8ebb7ffacbef521d2def3c1dd058c Mon Sep 17 00:00:00 2001 From: VerySoft Date: Thu, 13 Jun 2024 22:21:06 -0400 Subject: [PATCH 1/5] enhanced player mob persistance --- .../preference_setup/general/01_basic.dm | 2 + code/modules/mob/living/Magic/magic.dm | 190 ++++++++++++++++++ vorestation.dme | 1 + 3 files changed, 193 insertions(+) create mode 100644 code/modules/mob/living/Magic/magic.dm diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index f9423f088a4..0d49607fbde 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -103,7 +103,9 @@ if (!isnull(raw_name) && CanUseTopic(user)) var/new_name = sanitize_name(raw_name, pref.species, is_FBP()) if(new_name) + var/old_name = pref.real_name //RS ADD pref.real_name = new_name + user.magic_rename(old_name, new_name) //RS ADD return TOPIC_REFRESH else to_chat(user, "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and .") diff --git a/code/modules/mob/living/Magic/magic.dm b/code/modules/mob/living/Magic/magic.dm new file mode 100644 index 00000000000..d61b8321090 --- /dev/null +++ b/code/modules/mob/living/Magic/magic.dm @@ -0,0 +1,190 @@ +/mob/living + var/datum/etching/etching + +/mob/living/Initialize() + . = ..() + init_magic() + +/mob/living/Login() + . = ..() + if(etching) + etching.load() + +/mob/living/Destroy() + if(etching) + var/datum/etching/E = etching + E.save(TRUE) + ..() + +/mob/living/Life() + . = ..() + process_magic() + +/mob/living/proc/init_magic() + if(ishuman(src) || isanimal(src)) + etching = new /datum/etching(src) + +/mob/living/proc/process_magic() + if(!etching) + return + var/datum/etching/E = etching + if(E.mana < E.max_mana) + E.mana += E.mana_regen + if(E.mana_cooldown) + E.mana_cooldown -- + +/datum/etching + var/mob/living/ourmob //Reference to the mob we are working with + var/true_name //Magic bs + var/mana = 0 //How much you have + var/max_mana = 0 //How much you could have + var/mana_regen = 0 //How fast it comes back + var/mana_cooldown = 0 //How soon you can do it again + var/core //Head/body + var/l_arm + var/r_arm + var/l_leg + var/r_leg + var/shutting_down = FALSE //If true it won't try to save again + var/save_path //The file path for the save/load function + var/list/xp = list() //A list of different experience values + +/datum/etching/New(var/L) + log_debug("ETCHING STARTED") + if(!L) + log_debug("Etching: No target, delete self") + qdel(src) + return + ourmob = L + log_debug("Etching: Registered to [ourmob]") + return ..() + +/datum/etching/Destroy() + . = ..() + ourmob = null + +/datum/etching/proc/get_save_path() + return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-etching.json" + +/datum/etching/proc/load() + if(IsGuestKey(ourmob.key)) + return + if(!ourmob.ckey) + log_debug("Aborting etching load for [ourmob.real_name], no ckey") + return + + save_path = get_save_path() + + if(!save_path) + log_debug("Etching load failed: No save_path") + return + if(!fexists(save_path)) + log_debug("Etching load failed: No file '[save_path]' exists. Beginning setup.") + setup() + return + + var/content + try + content = file2text(save_path) + catch(var/exception/E_content) + error("Exception when loading etching content - [save_path] - [content]: [E_content]") + + if(!content) + error("Etching failed to load for [ourmob.real_name], aborting.") + return + + var/list/load + + try + load = json_decode(file2text(save_path)) + catch(var/exception/E_json_decode) + error("Exception decoding etching content - [save_path] - [load]: [E_json_decode]") + + if(!load) + log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: [] ") + return + + true_name = load["true_name"] + core = load["core"] + l_arm = load["l_arm"] + r_arm = load["r_arm"] + l_leg = load["l_leg"] + r_leg = load["r_leg"] + xp = load["xp"] + + log_debug("Etching load complete for [ourmob.real_name].") + +/datum/etching/proc/save(delet = FALSE) + if(IsGuestKey(ourmob.key)) + return + if(!ourmob.ckey) + return + + if(shutting_down) //Don't try to save more than once if we're already saving and shutting down. + return + if(delet) //Our mob got deleted, so we're saving and quitting. + shutting_down = TRUE + + if(!save_path) + return + + var/list/to_save = list( + "true_name" = true_name, + "core" = core, + "l_arm" = l_arm, + "r_arm" = r_arm, + "l_leg" = l_leg, + "r_leg" = r_leg, + "xp" = xp + ) + + var/json_to_file = json_encode(to_save) + if(!json_to_file) + log_debug("Saving: [save_path] failed jsonencode") + return + + //Write it out + rustg_file_write(json_to_file, save_path) + + if(!fexists(save_path)) + log_debug("Saving: [save_path] failed file write") + + if(shutting_down) + ourmob = null + qdel(src) + +/datum/etching/proc/setup() + + log_debug("setup") + + return + +/mob/proc/magic_rename(var/old_name,var/new_name) + var/old_path = "data/player_saves/[copytext(ckey, 1, 2)]/[ckey]/magic/[old_name]-etching.json" + if(!fexists(old_path)) + return + var/list/load = json_decode(file2text(old_path)) + + var/new_path = "data/player_saves/[copytext(ckey, 1, 2)]/[ckey]/magic/[new_name]-etching.json" + + if(isliving(src)) //We might be playing as the mob we want to rename + var/mob/living/L = src + if(L.real_name == old_name) //We are + var/datum/etching/E = L.etching + E.save_path = new_path //Update the save path, in case we need to save again later to the mob's new name + + var/json_to_file = json_encode(load) + if(!json_to_file) + log_debug("Saving: [new_path] failed jsonencode on rename function") + return + + //Write it out + rustg_file_write(json_to_file, new_path) + + if(!fexists(new_path)) + log_debug("Saving: [new_path] failed file write on rename function") + return + fdel(old_path) + if(fexists(old_path)) + log_debug("Saving: [old_path] failed to delete on rename function") + return diff --git a/vorestation.dme b/vorestation.dme index 73c25aee3ba..a3aed9811b4 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -2979,6 +2979,7 @@ #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_powers.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm" +#include "code\modules\mob\living\Magic\magic.dm" #include "code\modules\mob\living\silicon\death.dm" #include "code\modules\mob\living\silicon\emote.dm" #include "code\modules\mob\living\silicon\laws.dm" From 947e9b6ca6ef90f035e88c6a464d39a31112110a Mon Sep 17 00:00:00 2001 From: VerySoft Date: Fri, 14 Jun 2024 00:02:58 -0400 Subject: [PATCH 2/5] 0002 --- code/modules/mob/living/Magic/magic.dm | 28 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/code/modules/mob/living/Magic/magic.dm b/code/modules/mob/living/Magic/magic.dm index d61b8321090..83962879e06 100644 --- a/code/modules/mob/living/Magic/magic.dm +++ b/code/modules/mob/living/Magic/magic.dm @@ -87,10 +87,11 @@ try content = file2text(save_path) catch(var/exception/E_content) - error("Exception when loading etching content - [save_path] - [content]: [E_content]") + error("Exception when loading etching content - Path: [save_path] - Content: [content]: [E_content]") if(!content) - error("Etching failed to load for [ourmob.real_name], aborting.") + log_debug("Etching failed to load for [ourmob.real_name], aborting and clearing save_path.") + save_path = null return var/list/load @@ -98,10 +99,11 @@ try load = json_decode(file2text(save_path)) catch(var/exception/E_json_decode) - error("Exception decoding etching content - [save_path] - [load]: [E_json_decode]") + error("Exception decoding etching content - Path: [save_path] - Content: [content] - Load: [load]: [E_json_decode]") if(!load) - log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: [] ") + log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: '[content]'. Aborting and clearing save_path.") + save_path = null return true_name = load["true_name"] @@ -117,8 +119,6 @@ /datum/etching/proc/save(delet = FALSE) if(IsGuestKey(ourmob.key)) return - if(!ourmob.ckey) - return if(shutting_down) //Don't try to save more than once if we're already saving and shutting down. return @@ -138,13 +138,23 @@ "xp" = xp ) - var/json_to_file = json_encode(to_save) + var/json_to_file + try + throw EXCEPTION("Load stage 1 fail") + json_to_file = json_encode(to_save) + catch + error("Etching failed to encode to json for [ourmob.real_name]") + if(!json_to_file) - log_debug("Saving: [save_path] failed jsonencode") + log_debug("Saving: [save_path] failed json encode.") return //Write it out - rustg_file_write(json_to_file, save_path) + try + throw EXCEPTION("Saving stage 2 fail") + rustg_file_write(json_to_file, save_path) + catch + error("Etching failed to write to file for [ourmob.real_name]: [json_to_file] - [save_path]") if(!fexists(save_path)) log_debug("Saving: [save_path] failed file write") From 5bc6f92dac333851b38898b76b7dd0259c6a99b5 Mon Sep 17 00:00:00 2001 From: VerySoft Date: Sun, 16 Jun 2024 17:55:24 -0400 Subject: [PATCH 3/5] 1755 --- code/modules/client/stored_item.dm | 49 ++++++++++- code/modules/mob/living/Magic/magic.dm | 115 +++++++++++++++++++++---- 2 files changed, 147 insertions(+), 17 deletions(-) diff --git a/code/modules/client/stored_item.dm b/code/modules/client/stored_item.dm index cd0f8829d29..224b9bfc864 100644 --- a/code/modules/client/stored_item.dm +++ b/code/modules/client/stored_item.dm @@ -74,7 +74,7 @@ busy_bank = TRUE var/I = persist_item_savefile_load(user, "type") var/Iname = persist_item_savefile_load(user, "name") - var/choice = tgui_alert(user, "What would you like to do [src]?", "[src]", list("Check contents", "Retrieve item", "Info", "Cancel"), timeout = 10 SECONDS) + var/choice = tgui_alert(user, "What would you like to do [src]?", "[src]", list("Check contents", "Retrieve item","Retrieve Coin", "Info", "Cancel"), timeout = 10 SECONDS) if(!choice || choice == "Cancel" || !Adjacent(user) || inoperable() || panel_open) busy_bank = FALSE return @@ -117,6 +117,40 @@ to_chat(user, "\The [src] can store a single item for you between shifts! Anything that has been retrieved from the bank cannot be stored again in the same shift. Anyone can withdraw from the bank one time per shift. Some items are not able to be accepted by the bank.") busy_bank = FALSE return + else if(choice == "Retrieve Coin") + if(user.etching) + var/datum/etching/E = user.etching + if(E.triangles <= 0) + to_chat(user, "You haven't got any coins banked...") + return + else + var/ourtris = tgui_input_number(user, "How much would you like to withdraw? You have ◬:[E.triangles] banked.", "Withdraw", timeout = 10 SECONDS) + if(ourtris <= 0) + busy_bank = FALSE + return + if(ourtris > E.triangles) + to_chat(user, "\The [src] buzzes at you and flashes red. You do not have ◬:[ourtris] banked. You have a balance of ◬:[E.triangles]...") + busy_bank = FALSE + return + ourtris = round(ourtris) + E.triangles -= ourtris + visible_message("\The [src] rattles as it dispenses coins!") + busy_bank = FALSE + var/turf/here = get_turf(src) + while(ourtris > 0) + if(ourtris >= 20) + new /obj/item/weapon/aliencoin/phoron(here) + ourtris -= 20 + else if(ourtris >= 10) + new /obj/item/weapon/aliencoin/gold(here) + ourtris -= 10 + else if(ourtris >= 5) + new /obj/item/weapon/aliencoin/silver(here) + ourtris -= 5 + else + new /obj/item/weapon/aliencoin/basic(here) + ourtris -- + else if(!I) to_chat(user, "\The [src] doesn't seem to have anything for you...") busy_bank = FALSE @@ -128,6 +162,17 @@ to_chat(user, "\The [src] is already in use.") return busy_bank = TRUE + //RS EDIT BEGIN + if(istype(O, /obj/item/weapon/aliencoin)) + if(user.etching) + var/obj/item/weapon/aliencoin/coin = O + user.update_etching("triangles", coin.value) + user.drop_item() + to_chat(user, "\The [src] SCHLORPS up \the [O]!!!") + qdel(O) + busy_bank = FALSE + return + //RS EDIT END var/I = persist_item_savefile_load(user, "type") if(!istool(O) && O.persist_storable) if(ispath(I)) @@ -255,4 +300,4 @@ /obj/item/weapon/spacecasinocash persist_storable = FALSE /obj/item/device/personal_shield_generator - persist_storable = FALSE \ No newline at end of file + persist_storable = FALSE diff --git a/code/modules/mob/living/Magic/magic.dm b/code/modules/mob/living/Magic/magic.dm index 83962879e06..ac90c650592 100644 --- a/code/modules/mob/living/Magic/magic.dm +++ b/code/modules/mob/living/Magic/magic.dm @@ -18,23 +18,29 @@ /mob/living/Life() . = ..() - process_magic() + if(etching) + etching.process_etching() /mob/living/proc/init_magic() - if(ishuman(src) || isanimal(src)) + if((ishuman(src) && !(istype(src, /mob/living/carbon/human/dummy))) || isanimal(src)) etching = new /datum/etching(src) -/mob/living/proc/process_magic() - if(!etching) - return - var/datum/etching/E = etching - if(E.mana < E.max_mana) - E.mana += E.mana_regen - if(E.mana_cooldown) - E.mana_cooldown -- +/mob/living/proc/update_etching(mode,value) + if(etching) + etching.update_etching(mode,value) + +/mob/living/proc/grant_xp(kind,value) + if(etching) + etching.grant_xp(kind,value) + +/mob/living/memory() + . = ..() + if(etching) + etching.report_status() /datum/etching var/mob/living/ourmob //Reference to the mob we are working with + var/event_character = FALSE //If true, saves to an alternative path and allows editing var/true_name //Magic bs var/mana = 0 //How much you have var/max_mana = 0 //How much you could have @@ -49,6 +55,12 @@ var/save_path //The file path for the save/load function var/list/xp = list() //A list of different experience values + var/triangles = 0 //Triangle money + + var/savable = TRUE //Will never save while false + var/needs_saving = FALSE //For if changes have occured, it will try to save if it can + var/save_cooldown = 0 + /datum/etching/New(var/L) log_debug("ETCHING STARTED") if(!L) @@ -57,26 +69,46 @@ return ourmob = L log_debug("Etching: Registered to [ourmob]") + save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. return ..() /datum/etching/Destroy() . = ..() ourmob = null +/datum/etching/proc/process_etching() + if(mana < max_mana) + mana += mana_regen + if(mana_cooldown) + mana_cooldown -- + + if(savable) + if(save_cooldown <= 0) + save() + save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. + else + save_cooldown -- + /datum/etching/proc/get_save_path() - return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-etching.json" + + if(event_character) + return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-EVENT-etching.json" + else + return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-etching.json" /datum/etching/proc/load() if(IsGuestKey(ourmob.key)) return if(!ourmob.ckey) log_debug("Aborting etching load for [ourmob.real_name], no ckey") + savable = FALSE return save_path = get_save_path() if(!save_path) log_debug("Etching load failed: No save_path") + savable = FALSE return if(!fexists(save_path)) log_debug("Etching load failed: No file '[save_path]' exists. Beginning setup.") @@ -92,6 +124,7 @@ if(!content) log_debug("Etching failed to load for [ourmob.real_name], aborting and clearing save_path.") save_path = null + savable = FALSE return var/list/load @@ -104,6 +137,7 @@ if(!load) log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: '[content]'. Aborting and clearing save_path.") save_path = null + savable = FALSE return true_name = load["true_name"] @@ -113,10 +147,13 @@ l_leg = load["l_leg"] r_leg = load["r_leg"] xp = load["xp"] + triangles = load["triangles"] log_debug("Etching load complete for [ourmob.real_name].") /datum/etching/proc/save(delet = FALSE) + if(!savable || !needs_saving) + return if(IsGuestKey(ourmob.key)) return @@ -125,7 +162,10 @@ if(delet) //Our mob got deleted, so we're saving and quitting. shutting_down = TRUE - if(!save_path) + if(!save_path || !ishuman(ourmob) || istype(ourmob, /mob/living/carbon/human/dummy)) + if(shutting_down) + ourmob = null + qdel(src) return var/list/to_save = list( @@ -135,12 +175,12 @@ "r_arm" = r_arm, "l_leg" = l_leg, "r_leg" = r_leg, - "xp" = xp + "xp" = xp, + "triangles" = triangles ) var/json_to_file try - throw EXCEPTION("Load stage 1 fail") json_to_file = json_encode(to_save) catch error("Etching failed to encode to json for [ourmob.real_name]") @@ -151,7 +191,6 @@ //Write it out try - throw EXCEPTION("Saving stage 2 fail") rustg_file_write(json_to_file, save_path) catch error("Etching failed to write to file for [ourmob.real_name]: [json_to_file] - [save_path]") @@ -159,6 +198,8 @@ if(!fexists(save_path)) log_debug("Saving: [save_path] failed file write") + needs_saving = FALSE + if(shutting_down) ourmob = null qdel(src) @@ -198,3 +239,47 @@ if(fexists(old_path)) log_debug("Saving: [old_path] failed to delete on rename function") return + +/datum/etching/proc/update_etching(mode,value) + switch(mode) + if("triangles") + triangles += value + + needs_saving = TRUE + +/datum/etching/proc/grant_xp(kind,value) + xp["[kind]"] += value + needs_saving = TRUE + +/datum/etching/proc/report_status() + if(!save_path) + return + . = ": [triangles]\n\n" + + var/extra = FALSE + if(core) + . += "Core: [core]\n" + extra = TRUE + if(l_arm) + . += "[l_arm]\n" + extra = TRUE + if(r_arm) + . += "[r_arm]\n" + extra = TRUE + if(l_arm) + . += "[l_leg]\n" + extra = TRUE + if(r_leg) + . += "[r_leg]\n" + extra = TRUE + + if(extra) + . += "\n" + + for(var/thing in xp) + . += "[thing]: [xp[thing]]\n" + + to_chat(ourmob, .) + +/datum/etching/vv_edit_var(var_name, var_value) + return FALSE From ed1592e1754a7f5c30d84a936ab30d4a9855c3ad Mon Sep 17 00:00:00 2001 From: VerySoft Date: Tue, 25 Jun 2024 13:44:59 -0400 Subject: [PATCH 4/5] 1344 --- code/modules/mob/living/Magic/healing.dm | 47 +++++++++++++++++++++++ code/modules/mob/living/Magic/magic.dm | 48 ++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 code/modules/mob/living/Magic/healing.dm diff --git a/code/modules/mob/living/Magic/healing.dm b/code/modules/mob/living/Magic/healing.dm new file mode 100644 index 00000000000..0f524caa1f7 --- /dev/null +++ b/code/modules/mob/living/Magic/healing.dm @@ -0,0 +1,47 @@ +/////HEALING MAGIC///// + +/mob/living/proc/regenerate_other() + set name = "Regenerate" + set desc = "Spend energy to heal physical wounds in another creature." + set category = "Magic" + + if(!etching) + to_chat("You can't do magic.") //:C + return FALSE + + var/spell_lv = 1 //Determines how many slots you need devoted to this magic + var/spell_class = HEALING_MAGIC //Used with above, this is the kind of magic you need + var/req_standing = TRUE //If true, must be on your feet and unrestrained + var/req_corporeal = TRUE //If true, must not be phased out or otherwise ghostly + var/req_visible = TRUE //If true, must not be invisible + var/cost = 0 //Automatically determined by a variety of factors + + if(!admin_magic) + cost = etching.calculate_magic_cost(spell_class,spell_lv) + + if(!consider_magic(cost,spell_class,spell_lv,req_standing,req_corporeal,req_visible)) + return FALSE + + //Unique stuff goes beween here! + + var/list/viewed = oviewers(1) + var/list/targets = list() + for(var/mob/living/L in viewed) + targets += L + if(!targets.len) + to_chat(src,"Nobody nearby to mend!") + return FALSE + + var/mob/living/target = tgui_input_list(src,"Pick someone to mend:","Mend Other", targets) + if(!target) + return FALSE + + target.add_modifier(/datum/modifier/shadekin/heal_boop,1 MINUTE) + playsound(src, 'sound/effects/EMPulse.ogg', 75, 1) + visible_message("\The [src] touches \the [target]...") + face_atom(target) + + //STOP BEING UNIQUE + + consume_magic(cost, spell_lv) + return TRUE diff --git a/code/modules/mob/living/Magic/magic.dm b/code/modules/mob/living/Magic/magic.dm index ac90c650592..07eaea4ce24 100644 --- a/code/modules/mob/living/Magic/magic.dm +++ b/code/modules/mob/living/Magic/magic.dm @@ -1,5 +1,11 @@ +#define BASE_MAGIC_COOLDOWN = 15 +#define BASE_MAGIC_COST = 33 + +#define HEALING_MAGIC = "healing" + /mob/living var/datum/etching/etching + var/admin_magic = FALSE /mob/living/Initialize() . = ..() @@ -38,6 +44,29 @@ if(etching) etching.report_status() +/mob/living/proc/consider_magic(cost,spell_class,spell_lv,req_standing,req_corporeal,req_visible) + if(!etching.consider_magic(cost,spell_class,spell_lv)) + return FALSE + if(req_standing && (resting||weakened||buckled)) //Buckled is assuming that we might be restrained. Not bothering with checking carbon handcuffs, since nets exist and I am pretty sure that's just a buckle + to_chat(src, "You need to be standing and free to move around to do that!") + return FALSE + if(req_corporeal && incorporeal_move) + to_chat(src, "Can't do that while phased out!") + return FALSE + if(req_visible && invisibility) + to_chat(src, "Can't do that without revealing yourself!") + return FALSE + return TRUE + +/mob/living/proc/consume_mana(cost,spell_lv) + if(cost <= 0) + return + etching.mana -= cost + + if(etching.mana < 0) + etching.mana = 0 + etching.mana_cooldown = BASE_MAGIC_COOLDOWN * spell_lv //life tick * lv = about 30 seconds per level + /datum/etching var/mob/living/ourmob //Reference to the mob we are working with var/event_character = FALSE //If true, saves to an alternative path and allows editing @@ -46,6 +75,7 @@ var/max_mana = 0 //How much you could have var/mana_regen = 0 //How fast it comes back var/mana_cooldown = 0 //How soon you can do it again + var/mana_efficiency = 1 //Multiplier for how efficiently you use your mana var/core //Head/body var/l_arm var/r_arm @@ -283,3 +313,21 @@ /datum/etching/vv_edit_var(var_name, var_value) return FALSE + +/datum/etching/proc/consider_magic(cost,spell_class,spell_lv) + if(admin_magic) + return TRUE + if(mana_cooldown) + to_chat(ourmob, "You are still recovering! (([mana_cooldown]))") + return FALSE + if(cost > mana) + to_chat(ourmob, "You haven't got enough mana! (([mana]/[cost]))") + return FALSE + +// if(not some_kind_of_level_check()) +// return FALSE + + return TRUE + +/datum/etching/proc/calculate_magic_cost(spell_class,spell_lv) + return (BASE_MAGIC_COST * spell_lv) * mana_efficiency From 2c6bfc4dc193d0ce7c35682b6d46d2a3c21fb50d Mon Sep 17 00:00:00 2001 From: VerySoft Date: Fri, 6 Dec 2024 01:11:47 -0500 Subject: [PATCH 5/5] 0111 --- code/__defines/admin_vr.dm | 1 + code/modules/admin/verbs/smite.dm | 5 +- code/modules/client/stored_item.dm | 56 ++- .../character_persistance_core.dm | 330 ++++++++++++++++++ code/modules/mob/living/Magic/magic.dm | 244 ++----------- code/modules/mob/living/item_storage.dm | 70 ++++ 6 files changed, 464 insertions(+), 242 deletions(-) create mode 100644 code/modules/mob/living/Character Persist/character_persistance_core.dm create mode 100644 code/modules/mob/living/item_storage.dm diff --git a/code/__defines/admin_vr.dm b/code/__defines/admin_vr.dm index 5cc4ac22992..74720299284 100644 --- a/code/__defines/admin_vr.dm +++ b/code/__defines/admin_vr.dm @@ -4,3 +4,4 @@ #define SMITE_AD_SPAM "Ad Spam" #define SMITE_AUTOSAVE "10 Second Autosave" #define SMITE_AUTOSAVE_WIDE "10 Second Autosave (AoE)" +#define SMITE_XP "Grant XP" diff --git a/code/modules/admin/verbs/smite.dm b/code/modules/admin/verbs/smite.dm index 9ecaeec1a54..d9eef63d5dd 100644 --- a/code/modules/admin/verbs/smite.dm +++ b/code/modules/admin/verbs/smite.dm @@ -8,7 +8,7 @@ if(!istype(target)) return - var/list/smite_types = list(SMITE_BREAKLEGS,SMITE_BLUESPACEARTILLERY,SMITE_SPONTANEOUSCOMBUSTION,SMITE_LIGHTNINGBOLT, + var/list/smite_types = list(SMITE_XP,SMITE_BREAKLEGS,SMITE_BLUESPACEARTILLERY,SMITE_SPONTANEOUSCOMBUSTION,SMITE_LIGHTNINGBOLT, SMITE_SHADEKIN_ATTACK,SMITE_SHADEKIN_NOMF,SMITE_AD_SPAM,SMITE_REDSPACE_ABDUCT,SMITE_AUTOSAVE,SMITE_AUTOSAVE_WIDE) var/smite_choice = tgui_input_list(usr, "Select the type of SMITE for [target]","SMITE Type Choice", smite_types) @@ -157,7 +157,8 @@ if(SMITE_AD_SPAM) if(target.client) target.client.create_fake_ad_popup_multiple(/obj/screen/popup/default, 15) - + if(SMITE_XP) + target.grant_xp() else return //Injection? Don't print any messages. diff --git a/code/modules/client/stored_item.dm b/code/modules/client/stored_item.dm index 224b9bfc864..052b6b6161e 100644 --- a/code/modules/client/stored_item.dm +++ b/code/modules/client/stored_item.dm @@ -51,6 +51,10 @@ F["persist name"] >> persist_name return persist_name +/obj/machinery/item_bank/proc/legacy_detect(mob/living/user) + if (fexists(src.persist_item_savefile_path(user))) + return TRUE + return FALSE /obj/machinery/item_bank/Initialize() . = ..() @@ -72,16 +76,22 @@ to_chat(user, "\The [src] is already in use.") return busy_bank = TRUE - var/I = persist_item_savefile_load(user, "type") - var/Iname = persist_item_savefile_load(user, "name") - var/choice = tgui_alert(user, "What would you like to do [src]?", "[src]", list("Check contents", "Retrieve item","Retrieve Coin", "Info", "Cancel"), timeout = 10 SECONDS) + if(legacy_detect(user)) + if(tgui_alert(user, "A legacy item has been detected in storage. This item must be bound to a character. Would you like to add it to [user.real_name]'s general storage?", "[src] legacy item detected", list("Yes","No"), timeout = 10 SECONDS) == "Yes") + + var/itemname = persist_item_savefile_load(user, "name") + var/itemtype = persist_item_savefile_load(user, "type") + user.etching.legacy_conversion(itemname,itemtype) + var/path = src.persist_item_savefile_path(user) +// fdel(path) + log_debug("[user]/[user.ckey] converted a legacy item persist file to an item_storage state. Item was, [itemname] - [itemtype]") + busy_bank = FALSE + return + var/choice = tgui_alert(user, "What would you like to do [src]?", "[src]", list("Retrieve item","Retrieve Coin", "Info", "Cancel"), timeout = 10 SECONDS) if(!choice || choice == "Cancel" || !Adjacent(user) || inoperable() || panel_open) busy_bank = FALSE return - else if(choice == "Check contents" && I) - to_chat(user, "\The [src] has \the [Iname] for you!") - busy_bank = FALSE - else if(choice == "Retrieve item" && I) + else if(choice == "Retrieve item") if(user.hands_are_full()) to_chat(user,"Your hands are full!") busy_bank = FALSE @@ -90,7 +100,17 @@ to_chat(user, "You have already taken something out of \the [src] this shift.") busy_bank = FALSE return - choice = tgui_alert(user, "If you remove this item from the bank, it will be unable to be stored again. Do you still want to remove it?", "[src]", list("No", "Yes"), timeout = 10 SECONDS) + var/list/our_item = list() + if(user.etching.item_storage.len) + our_item = tgui_input_list(user, "Which item would you like to retrieve?", "[src]",user.etching.item_storage) + if(!our_item) + busy_bank = FALSE + return + else + to_chat(user, "\The [src] doesn't seem to have anything for you...") + busy_bank = FALSE + return + choice = tgui_alert(user, "If you remove \the [our_item] from the bank, it will be unable to be stored again. Do you still want to remove it?", "[src]", list("No", "Yes"), timeout = 10 SECONDS) icon_state = "item_bank_o" if(!choice || choice == "No" || !Adjacent(user) || inoperable() || panel_open) busy_bank = FALSE @@ -100,21 +120,20 @@ busy_bank = FALSE icon_state = "item_bank" return - var/obj/N = new I(get_turf(src)) + var/ourtype = user.etching.item_storage[our_item] + var/obj/N = new ourtype(get_turf(src)) log_admin("[key_name_admin(user)] retrieved [N] from the item bank.") visible_message("\The [src] dispenses the [N] to \the [user].") user.put_in_hands(N) N.persist_storable = FALSE - var/path = src.persist_item_savefile_path(user) - var/savefile/F = new /savefile(src.persist_item_savefile_path(user)) - F["persist item"] << null - F["persist name"] << null - fdel(path) item_takers += user.ckey + user.etching.item_storage -= our_item + user.etching.needs_saving = TRUE busy_bank = FALSE icon_state = "item_bank" + else if(choice == "Info") - to_chat(user, "\The [src] can store a single item for you between shifts! Anything that has been retrieved from the bank cannot be stored again in the same shift. Anyone can withdraw from the bank one time per shift. Some items are not able to be accepted by the bank.") + to_chat(user, "\The [src] can store items for you between shifts! Anything that has been retrieved from the bank cannot be stored again in the same shift. Anyone can withdraw from the bank one time per shift. Some items are not able to be accepted by the bank.") busy_bank = FALSE return else if(choice == "Retrieve Coin") @@ -151,10 +170,6 @@ new /obj/item/weapon/aliencoin/basic(here) ourtris -- - else if(!I) - to_chat(user, "\The [src] doesn't seem to have anything for you...") - busy_bank = FALSE - /obj/machinery/item_bank/attackby(obj/item/O, mob/living/user) if(!ishuman(user)) return @@ -173,6 +188,8 @@ busy_bank = FALSE return //RS EDIT END + user.etching.store_item(O,src) +/* //RS REMOVAL START - //Removed the old way of storing items, as it is no longer needed. var/I = persist_item_savefile_load(user, "type") if(!istool(O) && O.persist_storable) if(ispath(I)) @@ -203,6 +220,7 @@ else to_chat(user, "You cannot store \the [O]. \The [src] either does not accept that, or it has already been retrieved from storage this shift.") busy_bank = FALSE +*/ //RS REMOVAL END /////STORABLE ITEMS AND ALL THAT JAZZ///// //I am only really intending this to be used for single items. Mostly stuff you got right now, but can't/don't want to use right now. diff --git a/code/modules/mob/living/Character Persist/character_persistance_core.dm b/code/modules/mob/living/Character Persist/character_persistance_core.dm new file mode 100644 index 00000000000..41a3487a8a2 --- /dev/null +++ b/code/modules/mob/living/Character Persist/character_persistance_core.dm @@ -0,0 +1,330 @@ +/mob/living + var/datum/etching/etching + var/admin_magic = FALSE + +/mob/living/Initialize() + . = ..() + init_etching() + +/mob/living/Login() + . = ..() + if(etching) + etching.load() + +/mob/living/Destroy() + if(etching && istype(etching, /datum/etching)) + etching.save(TRUE) + ..() + +/mob/living/Life() + . = ..() + if(etching) + etching.process_etching() + +/mob/living/proc/init_etching() + if((ishuman(src) && !(istype(src, /mob/living/carbon/human/dummy))) || isanimal(src)) + etching = new /datum/etching(src) + +/mob/living/proc/update_etching(mode,value) + if(etching) + etching.update_etching(mode,value) + +/mob/living/proc/grant_xp(kind,value) + if(!etching) + return + if(!kind || !value) + var/list/xp_list = list() + xp_list += etching.xp + xp_list += "New kind of XP" + kind = tgui_input_list(usr, "What kind of XP would you like to add?", "Grant XP", xp_list) + if(!kind) + return + if(kind == "New kind of XP") + kind = tgui_input_text(usr, "What kind of XP would you like to add?", "Grant XP", prevent_enter = TRUE) + value = tgui_input_number(usr, "How many [kind] should be granted?", "Grant [kind]") + if(!value) + return + + etching.grant_xp(kind,value) + +/mob/living/memory() + . = ..() + if(etching) + etching.report_status() + +/datum/etching + var/mob/living/ourmob //Reference to the mob we are working with + var/event_character = FALSE //If true, saves to an alternative path and allows editing + + var/shutting_down = FALSE //If true it won't try to save again + var/save_path //The file path for the save/load function + var/list/xp = list() //A list of different experience values + + var/savable = TRUE //Will never save while false + var/needs_saving = FALSE //For if changes have occured, it will try to save if it can + var/save_cooldown = 0 + +/datum/etching/New(var/L) + log_debug("ETCHING STARTED") + if(!L) + log_debug("Etching: No target, delete self") + qdel(src) + return + if(!isliving(L)) + log_debug("Etching: Target [L] is not living, delete self") + qdel(src) + return + ourmob = L + log_debug("Etching: Registered to [ourmob.ckey]") + save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. + return ..() + +/datum/etching/Destroy() + . = ..() + ourmob = null + +/datum/etching/proc/process_etching() + if(savable) + if(save_cooldown <= 0) + save() + save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. + else + save_cooldown -- + +/datum/etching/proc/get_save_path() + + if(event_character) + save_path = "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-EVENT-etching.json" + else + save_path = "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-etching.json" + +/datum/etching/proc/load() + if(IsGuestKey(ourmob.key)) + return + if(!ourmob.ckey) + log_debug("Aborting etching load for [ourmob.real_name], no ckey") + savable = FALSE + return + + get_save_path() + + if(!save_path) + log_debug("Etching load failed: No save_path") + savable = FALSE + return + if(!fexists(save_path)) + log_debug("Etching load failed: No file '[save_path]' exists. Beginning setup.") + setup() + return + + var/content + try + content = file2text(save_path) + catch(var/exception/E_content) + error("Exception when loading etching content - Path: [save_path] - Content: [content]: [E_content]") + + if(!content) + log_debug("Etching failed to load for [ourmob.real_name], aborting and clearing save_path.") + save_path = null + savable = FALSE + return + + var/list/load + + try + load = json_decode(file2text(save_path)) + catch(var/exception/E_json_decode) + error("Exception decoding etching content - Path: [save_path] - Content: [content] - Load: [load]: [E_json_decode]") + + if(!load) + log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: '[content]'. Aborting and clearing save_path.") + save_path = null + savable = FALSE + return + + true_name = load["true_name"] + core = load["core"] + l_arm = load["l_arm"] + r_arm = load["r_arm"] + l_leg = load["l_leg"] + r_leg = load["r_leg"] + xp = null + xp = load["xp"] + triangles = load["triangles"] + item_storage = null + item_storage = load["item_storage"] + unlockables = load["unlockables"] + + log_debug("Etching load complete for [ourmob.real_name].") + +/datum/etching/proc/save(delet = FALSE) + if(IsGuestKey(ourmob.key)) + return + + if((!savable && !event_character) || !needs_saving) + return + + if(shutting_down) //Don't try to save more than once if we're already saving and shutting down. + return + if(delet) //Our mob got deleted, so we're saving and quitting. + shutting_down = TRUE + + if(!save_path || !ishuman(ourmob) || istype(ourmob, /mob/living/carbon/human/dummy)) + if(shutting_down) + ourmob = null + qdel(src) + return + + var/list/to_save = list( + "true_name" = true_name, + "core" = core, + "l_arm" = l_arm, + "r_arm" = r_arm, + "l_leg" = l_leg, + "r_leg" = r_leg, + "xp" = xp, + "triangles" = triangles, + "item_storage" = item_storage, + "unlockables" = unlockables + ) + + var/json_to_file + try + json_to_file = json_encode(to_save) + catch + error("Etching failed to encode to json for [ourmob.real_name]") + + if(!json_to_file) + log_debug("Saving: [save_path] failed json encode.") + return + + //Write it out + try + rustg_file_write(json_to_file, save_path) + catch + error("Etching failed to write to file for [ourmob.real_name]: [json_to_file] - [save_path]") + + if(!fexists(save_path)) + log_debug("Saving: [save_path] failed file write") + + needs_saving = FALSE + + if(shutting_down) + ourmob = null + qdel(src) + +/datum/etching/proc/setup() + + log_debug("setup") + + return + +/datum/etching/proc/update_etching(mode,value) + needs_saving = TRUE + +/datum/etching/proc/grant_xp(kind,value) + xp["[kind]"] += value + to_chat(ourmob,"You earned [value] [kind]!") + needs_saving = TRUE + +/datum/etching/proc/report_status() + if(!save_path) + return + + var/our_xp = report_xp() + if(our_xp) + . = our_xp + + var/our_magic = report_magic() + if(our_magic) + if(.) + . += "\n" + . += our_magic + + var/our_money = report_money() + if(our_money) + if(.) + . += "\n" + . += our_money + + to_chat(ourmob, .) + +/datum/etching/proc/report_xp() + for(var/thing in xp) + . += "[capitalize(thing)]: [xp[thing]]\n" + +/datum/etching/vv_edit_var(var_name, var_value) + to_world("[var_name]") + if(var_name == "event_character") + enable_event_character() + return + else if(var_name == "savable") + return FALSE + else if(var_name == "unlockables") + return FALSE + if(!event_character) + return FALSE + + else + needs_saving = TRUE + return ..() + +/datum/etching/get_view_variables_options() + return ..() + {" + + + + + "} + +/datum/etching/proc/enable_event_character() + event_character = TRUE + get_save_path() + savable = FALSE + +/client/view_var_Topic(href, href_list, hsrc) + . = ..() + + if(href_list["event_etching"]) + if(!check_rights(R_FUN)) return + + var/mob/living/L = locate(href_list["event_etching"]) + if(!L.etching) + to_chat(usr, "\The [L] has no etching.") + return + if(tgui_alert(usr, "Enable event mode for [L]'s etching? This will disable normal saving, but enable variable editing.","Confirm",list("Enable","Cancel")) != "Enable") return + + if(!L) + to_chat(usr, "\The [L] no longer exists.") + return + if(!L.etching) + to_chat(usr, "\The [L] has no etching.") + return + L.etching.enable_event_character() + if(href_list["save_etching"]) + if(!check_rights(R_FUN)) return + + var/mob/living/L = locate(href_list["save_etching"]) + if(!L.etching) + to_chat(usr, "\The [L] has no etching.") + return + if(!L.etching.savable && !L.etching.event_character) + to_chat(usr, "\The [L]'s etching can not be saved in this state.") + return + if(L.etching.event_character) + to_chat(usr, "Saving [L]'s event etching.") + else + to_chat(usr, "Saving [L]'s etching.") + L.etching.save() + if(href_list["load_etching"]) + if(!check_rights(R_FUN)) return + + var/mob/living/L = locate(href_list["load_etching"]) + if(!L.etching) + to_chat(usr, "\The [L] has no etching.") + return + if(L.etching.event_character) + to_chat(usr, "Loading [L]'s event etching.") + else + to_chat(usr, "Loading [L]'s etching.") + L.etching.load() diff --git a/code/modules/mob/living/Magic/magic.dm b/code/modules/mob/living/Magic/magic.dm index 07eaea4ce24..97a6ad2e701 100644 --- a/code/modules/mob/living/Magic/magic.dm +++ b/code/modules/mob/living/Magic/magic.dm @@ -1,48 +1,13 @@ -#define BASE_MAGIC_COOLDOWN = 15 -#define BASE_MAGIC_COST = 33 +/* +TO DO: +Add grant xp smite +make sure multiple instances of grant xp are additive, and don't overwrite +*/ -#define HEALING_MAGIC = "healing" - -/mob/living - var/datum/etching/etching - var/admin_magic = FALSE - -/mob/living/Initialize() - . = ..() - init_magic() - -/mob/living/Login() - . = ..() - if(etching) - etching.load() - -/mob/living/Destroy() - if(etching) - var/datum/etching/E = etching - E.save(TRUE) - ..() - -/mob/living/Life() - . = ..() - if(etching) - etching.process_etching() +#define BASE_MAGIC_COOLDOWN 15 +#define BASE_MAGIC_COST 33 -/mob/living/proc/init_magic() - if((ishuman(src) && !(istype(src, /mob/living/carbon/human/dummy))) || isanimal(src)) - etching = new /datum/etching(src) - -/mob/living/proc/update_etching(mode,value) - if(etching) - etching.update_etching(mode,value) - -/mob/living/proc/grant_xp(kind,value) - if(etching) - etching.grant_xp(kind,value) - -/mob/living/memory() - . = ..() - if(etching) - etching.report_status() +#define HEALING_MAGIC = "healing" /mob/living/proc/consider_magic(cost,spell_class,spell_lv,req_standing,req_corporeal,req_visible) if(!etching.consider_magic(cost,spell_class,spell_lv)) @@ -61,15 +26,9 @@ /mob/living/proc/consume_mana(cost,spell_lv) if(cost <= 0) return - etching.mana -= cost - - if(etching.mana < 0) - etching.mana = 0 - etching.mana_cooldown = BASE_MAGIC_COOLDOWN * spell_lv //life tick * lv = about 30 seconds per level + etching.consume_mana(cost,spell_lv) /datum/etching - var/mob/living/ourmob //Reference to the mob we are working with - var/event_character = FALSE //If true, saves to an alternative path and allows editing var/true_name //Magic bs var/mana = 0 //How much you have var/max_mana = 0 //How much you could have @@ -81,164 +40,25 @@ var/r_arm var/l_leg var/r_leg - var/shutting_down = FALSE //If true it won't try to save again - var/save_path //The file path for the save/load function - var/list/xp = list() //A list of different experience values - - var/triangles = 0 //Triangle money - - var/savable = TRUE //Will never save while false - var/needs_saving = FALSE //For if changes have occured, it will try to save if it can - var/save_cooldown = 0 - -/datum/etching/New(var/L) - log_debug("ETCHING STARTED") - if(!L) - log_debug("Etching: No target, delete self") - qdel(src) - return - ourmob = L - log_debug("Etching: Registered to [ourmob]") - save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. - return ..() /datum/etching/Destroy() . = ..() ourmob = null -/datum/etching/proc/process_etching() +/datum/etching/process_etching() + . = ..() if(mana < max_mana) mana += mana_regen if(mana_cooldown) mana_cooldown -- - if(savable) - if(save_cooldown <= 0) - save() - save_cooldown = rand(200,350) //Make the number be random so that there's less chance it tries to autosave everyone at the same time. - else - save_cooldown -- - -/datum/etching/proc/get_save_path() - - if(event_character) - return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-EVENT-etching.json" - else - return "data/player_saves/[copytext(ourmob.ckey, 1, 2)]/[ourmob.ckey]/magic/[ourmob.real_name]-etching.json" - -/datum/etching/proc/load() - if(IsGuestKey(ourmob.key)) - return - if(!ourmob.ckey) - log_debug("Aborting etching load for [ourmob.real_name], no ckey") - savable = FALSE - return - - save_path = get_save_path() - - if(!save_path) - log_debug("Etching load failed: No save_path") - savable = FALSE - return - if(!fexists(save_path)) - log_debug("Etching load failed: No file '[save_path]' exists. Beginning setup.") - setup() - return - - var/content - try - content = file2text(save_path) - catch(var/exception/E_content) - error("Exception when loading etching content - Path: [save_path] - Content: [content]: [E_content]") - - if(!content) - log_debug("Etching failed to load for [ourmob.real_name], aborting and clearing save_path.") - save_path = null - savable = FALSE - return - - var/list/load - - try - load = json_decode(file2text(save_path)) - catch(var/exception/E_json_decode) - error("Exception decoding etching content - Path: [save_path] - Content: [content] - Load: [load]: [E_json_decode]") - - if(!load) - log_debug("Etching json_decode failed! File path: '[save_path]'. Load contents: '[content]'. Aborting and clearing save_path.") - save_path = null - savable = FALSE - return - - true_name = load["true_name"] - core = load["core"] - l_arm = load["l_arm"] - r_arm = load["r_arm"] - l_leg = load["l_leg"] - r_leg = load["r_leg"] - xp = load["xp"] - triangles = load["triangles"] - - log_debug("Etching load complete for [ourmob.real_name].") - -/datum/etching/proc/save(delet = FALSE) - if(!savable || !needs_saving) - return - if(IsGuestKey(ourmob.key)) - return - - if(shutting_down) //Don't try to save more than once if we're already saving and shutting down. - return - if(delet) //Our mob got deleted, so we're saving and quitting. - shutting_down = TRUE - - if(!save_path || !ishuman(ourmob) || istype(ourmob, /mob/living/carbon/human/dummy)) - if(shutting_down) - ourmob = null - qdel(src) - return - - var/list/to_save = list( - "true_name" = true_name, - "core" = core, - "l_arm" = l_arm, - "r_arm" = r_arm, - "l_leg" = l_leg, - "r_leg" = r_leg, - "xp" = xp, - "triangles" = triangles - ) - - var/json_to_file - try - json_to_file = json_encode(to_save) - catch - error("Etching failed to encode to json for [ourmob.real_name]") - - if(!json_to_file) - log_debug("Saving: [save_path] failed json encode.") - return - - //Write it out - try - rustg_file_write(json_to_file, save_path) - catch - error("Etching failed to write to file for [ourmob.real_name]: [json_to_file] - [save_path]") - - if(!fexists(save_path)) - log_debug("Saving: [save_path] failed file write") - - needs_saving = FALSE - - if(shutting_down) - ourmob = null - qdel(src) - -/datum/etching/proc/setup() - - log_debug("setup") - - return +/datum/etching/proc/consume_mana(cost,spell_lv) + var/howmuch = mana - cost + if(howmuch < 0) + return FALSE + mana = howmuch + mana_cooldown = (BASE_MAGIC_COOLDOWN * spell_lv) //life tick * lv = about 30 seconds per level + return TRUE /mob/proc/magic_rename(var/old_name,var/new_name) var/old_path = "data/player_saves/[copytext(ckey, 1, 2)]/[ckey]/magic/[old_name]-etching.json" @@ -270,22 +90,10 @@ log_debug("Saving: [old_path] failed to delete on rename function") return -/datum/etching/proc/update_etching(mode,value) - switch(mode) - if("triangles") - triangles += value - - needs_saving = TRUE - -/datum/etching/proc/grant_xp(kind,value) - xp["[kind]"] += value - needs_saving = TRUE - -/datum/etching/proc/report_status() - if(!save_path) - return - . = ": [triangles]\n\n" +///datum/etching/update_etching(mode,value) +// . = ..() +/datum/etching/proc/report_magic() var/extra = FALSE if(core) . += "Core: [core]\n" @@ -306,16 +114,10 @@ if(extra) . += "\n" - for(var/thing in xp) - . += "[thing]: [xp[thing]]\n" - - to_chat(ourmob, .) - -/datum/etching/vv_edit_var(var_name, var_value) - return FALSE + return . /datum/etching/proc/consider_magic(cost,spell_class,spell_lv) - if(admin_magic) + if(ourmob.admin_magic) return TRUE if(mana_cooldown) to_chat(ourmob, "You are still recovering! (([mana_cooldown]))") diff --git a/code/modules/mob/living/item_storage.dm b/code/modules/mob/living/item_storage.dm new file mode 100644 index 00000000000..3780c49aca2 --- /dev/null +++ b/code/modules/mob/living/item_storage.dm @@ -0,0 +1,70 @@ +/* +TO DO: +Figure out how often the time codes get updated, to make sure multiple store instances won't duplicate the code +*/ + +#define item_storage_maximum 50 + +var/global/list/permanent_unlockables = list( + /obj/item/weapon/gun/energy/sizegun +) + +/datum/etching + var/triangles = 0 //Triangle money + var/list/item_storage = list() //Various items that are stored in the bank, these can only be stored and pulled out once + var/list/unlockables = list() //Scene items that, once stored, can be pulled once per round forever. + +/datum/etching/proc/store_item(item,var/obj/machinery/item_bank/bank) + if(!isobj(item)) + return + var/obj/O = item + if(O.type in permanent_unlockables && O.persist_storable) + to_world("WOW YOU GOT AN UNLOCKABLE WOAH!!!") + + else if(!istool(O) && O.persist_storable) + if(item_storage.len >= item_storage_maximum) + to_chat(ourmob, "You can not store \the [O]. Your lockbox is too full.") + bank.busy_bank = FALSE + return + var/choice = tgui_alert(ourmob, "If you store \the [O], anything it contains may be lost to \the [bank]. Are you sure?", "[bank]", list("Store", "Cancel"), timeout = 10 SECONDS) + if(!choice || choice == "Cancel" || !bank.Adjacent(ourmob) || bank.inoperable() || bank.panel_open) + bank.busy_bank = FALSE + return + for(var/obj/check in O.contents) + if(!check.persist_storable) + to_chat(ourmob, "\The [bank] buzzes. \The [O] contains [check], which cannot be stored. Please remove this item before attempting to store \the [O]. As a reminder, any contents of \the [O] will be lost if you store it with contents.") + bank.busy_bank = FALSE + return + ourmob.visible_message("\The [ourmob] begins storing \the [O] in \the [bank].","You begin storing \the [O] in \the [bank].") + bank.icon_state = "item_bank_o" + if(!do_after(ourmob, 10 SECONDS, bank, exclusive = TASK_ALL_EXCLUSIVE) || bank.inoperable()) + bank.busy_bank = FALSE + bank.icon_state = "item_bank" + return + save_item(O) + ourmob.visible_message("\The [ourmob] stores \the [O] in \the [bank].","You stored \the [O] in \the [bank].") + log_admin("[key_name_admin(ourmob)] stored [O] in the item bank.") + qdel(O) + bank.busy_bank = FALSE + bank.icon_state = "item_bank" + else + to_chat(ourmob, "You cannot store \the [O]. \The [bank] either does not accept that, or it has already been retrieved from storage this shift.") + bank.busy_bank = FALSE + +/datum/etching/proc/save_item(var/obj/O) + item_storage += list("[initial(O.name)] - [time2text(world.realtime, "YYYYMMDDhhmmss")]" = O.type) + needs_saving = TRUE + +/datum/etching/proc/legacy_conversion(I_name,I_type) + item_storage += list("[I_name] - [time2text(world.realtime, "YYYYMMDDhhmmss")]" = I_type) + needs_saving = TRUE + +/datum/etching/update_etching(mode, value) + . = ..() + switch(mode) + if("triangles") + triangles += value + +/datum/etching/proc/report_money() + . = ": [triangles]\n\n" + return .