diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index f6293454ee..c75adfa49e 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -56,6 +56,10 @@
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_SET_SD_CODE "(SETCODE)"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]"
+//ambition port start
+#define ADMIN_TPMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_JMP(user)] [ADMIN_FLW(user)]"
+#define ADMIN_TPMONTY(user) "[key_name_admin(user)] [ADMIN_TPMONTY_NONAME(user)]"
+//ambition port end
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
#define ADMIN_JMP(src) "(JMP)"
#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]"
diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm
index 29c7a25dad..13a7633409 100644
--- a/code/__DEFINES/cooldowns.dm
+++ b/code/__DEFINES/cooldowns.dm
@@ -27,6 +27,7 @@
//INDEXES
#define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet"
+#define COOLDOWN_AMBITION "ambition"
//TIMER COOLDOWN MACROS
@@ -40,6 +41,12 @@
#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)
+#define COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time))
+
+#define COOLDOWN_CHECK(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index)
+
+#define COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)
+
/*
* Stoppable timer cooldowns.
* Use indexes the same as the regular tiemr cooldowns.
diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index 9403eca2da..a9e23bb67c 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -86,6 +86,9 @@
#define EMOTE_OMNI 4
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
+//ambition port start
+#define MAX_AMBITION_LEN 1024
+//ambition port end
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
#define MAX_FLAVOR_LEN 4096
#define MAX_TASTE_LEN 40 //lick... vore... ew...
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index a554397c41..608da83dd9 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -13,6 +13,9 @@
#define UNSETEMPTY(L) if (L && !length(L)) L = null
#define LAZYCOPY(L) (L ? L.Copy() : list() )
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
+//ambition port start
+#define LAZYCUT(L, S, E) if((length(L) >= S) && (E == 0 || length(L) >= (E - 1))) { L.Cut(S, E); if(!length(L)) { L = null; } }
+//ambition port end
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
#define LAZYFIND(L, V) L ? L.Find(V) : 0
diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index cd59dfd9cf..ad57ce42ac 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -491,6 +491,11 @@
currrent_category = A.roundend_category
previous_category = A
result += A.roundend_report()
+//ambition port start
+ for(var/count in 1 to LAZYLEN(A.owner.ambitions))
+ result += "
Ambition #[count]: [A.owner.ambitions[count]]"
+//ambition port end
+
result += "
"
CHECK_TICK
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 63da60d7b5..a65e9ddb81 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -441,3 +441,8 @@
config_entry_value = TRUE
/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+
+//ambition port start
+/datum/config_entry/number/max_ambitions // Maximum number of ambitions a mind can store.
+ config_entry_value = 5
+//amibiton port end
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 42580425ce..74dfbbddd9 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -49,6 +49,11 @@
/// A weak reference to another datum
var/datum/weakref/weak_reference
+//ambition port start
+ ///Lazy associative list of currently active cooldowns.
+ var/list/cooldowns
+//ambition port end
+
/*
* Lazy associative list of currently active cooldowns.
*
@@ -261,3 +266,11 @@
return
SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index))
TIMER_COOLDOWN_END(source, index)
+
+//ambition port start
+///Callback called by a timer to end an associative-list-indexed cooldown.
+/proc/end_cooldown(datum/source, index)
+ if(QDELETED(source))
+ return
+ COOLDOWN_END(source, index)
+//ambition port end
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 897e2e7d71..e6414f1d9f 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -28,6 +28,10 @@
yourself.
*/
+//ambition port start
+#define AMBITION_COOLDOWN_TIME (5 SECONDS)
+//ambition port end
+
/datum/mind
var/key
@@ -68,6 +72,11 @@
/// Our skill holder.
var/datum/skill_holder/skill_holder
+//ambition port start
+ /// Lazy list for antagonists to set goals they wish to achieve, to be shown at the round-end report.
+ var/list/ambitions
+//ambition port end
+
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
var/mob/original_character
@@ -173,7 +182,10 @@
qdel(A)
return
A.owner = src
- LAZYADD(antag_datums, A)
+//ambitions port start
+ do_add_antag_datum(A)
+//ambitions port end
+
A.create_team(team)
var/datum/team/antag_team = A.get_team()
if(antag_team)
@@ -181,6 +193,14 @@
A.on_gain()
return A
+//ambitions port start
+/datum/mind/proc/do_add_antag_datum(instanced_datum)
+ . = LAZYLEN(antag_datums)
+ LAZYADD(antag_datums, instanced_datum)
+ if(!.)
+ current.verbs += /mob/proc/edit_ambitions
+//ambitions port end
+
/datum/mind/proc/remove_antag_datum(datum_type)
if(!datum_type)
return
@@ -195,6 +215,15 @@
var/datum/antagonist/A = a
A.on_removal()
+//ambitions port start
+/datum/mind/proc/do_remove_antag_datum(instanced_datum)
+ . = LAZYLEN(antag_datums)
+ LAZYREMOVE(antag_datums, instanced_datum)
+ if(. && !LAZYLEN(antag_datums))
+ current.verbs -= /mob/proc/edit_ambitions
+ ambitions = null
+//ambitions port end
+
/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE)
if(!datum_type)
return
@@ -374,10 +403,10 @@
message_admins("[ADMIN_LOOKUPFLW(current)] has been created by [ADMIN_LOOKUPFLW(creator)], an antagonist.")
to_chat(current, "Despite your creators current allegiances, your true master remains [creator.real_name]. If their loyalties change, so do yours. This will never change unless your creator's body is destroyed.")
-/datum/mind/proc/show_memory(mob/recipient, window=1)
- if(!recipient)
- recipient = current
- var/output = "[current.real_name]'s Memories:
"
+//ambitions port start
+/datum/mind/proc/show_memory()
+ var/list/output = list("[current.real_name]'s Memories:
")
+//ambitions port end
output += memory
@@ -398,17 +427,211 @@
output += "
Conspirator: [M.name]"
output += ""
- if(window)
- recipient << browse(output,"window=memory")
- else if(all_objectives.len || memory)
- to_chat(recipient, "[output]")
+//ambition port start
+ if(LAZYLEN(ambitions))
+ for(var/count in 1 to LAZYLEN(ambitions))
+ output += "
Ambition #[count]: [ambitions[count]]"
+
+ if(!memory && !length(all_objectives) && !LAZYLEN(ambitions))
+ output += ""
+
+ return output.Join()
+
+
+/datum/mind/proc/show_editable_ambitions()
+ var/list/output = list("[current.real_name]'s Ambitions:
")
+ if(!LAZYLEN(ambitions))
+ output += "- NONE"
+ if(LAZYLEN(antag_datums))
+ output +="
- (Add Ambition)"
+ else
+ for(var/count in 1 to LAZYLEN(ambitions))
+ output += "
- Ambition #[count] (Edit) (Remove):
[ambitions[count]]"
+ if(LAZYLEN(ambitions) < 5)
+ output += " - (Add Ambition)"
+ output += "
- (Refresh)
"
+ return output.Join()
+
+
+/mob/proc/edit_ambitions()
+ set name = "Ambitions"
+ set category = "IC"
+ set desc = "View and edit your character's ambitions."
+ mind.do_edit_ambitions()
+
+
+/datum/mind/proc/do_edit_ambitions()
+ var/datum/browser/popup = new(usr, "ambitions", "Ambitions")
+ popup.set_content(show_editable_ambitions())
+ popup.open()
+//ambition port end
/datum/mind/Topic(href, href_list)
+//ambition port start
+ if (href_list["refresh_ambitions"])
+ do_edit_ambitions()
+ return
+
+ else if (href_list["add_ambition"])
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ return
+ if(!antag_datums)
+ return
+ var/max_ambitions = CONFIG_GET(number/max_ambitions)
+ if(LAZYLEN(ambitions) >= max_ambitions)
+ to_chat(usr, "There's a limit of [max_ambitions] ambitions. Edit or remove some to accomodate for your new additions.")
+ do_edit_ambitions()
+ return
+ var/new_ambition = stripped_multiline_input(usr, "Write new ambition", "Ambition", "", MAX_AMBITION_LEN)
+ if(isnull(new_ambition))
+ return
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ to_chat(usr, "The mind holder is no longer a living creature.")
+ return
+ if(!antag_datums)
+ to_chat(usr, "The mind holder is no longer an antagonist.")
+ return
+ if(LAZYLEN(ambitions) >= max_ambitions)
+ to_chat(usr, "There's a limit of [max_ambitions] ambitions. Edit or remove some to accomodate for your new additions.")
+ do_edit_ambitions()
+ return
+ COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME)
+ LAZYADD(ambitions, new_ambition)
+ if(usr == current)
+ log_game("[key_name(usr)] has created their ambition of index [LAZYLEN(ambitions)].\nNEW AMBITION:\n[new_ambition]")
+ else
+ log_game("[key_name(usr)] has created [key_name(current)]'s ambition of index [LAZYLEN(ambitions)].\nNEW AMBITION:\n[new_ambition]")
+ message_admins("[ADMIN_TPMONTY(usr)] has created [ADMIN_TPMONTY(current)]'s ambition of index [LAZYLEN(ambitions)].")
+ do_edit_ambitions()
+ return
+
+ else if (href_list["edit_ambition"])
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ return
+ if(!antag_datums)
+ return
+ var/ambition_index = text2num(href_list["edit_ambition"])
+ if(!isnum(ambition_index) || ambition_index < 0 || ambition_index % 1)
+ log_admin_private("[key_name(usr)] attempted to edit their ambitions with and invalid ambition_index ([ambition_index]) at [AREACOORD(usr.loc)].")
+ message_admins("[ADMIN_TPMONTY(usr)] attempted to edit their ambitions with and invalid ambition_index ([ambition_index]). Possible HREF exploit.")
+ return
+ if(ambition_index > LAZYLEN(ambitions))
+ return
+ var/old_ambition = ambitions[ambition_index]
+ var/new_ambition = stripped_multiline_input(usr, "Write new ambition", "Ambition", ambitions[ambition_index], MAX_AMBITION_LEN)
+ if(isnull(new_ambition))
+ return
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ to_chat(usr, "The mind holder is no longer a living creature.")
+ return
+ if(!antag_datums)
+ to_chat(usr, "The mind holder is no longer an antagonist.")
+ return
+ if(ambition_index > LAZYLEN(ambitions))
+ to_chat(usr, "The ambition we were editing was deleted before we finished. Aborting.")
+ do_edit_ambitions()
+ return
+ if(old_ambition != ambitions[ambition_index])
+ to_chat(usr, "The ambition has changed since we started editing it. Aborting to prevent data loss.")
+ do_edit_ambitions()
+ return
+ COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME)
+ ambitions[ambition_index] = new_ambition
+ if(usr == current)
+ log_game("[key_name(usr)] has edited their ambition of index [ambition_index].\nOLD AMBITION:\n[old_ambition]\nNEW AMBITION:\n[new_ambition]")
+ else
+ log_game("[key_name(usr)] has edited [key_name(current)]'s ambition of index [ambition_index].\nOLD AMBITION:\n[old_ambition]\nNEW AMBITION:\n[new_ambition]")
+ message_admins("[ADMIN_TPMONTY(usr)] has edited [ADMIN_TPMONTY(current)]'s ambition of index [ambition_index].")
+ do_edit_ambitions()
+ return
+
+ else if (href_list["remove_ambition"])
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ return
+ if(!antag_datums)
+ return
+ var/ambition_index = text2num(href_list["remove_ambition"])
+ if(ambition_index > LAZYLEN(ambitions))
+ do_edit_ambitions()
+ return
+ if(!isnum(ambition_index) || ambition_index < 0 || ambition_index % 1)
+ log_admin_private("[key_name(usr)] attempted to remove an ambition with and invalid ambition_index ([ambition_index]) at [AREACOORD(usr.loc)].")
+ message_admins("[ADMIN_TPMONTY(usr)] attempted to remove an ambition with and invalid ambition_index ([ambition_index]). Possible HREF exploit.")
+ return
+ var/old_ambition = ambitions[ambition_index]
+ if(alert(usr, "Are you sure you want to delete this ambition?", "Delete ambition", "Yes", "No") != "Yes")
+ return
+ if(!check_rights(R_ADMIN))
+ if(usr != current)
+ return
+ if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION))
+ to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.")
+ return
+ if(!isliving(current))
+ to_chat(usr, "The mind holder is no longer a living creature. The ambition we were deleting should no longer exist already.")
+ return
+ if(!antag_datums)
+ to_chat(usr, "The mind holder is no longer an antagonist. The ambition we were deleting should no longer exist already.")
+ return
+ if(ambition_index > LAZYLEN(ambitions))
+ to_chat(usr, "The ambition we were deleting was deleted before we finished. No need to continue.")
+ do_edit_ambitions()
+ return
+ if(old_ambition != ambitions[ambition_index])
+ to_chat(usr, "The ambition has changed since we started considering its deletion. Aborting to prevent conflicts.")
+ do_edit_ambitions()
+ return
+ COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME)
+ LAZYCUT(ambitions, ambition_index, ambition_index + 1)
+ if(usr == current)
+ log_game("[key_name(usr)] has deleted their ambition of index [ambition_index].\nDELETED AMBITION:\n[old_ambition]")
+ else
+ log_game("[key_name(usr)] has deleted [key_name(current)]'s ambition of index [ambition_index].\nDELETED AMBITION:\n[old_ambition]")
+ message_admins("[ADMIN_TPMONTY(usr)] has deleted [ADMIN_TPMONTY(current)]'s ambition of index [ambition_index].")
+ do_edit_ambitions()
+ return
if(!check_rights(R_ADMIN))
return
var/self_antagging = usr == current
+ if(href_list["edit_ambitions_panel"])
+ do_edit_ambitions()
+ return
+ else if(href_list["refresh_antag_panel"])
+ traitor_panel()
+ return
+//ambition port end
if(href_list["add_antag"])
add_antag_wrapper(text2path(href_list["add_antag"]),usr)
if(href_list["remove_antag"])
@@ -814,3 +1037,7 @@
..()
mind.assigned_role = ROLE_PAI
mind.special_role = ""
+
+//ambition port start
+#undef AMBITION_COOLDOWN_TIME
+//ambition port end
diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm
index 88aab2c4ce..502ee116c1 100644
--- a/code/modules/admin/antag_panel.dm
+++ b/code/modules/admin/antag_panel.dm
@@ -97,10 +97,14 @@ GLOBAL_VAR(antag_prototypes)
alert("This mind doesn't have a mob, or is deleted! For some reason!", "Edit Memory")
return
- var/out = "[name][(current && (current.real_name!=name))?" (as [current.real_name])":""]
"
- out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
"
- out += "Assigned role: [assigned_role]. Edit
"
- out += "Faction and special role: [special_role]
"
+//ambition port start
+ var/list/out = list(
+ "[name][(current && (current.real_name!=name))?" (as [current.real_name])":""]
\
+ Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
\
+ Assigned role: [assigned_role]. Edit
\
+ Faction and special role: [special_role]
"
+ )
+//ambition port end
var/special_statuses = get_special_statuses()
if(length(special_statuses))
@@ -191,6 +195,16 @@ GLOBAL_VAR(antag_prototypes)
//Uplink
if(ishuman(current))
var/uplink_info = "Uplink:"
+//ambition port start
+ //Ambitions
+ out += "[current.real_name]'s Ambitions: Edit Ambitions
"
+ if(!LAZYLEN(ambitions))
+ out += "- NONE
- "
+ else
+ for(var/count in 1 to LAZYLEN(ambitions))
+ out += "
- Ambition #[count]:
[ambitions[count]]"
+ out += "
"
+
var/datum/component/uplink/U = find_syndicate_uplink()
if(U)
uplink_info += "take"
@@ -204,14 +218,16 @@ GLOBAL_VAR(antag_prototypes)
out += uplink_info + "
"
//Common Memory
- var/common_memory = "Common Memory:"
- common_memory += memory
- common_memory += "Edit Memory"
- out += common_memory + "
"
+ out += "
Common Memory:"
+ out += memory
+ out += "Edit Memory
"
//Other stuff
out += get_common_admin_commands()
+ out += "
Refresh"
var/datum/browser/panel = new(usr, "traitorpanel", "", 600, 600)
+ panel.set_content(out.Join())
+//ambition port end
panel.set_content(out)
panel.open()
return
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 14f7b34309..df9a8bff2e 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -35,8 +35,9 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/Destroy()
GLOB.antagonists -= src
- if(owner)
- LAZYREMOVE(owner.antag_datums, src)
+//ambition port start
+ owner?.do_remove_antag_datum(src)
+//ambition port end
owner = null
return ..()
@@ -133,7 +134,9 @@ GLOBAL_LIST_EMPTY(antagonists)
remove_innate_effects()
clear_antag_moodies()
if(owner)
- LAZYREMOVE(owner.antag_datums, src)
+//ambition port start
+ owner.do_remove_antag_datum(src)
+//ambition port end
for(var/A in skill_modifiers)
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
if(!silent && owner.current)
diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm
index 208fefee70..a3c47c10a5 100644
--- a/code/modules/antagonists/changeling/powers/absorb.dm
+++ b/code/modules/antagonists/changeling/powers/absorb.dm
@@ -65,7 +65,9 @@
user.copy_languages(target, LANGUAGE_ABSORB)
if(target.mind && user.mind)//if the victim and user have minds
- target.mind.show_memory(user, 0) //I can read your mind, kekeke. Output all their notes.
+//ambition port start
+ to_chat(user, "[target.mind.show_memory()]") //I can read your mind. Output all their notes.
+//ambition port end
//Some of target's recent speech, so the changeling can attempt to imitate them better.
//Recent as opposed to all because rounds tend to have a LOT of text.
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index 2b1c2de17a..000436ab29 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -2,7 +2,10 @@
..()
//Mind updates
sync_mind()
- mind.show_memory(src, 0)
+//ambition port start
+ if(mind.memory || mind.antag_datums)
+ to_chat(src, "[mind.show_memory()]")
+//ambition port end
//Round specific stuff
if(SSticker.mode)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 824e262ae1..a29cd8c24a 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -441,7 +441,11 @@
set category = "IC"
set desc = "View your character's notes memory."
if(mind)
- mind.show_memory(src)
+//ambition port start
+ var/datum/browser/popup = new(src, "memory", "Memory and Notes")
+ popup.set_content(mind.show_memory())
+ popup.open()
+//ambition port
else
to_chat(src, "You don't have a mind datum for some reason, so you can't look at your notes, if you had any.")