From 7f385648381af7313848eba031fdf49071738d98 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 19:55:53 +0100 Subject: [PATCH 01/43] i can't believe kevin made me code im taking severe offense to this --- code/__DEFINES/admin.dm | 4 + code/__DEFINES/cooldowns.dm | 7 + code/__DEFINES/say.dm | 3 + code/__HELPERS/_lists.dm | 3 + code/__HELPERS/roundend.dm | 5 + .../configuration/entries/general.dm | 5 + code/datums/datum.dm | 13 + code/datums/mind.dm | 245 +++++++++++++++++- code/modules/admin/antag_panel.dm | 32 ++- .../antagonists/_common/antag_datum.dm | 9 +- .../antagonists/changeling/powers/absorb.dm | 4 +- code/modules/mob/living/login.dm | 5 +- code/modules/mob/mob.dm | 6 +- 13 files changed, 318 insertions(+), 23 deletions(-) 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:
    " + 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
    " + 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.") From dbabbb10625dc353e3567c41e73cee1a81e23b13 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 20:31:57 +0100 Subject: [PATCH 02/43] objectives hrnrghghgh --- code/__DEFINES/cooldowns.dm | 2 +- code/datums/mind.dm | 521 +++++++++++++++--- code/modules/admin/admin.dm | 14 +- code/modules/admin/topic.dm | 11 + .../antagonists/_common/antag_datum.dm | 5 + 5 files changed, 483 insertions(+), 70 deletions(-) diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index 13a7633409..947f3202e6 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -28,7 +28,7 @@ //INDEXES #define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet" #define COOLDOWN_AMBITION "ambition" - +#define COOLDOWN_OBJECTIVES "objectives" //TIMER COOLDOWN MACROS diff --git a/code/datums/mind.dm b/code/datums/mind.dm index e6414f1d9f..a612938965 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -30,6 +30,7 @@ */ //ambition port start #define AMBITION_COOLDOWN_TIME (5 SECONDS) +#define OBJECTIVES_COOLDOWN_TIME (10 MINUTES) //ambition port end @@ -198,7 +199,7 @@ . = LAZYLEN(antag_datums) LAZYADD(antag_datums, instanced_datum) if(!.) - current.verbs += /mob/proc/edit_ambitions + current.verbs += /mob/proc/edit_objectives_and_ambitions //ambitions port end /datum/mind/proc/remove_antag_datum(datum_type) @@ -220,8 +221,8 @@ . = LAZYLEN(antag_datums) LAZYREMOVE(antag_datums, instanced_datum) if(. && !LAZYLEN(antag_datums)) - current.verbs -= /mob/proc/edit_ambitions ambitions = null + current.verbs += /mob/proc/edit_objectives_and_ambitions //ambitions port end /datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) @@ -438,18 +439,56 @@ return output.Join() -/datum/mind/proc/show_editable_ambitions() - var/list/output = list("[current.real_name]'s Ambitions:

    (Refresh)" return output.Join() @@ -460,24 +499,53 @@ mind.do_edit_ambitions() -/datum/mind/proc/do_edit_ambitions() - var/datum/browser/popup = new(usr, "ambitions", "Ambitions") - popup.set_content(show_editable_ambitions()) +/datum/mind/proc/do_edit_objectives_ambitions() + var/datum/browser/popup = new(usr, "objectives and ambitions", "Objectives and Ambitions") + popup.set_content(show_editable_objectives_and_ambitions()) popup.open() + +GLOBAL_VAR_INIT(requested_objective_uid, 0) +GLOBAL_LIST(objective_choices) + +/proc/populate_objective_choices() + GLOB.objective_choices = list() + var/list/allowed_types = list( + /datum/objective/custom, + /datum/objective/assassinate, + /datum/objective/assassinate/once, + /datum/objective/maroon, + /datum/objective/debrain, + /datum/objective/protect, + /datum/objective/destroy, + /datum/objective/hijack, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/nuclear, + /datum/objective/absorb, + /datum/objective/blackmail_implant //SKYRAT ADDITION + ) + + for(var/t in allowed_types) + var/datum/objective/type_cast = t + GLOB.objective_choices[initial(type_cast.name)] = t //ambition port end /datum/mind/Topic(href, href_list) //ambition port start - if (href_list["refresh_ambitions"]) - do_edit_ambitions() + if (href_list["refresh_obj_amb"]) + do_edit_objectives_ambitions() + return else if (href_list["add_ambition"]) - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") return if(!isliving(current)) return @@ -486,16 +554,16 @@ 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() + do_edit_objectives_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(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") return if(!isliving(current)) to_chat(usr, "The mind holder is no longer a living creature.") @@ -505,7 +573,7 @@ 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() + do_edit_objectives_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) LAZYADD(ambitions, new_ambition) @@ -514,15 +582,15 @@ 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() + do_edit_objectives_ambitions() return else if (href_list["edit_ambition"]) - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") return if(!isliving(current)) return @@ -539,11 +607,11 @@ 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(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") return if(!isliving(current)) to_chat(usr, "The mind holder is no longer a living creature.") @@ -553,11 +621,11 @@ return if(ambition_index > LAZYLEN(ambitions)) to_chat(usr, "The ambition we were editing was deleted before we finished. Aborting.") - do_edit_ambitions() + do_edit_objectives_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() + do_edit_objectives_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) ambitions[ambition_index] = new_ambition @@ -566,15 +634,15 @@ 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() + do_edit_objectives_ambitions() return else if (href_list["remove_ambition"]) - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") return if(!isliving(current)) return @@ -582,7 +650,7 @@ return var/ambition_index = text2num(href_list["remove_ambition"]) if(ambition_index > LAZYLEN(ambitions)) - do_edit_ambitions() + do_edit_objectives_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)].") @@ -591,11 +659,11 @@ 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(!check_rights(R_ADMIN, FALSE)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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.") @@ -605,11 +673,11 @@ 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() + do_edit_objectives_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() + do_edit_objectives_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) LAZYCUT(ambitions, ambition_index, ambition_index + 1) @@ -618,7 +686,113 @@ 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() + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_add"]) + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(!istype(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + if(!GLOB.objective_choices) + populate_objective_choices() + var/choe = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_choices + var/selected_type = GLOB.objective_choices[choe] + if(!selected_type) + return + var/new_objective = stripped_multiline_input(usr,\ + selected_type == /datum/objective/custom\ + ? "Write the custom objective you'd like to request the admins to grant you.\ + Remember they can edit or deny your request. There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown."\ + : "Justify your request for a new objective to the admins. Add the required clarifations, if you have a specific targets in mind or the likes.\ + Remember they can edit or deny your request. There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.",\ + "New Objective", max_length = MAX_MESSAGE_LEN) + if(isnull(new_objective)) + return + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + if(QDELETED(target_antag)) + return + COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + var/uid = "[GLOB.requested_objective_uid++]" + LAZYADD(target_antag.requested_objectives, uid) + target_antag.requested_objectives[uid] = list("type" = selected_type, "text" = new_objective) + log_admin("[key_name(usr)] has requested a [choe] objective: [new_objective]") + message_admins("[ADMIN_TPMONTY(usr)] has requested a [choe] objective. (RPLY)") + to_chat(usr, "The admins have been notified of your request!") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_delete"]) + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + var/datum/objective/objective_to_delete = locate(href_list["req_obj_delete"]) + if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + var/justifation = stripped_multiline_input(usr, + "Justify your request for a deleting this objective to the admins.\ + There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", + "Objective Deletion", max_length = MAX_MESSAGE_LEN) + if(isnull(justifation)) + return + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + if(QDELETED(objective_to_delete)) + do_edit_objectives_ambitions() + return + COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + log_admin("[key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]") + message_admins("[ADMIN_TPMONTY(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") + to_chat(usr, "The admins have been notified of your request!") + do_edit_objectives_ambitions() + return + else if (href_list["req_obj_completed"]) + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + var/datum/objective/objective_to_complete = locate(href_list["req_obj_completed"]) + if(!istype(objective_to_complete) || QDELETED(objective_to_complete)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + var/justifation = stripped_multiline_input(usr, + "Justify your request for the [objective_to_complete.completed ? "completion" : "incompletion"] of this objective to the admins.\ + There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", + "Objective [objective_to_complete.completed ? "Completion" : "Incompletion"]", max_length = MAX_MESSAGE_LEN) + if(isnull(justifation)) + return + if(usr != current) + return + if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") + return + if(QDELETED(objective_to_complete)) + do_edit_objectives_ambitions() + return + COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + log_admin("[key_name(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]") + message_admins("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") + to_chat(usr, "The admins have been notified of your request!") + do_edit_objectives_ambitions() return if(!check_rights(R_ADMIN)) return @@ -626,12 +800,236 @@ var/self_antagging = usr == current if(href_list["edit_ambitions_panel"]) - do_edit_ambitions() + do_edit_objectives_ambitions() return + else if(href_list["refresh_antag_panel"]) traitor_panel() return + + else if (href_list["req_obj_edit"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective reference.") + return + + switch(alert(usr, "Do you want to edit the requested objective type or text?", "Edit requested objective", "Type", "Text", "Cancel")) + if("Type") + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + var/datum/objective/type_cast = requested_objective["type"] + var/selected_type = input("Select new requested objective type:", "Requested Objective type", initial(type_cast.name)) as null|anything in GLOB.objective_choices + selected_type = GLOB.objective_choices[selected_type] + if(!selected_type) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") + message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") + requested_objective["type"] = selected_type + if("Text") + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_objective["text"], MAX_MESSAGE_LEN) + if (isnull(new_text)) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") + message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") + requested_objective["text"] = new_text + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_accept"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective reference.") + return + if(alert(usr, "Are you sure you want to approve this objective?", "Approve objective", "Yes", "No") != "Yes") + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + var/objective_path = requested_objective["type"] + var/datum/objective/new_objective = new objective_path + new_objective.owner = src + if(istype(new_objective, /datum/objective/custom)) + new_objective.explanation_text = requested_objective["text"] + else + new_objective.admin_edit(usr) + antag_datum.objectives += new_objective + LAZYREMOVE(antag_datum.requested_objectives, uid) + message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") + log_admin("[key_name(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") + to_chat(current, "Your objective request has been approved.") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_deny"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective reference.") + return + var/justifation = stripped_multiline_input(usr, "Justify why you are denying this objective request.", "Deny", memory, MAX_MESSAGE_LEN) + if(isnull(justifation)) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") + do_edit_objectives_ambitions() + return + var/datum/objective/type_cast = requested_objective["type"] + var/objective_name = initial(type_cast.name) + message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") + log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") + to_chat(current, "Your objective request has been denied for the following reason: [justifation]") + LAZYREMOVE(antag_datum.requested_objectives, uid) + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_complete_toggle"]) + var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) + if(!istype(objective_to_toggle) || QDELETED(objective_to_toggle)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_toggle.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + objective_to_toggle.completed = !objective_to_toggle.completed + message_admins("[key_name_admin(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") + log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") + if(alert(usr, "Would you like to alert the player of the change?", "Deny objective", "Yes", "No") == "Yes") + to_chat(current, "[objective_to_toggle.completed ? "" : ""]Your objective status has changed!") + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_delete"]) + var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) + if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_delete.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + if(alert(usr, "Are you sure you want to delete this objective?", "Delete objective", "Yes", "No") != "Yes") + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(objective_to_delete)) + return + message_admins("[key_name_admin(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") + log_admin("[key_name(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") + qdel(objective_to_delete) + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_edit"]) + var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) + if(!istype(objective_to_edit) || QDELETED(objective_to_edit)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_edit.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + var/explanation_before = objective_to_edit.explanation_text + objective_to_edit.admin_edit(usr) + if(QDELETED(objective_to_edit)) + return + message_admins("[key_name_admin(usr)] edited an objective from [current]:\ + Before: [explanation_before]\ + After: [objective_to_edit.explanation_text]") + log_admin("[key_name(usr)] edited an objective from [current]:\ + Before: [explanation_before]\ + After: [objective_to_edit.explanation_text]") + do_edit_objectives_ambitions() + return + //ambition port end + if(href_list["add_antag"]) add_antag_wrapper(text2path(href_list["add_antag"]),usr) if(href_list["remove_antag"]) @@ -691,38 +1089,16 @@ else target_antag = target - var/static/list/choices - if(!choices) - choices = list() +//ambition port start + if(!GLOB.objective_choices) + populate_objective_choices() - var/list/allowed_types = list( - /datum/objective/assassinate, - /datum/objective/assassinate/once, - /datum/objective/maroon, - /datum/objective/debrain, - /datum/objective/protect, - /datum/objective/destroy, - /datum/objective/hijack, - /datum/objective/escape, - /datum/objective/survive, - /datum/objective/martyr, - /datum/objective/steal, - /datum/objective/download, - /datum/objective/nuclear, - /datum/objective/absorb, - /datum/objective/custom - ) + if(old_objective && GLOB.objective_choices[old_objective.name]) + def_value = old_objective.name - for(var/T in allowed_types) - var/datum/objective/X = T - choices[initial(X.name)] = T - - if(old_objective) - if(old_objective.name in choices) - def_value = old_objective.name - - var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices - selected_type = choices[selected_type] + var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in GLOB.objective_choices + selected_type = GLOB.objective_choices[selected_type] +//ambition port end if (!selected_type) return @@ -749,6 +1125,11 @@ target_antag.objectives.Insert(objective_pos, new_objective) message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") +//ambition port start + if(href_list["ambition_panel"]) + do_edit_objectives_ambitions() + return +//ambition port end else if(href_list["traitor_class"]) var/static/list/choices @@ -834,6 +1215,12 @@ else if (href_list["obj_announce"]) announce_objectives() +//ambition port start + if(href_list["ambition_panel"]) + do_edit_objectives_ambitions() + return +//ambition port end + //Something in here might have changed your mob if(self_antagging && (!usr || !usr.client) && current.client) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index d4afc3dbb4..6a2bc83db7 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -25,7 +25,9 @@ to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.", confidential = TRUE) return - var/body = "Options for [M.key]" +//ambition port start + var/list/body = list("Options for [M.key]") +//ambition port end body += "Options panel for [M]" if(M.client) body += " played by [M.client] " @@ -125,6 +127,10 @@ body += "Subtle message | " // body += "Play sound to | " body += "Language Menu" +//ambition port start + if(M.mind) + body += " | Objective-Ambition Menu" +//ambition port end if (M.client) if(!isnewplayer(M)) @@ -206,7 +212,11 @@ body += "
    " body += "" - usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515") +//ambition port start + var/datum/browser/popup = new(usr, "adminplayeropts-[REF(M)]", "Player Panel", nwidth = 550, nheight = 515) + popup.set_content(body.Join()) + popup.open() +//ambition port end SSblackbox.record_feedback("tally", "admin_verb", 1, "Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 05e791984a..9cd4fd203c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2251,6 +2251,17 @@ var/mob/M = locate(href_list["HeadsetMessage"]) usr.client.admin_headset_message(M) +//ambition port start + else if(href_list["ObjectiveRequest"]) + if(!check_rights(R_ADMIN)) + return + var/datum/mind/requesting_mind = locate(href_list["ObjectiveRequest"]) + if(!istype(requesting_mind) || QDELETED(requesting_mind)) + to_chat(usr, "This mind reference is no longer valid. It has probably since been destroyed.") + return + requesting_mind.do_edit_objectives_ambitions() + return +//ambition port end else if(href_list["reject_custom_name"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index df9a8bff2e..fbe40f80b8 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -25,6 +25,11 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. var/threat = 0 // Amount of threat this antag poses, for dynamic mode +//ambition port start + /// Lazy list for antagonists to request the admins objectives. + var/list/requested_objectives +//ambition port end + var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors var/list/skill_modifiers From aa6402427b1f903d4e6ab864218441e5eb28d731 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:11:09 +0100 Subject: [PATCH 03/43] god why am i doing it this way instead of just looking at end changes im going through every single commit im retarded --- code/__DEFINES/antagonists.dm | 6 + code/datums/mind.dm | 332 +++++++++++++----- .../antagonists/_common/antag_datum.dm | 43 ++- 3 files changed, 287 insertions(+), 94 deletions(-) diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index e71243994d..f80652523e 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -110,3 +110,9 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance #define BLOB_SPREAD_COST 4 #define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread #define BLOB_REFLECTOR_COST 15 + +//Objectives-Ambitions Panel +#define REQUEST_NEW_OBJECTIVE "new_objective" +#define REQUEST_DEL_OBJECTIVE "del_objective" +#define REQUEST_WIN_OBJECTIVE "win_objective" +#define REQUEST_LOSE_OBJECTIVE "lose_objective" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index a612938965..fa40b8c70d 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -454,21 +454,45 @@ if(!length(antag_datum.objectives)) output += "
  • NONE" else - for(var/count in 1 to length(antag_datum.objectives)) - var/datum/objective/objective = antag_datum.objectives[count] - output += "
  • [count]: [objective.explanation_text]" - if(self_mind) - output += " Request Remove [objective.completed ? "Request incompletion" : "Request completion"]
    " - if(is_admin) - output += " Edit Remove [objective.completed ? "Mark as incomplete" : "Mark as complete"]
    " + for(var/uid in antag_datum.requested_objective_changes) + var/list/objectives_info = antag_datum.requested_objective_changes[uid] + var/obj_request = objectives_info["request"] + switch(obj_request) + if(REQUEST_NEW_OBJECTIVE) + var/datum/objective/type_cast_objective = objectives_info["target"] + var/objective_text = objectives_info["text"] + output += "
  • Request #[uid]: ADD [initial(type_cast_objective.name)] - [objective_text]" + if(is_admin) + output += " Accept Edit Deny" + if(REQUEST_DEL_OBJECTIVE) + var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives + if(QDELETED(objective_ref)) + stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + antag_datum.remove_objective_change(uid) + continue + output += "
  • Request #[uid]: DEL [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" + if(is_admin) + output += " Accept Deny" + if(REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives + if(QDELETED(objective_ref)) + stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + antag_datum.remove_objective_change(uid) + continue + output += "
  • Request #[uid]: [obj_request == REQUEST_WIN_OBJECTIVE ? "WIN" : "LOSE"] [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" + if(is_admin) + output += " Accept Deny" + else + stack_trace("Objective request found with no request index. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + continue output += "" if(is_admin) output += "Announce objectives
    " - output += "
    Requested Objectives:" + output += "
    Requested Objective Changes:" if(self_mind) output += " Request objective" output += "
      " - if(!length(antag_datum.requested_objectives)) + if(!length(antag_datum.requested_objective_changes)) output += "
    • NONE" else for(var/uid in antag_datum.requested_objectives) @@ -493,7 +517,7 @@ /mob/proc/edit_ambitions() - set name = "Ambitions" + set name = "Objectives and Ambitions" set category = "IC" set desc = "View and edit your character's ambitions." mind.do_edit_ambitions() @@ -505,6 +529,28 @@ popup.open() GLOBAL_VAR_INIT(requested_objective_uid, 0) + + +GLOBAL_LIST(objective_player_choices) + +/proc/populate_objective_player_choices() + GLOB.objective_player_choices = list() + var/list/allowed_types = list( + /datum/objective/custom, + /datum/objective/assassinate/once, + /datum/objective/protect, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + ) + + for(var/t in allowed_types) + var/datum/objective/type_cast = t + GLOB.objective_player_choices[initial(type_cast.name)] = t + + GLOBAL_LIST(objective_choices) /proc/populate_objective_choices() @@ -696,14 +742,14 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums - if(!istype(target_antag)) + if(QDELETED(target_antag)) to_chat(usr, "No antagonist found for this objective.") do_edit_objectives_ambitions() return - if(!GLOB.objective_choices) - populate_objective_choices() - var/choe = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_choices - var/selected_type = GLOB.objective_choices[choe] + if(!GLOB.objective_player_choices) + populate_objective_player_choices() + var/choice = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_player_choices + var/selected_type = GLOB.objective_player_choices[choice] if(!selected_type) return var/new_objective = stripped_multiline_input(usr,\ @@ -724,11 +770,10 @@ GLOBAL_LIST(objective_choices) return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) var/uid = "[GLOB.requested_objective_uid++]" - LAZYADD(target_antag.requested_objectives, uid) - target_antag.requested_objectives[uid] = list("type" = selected_type, "text" = new_objective) - log_admin("[key_name(usr)] has requested a [choe] objective: [new_objective]") - message_admins("[ADMIN_TPMONTY(usr)] has requested a [choe] objective. (RPLY)") - to_chat(usr, "The admins have been notified of your request!") + target_antag.add_objective_change(uid, list("request" = REQUEST_NEW_OBJECTIVE, "target" = selected_type, "text" = new_objective)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested a [choice] objective: [new_objective]") + target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested a [choice] objective. (RPLY)") + to_chat(usr do_edit_objectives_ambitions() return @@ -738,12 +783,18 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - var/datum/objective/objective_to_delete = locate(href_list["req_obj_delete"]) + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + var/objective_reference = href_list["req_obj_delete"] + var/datum/objective/objective_to_delete = locate(objective_reference) in target_antag.objectives if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return - var/justifation = stripped_multiline_input(usr, + var/justification = stripped_multiline_input(usr, "Justify your request for a deleting this objective to the admins.\ There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", "Objective Deletion", max_length = MAX_MESSAGE_LEN) @@ -754,13 +805,21 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - if(QDELETED(objective_to_delete)) + if(QDELETED(objective_to_delete) || QDELETED(target_antag)) do_edit_objectives_ambitions() return + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + to_chat(usr, "There is already a change request tied to this objective waiting to be processed. Ahelp or wait for it to be resolved before adding a new one.") + return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - log_admin("[key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]") - message_admins("[ADMIN_TPMONTY(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") - to_chat(usr, "The admins have been notified of your request!") + var/uid = "[GLOB.requested_objective_uid++]" + target_antag.add_objective_change(uid, list("request" = REQUEST_DEL_OBJECTIVE, "target" = objective_reference, "text" = justification)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justification is as follows: [justification]") + target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested the deletion of an objective: (RPLY)") + to_chat(usr, "The admins have been notified of your request!") do_edit_objectives_ambitions() return else if (href_list["req_obj_completed"]) @@ -769,29 +828,43 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - var/datum/objective/objective_to_complete = locate(href_list["req_obj_completed"]) + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + var/objective_reference = href_list["req_obj_completed"] + var/datum/objective/objective_to_complete = locate(objective_reference) in target_antag.objectives if(!istype(objective_to_complete) || QDELETED(objective_to_complete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return - var/justifation = stripped_multiline_input(usr, - "Justify your request for the [objective_to_complete.completed ? "completion" : "incompletion"] of this objective to the admins.\ + var/justification = stripped_multiline_input(usr, + "Justify to the admins your request to mark this objective as [objective_to_complete.completed ? "incomplete" : "completed"].\ There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", - "Objective [objective_to_complete.completed ? "Completion" : "Incompletion"]", max_length = MAX_MESSAGE_LEN) - if(isnull(justifation)) + "Objective [objective_to_complete.completed ? "Incompletion" : "Completion"]", max_length = MAX_MESSAGE_LEN) + if(isnull(justification)) return if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - if(QDELETED(objective_to_complete)) + if(QDELETED(objective_to_complete) || QDELETED(target_antag)) do_edit_objectives_ambitions() return + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + to_chat(usr, "There is already a change request tied to this objective waiting to be processed. Ahelp or wait for it to be resolved before adding a new one.") + return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - log_admin("[key_name(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]") - message_admins("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") - to_chat(usr, "The admins have been notified of your request!") + var/uid = "[GLOB.requested_objective_uid++]" + target_antag.add_objective_change(uid, list("request" = (objective_to_complete.completed ? REQUEST_LOSE_OBJECTIVE : REQUEST_WIN_OBJECTIVE), "target" = objective_reference, "text" = justification)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested the [objective_to_complete.completed ? "incompletion" : "completion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justification is as follows: [justification]") + target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "incompletion" : "completion"] of an objective: (RPLY)") + to_chat(usr, "The admins have been notified of your request!") do_edit_objectives_ambitions() return if(!check_rights(R_ADMIN)) @@ -808,7 +881,7 @@ GLOBAL_LIST(objective_choices) return else if (href_list["req_obj_edit"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) in antag_datums if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -818,12 +891,15 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) do_edit_objectives_ambitions() to_chat(usr, "Invalid requested objective reference.") return - + if(requested_obj_change["request"] != REQUEST_NEW_OBJECTIVE) + do_edit_objectives_ambitions() + to_chat(usr, "This is not an editable request. How did you even got here?") + return switch(alert(usr, "Do you want to edit the requested objective type or text?", "Edit requested objective", "Type", "Text", "Cancel")) if("Type") if(!check_rights(R_ADMIN)) @@ -832,11 +908,11 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - var/datum/objective/type_cast = requested_objective["type"] + var/datum/objective/type_cast = requested_obj_change["target"] var/selected_type = input("Select new requested objective type:", "Requested Objective type", initial(type_cast.name)) as null|anything in GLOB.objective_choices selected_type = GLOB.objective_choices[selected_type] if(!selected_type) @@ -847,13 +923,13 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") - message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") - requested_objective["type"] = selected_type + log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") + message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") + requested_obj_change["target"] = selected_type if("Text") if(!check_rights(R_ADMIN)) return @@ -861,11 +937,11 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_objective["text"], MAX_MESSAGE_LEN) + var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_obj_change["text"], MAX_MESSAGE_LEN) if (isnull(new_text)) return if(!check_rights(R_ADMIN)) @@ -874,18 +950,18 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") - message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") - requested_objective["text"] = new_text + log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") + message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") + requested_obj_change["text"] = new_text do_edit_objectives_ambitions() return else if (href_list["req_obj_accept"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) in antag_datums if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -895,12 +971,29 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) do_edit_objectives_ambitions() to_chat(usr, "Invalid requested objective reference.") return - if(alert(usr, "Are you sure you want to approve this objective?", "Approve objective", "Yes", "No") != "Yes") + + var/datum/objective/request_target + var/request_type = requested_obj_change["request"] + switch(request_type) + if(REQUEST_NEW_OBJECTIVE) + request_target = requested_obj_change["target"] + if(!ispath(request_target, /datum/objective)) + to_chat(usr, "Invalid requested objective target path.") + return + if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + request_target = locate(requested_obj_change["target"]) in antag_datum.objectives + if(QDELETED(request_target)) + to_chat(usr, "Invalid requested objective target reference.") + return + else + to_chat(usr, "Invalid request type.") + return + if(alert(usr, "Are you sure you want to approve this objective change?", "Approve objective change", "Yes", "No") != "Yes") return if(!check_rights(R_ADMIN)) return @@ -908,27 +1001,53 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - var/objective_path = requested_objective["type"] - var/datum/objective/new_objective = new objective_path - new_objective.owner = src - if(istype(new_objective, /datum/objective/custom)) - new_objective.explanation_text = requested_objective["text"] - else - new_objective.admin_edit(usr) - antag_datum.objectives += new_objective - LAZYREMOVE(antag_datum.requested_objectives, uid) - message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") - log_admin("[key_name(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") - to_chat(current, "Your objective request has been approved.") + switch(request_type) //Last checks + if(REQUEST_NEW_OBJECTIVE) + if(!ispath(request_target, /datum/objective)) + stack_trace("Invalid target on objective change request: [request_target]") + do_edit_objectives_ambitions() + return + if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + if(QDELETED(request_target)) + to_chat(usr, "Invalid requested objective target reference.") + return + else + to_chat(usr, "Invalid request type.") + return + antag_datum.remove_objective_change(uid) + switch(request_type) //All is clear, let get things done. + if(REQUEST_NEW_OBJECTIVE) + request_target = new request_target() + request_target.owner = src + if(istype(request_target, /datum/objective/custom)) + request_target.explanation_text = requested_obj_change["text"] + else + request_target.admin_edit(usr) + antag_datum.objectives += request_target + message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved a requested objective from [current]: [request_target.explanation_text]") + if(REQUEST_DEL_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") + qdel(request_target) + if(REQUEST_WIN_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") + request_target.completed = TRUE + if(REQUEST_LOSE_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") + request_target.completed = FALSE + to_chat(current, "Your objective change request has been approved.") do_edit_objectives_ambitions() return else if (href_list["req_obj_deny"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) in antag_datums if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -938,13 +1057,13 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) do_edit_objectives_ambitions() - to_chat(usr, "Invalid requested objective reference.") + to_chat(usr, "Invalid requested objective change reference.") return - var/justifation = stripped_multiline_input(usr, "Justify why you are denying this objective request.", "Deny", memory, MAX_MESSAGE_LEN) - if(isnull(justifation)) + var/justification = stripped_multiline_input(usr, "Justify why you are denying this objective request change.", "Deny", memory, MAX_MESSAGE_LEN) + if(isnull(justification)) return if(!check_rights(R_ADMIN)) return @@ -952,22 +1071,31 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") do_edit_objectives_ambitions() return - var/datum/objective/type_cast = requested_objective["type"] + var/datum/objective/type_cast = requested_obj_change["target"] var/objective_name = initial(type_cast.name) - message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") - log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") - to_chat(current, "Your objective request has been denied for the following reason: [justifation]") - LAZYREMOVE(antag_datum.requested_objectives, uid) + message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") + log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") + to_chat(current, "Your objective request has been denied for the following reason: [justification]") + antag_datum.remove_objective_change(uid) do_edit_objectives_ambitions() return else if (href_list["obj_panel_complete_toggle"]) - var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) - if(!istype(objective_to_toggle) || QDELETED(objective_to_toggle)) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) in antag_datum.objectives + if(QDELETED(objective_to_toggle)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -984,8 +1112,17 @@ GLOBAL_LIST(objective_choices) return else if (href_list["obj_panel_delete"]) - var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) - if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) in antag_datum.objectives + if(QDELETED(objective_to_delete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -1006,8 +1143,17 @@ GLOBAL_LIST(objective_choices) return else if (href_list["obj_panel_edit"]) - var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) - if(!istype(objective_to_edit) || QDELETED(objective_to_edit)) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) in antag_datum.objectives + if(QDELETED(objective_to_edit)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -1219,7 +1365,7 @@ GLOBAL_LIST(objective_choices) if(href_list["ambition_panel"]) do_edit_objectives_ambitions() return -//ambition port end +//ambition port //Something in here might have changed your mob diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index fbe40f80b8..6b1c4933f4 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -27,7 +27,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/threat = 0 // Amount of threat this antag poses, for dynamic mode //ambition port start /// Lazy list for antagonists to request the admins objectives. - var/list/requested_objectives + var/list/requested_objective_changes //ambition port end var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors @@ -302,3 +302,44 @@ GLOBAL_LIST_EMPTY(antagonists) else return ..() + +///Sends a message to the admins notifying them of a change request. Is a bit more insistent if there's pending requests. +/datum/antagonist/proc/notify_admins_of_request(notification_message) + if(LAZYLEN(requested_objective_changes) > 1) //Not the first unprocessed request, be a bit more insistent. + for(var/a in GLOB.admins) + var/client/admin_client = a + if(admin_client.prefs.toggles & SOUND_ADMINHELP) + SEND_SOUND(admin_client, sound('sound/effects/adminhelp.ogg')) + window_flash(admin_client) + message_admins(notification_message) + + +///Clears change requests from deleted objectives to avoid broken references. +/datum/antagonist/proc/clean_request_from_del_objective(datum/objective/source, force) + var/objective_reference = REF(source) + for(var/uid in requested_objective_changes) + var/list/change_request = requested_objective_changes[uid] + if(change_request["target"] != objective_reference) + continue + LAZYREMOVE(requested_objective_changes, uid) + + +/datum/antagonist/proc/add_objective_change(uid, list/additions) + LAZYADD(requested_objective_changes, uid) + var/datum/objective/request_target = additions["target"] + if(!ispath(request_target)) + request_target = locate(request_target) in objectives + if(istype(request_target)) + RegisterSignal(request_target, COMSIG_PARENT_QDELETING, .proc/clean_request_from_del_objective) + requested_objective_changes[uid] = additions + + +/datum/antagonist/proc/remove_objective_change(uid) + if(!LAZYACCESS(requested_objective_changes, uid)) + return + var/datum/objective/request_target = requested_objective_changes[uid]["target"] + if(!ispath(request_target)) + request_target = locate(request_target) in objectives + if(istype(request_target)) + UnregisterSignal(request_target, COMSIG_PARENT_QDELETING) + LAZYREMOVE(requested_objective_changes, uid) From b99b9f65d6462ef740eabdb5cf2799d905ba53eb Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:19:53 +0100 Subject: [PATCH 04/43] Revert "god why am i doing it this way instead of just looking at end changes" This reverts commit aa6402427b1f903d4e6ab864218441e5eb28d731. --- code/__DEFINES/antagonists.dm | 6 - code/datums/mind.dm | 332 +++++------------- .../antagonists/_common/antag_datum.dm | 43 +-- 3 files changed, 94 insertions(+), 287 deletions(-) diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index f80652523e..e71243994d 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -110,9 +110,3 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance #define BLOB_SPREAD_COST 4 #define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread #define BLOB_REFLECTOR_COST 15 - -//Objectives-Ambitions Panel -#define REQUEST_NEW_OBJECTIVE "new_objective" -#define REQUEST_DEL_OBJECTIVE "del_objective" -#define REQUEST_WIN_OBJECTIVE "win_objective" -#define REQUEST_LOSE_OBJECTIVE "lose_objective" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index fa40b8c70d..a612938965 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -454,45 +454,21 @@ if(!length(antag_datum.objectives)) output += "
    • NONE" else - for(var/uid in antag_datum.requested_objective_changes) - var/list/objectives_info = antag_datum.requested_objective_changes[uid] - var/obj_request = objectives_info["request"] - switch(obj_request) - if(REQUEST_NEW_OBJECTIVE) - var/datum/objective/type_cast_objective = objectives_info["target"] - var/objective_text = objectives_info["text"] - output += "
    • Request #[uid]: ADD [initial(type_cast_objective.name)] - [objective_text]" - if(is_admin) - output += " Accept Edit Deny" - if(REQUEST_DEL_OBJECTIVE) - var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives - if(QDELETED(objective_ref)) - stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") - antag_datum.remove_objective_change(uid) - continue - output += "
    • Request #[uid]: DEL [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" - if(is_admin) - output += " Accept Deny" - if(REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) - var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives - if(QDELETED(objective_ref)) - stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") - antag_datum.remove_objective_change(uid) - continue - output += "
    • Request #[uid]: [obj_request == REQUEST_WIN_OBJECTIVE ? "WIN" : "LOSE"] [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" - if(is_admin) - output += " Accept Deny" - else - stack_trace("Objective request found with no request index. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") - continue + for(var/count in 1 to length(antag_datum.objectives)) + var/datum/objective/objective = antag_datum.objectives[count] + output += "
    • [count]: [objective.explanation_text]" + if(self_mind) + output += " Request Remove [objective.completed ? "Request incompletion" : "Request completion"]
      " + if(is_admin) + output += " Edit Remove [objective.completed ? "Mark as incomplete" : "Mark as complete"]
      " output += "
    " if(is_admin) output += "Announce objectives
    " - output += "
    Requested Objective Changes:" + output += "
    Requested Objectives:" if(self_mind) output += " Request objective" output += "
      " - if(!length(antag_datum.requested_objective_changes)) + if(!length(antag_datum.requested_objectives)) output += "
    • NONE" else for(var/uid in antag_datum.requested_objectives) @@ -517,7 +493,7 @@ /mob/proc/edit_ambitions() - set name = "Objectives and Ambitions" + set name = "Ambitions" set category = "IC" set desc = "View and edit your character's ambitions." mind.do_edit_ambitions() @@ -529,28 +505,6 @@ popup.open() GLOBAL_VAR_INIT(requested_objective_uid, 0) - - -GLOBAL_LIST(objective_player_choices) - -/proc/populate_objective_player_choices() - GLOB.objective_player_choices = list() - var/list/allowed_types = list( - /datum/objective/custom, - /datum/objective/assassinate/once, - /datum/objective/protect, - /datum/objective/escape, - /datum/objective/survive, - /datum/objective/martyr, - /datum/objective/steal, - /datum/objective/download, - ) - - for(var/t in allowed_types) - var/datum/objective/type_cast = t - GLOB.objective_player_choices[initial(type_cast.name)] = t - - GLOBAL_LIST(objective_choices) /proc/populate_objective_choices() @@ -742,14 +696,14 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(target_antag)) + if(!istype(target_antag)) to_chat(usr, "No antagonist found for this objective.") do_edit_objectives_ambitions() return - if(!GLOB.objective_player_choices) - populate_objective_player_choices() - var/choice = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_player_choices - var/selected_type = GLOB.objective_player_choices[choice] + if(!GLOB.objective_choices) + populate_objective_choices() + var/choe = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_choices + var/selected_type = GLOB.objective_choices[choe] if(!selected_type) return var/new_objective = stripped_multiline_input(usr,\ @@ -770,10 +724,11 @@ GLOBAL_LIST(objective_choices) return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) var/uid = "[GLOB.requested_objective_uid++]" - target_antag.add_objective_change(uid, list("request" = REQUEST_NEW_OBJECTIVE, "target" = selected_type, "text" = new_objective)) - log_admin("Objectives request [uid] - [key_name(usr)] has requested a [choice] objective: [new_objective]") - target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested a [choice] objective. (RPLY)") - to_chat(usr + LAZYADD(target_antag.requested_objectives, uid) + target_antag.requested_objectives[uid] = list("type" = selected_type, "text" = new_objective) + log_admin("[key_name(usr)] has requested a [choe] objective: [new_objective]") + message_admins("[ADMIN_TPMONTY(usr)] has requested a [choe] objective. (RPLY)") + to_chat(usr, "The admins have been notified of your request!") do_edit_objectives_ambitions() return @@ -783,18 +738,12 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(target_antag)) - to_chat(usr, "No antagonist found for this objective.") - do_edit_objectives_ambitions() - return - var/objective_reference = href_list["req_obj_delete"] - var/datum/objective/objective_to_delete = locate(objective_reference) in target_antag.objectives + var/datum/objective/objective_to_delete = locate(href_list["req_obj_delete"]) if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return - var/justification = stripped_multiline_input(usr, + var/justifation = stripped_multiline_input(usr, "Justify your request for a deleting this objective to the admins.\ There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", "Objective Deletion", max_length = MAX_MESSAGE_LEN) @@ -805,21 +754,13 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - if(QDELETED(objective_to_delete) || QDELETED(target_antag)) + if(QDELETED(objective_to_delete)) do_edit_objectives_ambitions() return - for(var/index in target_antag.requested_objective_changes) - var/list/change_request = target_antag.requested_objective_changes[index] - if(change_request["target"] != objective_reference) - continue - to_chat(usr, "There is already a change request tied to this objective waiting to be processed. Ahelp or wait for it to be resolved before adding a new one.") - return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - var/uid = "[GLOB.requested_objective_uid++]" - target_antag.add_objective_change(uid, list("request" = REQUEST_DEL_OBJECTIVE, "target" = objective_reference, "text" = justification)) - log_admin("Objectives request [uid] - [key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justification is as follows: [justification]") - target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested the deletion of an objective: (RPLY)") - to_chat(usr, "The admins have been notified of your request!") + log_admin("[key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]") + message_admins("[ADMIN_TPMONTY(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") + to_chat(usr, "The admins have been notified of your request!") do_edit_objectives_ambitions() return else if (href_list["req_obj_completed"]) @@ -828,43 +769,29 @@ GLOBAL_LIST(objective_choices) if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(target_antag)) - to_chat(usr, "No antagonist found for this objective.") - do_edit_objectives_ambitions() - return - var/objective_reference = href_list["req_obj_completed"] - var/datum/objective/objective_to_complete = locate(objective_reference) in target_antag.objectives + var/datum/objective/objective_to_complete = locate(href_list["req_obj_completed"]) if(!istype(objective_to_complete) || QDELETED(objective_to_complete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return - var/justification = stripped_multiline_input(usr, - "Justify to the admins your request to mark this objective as [objective_to_complete.completed ? "incomplete" : "completed"].\ + var/justifation = stripped_multiline_input(usr, + "Justify your request for the [objective_to_complete.completed ? "completion" : "incompletion"] of this objective to the admins.\ There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", - "Objective [objective_to_complete.completed ? "Incompletion" : "Completion"]", max_length = MAX_MESSAGE_LEN) - if(isnull(justification)) + "Objective [objective_to_complete.completed ? "Completion" : "Incompletion"]", max_length = MAX_MESSAGE_LEN) + if(isnull(justifation)) return if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") return - if(QDELETED(objective_to_complete) || QDELETED(target_antag)) + if(QDELETED(objective_to_complete)) do_edit_objectives_ambitions() return - for(var/index in target_antag.requested_objective_changes) - var/list/change_request = target_antag.requested_objective_changes[index] - if(change_request["target"] != objective_reference) - continue - to_chat(usr, "There is already a change request tied to this objective waiting to be processed. Ahelp or wait for it to be resolved before adding a new one.") - return COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - var/uid = "[GLOB.requested_objective_uid++]" - target_antag.add_objective_change(uid, list("request" = (objective_to_complete.completed ? REQUEST_LOSE_OBJECTIVE : REQUEST_WIN_OBJECTIVE), "target" = objective_reference, "text" = justification)) - log_admin("Objectives request [uid] - [key_name(usr)] has requested the [objective_to_complete.completed ? "incompletion" : "completion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justification is as follows: [justification]") - target_antag.notify_admins_of_request("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "incompletion" : "completion"] of an objective: (RPLY)") - to_chat(usr, "The admins have been notified of your request!") + log_admin("[key_name(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]") + message_admins("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") + to_chat(usr, "The admins have been notified of your request!") do_edit_objectives_ambitions() return if(!check_rights(R_ADMIN)) @@ -881,7 +808,7 @@ GLOBAL_LIST(objective_choices) return else if (href_list["req_obj_edit"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) in antag_datums + var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -891,15 +818,12 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) - if(!requested_obj_change) + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) do_edit_objectives_ambitions() to_chat(usr, "Invalid requested objective reference.") return - if(requested_obj_change["request"] != REQUEST_NEW_OBJECTIVE) - do_edit_objectives_ambitions() - to_chat(usr, "This is not an editable request. How did you even got here?") - return + switch(alert(usr, "Do you want to edit the requested objective type or text?", "Edit requested objective", "Type", "Text", "Cancel")) if("Type") if(!check_rights(R_ADMIN)) @@ -908,11 +832,11 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - var/datum/objective/type_cast = requested_obj_change["target"] + var/datum/objective/type_cast = requested_objective["type"] var/selected_type = input("Select new requested objective type:", "Requested Objective type", initial(type_cast.name)) as null|anything in GLOB.objective_choices selected_type = GLOB.objective_choices[selected_type] if(!selected_type) @@ -923,13 +847,13 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") - message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") - requested_obj_change["target"] = selected_type + log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") + message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") + requested_objective["type"] = selected_type if("Text") if(!check_rights(R_ADMIN)) return @@ -937,11 +861,11 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_obj_change["text"], MAX_MESSAGE_LEN) + var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_objective["text"], MAX_MESSAGE_LEN) if (isnull(new_text)) return if(!check_rights(R_ADMIN)) @@ -950,18 +874,18 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") - message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") - requested_obj_change["text"] = new_text + log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") + message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") + requested_objective["text"] = new_text do_edit_objectives_ambitions() return else if (href_list["req_obj_accept"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) in antag_datums + var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -971,29 +895,12 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) - if(!requested_obj_change) + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) do_edit_objectives_ambitions() to_chat(usr, "Invalid requested objective reference.") return - - var/datum/objective/request_target - var/request_type = requested_obj_change["request"] - switch(request_type) - if(REQUEST_NEW_OBJECTIVE) - request_target = requested_obj_change["target"] - if(!ispath(request_target, /datum/objective)) - to_chat(usr, "Invalid requested objective target path.") - return - if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) - request_target = locate(requested_obj_change["target"]) in antag_datum.objectives - if(QDELETED(request_target)) - to_chat(usr, "Invalid requested objective target reference.") - return - else - to_chat(usr, "Invalid request type.") - return - if(alert(usr, "Are you sure you want to approve this objective change?", "Approve objective change", "Yes", "No") != "Yes") + if(alert(usr, "Are you sure you want to approve this objective?", "Approve objective", "Yes", "No") != "Yes") return if(!check_rights(R_ADMIN)) return @@ -1001,53 +908,27 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - switch(request_type) //Last checks - if(REQUEST_NEW_OBJECTIVE) - if(!ispath(request_target, /datum/objective)) - stack_trace("Invalid target on objective change request: [request_target]") - do_edit_objectives_ambitions() - return - if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) - if(QDELETED(request_target)) - to_chat(usr, "Invalid requested objective target reference.") - return - else - to_chat(usr, "Invalid request type.") - return - antag_datum.remove_objective_change(uid) - switch(request_type) //All is clear, let get things done. - if(REQUEST_NEW_OBJECTIVE) - request_target = new request_target() - request_target.owner = src - if(istype(request_target, /datum/objective/custom)) - request_target.explanation_text = requested_obj_change["text"] - else - request_target.admin_edit(usr) - antag_datum.objectives += request_target - message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [request_target.explanation_text]") - log_admin("[key_name(usr)] approved a requested objective from [current]: [request_target.explanation_text]") - if(REQUEST_DEL_OBJECTIVE) - message_admins("[key_name_admin(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") - log_admin("[key_name(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") - qdel(request_target) - if(REQUEST_WIN_OBJECTIVE) - message_admins("[key_name_admin(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") - log_admin("[key_name(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") - request_target.completed = TRUE - if(REQUEST_LOSE_OBJECTIVE) - message_admins("[key_name_admin(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") - log_admin("[key_name(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") - request_target.completed = FALSE - to_chat(current, "Your objective change request has been approved.") + var/objective_path = requested_objective["type"] + var/datum/objective/new_objective = new objective_path + new_objective.owner = src + if(istype(new_objective, /datum/objective/custom)) + new_objective.explanation_text = requested_objective["text"] + else + new_objective.admin_edit(usr) + antag_datum.objectives += new_objective + LAZYREMOVE(antag_datum.requested_objectives, uid) + message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") + log_admin("[key_name(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") + to_chat(current, "Your objective request has been approved.") do_edit_objectives_ambitions() return else if (href_list["req_obj_deny"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) in antag_datums + var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) if(QDELETED(antag_datum)) do_edit_objectives_ambitions() to_chat(usr, "No antag found.") @@ -1057,13 +938,13 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "Invalid antag reference.") return var/uid = href_list["req_obj_id"] - var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) - if(!requested_obj_change) + var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) + if(!requested_objective) do_edit_objectives_ambitions() - to_chat(usr, "Invalid requested objective change reference.") + to_chat(usr, "Invalid requested objective reference.") return - var/justification = stripped_multiline_input(usr, "Justify why you are denying this objective request change.", "Deny", memory, MAX_MESSAGE_LEN) - if(isnull(justification)) + var/justifation = stripped_multiline_input(usr, "Justify why you are denying this objective request.", "Deny", memory, MAX_MESSAGE_LEN) + if(isnull(justifation)) return if(!check_rights(R_ADMIN)) return @@ -1071,31 +952,22 @@ GLOBAL_LIST(objective_choices) to_chat(usr, "No antag found.") do_edit_objectives_ambitions() return - if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) - to_chat(usr, "Invalid requested objective change reference.") + if(!LAZYACCESS(antag_datum.requested_objectives, uid)) + to_chat(usr, "Invalid requested objective reference.") do_edit_objectives_ambitions() return - var/datum/objective/type_cast = requested_obj_change["target"] + var/datum/objective/type_cast = requested_objective["type"] var/objective_name = initial(type_cast.name) - message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") - log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") - to_chat(current, "Your objective request has been denied for the following reason: [justification]") - antag_datum.remove_objective_change(uid) + message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") + log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") + to_chat(current, "Your objective request has been denied for the following reason: [justifation]") + LAZYREMOVE(antag_datum.requested_objectives, uid) do_edit_objectives_ambitions() return else if (href_list["obj_panel_complete_toggle"]) - var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) in antag_datum.objectives - if(QDELETED(objective_to_toggle)) + var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) + if(!istype(objective_to_toggle) || QDELETED(objective_to_toggle)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -1112,17 +984,8 @@ GLOBAL_LIST(objective_choices) return else if (href_list["obj_panel_delete"]) - var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) in antag_datum.objectives - if(QDELETED(objective_to_delete)) + var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) + if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -1143,17 +1006,8 @@ GLOBAL_LIST(objective_choices) return else if (href_list["obj_panel_edit"]) - var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) in antag_datum.objectives - if(QDELETED(objective_to_edit)) + var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) + if(!istype(objective_to_edit) || QDELETED(objective_to_edit)) to_chat(usr, "No objective found. Perhaps it was already deleted?") do_edit_objectives_ambitions() return @@ -1365,7 +1219,7 @@ GLOBAL_LIST(objective_choices) if(href_list["ambition_panel"]) do_edit_objectives_ambitions() return -//ambition port +//ambition port end //Something in here might have changed your mob diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 6b1c4933f4..fbe40f80b8 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -27,7 +27,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/threat = 0 // Amount of threat this antag poses, for dynamic mode //ambition port start /// Lazy list for antagonists to request the admins objectives. - var/list/requested_objective_changes + var/list/requested_objectives //ambition port end var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors @@ -302,44 +302,3 @@ GLOBAL_LIST_EMPTY(antagonists) else return ..() - -///Sends a message to the admins notifying them of a change request. Is a bit more insistent if there's pending requests. -/datum/antagonist/proc/notify_admins_of_request(notification_message) - if(LAZYLEN(requested_objective_changes) > 1) //Not the first unprocessed request, be a bit more insistent. - for(var/a in GLOB.admins) - var/client/admin_client = a - if(admin_client.prefs.toggles & SOUND_ADMINHELP) - SEND_SOUND(admin_client, sound('sound/effects/adminhelp.ogg')) - window_flash(admin_client) - message_admins(notification_message) - - -///Clears change requests from deleted objectives to avoid broken references. -/datum/antagonist/proc/clean_request_from_del_objective(datum/objective/source, force) - var/objective_reference = REF(source) - for(var/uid in requested_objective_changes) - var/list/change_request = requested_objective_changes[uid] - if(change_request["target"] != objective_reference) - continue - LAZYREMOVE(requested_objective_changes, uid) - - -/datum/antagonist/proc/add_objective_change(uid, list/additions) - LAZYADD(requested_objective_changes, uid) - var/datum/objective/request_target = additions["target"] - if(!ispath(request_target)) - request_target = locate(request_target) in objectives - if(istype(request_target)) - RegisterSignal(request_target, COMSIG_PARENT_QDELETING, .proc/clean_request_from_del_objective) - requested_objective_changes[uid] = additions - - -/datum/antagonist/proc/remove_objective_change(uid) - if(!LAZYACCESS(requested_objective_changes, uid)) - return - var/datum/objective/request_target = requested_objective_changes[uid]["target"] - if(!ispath(request_target)) - request_target = locate(request_target) in objectives - if(istype(request_target)) - UnregisterSignal(request_target, COMSIG_PARENT_QDELETING) - LAZYREMOVE(requested_objective_changes, uid) From a061f02b5b5e60a04c3f48a83083f5c8902c9857 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:19:56 +0100 Subject: [PATCH 05/43] Revert "objectives" This reverts commit dbabbb10625dc353e3567c41e73cee1a81e23b13. --- code/__DEFINES/cooldowns.dm | 2 +- code/datums/mind.dm | 521 +++--------------- code/modules/admin/admin.dm | 14 +- code/modules/admin/topic.dm | 11 - .../antagonists/_common/antag_datum.dm | 5 - 5 files changed, 70 insertions(+), 483 deletions(-) diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index 947f3202e6..13a7633409 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -28,7 +28,7 @@ //INDEXES #define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet" #define COOLDOWN_AMBITION "ambition" -#define COOLDOWN_OBJECTIVES "objectives" + //TIMER COOLDOWN MACROS diff --git a/code/datums/mind.dm b/code/datums/mind.dm index a612938965..e6414f1d9f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -30,7 +30,6 @@ */ //ambition port start #define AMBITION_COOLDOWN_TIME (5 SECONDS) -#define OBJECTIVES_COOLDOWN_TIME (10 MINUTES) //ambition port end @@ -199,7 +198,7 @@ . = LAZYLEN(antag_datums) LAZYADD(antag_datums, instanced_datum) if(!.) - current.verbs += /mob/proc/edit_objectives_and_ambitions + current.verbs += /mob/proc/edit_ambitions //ambitions port end /datum/mind/proc/remove_antag_datum(datum_type) @@ -221,8 +220,8 @@ . = LAZYLEN(antag_datums) LAZYREMOVE(antag_datums, instanced_datum) if(. && !LAZYLEN(antag_datums)) + current.verbs -= /mob/proc/edit_ambitions ambitions = null - current.verbs += /mob/proc/edit_objectives_and_ambitions //ambitions port end /datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) @@ -439,56 +438,18 @@ return output.Join() -/datum/mind/proc/show_editable_objectives_and_ambitions() - var/is_admin = check_rights(R_ADMIN, FALSE) - var/self_mind = usr == current - if(!is_admin && !self_mind) - return "" - var/list/output = list() - for(var/a in antag_datums) - var/datum/antagonist/antag_datum = a - output += "Objectives:" - if(is_admin) - output += " Add Objective" - output += "" - if(is_admin) - output += "Announce objectives
      " - output += "
      Requested Objectives:" - if(self_mind) - output += " Request objective" - output += "
        " - if(!length(antag_datum.requested_objectives)) - output += "
      • NONE" - else - for(var/uid in antag_datum.requested_objectives) - var/list/objectives_info = antag_datum.requested_objectives[uid] - var/datum/objective/type_cast_objective = objectives_info["type"] - var/objective_text = objectives_info["text"] - output += "
      • Request #[uid]: [initial(type_cast_objective.name)] - [objective_text]" - if(is_admin) - output += " Accept Edit Deny" - output += "

      " - output += "[current.real_name]'s Ambitions:" - if(LAZYLEN(ambitions) < CONFIG_GET(number/max_ambitions)) - output += " Add Ambition" - output += "
        " +/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]]" - output += "

        (Refresh)" + if(LAZYLEN(ambitions) < 5) + output += "
      • (Add Ambition)" + output += "
      • (Refresh)
      " return output.Join() @@ -499,53 +460,24 @@ mind.do_edit_ambitions() -/datum/mind/proc/do_edit_objectives_ambitions() - var/datum/browser/popup = new(usr, "objectives and ambitions", "Objectives and Ambitions") - popup.set_content(show_editable_objectives_and_ambitions()) +/datum/mind/proc/do_edit_ambitions() + var/datum/browser/popup = new(usr, "ambitions", "Ambitions") + popup.set_content(show_editable_ambitions()) popup.open() - -GLOBAL_VAR_INIT(requested_objective_uid, 0) -GLOBAL_LIST(objective_choices) - -/proc/populate_objective_choices() - GLOB.objective_choices = list() - var/list/allowed_types = list( - /datum/objective/custom, - /datum/objective/assassinate, - /datum/objective/assassinate/once, - /datum/objective/maroon, - /datum/objective/debrain, - /datum/objective/protect, - /datum/objective/destroy, - /datum/objective/hijack, - /datum/objective/escape, - /datum/objective/survive, - /datum/objective/martyr, - /datum/objective/steal, - /datum/objective/download, - /datum/objective/nuclear, - /datum/objective/absorb, - /datum/objective/blackmail_implant //SKYRAT ADDITION - ) - - for(var/t in allowed_types) - var/datum/objective/type_cast = t - GLOB.objective_choices[initial(type_cast.name)] = t //ambition port end /datum/mind/Topic(href, href_list) //ambition port start - if (href_list["refresh_obj_amb"]) - do_edit_objectives_ambitions() - + if (href_list["refresh_ambitions"]) + do_edit_ambitions() return else if (href_list["add_ambition"]) - if(!check_rights(R_ADMIN, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") return if(!isliving(current)) return @@ -554,16 +486,16 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() + 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, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + 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.") @@ -573,7 +505,7 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() + do_edit_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) LAZYADD(ambitions, new_ambition) @@ -582,15 +514,15 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() + do_edit_ambitions() return else if (href_list["edit_ambition"]) - if(!check_rights(R_ADMIN, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") return if(!isliving(current)) return @@ -607,11 +539,11 @@ GLOBAL_LIST(objective_choices) 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, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + 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.") @@ -621,11 +553,11 @@ GLOBAL_LIST(objective_choices) return if(ambition_index > LAZYLEN(ambitions)) to_chat(usr, "The ambition we were editing was deleted before we finished. Aborting.") - do_edit_objectives_ambitions() + 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_objectives_ambitions() + do_edit_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) ambitions[ambition_index] = new_ambition @@ -634,15 +566,15 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() + do_edit_ambitions() return else if (href_list["remove_ambition"]) - if(!check_rights(R_ADMIN, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 10] seconds between changes.") return if(!isliving(current)) return @@ -650,7 +582,7 @@ GLOBAL_LIST(objective_choices) return var/ambition_index = text2num(href_list["remove_ambition"]) if(ambition_index > LAZYLEN(ambitions)) - do_edit_objectives_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)].") @@ -659,11 +591,11 @@ GLOBAL_LIST(objective_choices) 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, FALSE)) + if(!check_rights(R_ADMIN)) if(usr != current) return if(COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) - to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] seconds between changes.") + 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.") @@ -673,11 +605,11 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() + 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_objectives_ambitions() + do_edit_ambitions() return COOLDOWN_START(src, COOLDOWN_AMBITION, AMBITION_COOLDOWN_TIME) LAZYCUT(ambitions, ambition_index, ambition_index + 1) @@ -686,113 +618,7 @@ GLOBAL_LIST(objective_choices) 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_objectives_ambitions() - return - - else if (href_list["req_obj_add"]) - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums - if(!istype(target_antag)) - to_chat(usr, "No antagonist found for this objective.") - do_edit_objectives_ambitions() - return - if(!GLOB.objective_choices) - populate_objective_choices() - var/choe = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_choices - var/selected_type = GLOB.objective_choices[choe] - if(!selected_type) - return - var/new_objective = stripped_multiline_input(usr,\ - selected_type == /datum/objective/custom\ - ? "Write the custom objective you'd like to request the admins to grant you.\ - Remember they can edit or deny your request. There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown."\ - : "Justify your request for a new objective to the admins. Add the required clarifations, if you have a specific targets in mind or the likes.\ - Remember they can edit or deny your request. There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.",\ - "New Objective", max_length = MAX_MESSAGE_LEN) - if(isnull(new_objective)) - return - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - if(QDELETED(target_antag)) - return - COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - var/uid = "[GLOB.requested_objective_uid++]" - LAZYADD(target_antag.requested_objectives, uid) - target_antag.requested_objectives[uid] = list("type" = selected_type, "text" = new_objective) - log_admin("[key_name(usr)] has requested a [choe] objective: [new_objective]") - message_admins("[ADMIN_TPMONTY(usr)] has requested a [choe] objective. (RPLY)") - to_chat(usr, "The admins have been notified of your request!") - do_edit_objectives_ambitions() - return - - else if (href_list["req_obj_delete"]) - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - var/datum/objective/objective_to_delete = locate(href_list["req_obj_delete"]) - if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) - to_chat(usr, "No objective found. Perhaps it was already deleted?") - do_edit_objectives_ambitions() - return - var/justifation = stripped_multiline_input(usr, - "Justify your request for a deleting this objective to the admins.\ - There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", - "Objective Deletion", max_length = MAX_MESSAGE_LEN) - if(isnull(justifation)) - return - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - if(QDELETED(objective_to_delete)) - do_edit_objectives_ambitions() - return - COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - log_admin("[key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]") - message_admins("[ADMIN_TPMONTY(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") - to_chat(usr, "The admins have been notified of your request!") - do_edit_objectives_ambitions() - return - else if (href_list["req_obj_completed"]) - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - var/datum/objective/objective_to_complete = locate(href_list["req_obj_completed"]) - if(!istype(objective_to_complete) || QDELETED(objective_to_complete)) - to_chat(usr, "No objective found. Perhaps it was already deleted?") - do_edit_objectives_ambitions() - return - var/justifation = stripped_multiline_input(usr, - "Justify your request for the [objective_to_complete.completed ? "completion" : "incompletion"] of this objective to the admins.\ - There's a 10 minutes cooldown between requests, so try to think it through before sending it. Cancelling does not trigger the cooldown.", - "Objective [objective_to_complete.completed ? "Completion" : "Incompletion"]", max_length = MAX_MESSAGE_LEN) - if(isnull(justifation)) - return - if(usr != current) - return - if(COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) - to_chat(usr, "You must wait [round(OBJECTIVES_COOLDOWN_TIME / 600, 0.1)] minutes between requests.") - return - if(QDELETED(objective_to_complete)) - do_edit_objectives_ambitions() - return - COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) - log_admin("[key_name(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]") - message_admins("[ADMIN_TPMONTY(usr)] has requested the [objective_to_complete.completed ? "completion" : "incompletion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justifation is as follows: [justifation]\n(RPLY)") - to_chat(usr, "The admins have been notified of your request!") - do_edit_objectives_ambitions() + do_edit_ambitions() return if(!check_rights(R_ADMIN)) return @@ -800,236 +626,12 @@ GLOBAL_LIST(objective_choices) var/self_antagging = usr == current if(href_list["edit_ambitions_panel"]) - do_edit_objectives_ambitions() + do_edit_ambitions() return - else if(href_list["refresh_antag_panel"]) traitor_panel() return - - else if (href_list["req_obj_edit"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid requested objective reference.") - return - - switch(alert(usr, "Do you want to edit the requested objective type or text?", "Edit requested objective", "Type", "Text", "Cancel")) - if("Type") - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - var/datum/objective/type_cast = requested_objective["type"] - var/selected_type = input("Select new requested objective type:", "Requested Objective type", initial(type_cast.name)) as null|anything in GLOB.objective_choices - selected_type = GLOB.objective_choices[selected_type] - if(!selected_type) - return - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") - message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_objective["type"]] to [selected_type]") - requested_objective["type"] = selected_type - if("Text") - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_objective["text"], MAX_MESSAGE_LEN) - if (isnull(new_text)) - return - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") - message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_objective["text"]] to [new_text]") - requested_objective["text"] = new_text - do_edit_objectives_ambitions() - return - - else if (href_list["req_obj_accept"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid requested objective reference.") - return - if(alert(usr, "Are you sure you want to approve this objective?", "Approve objective", "Yes", "No") != "Yes") - return - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - var/objective_path = requested_objective["type"] - var/datum/objective/new_objective = new objective_path - new_objective.owner = src - if(istype(new_objective, /datum/objective/custom)) - new_objective.explanation_text = requested_objective["text"] - else - new_objective.admin_edit(usr) - antag_datum.objectives += new_objective - LAZYREMOVE(antag_datum.requested_objectives, uid) - message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") - log_admin("[key_name(usr)] approved a requested objective from [current]: [new_objective.explanation_text]") - to_chat(current, "Your objective request has been approved.") - do_edit_objectives_ambitions() - return - - else if (href_list["req_obj_deny"]) - var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) - if(QDELETED(antag_datum)) - do_edit_objectives_ambitions() - to_chat(usr, "No antag found.") - return - if(antag_datum.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid antag reference.") - return - var/uid = href_list["req_obj_id"] - var/list/requested_objective = LAZYACCESS(antag_datum.requested_objectives, uid) - if(!requested_objective) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid requested objective reference.") - return - var/justifation = stripped_multiline_input(usr, "Justify why you are denying this objective request.", "Deny", memory, MAX_MESSAGE_LEN) - if(isnull(justifation)) - return - if(!check_rights(R_ADMIN)) - return - if(QDELETED(antag_datum)) - to_chat(usr, "No antag found.") - do_edit_objectives_ambitions() - return - if(!LAZYACCESS(antag_datum.requested_objectives, uid)) - to_chat(usr, "Invalid requested objective reference.") - do_edit_objectives_ambitions() - return - var/datum/objective/type_cast = requested_objective["type"] - var/objective_name = initial(type_cast.name) - message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") - log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_objective["text"]]") - to_chat(current, "Your objective request has been denied for the following reason: [justifation]") - LAZYREMOVE(antag_datum.requested_objectives, uid) - do_edit_objectives_ambitions() - return - - else if (href_list["obj_panel_complete_toggle"]) - var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) - if(!istype(objective_to_toggle) || QDELETED(objective_to_toggle)) - to_chat(usr, "No objective found. Perhaps it was already deleted?") - do_edit_objectives_ambitions() - return - if(objective_to_toggle.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid objective reference.") - return - objective_to_toggle.completed = !objective_to_toggle.completed - message_admins("[key_name_admin(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") - log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") - if(alert(usr, "Would you like to alert the player of the change?", "Deny objective", "Yes", "No") == "Yes") - to_chat(current, "[objective_to_toggle.completed ? "" : ""]Your objective status has changed!") - do_edit_objectives_ambitions() - return - - else if (href_list["obj_panel_delete"]) - var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) - if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) - to_chat(usr, "No objective found. Perhaps it was already deleted?") - do_edit_objectives_ambitions() - return - if(objective_to_delete.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid objective reference.") - return - if(alert(usr, "Are you sure you want to delete this objective?", "Delete objective", "Yes", "No") != "Yes") - return - if(!check_rights(R_ADMIN)) - return - if(QDELETED(objective_to_delete)) - return - message_admins("[key_name_admin(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") - log_admin("[key_name(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") - qdel(objective_to_delete) - do_edit_objectives_ambitions() - return - - else if (href_list["obj_panel_edit"]) - var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) - if(!istype(objective_to_edit) || QDELETED(objective_to_edit)) - to_chat(usr, "No objective found. Perhaps it was already deleted?") - do_edit_objectives_ambitions() - return - if(objective_to_edit.owner != src) - do_edit_objectives_ambitions() - to_chat(usr, "Invalid objective reference.") - return - var/explanation_before = objective_to_edit.explanation_text - objective_to_edit.admin_edit(usr) - if(QDELETED(objective_to_edit)) - return - message_admins("[key_name_admin(usr)] edited an objective from [current]:\ - Before: [explanation_before]\ - After: [objective_to_edit.explanation_text]") - log_admin("[key_name(usr)] edited an objective from [current]:\ - Before: [explanation_before]\ - After: [objective_to_edit.explanation_text]") - do_edit_objectives_ambitions() - return - //ambition port end - if(href_list["add_antag"]) add_antag_wrapper(text2path(href_list["add_antag"]),usr) if(href_list["remove_antag"]) @@ -1089,16 +691,38 @@ GLOBAL_LIST(objective_choices) else target_antag = target -//ambition port start - if(!GLOB.objective_choices) - populate_objective_choices() + var/static/list/choices + if(!choices) + choices = list() - if(old_objective && GLOB.objective_choices[old_objective.name]) - def_value = old_objective.name + var/list/allowed_types = list( + /datum/objective/assassinate, + /datum/objective/assassinate/once, + /datum/objective/maroon, + /datum/objective/debrain, + /datum/objective/protect, + /datum/objective/destroy, + /datum/objective/hijack, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/nuclear, + /datum/objective/absorb, + /datum/objective/custom + ) - var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in GLOB.objective_choices - selected_type = GLOB.objective_choices[selected_type] -//ambition port end + for(var/T in allowed_types) + var/datum/objective/X = T + choices[initial(X.name)] = T + + if(old_objective) + if(old_objective.name in choices) + def_value = old_objective.name + + var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices + selected_type = choices[selected_type] if (!selected_type) return @@ -1125,11 +749,6 @@ GLOBAL_LIST(objective_choices) target_antag.objectives.Insert(objective_pos, new_objective) message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") -//ambition port start - if(href_list["ambition_panel"]) - do_edit_objectives_ambitions() - return -//ambition port end else if(href_list["traitor_class"]) var/static/list/choices @@ -1215,12 +834,6 @@ GLOBAL_LIST(objective_choices) else if (href_list["obj_announce"]) announce_objectives() -//ambition port start - if(href_list["ambition_panel"]) - do_edit_objectives_ambitions() - return -//ambition port end - //Something in here might have changed your mob if(self_antagging && (!usr || !usr.client) && current.client) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 6a2bc83db7..d4afc3dbb4 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -25,9 +25,7 @@ to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.", confidential = TRUE) return -//ambition port start - var/list/body = list("Options for [M.key]") -//ambition port end + var/body = "Options for [M.key]" body += "Options panel for [M]" if(M.client) body += " played by [M.client] " @@ -127,10 +125,6 @@ body += "Subtle message | " // body += "Play sound to | " body += "Language Menu" -//ambition port start - if(M.mind) - body += " | Objective-Ambition Menu" -//ambition port end if (M.client) if(!isnewplayer(M)) @@ -212,11 +206,7 @@ body += "
      " body += "" -//ambition port start - var/datum/browser/popup = new(usr, "adminplayeropts-[REF(M)]", "Player Panel", nwidth = 550, nheight = 515) - popup.set_content(body.Join()) - popup.open() -//ambition port end + usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515") SSblackbox.record_feedback("tally", "admin_verb", 1, "Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 9cd4fd203c..05e791984a 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2251,17 +2251,6 @@ var/mob/M = locate(href_list["HeadsetMessage"]) usr.client.admin_headset_message(M) -//ambition port start - else if(href_list["ObjectiveRequest"]) - if(!check_rights(R_ADMIN)) - return - var/datum/mind/requesting_mind = locate(href_list["ObjectiveRequest"]) - if(!istype(requesting_mind) || QDELETED(requesting_mind)) - to_chat(usr, "This mind reference is no longer valid. It has probably since been destroyed.") - return - requesting_mind.do_edit_objectives_ambitions() - return -//ambition port end else if(href_list["reject_custom_name"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index fbe40f80b8..df9a8bff2e 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -25,11 +25,6 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. var/threat = 0 // Amount of threat this antag poses, for dynamic mode -//ambition port start - /// Lazy list for antagonists to request the admins objectives. - var/list/requested_objectives -//ambition port end - var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors var/list/skill_modifiers From 2f1aba4f800ffd155f11130c08d4bea5d07a0f74 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:19:59 +0100 Subject: [PATCH 06/43] Revert "i can't believe kevin made me code" This reverts commit 7f385648381af7313848eba031fdf49071738d98. --- code/__DEFINES/admin.dm | 4 - code/__DEFINES/cooldowns.dm | 7 - code/__DEFINES/say.dm | 3 - code/__HELPERS/_lists.dm | 3 - code/__HELPERS/roundend.dm | 5 - .../configuration/entries/general.dm | 5 - code/datums/datum.dm | 13 - code/datums/mind.dm | 245 +----------------- code/modules/admin/antag_panel.dm | 32 +-- .../antagonists/_common/antag_datum.dm | 9 +- .../antagonists/changeling/powers/absorb.dm | 4 +- code/modules/mob/living/login.dm | 5 +- code/modules/mob/mob.dm | 6 +- 13 files changed, 23 insertions(+), 318 deletions(-) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index c75adfa49e..f6293454ee 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -56,10 +56,6 @@ #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 13a7633409..29c7a25dad 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -27,7 +27,6 @@ //INDEXES #define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet" -#define COOLDOWN_AMBITION "ambition" //TIMER COOLDOWN MACROS @@ -41,12 +40,6 @@ #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 a9e23bb67c..9403eca2da 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -86,9 +86,6 @@ #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 608da83dd9..a554397c41 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -13,9 +13,6 @@ #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 ad57ce42ac..cd59dfd9cf 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -491,11 +491,6 @@ 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 a65e9ddb81..63da60d7b5 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -441,8 +441,3 @@ 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 74dfbbddd9..42580425ce 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -49,11 +49,6 @@ /// 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. * @@ -266,11 +261,3 @@ 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 e6414f1d9f..897e2e7d71 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -28,10 +28,6 @@ yourself. */ -//ambition port start -#define AMBITION_COOLDOWN_TIME (5 SECONDS) -//ambition port end - /datum/mind var/key @@ -72,11 +68,6 @@ /// 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 @@ -182,10 +173,7 @@ qdel(A) return A.owner = src -//ambitions port start - do_add_antag_datum(A) -//ambitions port end - + LAZYADD(antag_datums, A) A.create_team(team) var/datum/team/antag_team = A.get_team() if(antag_team) @@ -193,14 +181,6 @@ 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 @@ -215,15 +195,6 @@ 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 @@ -403,10 +374,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.") -//ambitions port start -/datum/mind/proc/show_memory() - var/list/output = list("[current.real_name]'s Memories:
      ") -//ambitions port end +/datum/mind/proc/show_memory(mob/recipient, window=1) + if(!recipient) + recipient = current + var/output = "[current.real_name]'s Memories:
      " output += memory @@ -427,211 +398,17 @@ output += "
    • Conspirator: [M.name]
    • " 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 += "
    • NONE
    " - - 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 + if(window) + recipient << browse(output,"window=memory") + else if(all_objectives.len || memory) + to_chat(recipient, "[output]") /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"]) @@ -1037,7 +814,3 @@ ..() 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 502ee116c1..88aab2c4ce 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -97,14 +97,10 @@ GLOBAL_VAR(antag_prototypes) alert("This mind doesn't have a mob, or is deleted! For some reason!", "Edit Memory") return -//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/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]
    " var/special_statuses = get_special_statuses() if(length(special_statuses)) @@ -195,16 +191,6 @@ 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" @@ -218,16 +204,14 @@ GLOBAL_VAR(antag_prototypes) out += uplink_info + "
    " //Common Memory - out += "
    Common Memory:" - out += memory - out += "Edit Memory
    " + var/common_memory = "Common Memory:" + common_memory += memory + common_memory += "Edit Memory" + out += common_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 df9a8bff2e..14f7b34309 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -35,9 +35,8 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/Destroy() GLOB.antagonists -= src -//ambition port start - owner?.do_remove_antag_datum(src) -//ambition port end + if(owner) + LAZYREMOVE(owner.antag_datums, src) owner = null return ..() @@ -134,9 +133,7 @@ GLOBAL_LIST_EMPTY(antagonists) remove_innate_effects() clear_antag_moodies() if(owner) -//ambition port start - owner.do_remove_antag_datum(src) -//ambition port end + LAZYREMOVE(owner.antag_datums, src) 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 a3c47c10a5..208fefee70 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -65,9 +65,7 @@ user.copy_languages(target, LANGUAGE_ABSORB) if(target.mind && user.mind)//if the victim and user have minds -//ambition port start - to_chat(user, "[target.mind.show_memory()]") //I can read your mind. Output all their notes. -//ambition port end + target.mind.show_memory(user, 0) //I can read your mind, kekeke. Output all their notes. //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 000436ab29..2b1c2de17a 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -2,10 +2,7 @@ ..() //Mind updates sync_mind() -//ambition port start - if(mind.memory || mind.antag_datums) - to_chat(src, "[mind.show_memory()]") -//ambition port end + mind.show_memory(src, 0) //Round specific stuff if(SSticker.mode) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a29cd8c24a..824e262ae1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -441,11 +441,7 @@ set category = "IC" set desc = "View your character's notes memory." if(mind) -//ambition port start - var/datum/browser/popup = new(src, "memory", "Memory and Notes") - popup.set_content(mind.show_memory()) - popup.open() -//ambition port + mind.show_memory(src) 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.") From 8178b7073ad208ca0696ae7278c97ba32769f907 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:50:29 +0100 Subject: [PATCH 07/43] It's done, atleast the code is --- code/__DEFINES/admin.dm | 4 + code/__DEFINES/antagonists.dm | 6 + code/__DEFINES/cooldowns.dm | 6 +- code/__DEFINES/say.dm | 3 + code/__HELPERS/_lists.dm | 3 + code/__HELPERS/roundend.dm | 4 + .../configuration/entries/general.dm | 5 + code/datums/datum.dm | 38 + code/datums/mind.dm | 996 +++++++++++++++++- code/modules/admin/admin.dm | 14 +- code/modules/admin/antag_panel.dm | 32 +- code/modules/admin/topic.dm | 12 + .../antagonists/_common/antag_datum.dm | 43 +- .../antagonists/changeling/powers/absorb.dm | 4 +- code/modules/antagonists/cult/cult.dm | 5 +- code/modules/mob/living/login.dm | 5 +- code/modules/mob/mob.dm | 6 +- 17 files changed, 1128 insertions(+), 58 deletions(-) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index f6293454ee..d7fe3c76a1 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -57,6 +57,10 @@ #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)]" #define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]" +//ambition 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 end #define ADMIN_JMP(src) "(JMP)" #define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]" #define AREACOORD(src) "[src ? "[get_area_name(src, TRUE)] ([src.x], [src.y], [src.z])" : "nonexistent location"]" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index e71243994d..f80652523e 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -110,3 +110,9 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance #define BLOB_SPREAD_COST 4 #define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread #define BLOB_REFLECTOR_COST 15 + +//Objectives-Ambitions Panel +#define REQUEST_NEW_OBJECTIVE "new_objective" +#define REQUEST_DEL_OBJECTIVE "del_objective" +#define REQUEST_WIN_OBJECTIVE "win_objective" +#define REQUEST_LOSE_OBJECTIVE "lose_objective" diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index 29c7a25dad..df644c0fd6 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -27,7 +27,9 @@ //INDEXES #define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet" - +#define COOLDOWN_AMBITION "ambition" +#define COOLDOWN_OBJECTIVES "objectives" +#define COOLDOWN_OBJ_ADMIN_PING "obj_admin_ping" //TIMER COOLDOWN MACROS @@ -63,6 +65,8 @@ #define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time) +#define COOLDOWN_CHECK(cd_source, cd_index) (cd_source.cd_index < world.time) + //Returns true if the cooldown has run its course, false otherwise #define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time) diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 9403eca2da..90307c7f85 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 start +#define MAX_AMBITION_LEN 1024 +//ambition 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..04db6cec78 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 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 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..8e139175dd 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -491,6 +491,10 @@ currrent_category = A.roundend_category previous_category = A result += A.roundend_report() +//ambition start + for(var/count in 1 to LAZYLEN(A.owner.ambitions)) + result += "
    Ambition #[count]: [A.owner.ambitions[count]]" +//ambition end result += "

    " CHECK_TICK diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 63da60d7b5..4353d028f1 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 start +/datum/config_entry/number/max_ambitions // Maximum number of ambitions a mind can store. + config_entry_value = 5 +//ambition end diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 42580425ce..cb87734376 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 start + ///Lazy associative list of currently active cooldowns. + var/list/cooldowns +//ambition end + /* * Lazy associative list of currently active cooldowns. * @@ -231,6 +236,39 @@ else return returned +//ambition start +/** + * Callback called by a timer to end an associative-list-indexed cooldown. + * + * Arguments: + * * source - datum storing the cooldown + * * index - string index storing the cooldown on the cooldowns associative list + * + * This sends a signal reporting the cooldown end. + */ +/proc/end_cooldown(datum/source, index) + if(QDELETED(source)) + return + SEND_SIGNAL(source, COMSIG_CD_STOP(index)) + TIMER_COOLDOWN_END(source, index) + + +/** + * Proc used by stoppable timers to end a cooldown before the time has ran out. + * + * Arguments: + * * source - datum storing the cooldown + * * index - string index storing the cooldown on the cooldowns associative list + * + * This sends a signal reporting the cooldown end, passing the time left as an argument. + */ +/proc/reset_cooldown(datum/source, index) + if(QDELETED(source)) + return + SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index)) + TIMER_COOLDOWN_END(source, index) +//ambition end + /** * Callback called by a timer to end an associative-list-indexed cooldown. * diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 897e2e7d71..eb1c47e0aa 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -29,6 +29,12 @@ */ +//ambition start +#define AMBITION_COOLDOWN_TIME (5 SECONDS) +#define OBJECTIVES_COOLDOWN_TIME (2 SECONDS) +#define ADMIN_PING_COOLDOWN_TIME (10 MINUTES) +//ambition end + /datum/mind var/key var/name //replaces mob/var/original_name @@ -68,6 +74,11 @@ /// Our skill holder. var/datum/skill_holder/skill_holder +//ambition start + /// Lazy list for antagonists to set goals they wish to achieve, to be shown at the round-end report. + var/list/ambitions +//ambition 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 +184,9 @@ qdel(A) return A.owner = src - LAZYADD(antag_datums, A) +//ambition start + do_add_antag_datum(A) +//ambition end A.create_team(team) var/datum/team/antag_team = A.get_team() if(antag_team) @@ -181,6 +194,14 @@ A.on_gain() return A +//ambition start +/datum/mind/proc/do_add_antag_datum(instanced_datum) + . = LAZYLEN(antag_datums) + LAZYADD(antag_datums, instanced_datum) + if(!.) + current.verbs += /mob/proc/edit_objectives_and_ambitions +//ambition end + /datum/mind/proc/remove_antag_datum(datum_type) if(!datum_type) return @@ -189,6 +210,14 @@ A.on_removal() return TRUE +//ambition start +/datum/mind/proc/do_remove_antag_datum(instanced_datum) + . = LAZYLEN(antag_datums) + LAZYREMOVE(antag_datums, instanced_datum) + if(. && !LAZYLEN(antag_datums)) + ambitions = null + current.verbs -= /mob/proc/edit_objectives_and_ambitions +//ambition end /datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us. for(var/a in antag_datums) @@ -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:
    " +//ambition start +/datum/mind/proc/show_memory() + var/list/output = list("[current.real_name]'s Memories:
    ") +//ambition end output += memory @@ -398,16 +427,912 @@ 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 += "
    • NONE
    " + + return output.Join() + + +/datum/mind/proc/show_editable_objectives_and_ambitions() + var/is_admin = check_rights(R_ADMIN, FALSE) + var/self_mind = usr == current + if(!is_admin && !self_mind) + return "" + var/list/output = list() + for(var/a in antag_datums) + var/datum/antagonist/antag_datum = a + output += "Objectives:" + if(is_admin) + output += " Add Objective" + output += "" + if(is_admin) + output += "Announce objectives
    " + output += "
    Requested Objective Changes:" + if(self_mind) + output += " Request objective" + output += "
      " + if(!LAZYLEN(antag_datum.requested_objective_changes)) + output += "
    • NONE

    " + else + for(var/uid in antag_datum.requested_objective_changes) + var/list/objectives_info = antag_datum.requested_objective_changes[uid] + var/obj_request = objectives_info["request"] + switch(obj_request) + if(REQUEST_NEW_OBJECTIVE) + var/datum/objective/type_cast_objective = objectives_info["target"] + var/objective_text = objectives_info["text"] + output += "
  • Request #[uid]: ADD [initial(type_cast_objective.name)] - [objective_text]" + if(self_mind) + output += " Cancel Request" + if(is_admin) + output += " Accept Edit Deny" + if(REQUEST_DEL_OBJECTIVE) + var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives + if(QDELETED(objective_ref)) + stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + antag_datum.remove_objective_change(uid) + continue + output += "
  • Request #[uid]: DEL [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" + if(self_mind) + output += " Cancel Request" + if(is_admin) + output += " Accept Deny" + if(REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + var/datum/objective/objective_ref = locate(objectives_info["target"]) in antag_datum.objectives + if(QDELETED(objective_ref)) + stack_trace("Objective request found with deleted reference. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + antag_datum.remove_objective_change(uid) + continue + output += "
  • Request #[uid]: [obj_request == REQUEST_WIN_OBJECTIVE ? "WIN" : "LOSE"] [objective_ref.name] - [objective_ref.explanation_text] - [objectives_info["text"]]" + if(self_mind) + output += " Cancel Request" + if(is_admin) + output += " Accept Deny" + else + stack_trace("Objective request found with no request index. UID: [uid] | Antag: [antag_datum] | Mind: [src] | User: [usr]") + continue + output += "
    " + if(self_mind) + output += "Ping the admins
    " + if(is_admin) + output += "Clear ping cooldown
    " + output += "
    [current.real_name]'s Ambitions:" + if(LAZYLEN(ambitions) < CONFIG_GET(number/max_ambitions)) + output += " Add Ambition" + output += "
      " + if(!LAZYLEN(ambitions)) + output += "
    • NONE" + else + for(var/count in 1 to LAZYLEN(ambitions)) + output += "
    • Ambition #[count] (Edit) (Remove):
      [ambitions[count]]" + output += "

    (Refresh)" + return output.Join() + + +/mob/proc/edit_objectives_and_ambitions() + set name = "Objectives and Ambitions" + set category = "IC" + set desc = "View and edit your character's objectives and ambitions." + mind.do_edit_objectives_ambitions() + + +/datum/mind/proc/do_edit_objectives_ambitions() + var/datum/browser/popup = new(usr, "objectives and ambitions", "Objectives and Ambitions") + popup.set_content(show_editable_objectives_and_ambitions()) + popup.open() + + +GLOBAL_VAR_INIT(requested_objective_uid, 0) + + +GLOBAL_LIST(objective_player_choices) + +/proc/populate_objective_player_choices() + GLOB.objective_player_choices = list() + var/list/allowed_types = list( + /datum/objective/custom, + /datum/objective/assassinate/once, + /datum/objective/protect, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/blackmail_implant //SKYRAT ADDITION + ) + + for(var/t in allowed_types) + var/datum/objective/type_cast = t + GLOB.objective_player_choices[initial(type_cast.name)] = t + + +GLOBAL_LIST(objective_choices) + +/proc/populate_objective_choices() + GLOB.objective_choices = list() + var/list/allowed_types = list( + /datum/objective/custom, + /datum/objective/assassinate, + /datum/objective/assassinate/once, + /datum/objective/maroon, + /datum/objective/debrain, + /datum/objective/protect, + /datum/objective/destroy, + /datum/objective/hijack, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/nuclear, + /datum/objective/absorb, + /datum/objective/blackmail_implant //SKYRAT ADDITION + ) + + for(var/t in allowed_types) + var/datum/objective/type_cast = t + GLOB.objective_choices[initial(type_cast.name)] = t + + +/datum/mind/proc/on_objectives_request_cd_end(datum/source) + UnregisterSignal(src, list(COMSIG_CD_STOP(COOLDOWN_OBJ_ADMIN_PING), COMSIG_CD_RESET(COOLDOWN_OBJ_ADMIN_PING))) + if(!antag_datums) + return + to_chat(current, "You are now again able to ping the admins objective changes review requests.") + for(var/a in antag_datums) + var/datum/antagonist/antag_datum = a + if(!antag_datum.requested_objective_changes) + continue + to_chat(current, "You seem to have unanswered change requests. If there are online admins another gentle reminder might be in order.") + break +//ambition port end /datum/mind/Topic(href, href_list) +//ambition start + + if (href_list["refresh_obj_amb"]) + do_edit_objectives_ambitions() + return + + else if (href_list["add_ambition"]) + if(!check_rights(R_ADMIN, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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_objectives_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, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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_objectives_ambitions() + return + TIMER_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_objectives_ambitions() + return + + else if (href_list["edit_ambition"]) + if(!check_rights(R_ADMIN, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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_objectives_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_objectives_ambitions() + return + TIMER_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_objectives_ambitions() + return + + else if (href_list["remove_ambition"]) + if(!check_rights(R_ADMIN, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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_objectives_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, FALSE)) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_AMBITION)) + to_chat(usr, "You must wait [AMBITION_COOLDOWN_TIME * 0.1] 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_objectives_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_objectives_ambitions() + return + TIMER_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_objectives_ambitions() + return + + else if (href_list["req_obj_ping"]) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJ_ADMIN_PING)) + to_chat(usr, "You must wait [S_TIMER_COOLDOWN_TIMELEFT(src, COOLDOWN_OBJ_ADMIN_PING) * 0.1] seconds before your next admin ping.") + do_edit_objectives_ambitions() + return + if(!antag_datums) + return + var/pending_request = FALSE + for(var/a in antag_datums) + var/datum/antagonist/antag_datum = a + if(antag_datum.requested_objective_changes) + pending_request = TRUE + break + if(!pending_request) + to_chat(usr, "You have no pending requests to warn the admins about. Request changes for them to review before poking them.") + do_edit_objectives_ambitions() + return + var/justification = stripped_multiline_input(usr, + "Send a message to the admins requesting a review of your objective change requests.\ + There's a [ADMIN_PING_COOLDOWN_TIME * 0.1] seconds cooldown between requests, so try to think it through before sending it. Cancelling this does not trigger the cooldown.", + "Request Admin Review", max_length = MAX_MESSAGE_LEN) + if(isnull(justification)) + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJ_ADMIN_PING)) + to_chat(usr, "You must wait [S_TIMER_COOLDOWN_TIMELEFT(src, COOLDOWN_OBJ_ADMIN_PING) * 0.1] seconds before your next admin ping.") + do_edit_objectives_ambitions() + return + if(!antag_datums) + return + pending_request = FALSE + for(var/a in antag_datums) + var/datum/antagonist/antag_datum = a + if(antag_datum.requested_objective_changes) + pending_request = TRUE + break + if(!pending_request) + return + if(!length(GLOB.admins)) + to_chat(usr, "No admins currently connected, failed to notify them. Wait for one to connect before trying to ping them again.") + do_edit_objectives_ambitions() + return + S_TIMER_COOLDOWN_START(src, COOLDOWN_OBJ_ADMIN_PING, ADMIN_PING_COOLDOWN_TIME) + RegisterSignal(src, list(COMSIG_CD_STOP(COOLDOWN_OBJ_ADMIN_PING), COMSIG_CD_RESET(COOLDOWN_OBJ_ADMIN_PING)), .proc/on_objectives_request_cd_end) + log_admin("Objectives review request - [key_name(usr)] has requested a review of their objective changes, pinging the admins.") + for(var/a in GLOB.admins) + var/client/admin_client = a + if(admin_client.prefs.toggles & SOUND_ADMINHELP) + SEND_SOUND(admin_client, sound('sound/effects/adminhelp.ogg')) + window_flash(admin_client) + message_admins("[ADMIN_TPMONTY(usr)] has requested a review of their objective changes. (RPLY)") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_add"]) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + do_edit_objectives_ambitions() + return + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + if(!GLOB.objective_player_choices) + populate_objective_player_choices() + var/choice = input("Select desired objective type:", "Objective type") as null|anything in GLOB.objective_player_choices + var/selected_type = GLOB.objective_player_choices[choice] + if(!selected_type) + return + var/new_objective = stripped_multiline_input(usr,\ + selected_type == /datum/objective/custom\ + ? "Write the custom objective you'd like to request the admins to grant you. Remember they can edit or deny your request at their own discretion."\ + : "Justify your request for a new objective to the admins. Add the required clarifations, if you have a specific targets in mind and the likes.",\ + "New Objective", max_length = MAX_MESSAGE_LEN) + if(isnull(new_objective)) + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME] minutes between request changes.") + return + if(QDELETED(target_antag)) + return + TIMER_COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + var/uid = "[GLOB.requested_objective_uid++]" + target_antag.add_objective_change(uid, list("request" = REQUEST_NEW_OBJECTIVE, "target" = selected_type, "text" = new_objective)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested a [choice] objective: [new_objective]") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_cancel"]) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + var/uid = href_list["req_obj_cancel"] + if(!LAZYACCESS(target_antag.requested_objective_changes, uid)) + to_chat(usr, "No requested objective change found. Perhaps it was deleted already?") + do_edit_objectives_ambitions() + return + if(alert(usr, "Are you sure you want to delete this change request?", "Delete change request", "Yes", "No") != "Yes") + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + if(QDELETED(target_antag)) + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(target_antag.requested_objective_changes, uid)) + do_edit_objectives_ambitions() + return + TIMER_COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + log_admin("Objectives request deletion - [key_name(usr)] has deleted the objective change request of UID [uid].") + target_antag.remove_objective_change(uid) + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_delete"]) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + var/objective_reference = href_list["req_obj_delete"] + var/datum/objective/objective_to_delete = locate(objective_reference) in target_antag.objectives + if(!istype(objective_to_delete) || QDELETED(objective_to_delete)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + var/justification = stripped_multiline_input(usr, + "Justify your request for a deleting this objective to the admins.", + "Objective Deletion", max_length = MAX_MESSAGE_LEN) + if(isnull(justification)) + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + if(QDELETED(objective_to_delete) || QDELETED(target_antag)) + do_edit_objectives_ambitions() + return + var/matching_request = FALSE + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + matching_request = TRUE + break + if(matching_request) + if(alert(usr, "There is already a change request tied to this objective waiting to be processed. Adding this request will delete the old ones.", "Delete matching objective requests?", "Yes", "No") != "Yes") + do_edit_objectives_ambitions() + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + if(QDELETED(objective_to_delete) || QDELETED(target_antag)) + do_edit_objectives_ambitions() + return + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + target_antag.remove_objective_change(index) + TIMER_COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + var/uid = "[GLOB.requested_objective_uid++]" + target_antag.add_objective_change(uid, list("request" = REQUEST_DEL_OBJECTIVE, "target" = objective_reference, "text" = justification)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested the deletion of the following objective: [objective_to_delete.explanation_text].\nTheir justification is as follows: [justification]") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_completed"]) + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + var/datum/antagonist/target_antag = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(target_antag)) + to_chat(usr, "No antagonist found for this objective.") + do_edit_objectives_ambitions() + return + var/objective_reference = href_list["req_obj_completed"] + var/datum/objective/objective_to_complete = locate(objective_reference) in target_antag.objectives + if(!istype(objective_to_complete) || QDELETED(objective_to_complete)) + to_chat(usr, "No objective found. Perhaps it was deleted?") + do_edit_objectives_ambitions() + return + var/justification = stripped_multiline_input(usr, + "Justify to the admins your request to mark this objective as [objective_to_complete.completed ? "incomplete" : "completed"].", + "Objective [objective_to_complete.completed ? "Incompletion" : "Completion"]", max_length = MAX_MESSAGE_LEN) + if(isnull(justification)) + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + if(QDELETED(objective_to_complete) || QDELETED(target_antag)) + do_edit_objectives_ambitions() + return + var/matching_request = FALSE + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + matching_request = TRUE + break + if(matching_request) + if(alert(usr, "There is already a change request tied to this objective waiting to be processed. Adding this request will delete the old ones.", "Delete matching objective requests?", "Yes", "No") != "Yes") + return + if(usr != current) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJECTIVES)) + to_chat(usr, "You must wait [OBJECTIVES_COOLDOWN_TIME * 0.1] seconds between request changes.") + return + if(QDELETED(objective_to_complete) || QDELETED(target_antag)) + do_edit_objectives_ambitions() + return + for(var/index in target_antag.requested_objective_changes) + var/list/change_request = target_antag.requested_objective_changes[index] + if(change_request["target"] != objective_reference) + continue + target_antag.remove_objective_change(index) + TIMER_COOLDOWN_START(src, COOLDOWN_OBJECTIVES, OBJECTIVES_COOLDOWN_TIME) + var/uid = "[GLOB.requested_objective_uid++]" + target_antag.add_objective_change(uid, list("request" = (objective_to_complete.completed ? REQUEST_LOSE_OBJECTIVE : REQUEST_WIN_OBJECTIVE), "target" = objective_reference, "text" = justification)) + log_admin("Objectives request [uid] - [key_name(usr)] has requested the [objective_to_complete.completed ? "incompletion" : "completion"] of the following objective: [objective_to_complete.explanation_text].\nTheir justification is as follows: [justification]") + do_edit_objectives_ambitions() + return if(!check_rights(R_ADMIN)) return var/self_antagging = usr == current + if(href_list["edit_ambitions_panel"]) + do_edit_objectives_ambitions() + return + + else if(href_list["req_obj_ping_cd_clear"]) + if(!TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJ_ADMIN_PING)) + to_chat(usr, "Mind is not under a cooldown.") + do_edit_objectives_ambitions() + return + if(alert(usr, "Are you sure you want reset this cooldown, letting the user ping the admins again?", "Clear ping cooldown", "Yes", "No") != "Yes") + do_edit_objectives_ambitions() + return + if(!check_rights(R_ADMIN)) + return + if(!TIMER_COOLDOWN_CHECK(src, COOLDOWN_OBJ_ADMIN_PING)) + do_edit_objectives_ambitions() + return + S_TIMER_COOLDOWN_RESET(src, COOLDOWN_OBJ_ADMIN_PING) + do_edit_objectives_ambitions() + return + + else if(href_list["refresh_antag_panel"]) + traitor_panel() + return + + else if (href_list["req_obj_edit"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_edit"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective reference.") + return + if(requested_obj_change["request"] != REQUEST_NEW_OBJECTIVE) + do_edit_objectives_ambitions() + to_chat(usr, "This is not an editable request. How did you even got here?") + return + switch(alert(usr, "Do you want to edit the requested objective type or text?", "Edit requested objective", "Type", "Text", "Cancel")) + if("Type") + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + var/datum/objective/type_cast = requested_obj_change["target"] + var/selected_type = input("Select new requested objective type:", "Requested Objective type", initial(type_cast.name)) as null|anything in GLOB.objective_choices + selected_type = GLOB.objective_choices[selected_type] + if(!selected_type) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + log_admin("[key_name(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") + message_admins("[key_name_admin(usr)] has edited the requested objective type for [current], of UID [uid], from [requested_obj_change["target"]] to [selected_type]") + requested_obj_change["target"] = selected_type + if("Text") + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + var/new_text = stripped_multiline_input(usr, "Input new requested objective text", "Requested Objective Text", requested_obj_change["text"], MAX_MESSAGE_LEN) + if (isnull(new_text)) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + log_admin("[key_name(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") + message_admins("[key_name_admin(usr)] has edited the requested objective text for [current], of UID [uid], from [requested_obj_change["text"]] to [new_text]") + requested_obj_change["text"] = new_text + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_accept"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_accept"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective reference.") + return + + var/datum/objective/request_target + var/request_type = requested_obj_change["request"] + switch(request_type) + if(REQUEST_NEW_OBJECTIVE) + request_target = requested_obj_change["target"] + if(!ispath(request_target, /datum/objective)) + to_chat(usr, "Invalid requested objective target path.") + return + if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + request_target = locate(requested_obj_change["target"]) in antag_datum.objectives + if(QDELETED(request_target)) + to_chat(usr, "Invalid requested objective target reference.") + return + else + to_chat(usr, "Invalid request type.") + return + if(alert(usr, "Are you sure you want to approve this objective change?", "Approve objective change", "Yes", "No") != "Yes") + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + switch(request_type) //Last checks + if(REQUEST_NEW_OBJECTIVE) + if(!ispath(request_target, /datum/objective)) + stack_trace("Invalid target on objective change request: [request_target]") + do_edit_objectives_ambitions() + return + if(REQUEST_DEL_OBJECTIVE, REQUEST_WIN_OBJECTIVE, REQUEST_LOSE_OBJECTIVE) + if(QDELETED(request_target)) + to_chat(usr, "Invalid requested objective target reference.") + return + else + to_chat(usr, "Invalid request type.") + return + antag_datum.remove_objective_change(uid) + switch(request_type) //All is clear, let get things done. + if(REQUEST_NEW_OBJECTIVE) + request_target = new request_target() + request_target.owner = src + if(istype(request_target, /datum/objective/custom)) + request_target.explanation_text = requested_obj_change["text"] + else + request_target.admin_edit(usr) + antag_datum.objectives += request_target + message_admins("[key_name_admin(usr)] approved a requested objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved a requested objective from [current]: [request_target.explanation_text]") + if(REQUEST_DEL_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the request to delete an objective from [current]: [request_target.explanation_text]") + qdel(request_target) + if(REQUEST_WIN_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the victory request for an objective from [current]: [request_target.explanation_text]") + request_target.completed = TRUE + if(REQUEST_LOSE_OBJECTIVE) + message_admins("[key_name_admin(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") + log_admin("[key_name(usr)] approved the defeat request for an objective from [current]: [request_target.explanation_text]") + request_target.completed = FALSE + to_chat(current, "Your objective change request has been approved.") + do_edit_objectives_ambitions() + return + + else if (href_list["req_obj_deny"]) + var/datum/antagonist/antag_datum = locate(href_list["req_obj_deny"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/uid = href_list["req_obj_id"] + var/list/requested_obj_change = LAZYACCESS(antag_datum.requested_objective_changes, uid) + if(!requested_obj_change) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid requested objective change reference.") + return + var/justification = stripped_multiline_input(usr, "Justify why you are denying this objective request change.", "Deny", memory, MAX_MESSAGE_LEN) + if(isnull(justification)) + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(antag_datum)) + to_chat(usr, "No antag found.") + do_edit_objectives_ambitions() + return + if(!LAZYACCESS(antag_datum.requested_objective_changes, uid)) + to_chat(usr, "Invalid requested objective change reference.") + do_edit_objectives_ambitions() + return + var/datum/objective/type_cast = requested_obj_change["target"] + var/objective_name = initial(type_cast.name) + message_admins("[key_name_admin(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") + log_admin("[key_name(usr)] denied a requested [objective_name] objective from [current]: [requested_obj_change["text"]]") + to_chat(current, "Your objective request has been denied for the following reason: [justification]") + antag_datum.remove_objective_change(uid) + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_complete_toggle"]) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_toggle = locate(href_list["obj_panel_complete_toggle"]) in antag_datum.objectives + if(QDELETED(objective_to_toggle)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_toggle.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + objective_to_toggle.completed = !objective_to_toggle.completed + message_admins("[key_name_admin(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") + log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective_to_toggle.explanation_text]") + if(alert(usr, "Would you like to alert the player of the change?", "Deny objective", "Yes", "No") == "Yes") + to_chat(current, "[objective_to_toggle.completed ? "" : ""]Your objective status has changed!") + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_delete"]) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_delete = locate(href_list["obj_panel_delete"]) in antag_datum.objectives + if(QDELETED(objective_to_delete)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_delete.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + if(alert(usr, "Are you sure you want to delete this objective?", "Delete objective", "Yes", "No") != "Yes") + return + if(!check_rights(R_ADMIN)) + return + if(QDELETED(objective_to_delete)) + return + message_admins("[key_name_admin(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") + log_admin("[key_name(usr)] removed an objective from [current]: [objective_to_delete.explanation_text]") + qdel(objective_to_delete) + do_edit_objectives_ambitions() + return + + else if (href_list["obj_panel_edit"]) + var/datum/antagonist/antag_datum = locate(href_list["target_antag"]) in antag_datums + if(QDELETED(antag_datum)) + do_edit_objectives_ambitions() + to_chat(usr, "No antag found.") + return + if(antag_datum.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid antag reference.") + return + var/datum/objective/objective_to_edit = locate(href_list["obj_panel_edit"]) in antag_datum.objectives + if(QDELETED(objective_to_edit)) + to_chat(usr, "No objective found. Perhaps it was already deleted?") + do_edit_objectives_ambitions() + return + if(objective_to_edit.owner != src) + do_edit_objectives_ambitions() + to_chat(usr, "Invalid objective reference.") + return + var/explanation_before = objective_to_edit.explanation_text + objective_to_edit.admin_edit(usr) + if(QDELETED(objective_to_edit)) + return + message_admins("[key_name_admin(usr)] edited an objective from [current]:\ + Before: [explanation_before]\ + After: [objective_to_edit.explanation_text]") + log_admin("[key_name(usr)] edited an objective from [current]:\ + Before: [explanation_before]\ + After: [objective_to_edit.explanation_text]") + do_edit_objectives_ambitions() + return +//ambition end if(href_list["add_antag"]) add_antag_wrapper(text2path(href_list["add_antag"]),usr) @@ -468,38 +1393,16 @@ else target_antag = target - var/static/list/choices - if(!choices) - choices = list() +//ambition start + if(!GLOB.objective_choices) + populate_objective_choices() - var/list/allowed_types = list( - /datum/objective/assassinate, - /datum/objective/assassinate/once, - /datum/objective/maroon, - /datum/objective/debrain, - /datum/objective/protect, - /datum/objective/destroy, - /datum/objective/hijack, - /datum/objective/escape, - /datum/objective/survive, - /datum/objective/martyr, - /datum/objective/steal, - /datum/objective/download, - /datum/objective/nuclear, - /datum/objective/absorb, - /datum/objective/custom - ) + if(old_objective && GLOB.objective_choices[old_objective.name]) + def_value = old_objective.name - for(var/T in allowed_types) - var/datum/objective/X = T - choices[initial(X.name)] = T - - if(old_objective) - if(old_objective.name in choices) - def_value = old_objective.name - - var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices - selected_type = choices[selected_type] + var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in GLOB.objective_choices + selected_type = GLOB.objective_choices[selected_type] +//ambition end if (!selected_type) return @@ -527,6 +1430,12 @@ message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") +//ambition start + if(href_list["ambition_panel"]) + do_edit_objectives_ambitions() + return +//ambition end + else if(href_list["traitor_class"]) var/static/list/choices if(!choices) @@ -611,6 +1520,11 @@ else if (href_list["obj_announce"]) announce_objectives() +//ambition start + if(href_list["ambition_panel"]) + do_edit_objectives_ambitions() + return +//ambition end //Something in here might have changed your mob if(self_antagging && (!usr || !usr.client) && current.client) @@ -814,3 +1728,7 @@ ..() mind.assigned_role = ROLE_PAI mind.special_role = "" + +//ambition start +#undef AMBITION_COOLDOWN_TIME +//ambition end diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index d4afc3dbb4..35a3827766 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -25,7 +25,9 @@ to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.", confidential = TRUE) return - var/body = "Options for [M.key]" +//ambition start + var/list/body = list("Options for [M.key]") +//ambition end body += "Options panel for [M]" if(M.client) body += " played by [M.client] " @@ -125,6 +127,10 @@ body += "Subtle message | " // body += "Play sound to | " body += "Language Menu" +//ambition start + if(M.mind) + body += " | Objective-Ambition Menu" +//ambition end if (M.client) if(!isnewplayer(M)) @@ -206,7 +212,11 @@ body += "
    " body += "" - usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515") +//ambition start + var/datum/browser/popup = new(usr, "adminplayeropts-[REF(M)]", "Player Panel", nwidth = 550, nheight = 515) + popup.set_content(body.Join()) + popup.open() +//ambition end SSblackbox.record_feedback("tally", "admin_verb", 1, "Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index 88aab2c4ce..f5f3f1c9b3 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 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 end var/special_statuses = get_special_statuses() if(length(special_statuses)) @@ -203,15 +207,25 @@ GLOBAL_VAR(antag_prototypes) uplink_info += "." //hiel grammar out += uplink_info + "
    " +//ambition 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 += "
    " //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) + panel.set_content(out.Join()) +//ambition end panel.open() return diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 05e791984a..5021e94bc3 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2251,6 +2251,18 @@ var/mob/M = locate(href_list["HeadsetMessage"]) usr.client.admin_headset_message(M) +//ambition start + else if(href_list["ObjectiveRequest"]) + if(!check_rights(R_ADMIN)) + return + var/datum/mind/requesting_mind = locate(href_list["ObjectiveRequest"]) + if(!istype(requesting_mind) || QDELETED(requesting_mind)) + to_chat(usr, "This mind reference is no longer valid. It has probably since been destroyed.") + return + requesting_mind.do_edit_objectives_ambitions() + return +//ambition end + else if(href_list["reject_custom_name"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 14f7b34309..e16c5a1912 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -25,6 +25,10 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. var/threat = 0 // Amount of threat this antag poses, for dynamic mode +//ambition start + /// Lazy list for antagonists to request the admins objectives. + var/list/requested_objective_changes +//ambition end var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors var/list/skill_modifiers @@ -35,8 +39,9 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/Destroy() GLOB.antagonists -= src - if(owner) - LAZYREMOVE(owner.antag_datums, src) +//ambition start + owner?.do_remove_antag_datum(src) +//ambition end owner = null return ..() @@ -133,7 +138,9 @@ GLOBAL_LIST_EMPTY(antagonists) remove_innate_effects() clear_antag_moodies() if(owner) - LAZYREMOVE(owner.antag_datums, src) +//ambition start + owner.do_remove_antag_datum(src) +//ambition end for(var/A in skill_modifiers) owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type)) if(!silent && owner.current) @@ -294,3 +301,33 @@ GLOBAL_LIST_EMPTY(antagonists) else return ..() + +///Clears change requests from deleted objectives to avoid broken references. +/datum/antagonist/proc/clean_request_from_del_objective(datum/objective/source, force) + var/objective_reference = REF(source) + for(var/uid in requested_objective_changes) + var/list/change_request = requested_objective_changes[uid] + if(change_request["target"] != objective_reference) + continue + LAZYREMOVE(requested_objective_changes, uid) + + +/datum/antagonist/proc/add_objective_change(uid, list/additions) + LAZYADD(requested_objective_changes, uid) + var/datum/objective/request_target = additions["target"] + if(!ispath(request_target)) + request_target = locate(request_target) in objectives + if(istype(request_target)) + RegisterSignal(request_target, COMSIG_PARENT_QDELETING, .proc/clean_request_from_del_objective) + requested_objective_changes[uid] = additions + + +/datum/antagonist/proc/remove_objective_change(uid) + if(!LAZYACCESS(requested_objective_changes, uid)) + return + var/datum/objective/request_target = requested_objective_changes[uid]["target"] + if(!ispath(request_target)) + request_target = locate(request_target) in objectives + if(istype(request_target)) + UnregisterSignal(request_target, COMSIG_PARENT_QDELETING) + LAZYREMOVE(requested_objective_changes, uid) diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 208fefee70..4e68e27583 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 start + to_chat(user, "[target.mind.show_memory()]") //I can read your mind, kekeke. Output all their notes. +//ambition 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/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 09d8771a62..fb5cd7af93 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -49,7 +49,10 @@ cult_team = new_team /datum/antagonist/cult/proc/add_objectives() - objectives |= cult_team?.objectives +//ambition start + if(cult_team) + objectives |= cult_team.objectives +//ambition end /datum/antagonist/cult/Destroy() QDEL_NULL(communion) diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index 2b1c2de17a..e9bf3c5d49 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 start + if(mind.memory || mind.antag_datums) + to_chat(src, "[mind.show_memory()]") +//ambition end //Round specific stuff if(SSticker.mode) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 824e262ae1..b736e8b409 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 start + var/datum/browser/popup = new(src, "memory", "Memory and Notes") + popup.set_content(mind.show_memory()) + popup.open() +//ambition end 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.") From 03bd073cb53887282c3b2580228b096a26fb4a19 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Mar 2021 21:59:00 +0100 Subject: [PATCH 08/43] fixes compile errors --- code/datums/datum.dm | 37 ------------------------------------- code/datums/mind.dm | 2 -- 2 files changed, 39 deletions(-) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index cb87734376..7d054ad64c 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -49,11 +49,6 @@ /// A weak reference to another datum var/datum/weakref/weak_reference -//ambition start - ///Lazy associative list of currently active cooldowns. - var/list/cooldowns -//ambition end - /* * Lazy associative list of currently active cooldowns. * @@ -236,38 +231,6 @@ else return returned -//ambition start -/** - * Callback called by a timer to end an associative-list-indexed cooldown. - * - * Arguments: - * * source - datum storing the cooldown - * * index - string index storing the cooldown on the cooldowns associative list - * - * This sends a signal reporting the cooldown end. - */ -/proc/end_cooldown(datum/source, index) - if(QDELETED(source)) - return - SEND_SIGNAL(source, COMSIG_CD_STOP(index)) - TIMER_COOLDOWN_END(source, index) - - -/** - * Proc used by stoppable timers to end a cooldown before the time has ran out. - * - * Arguments: - * * source - datum storing the cooldown - * * index - string index storing the cooldown on the cooldowns associative list - * - * This sends a signal reporting the cooldown end, passing the time left as an argument. - */ -/proc/reset_cooldown(datum/source, index) - if(QDELETED(source)) - return - SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index)) - TIMER_COOLDOWN_END(source, index) -//ambition end /** * Callback called by a timer to end an associative-list-indexed cooldown. diff --git a/code/datums/mind.dm b/code/datums/mind.dm index eb1c47e0aa..87bd5b4dfd 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -554,7 +554,6 @@ GLOBAL_LIST(objective_player_choices) /datum/objective/martyr, /datum/objective/steal, /datum/objective/download, - /datum/objective/blackmail_implant //SKYRAT ADDITION ) for(var/t in allowed_types) @@ -582,7 +581,6 @@ GLOBAL_LIST(objective_choices) /datum/objective/download, /datum/objective/nuclear, /datum/objective/absorb, - /datum/objective/blackmail_implant //SKYRAT ADDITION ) for(var/t in allowed_types) From 54611bb04a5a62dfed265baa6b311e9cddfa905c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Mar 2021 14:30:10 +0100 Subject: [PATCH 09/43] Update cooldowns.dm --- code/__DEFINES/cooldowns.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index df644c0fd6..bcd91e2e47 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -65,8 +65,6 @@ #define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time) -#define COOLDOWN_CHECK(cd_source, cd_index) (cd_source.cd_index < world.time) - //Returns true if the cooldown has run its course, false otherwise #define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time) From 9750580fb5b71bab6e080dfd3bfc3fbdae463f28 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 24 Mar 2021 00:02:11 +0000 Subject: [PATCH 10/43] Automatic changelog compile [ci skip] --- html/changelog.html | 42 +++++++++++++--------- html/changelogs/.all_changelog.yml | 25 +++++++++++++ html/changelogs/AutoChangeLog-pr-14447.yml | 5 --- html/changelogs/AutoChangeLog-pr-14473.yml | 14 -------- html/changelogs/AutoChangeLog-pr-14475.yml | 6 ---- html/changelogs/AutoChangeLog-pr-14491.yml | 4 --- 6 files changed, 51 insertions(+), 45 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-14447.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-14473.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-14475.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-14491.yml diff --git a/html/changelog.html b/html/changelog.html index b240141879..28d851b295 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,27 +50,37 @@ -->
    -

    11 March 2021

    -

    Putnam3145 updated:

    +

    24 March 2021

    +

    Hatterhat updated:

      -
    • Supernova event
    • -
    • Bloodsucker day/night cycle now processes on a subsystem instead of using while and sleep (!!)
    • +
    • The NOGUNS trait now takes precedence over the triggerguard checks.
    -

    Sneakyrat updated:

    +

    ItzGabby updated:

      -
    • Fixes precise insertion ui(when it asks you how many sheets you want to put in the mat container) so you can actually choose how much to put in and it will still work if your stack is bigger than the remaining space
    • -
    • Fixes precise insertion not working for remote mat containers
    • -
    • Fixes Protolathe/mechfab insert material animations not working
    • -
    • Fixes the material insertion animation for protolathes occurring on the circuit printer
    • -
    • Fixes the material insertion animation not actually playing when it was started
    • -
    • Fixes the material insertion animation for iron not being made
    • -
    • Fixes the material insertion animation sometimes not picking the right material for sheets that have multiple different materials in them
    • +
    • Fluff Items with polychromic support
    • +
    • A new vendor called Bark box
    • +
    • A new form of snack with it's own box
    • +
    • Two harness, one of them being lewd
    • +
    • One new collar, with a ribbon. Classy.
    • +
    • More locked forms of collars
    • +
    • Purged old balls
    • +
    • Removed the funny buffs each colored tennis ball had, down with the powergame!
    • +
    • Added polychromic fluff icons, vendor icons, suit icons, snack icons, fancy box icons, and a polychromic version of Izzy's ball.
    • +
    • Deleted old balls, Izzy's Ball, except the rainbow one since it's special and as I did not go out of my way to get permission to touch.
    • +
    • Walked into vending.dm and glared for a moment at hydroponics' grammar.
    -

    necromanceranne updated:

    +

    LetterN updated:

      -
    • Properly segments all the augment sprites so that they correctly display.
    • -
    • Properly labels the augment limb icon sprites.
    • -
    • Fixes going over the defined limit of roundstart prosthetics
    • +
    • fixed laptops pickability
    • +
    • fixed closets being unweldable
    • +
    +

    qweq12yt updated:

    +
      +
    • added the black market uplink
    • +
    • added blackmarket.dmi
    • +
    • increased the black market interface's width, now the delivery options will show properly when the LTSRBT is built
    • +
    +

    23 March 2021

    LetterN updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index ae22fdc466..e114e7c3fa 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -28815,3 +28815,28 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. LetterN: - bugfix: NIRM departamental purchases now work. Have fun spending the entire R&D Budget! +2021-03-24: + Hatterhat: + - bugfix: The NOGUNS trait now takes precedence over the triggerguard checks. + ItzGabby: + - rscadd: Fluff Items with polychromic support + - rscadd: A new vendor called Bark box + - rscadd: A new form of snack with it's own box + - rscadd: Two harness, one of them being lewd + - rscadd: One new collar, with a ribbon. Classy. + - rscadd: More locked forms of collars + - rscdel: Purged old balls + - balance: Removed the funny buffs each colored tennis ball had, down with the powergame! + - imageadd: Added polychromic fluff icons, vendor icons, suit icons, snack icons, + fancy box icons, and a polychromic version of Izzy's ball. + - imagedel: Deleted old balls, Izzy's Ball, except the rainbow one since it's special + and as I did not go out of my way to get permission to touch. + - spellcheck: Walked into vending.dm and glared for a moment at hydroponics' grammar. + LetterN: + - bugfix: fixed laptops pickability + - bugfix: fixed closets being unweldable + qweq12yt: + - rscadd: added the black market uplink + - imageadd: added blackmarket.dmi + - bugfix: increased the black market interface's width, now the delivery options + will show properly when the LTSRBT is built diff --git a/html/changelogs/AutoChangeLog-pr-14447.yml b/html/changelogs/AutoChangeLog-pr-14447.yml deleted file mode 100644 index 1ed321f6b9..0000000000 --- a/html/changelogs/AutoChangeLog-pr-14447.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "LetterN" -delete-after: True -changes: - - bugfix: "fixed laptops pickability" - - bugfix: "fixed closets being unweldable" diff --git a/html/changelogs/AutoChangeLog-pr-14473.yml b/html/changelogs/AutoChangeLog-pr-14473.yml deleted file mode 100644 index 1d7db07abe..0000000000 --- a/html/changelogs/AutoChangeLog-pr-14473.yml +++ /dev/null @@ -1,14 +0,0 @@ -author: "ItzGabby" -delete-after: True -changes: - - rscadd: "Fluff Items with polychromic support" - - rscadd: "A new vendor called Bark box" - - rscadd: "A new form of snack with it's own box" - - rscadd: "Two harness, one of them being lewd" - - rscadd: "One new collar, with a ribbon. Classy." - - rscadd: "More locked forms of collars" - - rscdel: "Purged old balls" - - balance: "Removed the funny buffs each colored tennis ball had, down with the powergame!" - - imageadd: "Added polychromic fluff icons, vendor icons, suit icons, snack icons, fancy box icons, and a polychromic version of Izzy's ball." - - imagedel: "Deleted old balls, Izzy's Ball, except the rainbow one since it's special and as I did not go out of my way to get permission to touch." - - spellcheck: "Walked into vending.dm and glared for a moment at hydroponics' grammar." diff --git a/html/changelogs/AutoChangeLog-pr-14475.yml b/html/changelogs/AutoChangeLog-pr-14475.yml deleted file mode 100644 index 5c26ac3970..0000000000 --- a/html/changelogs/AutoChangeLog-pr-14475.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "qweq12yt" -delete-after: True -changes: - - rscadd: "added the black market uplink" - - imageadd: "added blackmarket.dmi" - - bugfix: "increased the black market interface's width, now the delivery options will show properly when the LTSRBT is built" diff --git a/html/changelogs/AutoChangeLog-pr-14491.yml b/html/changelogs/AutoChangeLog-pr-14491.yml deleted file mode 100644 index a40970617c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-14491.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Hatterhat" -delete-after: True -changes: - - bugfix: "The NOGUNS trait now takes precedence over the triggerguard checks." From aafd1ca6bcb044e5bc8a9afaa0e21bbc698e1bdb Mon Sep 17 00:00:00 2001 From: Changelogs Date: Thu, 25 Mar 2021 00:36:12 +0000 Subject: [PATCH 11/43] Automatic changelog compile [ci skip] --- html/changelog.html | 663 -------------------------------------------- 1 file changed, 663 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 28d851b295..bbf1a17862 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -889,669 +889,6 @@
      • Adds a way to give items to people, you can combat mode rightclick to offer it to one person, right click on people without mode and click the give verb, or use the hotkey CTRL G to offer it to everyone around you
      - -

      21 January 2021

      -

      Acer202 updated:

      -
        -
      • Main mining shuttle should no longer look at the public mining shuttle and attempt to dock ontop of it. Monastery shuttle should now function again.
      • -
      -

      Acer202, with minor help from The0bserver updated:

      -
        -
      • After internal deliberation, CentCom has decided to run a limited reinstatement of public mining shuttles for use in more tried and true station classes. CentCom would like to remind you that this privilege is easily revoked, and that abuse may result in immediate detonation.
      • -
      • Restores the mining shuttle on Pubby, Box, Delta, Meta, and Lambda Station.
      • -
      -

      ArcaneMusic, The0bserver-sys updated:

      -
        -
      • New from Hydrowear LLC: The Botanical Belt! This handy yellow belt lets you hold most of your botany gear, and a few beakers for reduced bag and floor clutter!
      • -
      • Gives Hydrotrays plumbing pipes automatically, allowing you to make a self sustaining tray via plumbing.
      • -
      • Gives Service access to Bluespace Beakers, at last, gives Cargo, Science, and Medical the ability to construct reinforced plungers for use on lavaland.
      • -
      -

      ArchieBeepBoop updated:

      -
        -
      • Upgraded Advanced RTG Machine Preset
      • -
      • Outlet Injector Mapping Asset Layer Fix
      • -
      • Jacqueen and the Christmas tree should no longer spawn abstract things that can cause shittons of runtimes.
      • -
      -

      Arturlang updated:

      -
        -
      • You can't tackle in nograv anymore
      • -
      • You cannot spam drink from blood bags anymore
      • -
      • Blood bag drinking inefficiency is now the right way, so you loose some of the blood drinking it straight
      • -
      • Handles more edge cases with construct soul returning
      • -
      • Being sacrificed by the cult no longer removes all hope of rescue.
      • -
      • Makes construct mind returning more robust
      • -
      • Prayers to admins now do a wee ding sound for all prayers, instead of just chaplains
      • -
      • Fixes the mint machine's UI
      • -
      • Hopefully fixes whitescreen issues for TGUI UI's by giving assets more time to get to the client
      • -
      • Fixes hijack implant APC UI, again
      • -
      • Comments out spaceman dmm do not sleeps for mob/proc/CommonClickOn, atom/proc/attack_hand, datum/proc/keyLoop and mob/living/proc/Life
      • -
      • Bloodsuckers tresspass ability can no longer work while they are not awake.
      • -
      • The cursed heart now only takes away half as much blood every loop, and can be used as long as you are alive, instead if only you are awake/able to use your hands
      • -
      -

      Bhijn updated:

      -
        -
      • Changeling loudness is now determined as an average of all their abilities, rather than the sum
      • -
      • To compensate for this, blood tests now require a loudness value of 1 or higher to detect ling blood. Additionally, blood test explosions are now triggered only when the loudness value is higher than 2.
      • -
      -

      BlackMajor updated:

      -
        -
      • Cyborg hypospray no longer injects if it means OD'ing while on help intent.
      • -
      -

      BlueWildrose updated:

      -
        -
      • Nyctophobia quirk now has some light lag compensation.
      • -
      • Fixes cloning computer UI not updating when pressing certain buttons - also adds extra check for names to update a message
      • -
      • Removes oversized genitalia analysis from medical scanners, since huge dick and titty are no longer a problem anymore thanks to advancements in that kind of technology when it comes to chemical fun times growth.
      • -
      • Fixed species-specific drinks not giving a mood boost if you are that species.
      • -
      • You will now only unbuckle fireman-carried/piggybacked people on disarm or harm intent.
      • -
      • The traitor AI can no longer activate the doomsday device while carded.
      • -
      • Fixes noodle size appearance for 12+ inch members.
      • -
      • Fixed the subtle hotkey being weird with its input prompts.
      • -
      • Adds a subtler anti-ghost hotkey. Default key is 6.
      • -
      • No more straining when your cock or breasts are growing via incubus draft or succubus milk.
      • -
      • PubbyStation now has two Christmas Tree spawners.
      • -
      • You can now have a max-roundstart-dicksize-config inch long johnson before you start suffering blood loss and slowdowns instead of a 20 inch one.
      • -
      • Color Mates have been added to all stations (except Snaxi). Enjoy coloring your attire without having to bug science!
      • -
      • Polychromic hoodies that were obtained from the loadout have functional colorable hoods now.
      • -
      • Adds in timid woman/man costumes. Available at your autodrobe! Also adds in garters as some new socks.
      • -
      • Corrected the capitalization in gasmask concealment examine text
      • -
      -

      Chiirno updated:

      -
        -
      • Added the paramedics EVA suit as a purchase from the cargo console.
      • -
      • Paramedics office and Surgery Storage Room
      • -
      • Remodeled the surgery room, as well as shrunk Morgue and Starboard Emergency Storage. Fiddled with some areas for better map edit clarity and fixed one runtime in Vacant Office A.
      • -
      • Added the paramedic closet sprite, a paramedic colored medical3 closet.
      • -
      • Added a paramedic closet, which is the standard medical3 closet with their suit, a pinpointer, and a crew monitor added.
      • -
      • Nightmare now deals additional damage to most light sources.
      • -
      • Nightmare now one-shots miners beacons and glowshrooms
      • -
      • Portable Chem Mixer now researchable from biotech node.
      • -
      • Chem masters can now dispense 20 instances of its outputs instead of 10.
      • -
      -

      Delams-The-SM updated:

      -
        -
      • Added 3 new emotes *hiss *purr *meow
      • -
      • ported sounds from Citadel RP for *purr and *meow
      • -
      • fixed randomization of colors for things like mulligan and Stabilized green slime extract for matrixed body parts
      • -
      -

      DeltaFire15 updated:

      -
        -
      • Biomechanical (hybrid) bodyparts now have access to wound-fixing surgeries.
      • -
      • A wound being fixed no longer just qdel()s surgeries connected to it.
      • -
      • Some robotic surgery steps are now a bit more clear.
      • -
      • Organs no longer get fed to people after successfully being inserted into them.
      • -
      • Not completing the do_after of a surgery no longer causes you to attack the target with whatever you were holding.
      • -
      • IPC cells & power cords are now printable after they are researched.
      • -
      • A new surgery, allowing revival of synths without a defib at hand.
      • -
      • Semi-permanent damage of Synth limbs caused by passing the damage threshold: 10 <- 15.
      • -
      • The embed removal surgery now has a version for Synths.
      • -
      • EMPs no longer hardstun Synths.
      • -
      • Portals no longer runtime because of incorrect args.
      • -
      • Abductors now can use experimental organ replacement surgery on robots / synthetics.
      • -
      • Fixes a minor incorrectness in ratvarian borg slabs (ratvar_act -> ui_act)
      • -
      • Changelings no longer double-deathgasp when activating the regen stasis ability while not dead.
      • -
      • People installing KA modkits in miner borgs is no longer broken.
      • -
      • Fixes the tail entwine messages displaying incorrectly.
      • -
      • Antagging / Deantagging Heretics now properly sets their special role.
      • -
      • The borg VTEC ability now actually gets removed when the upgrade is removed.
      • -
      • Supplypods shouldn't cause runtimes anymore, and shrapnel (pelletclouds) should work for them.
      • -
      • Robots (anyone with the robotic_organism trait) have toxins damage replaced with system corruption. See the PR for details.
      • -
      • Clockwork rites now support hiding specific rites from neutered servants.
      • -
      • AIs now only have to kill people once instead of permanently.
      • -
      • Scripture no longer sometimes eats part of its invocation.
      • -
      • APCs and silicons are now more susceptible to powerdrains (by the power_drain() proc, which is rare)
      • -
      • Void Volt has been modified from a chant to a singular pulse.
      • -
      • Robotpeople are now fully immune to the effects of alcohol (drunkness etc.)
      • -
      • Renames the alcohol intolerance trait in the code to make what it does more clear.
      • -
      • Self-fueling weldingtools recharge fuel properly again.
      • -
      • Brass welders now actually recharge faster than experimental ones.
      • -
      • Repeatable surgery steps can no longer cause an infinite loop if not completing the do_after
      • -
      • The Revenant self-revive ability is no longer broken.
      • -
      • Loot items mobs drop are no longer always failing to initialize.
      • -
      • Instant summons can no longer do wacky stuff with disposals (and nukes).
      • -
      • Objectives are no longer very broken.
      • -
      • Bloodcult stunhands now work against clockies like they were supposed to instead of hardstunning.
      • -
      • zeolites are now actual fermichems instead of being incredibly easy to make.
      • -
      • Using syringes / droppers on chem heaters with beakers in them works again.
      • -
      • Some edge cases causing issues with system corruption shouldn't be able to occur anymore.
      • -
      • Cyborg B.o.r.i.s. installation now checks for if the chest has a cell, just like how it does with MMIs.
      • -
      • The 'Your body is in a cloner' notification works again
      • -
      • Hijack implants should work properly again (or, at least better)
      • -
      • Liches are now good skeletons again instead of weak ones
      • -
      • The piratepad control cannot be destroyed again.
      • -
      • Pirates have received new supplies of jetpacks instead of useless oxygen tanks
      • -
      • Ratvarian AIs are once again able to show their linked borgs Ratvar's light
      • -
      • Hijackers are once again unable to detonate borgs without being adjacent to the console
      • -
      • Automated annoucement systems and gulag ore consoles no longer waste emag charges
      • -
      • Automated announcement systems once again can be remote controlled by non-AIs with silicon access
      • -
      • APCs being hijacked multiple times at once is no longer possible, preventing some issues
      • -
      • Recharging APCs no longer use 0.2% of the power they should be using.
      • -
      • APCs no longer always use as much power as they can for their cell, even if it is full.
      • -
      • Vampire shapeshifting should now behave as intended
      • -
      • Some synth damage stuff has been a bit rebalanced, see the PR for details.
      • -
      • Nanogel, available at medical and robotics, which fixes internal damage in sufficiently repaired robotic limbs.
      • -
      • Robotic Limbs now each have their own damage threshhold values
      • -
      • Robotic Limb damage threshholds are now seperated into threshhold itself and mindamage when passed balance; Hybrid limbs can now be injected with hypos, but not sprayed (Still not healed by chems)
      • -
      • Brain surgery has been tweaked back to allowing robotic limbs, blacklisting IPC brains instead.
      • -
      • Robot brain surgery can now be used on organic heads, if there is a IPC brain in them somehow.
      • -
      • The robot limb heal surgery can now be used even if the target's torso is not robotic, as long as they have robotic limbs
      • -
      • BODYPART_ROBOTIC / BODYPART_ORGANIC checks replaced with helper-procs whereever possible.
      • -
      • Added a BODYPART_HYBRID define for robotic bodyparts that behave organic in some regards.
      • -
      • The transmission sigil power drain works now
      • -
      • A certain lizard (totally not me) being stupid is no longer going to break regenerate_bodyparts
      • -
      • Combat mode now will not stay permanently disabled due to status effects not working as intended.
      • -
      • Attacking some certain objects no longer has no clickdelay.
      • -
      • the blacksmithing skill now works properly
      • -
      • Anvils cannot be interacted with with hammers whilst they are already being used
      • -
      • If someone has no gloves when interacting with heated ingots, they no longer ignore their effects.
      • -
      • A runtime caused by hallucinations is gone.
      • -
      • Cargo packs marked as 'no private buying' now actually register as such.
      • -
      • Fleshmend, Anatomic Panacea and bloodsucker healing now work for Synths / IPCs.
      • -
      • Medibots now ignore people they cannot help due to their biology.
      • -
      • get_damaged_bodyparts() is no longer broken.
      • -
      • Your target cryoing will no longer give you a free greentext.
      • -
      • Sleeper UI interactiveness now behaves correctly.
      • -
      -

      Detective-Google updated:

      -
        -
      • arcade carpet
      • -
      • explosions now get broadcasted to deadchat.
      • -
      • Lick radial
      • -
      • Hilbert's jukebox works
      • -
      • arcade carpets now actually work
      • -
      • the snow taxi is no longer the slow taxi
      • -
      -

      ERP mains updated:

      -
        -
      • Subtler Around Table is now a verb
      • -
      -

      EdgeLordExe, MoonFalcon updated:

      -
        -
      • Ported a bunch of heretic-related tweaks and changes from tg
      • -
      -

      EmeraldSundisk updated:

      -
        -
      • Adds a few new area designations primarily for CogStation, incorporates them into said map
      • -
      • Reorganizes some area designations for ease of use, along with renaming the central "Router" to "Routing Depot"
      • -
      • Fixes an incorrectly designated area in CogStation
      • -
      • Changes the area designations to be not varedited since the code didn't like that anymore
      • -
      • The cargo bay conveyor belts not only work with the shuttle now but go in the right direction to boot
      • -
      • Slight visual adjustments to cargo in light of this
      • -
      • The arcade's got RAD carpet now
      • -
      • Fixes the conveyor belt issues in Delta Station's cargo wing
      • -
      • Removes some of the dirt around the affected area (presumably they would have cleaned it up while working on it)
      • -
      • Adds a floor light to fix the "dark spot" cargo had
      • -
      • Adds a new "Computer Core" area designation for CogStation
      • -
      • Fixes some missing area strings
      • -
      • Replaces some firelocks with directional ones as to ensure desks/counters can still be accessed
      • -
      • The "Skelter ruin" now has stechkins as opposed to M1911s
      • -
      • Skelter's decorative bullet casings replaced to factor in the change in caliber
      • -
      • Skelter now has a combat knife and fluff note
      • -
      -

      Ghommie updated:

      -
        -
      • You can access the mime / clown mask skins radial menu once again.
      • -
      • Dice bags no longer act like cardboard boxes.
      • -
      • Abductors should be no longer mute.
      • -
      • Item action buttons should now properly show the item current overlays, most times.
      • -
      • The blackbox should now go into your hand slot when pried out, rather than tumbling on the ground everytime.
      • -
      • The Quick Equip hotkey is now usable by all living mobs (so long they have hands and equipment slots)
      • -
      -

      Ghommie, porting PRs by MMMiracles and pireamaineach, credits to BlueWildrose too. updated:

      -
        -
      • You can now draw on plasmaman helmets with a crayon to turn their frown upside-down.
      • -
      • Plasmaman helmets no longer hide your identity when worn by themselves.
      • -
      • Plasmaman helmets now have welding visors, which can't stack with their torches in the helmet and are visible.
      • -
      -

      Hatterhat updated:

      -
        -
      • Energy sabre reskin for the energy sword - access via alt-click.
      • -
      • Alt-click reskins are fixed.
      • -
      • Defibrillators and their many, many overlays were moved to another .dmi.
      • -
      • You can now change the color of an energy sword via multitool. Not deswords. Yet.
      • -
      • The Syndicate appear to be issuing new revolver variants.
      • -
      • Basic sticky technology is now a roundstart tech. Advanced sticky technology is BEPIS-locked, though. Theoretically.
      • -
      • Non-smithed katanas (including the temporal katana) can now fit in the twin sheath.
      • -
      • Cotton and durathread processing by hand now acts like grass. Stand on a pile of cotton (or durathread) and use a single bundle from it.
      • -
      • Utility uniforms now comply with the "nonproper equipment names" thing.
      • -
      • The CapDrobe now allows the captain to get his own clothes for free. Probably.
      • -
      • All captains' clothes now offer 15 woundarmor, up from the 5. Because apparently only the suit and tie and its suitskirt subtype have this wound armor, which is dumb.
      • -
      • The nature interaction shuttle with the monkeys now has tiny fans on the airlocks in, because that's apparently a feature that was missing.
      • -
      • More bags have been added to department vendors.
      • -
      • Every roundstart species (and also ash walkers) now has flesh and bone that can be wounded.
      • -
      • Recipes for sutures, regen mesh, and sterilized gauze have been adjusted to be easier, mostly.
      • -
      • Sterilized gauze is better at absorbing blood and being a splint.
      • -
      • Energy sabres now have an off inhand.
      • -
      • The bone gauntlets should be slightly less murderously punchy on the fast punches mode.
      • -
      • RPEDs now drop their lowest part tier first when quick-emptied (used inhand).
      • -
      • Improvised gauzes can now be crafted in stacks up to 10, like their maximum stacksize implies they should be capable of doing.
      • -
      • Pouring sterilizine on gauze now takes the proper 5u per sterilized gauze instead of 10u.
      • -
      • Cryogenics now screams on common again when your fuckbuddy heads out.
      • -
      • Survival daggers! A slightly more expensive survival knife that comes with a brighter flashlight. On the blade.
      • -
      • Luxury pod capsules look different from normal capsules.
      • -
      • The wastes of Lavaland and the icy caverns of Snow Taxi rumble in unison.
      • -
      • Exosuits sold on the Supply shuttle no longer leave wreckages.
      • -
      • Apparently, shrink rays were buyable again, despite a PR having been made a while ago specifically for removing shrink rays. They're gone again.
      • -
      • Changeling bone gauntlets! They punch the shit out of people really good.
      • -
      • Guerilla gloves and gorilla gloves inherit the strip modifiers of their predecessors, because apparently they had those.
      • -
      • Pugilists now always hit the targeted limb and never miss.
      • -
      • The dock-silver standard set by Box and Meta has been enforced across maps in rotation (Delta, Pubby, Lambda).
      • -
      • The Box whiteship now has its missing tiny fan back.
      • -
      • The survival dagger light on the sprite now actually turns on and off.
      • -
      • The survival dagger in the glaive kit that can also be bought by itself is now better at butchering things.
      • -
      -

      HeroWithYay updated:

      -
        -
      • Changed description of Necrotizing Fasciitis symptom.
      • -
      • Wormhole Projector and Gravity Gun now require anomaly cores to function instead of firing pins.
      • -
      -

      KeRSedChaplain updated:

      -
        -
      • Resprited the brass claw
      • -
      -

      LetterN updated:

      -
        -
      • 2 more ways to get up from z1
      • -
      • tweaked the z2 garden to be less blank
      • -
      • fixed telecomms pda log
      • -
      • Coin & Holochip support for slot machine
      • -
      • Stickybans are now saved in the DB too
      • -
      • Immersive ™ audio reverbs. (also adds multiz audio)
      • -
      • Semi-hardsync from TG
      • -
      • Updates rust-g
      • -
      • Uses git CI instead of travis/appveyor now
      • -
      • Updates git and build tests.
      • -
      • minimap text
      • -
      • ports cinematic upgrades
      • -
      -

      Linzolle updated:

      -
        -
      • entertainment monitors no longer invisible
      • -
      • entertainment monitors now light up and display text when motion is detected in thunderdome
      • -
      • lizard snouts are no longer *slightly* lighter than they are supposed to be.
      • -
      -

      MrJWhit updated:

      -
        -
      • Expanded space hermit base
      • -
      • Replaced engineering fuel tank with a large fuel tank
      • -
      • Changed access to sec suit storage from armory access in every map to other security access
      • -
      • Adds a space loop to every map in toxins
      • -
      • -
      • Added the ability for cargo to buy a large welding tank
      • -
      • Tweaked large tank reagent sprites to /tg/'s
      • -
      • Gives metastation toxins storage a scrubber and a vent
      • -
      • Updates suit storage info on Tip Of the Round.
      • -
      • Increased christmas event from 22th to 27th to 10th to 27th
      • -
      • Removes an opposum from the wall
      • -
      • Donut boxes show what's inside of them now
      • -
      • Updated meat icons
      • -
      • Canceling events gives more time to stop from 10 to 30
      • -
      • Fixes two chairs on one table
      • -
      • Removed the wires connecting the AI from the rest of the station on cogstation.
      • -
      • Fixes experimenter on cogstation.
      • -
      • Less pipes in the overall area in toxins on cogstation
      • -
      • Small fixes on security on boxstation
      • -
      • Updated jukebox sprite.
      • -
      • Fixes maint area in boxstation
      • -
      • Christmas starts on the 18th now
      • -
      • Adds a goose bar sign
      • -
      • Effects can no longer trigger landmines
      • -
      • Removes the screen flashing on climax.
      • -
      • Makes gas sensors fireproof.
      • -
      • A small bucket of random fixes,
      • -
      • Minor fixes to kilo
      • -
      • Porting garbage collection tweak from /tg/
      • -
      • Updates our dark gygax sprites to /tg/'s
      • -
      • Bugfix of a morph becoming an AI eye
      • -
      • Mining station oxygen locker on the cycling airlock starts out wrenched.
      • -
      • Nerf combat knife damage
      • -
      • Code improvement on ventcrawling
      • -
      -

      NT Cleaning Crews On Break updated:

      -
        -
      • Most kinds of dirt, grime, and debris are now persistent. Get to work, jannies.
      • -
      • Dirt can now be removed by tile replacements. Other cleanable decals can't, though.
      • -
      -

      Putnam3145 updated:

      -
        -
      • Replaces majority judgement with usual judgement.
      • -
      • Toilet loot spawners don't lag the server on server start with forced hard dels.
      • -
      • vore prefs save now
      • -
      • gear harness no longer magically covers up the body mechanically despite covering up nothing visually
      • -
      • Regen coma now puts into a coma even from crit or while unconscious.
      • -
      • Regen coma now properly weakens while asleep.
      • -
      • Multi-surgery unit test no longer fails at random.
      • -
      • Dwarf speech is no longer absolutely paranoid about word replacement.
      • -
      • Spontaneous brain trauma now requires minimum 5 players
      • -
      • Grab bag works as advertised.
      • -
      • Xeno threat in dynamic tripled.
      • -
      • Vote system #defines are now strings
      • -
      • Stat panel UI for ranked choice votes
      • -
      • A fallback for dynamic antag rolling that allows for it to just try between traitor, blood brothers, heretics, changeling, bloodsucker and devil until there are enough roundstart antags. This can also happen randomly anyway. Blood brothers and devil are disabled for now, but the code is there to enable them.
      • -
      • A new storyteller, "Grab Bag", that forces the above round type.
      • -
      • atmos subsystem no longer dies if there's too many gases
      • -
      • Emotes can properly be filtered for in TGUI.
      • -
      • Holofirelocks work now.
      • -
      • adminhelping no longer removes entire admin tab
      • -
      • end of round no longer removes entire admin tab
      • -
      • Fixed a runtime in every healing nanite program.
      • -
      • removed a unit test causing master to fail
      • -
      • Planetary atmos no longer does superconduction.
      • -
      • Dynamic vote no longer shows the none-storyteller.
      • -
      • You can now exit polycircuit input
      • -
      • Polycircuits now check for range
      • -
      • gear harness alt-click is now sane
      • -
      • rolldown() and toggle_jumpsuit_adjust() now no longer mix behavior-that-should-be-overridden and behavior-that-shouldn't-be-overridden in ways that make no sense.
      • -
      • Gear harness now covers nothing.
      • -
      • Chemical stuff now displays fermichem stuff properly
      • -
      • Rad collectors now get 1.25x as much energy from radiation
      • -
      • Rad collectors now put out 1.25x as much stored energy per tick
      • -
      • Above two rad collector changes give a total 56.25% power output increase
      • -
      • Zeolites now only generate 1/5 the heat when reacting and don't require a catalyst.
      • -
      -

      Ryll/Shaps updated:

      -
        -
      • Fixed an issue with player logs becoming confused when someone triggers multiple events within one second (like being attacked by two people at the same time) that would cause holes in the logs
      • -
      -

      SandPoot updated:

      -
        -
      • You can attack a pile of money on the floor with your id to put it all in quickly.
      • -
      • Changes the limb grower a lot.
      • -
      • "Limb" costs on limbgrower are actually displayed like it was meant to all along.
      • -
      • Swaps the gift static blacklist with a global list one.
      • -
      -

      SiliconMain updated:

      -
        -
      • Engi department has gas masks in loadout
      • -
      • hololocks (which haven't worked for god knows how long) commented out until auxmos is merged
      • -
      -

      Sonic121x updated:

      -
        -
      • alarm ert hardsuit sprite for naga and canine
      • -
      • adjust the naga ert hardsuit to cover the hand
      • -
      • cydonia hardsuit helmet
      • -
      • digi sprite uniform
      • -
      • digi leg suit
      • -
      -

      SpaceManiac updated:

      -
        -
      • Fixed the maphook
      • -
      -

      Thalpy updated:

      -
        -
      • fixes some bugs in jacqs code from edits to the codebase
      • -
      -

      The Grinch updated:

      -
        -
      • infinite presents from hilbert hotel
      • -
      -

      TheObserver updated:

      -
        -
      • Re-adds the rifle stock, and sets the improv shotgun to be as it was.
      • -
      • The maintenance rifle has been shelved - for now. Watch this space.
      • -
      -

      TheObserver-sys updated:

      -
        -
      • Drake? Where's the dead fairygrass sprite?
      • -
      -

      TheSpaghetti updated:

      -
        -
      • no more tumor bread double punctuation
      • -
      -

      Trilbyspaceclone updated:

      -
        -
      • Zeolites now use gold rather then uranium for catalyst
      • -
      • Zeolites are not as hard to make ph wise
      • -
      • Making Zeolites heats up the beaker less allowing for better control
      • -
      • ASP 9mm and M1911 can now have suppressers added
      • -
      • Brass welders are 50% faster at refueling
      • -
      • redoes self fueling welders in the code to be less speggie
      • -
      • the corporate unifoms can now be gotton in the clothing mate vender
      • -
      -

      TripleShades updated:

      -
        -
      • Firelock to Surgery Bay drapes change: Swapped Nanomed and Fire Alarm button locations in both Surgery Bays change: Removes the double mirror in both Surgery Bays to be a singular mirror change: Moved an intercom to not be doorstuck below Paramedical Office remove: One Surgery Observation Fire Alarm button
      • -
      • New Paramedic Office next to Genetics where the old Genetics Reception used to be change: Surgery, Surgery Observation, and Recovery Hall layout revamped drastically change: Maints below Surgery lowered by one tile to recover lost tile space from Surgery expansion
      • -
      -

      Tupinambis updated:

      -
        -
      • Arachnids (spider people) with limited night vision, flash vulnerability, and webbing.
      • -
      -

      Vynzill updated:

      -
        -
      • new gateway mission mapadd: jungleresort map
      • -
      • fixes high luminosity eyes
      • -
      -

      Xantholne updated:

      -
        -
      • Fixed new birds changing back to basic parrot when sitting
      • -
      • New parrots from the RP server, can be found in Bird Crate in Cargo
      • -
      • You can now tuck disky into bed
      • -
      • You can now make beds by applying a bed sheet to them
      • -
      • You can now tuck in pai cards into bed
      • -
      • Added bed tucking element, can be added to any held object to allow tucking into beds
      • -
      • Twin Sword Sheaths have an equipment icon and icon when worn now and make a sound when sheathed/unsheathed
      • -
      -

      Yakumo Chen updated:

      -
        -
      • Slime Jelly is no longer obtainable from slimepeople. Go ask Xenobio
      • -
      -

      YakumoChen updated:

      -
        -
      • To lower production costs, Buzz Fuzz is now manufactured with Real™️ Synthetic honey.
      • -
      -

      Zandario updated:

      -
        -
      • Added some framework for future species expansions, including clothing refitting.
      • -
      • Made majority of the relevant Species IDs and Categories pre-defined, also for easier expansion and use.
      • -
      • lum slime sprites work again
      • -
      • Slapped the Species Defines where relevant
      • -
      -

      corin9090 updated:

      -
        -
      • The chaplain's prayer beads can now be worn on your belt slot
      • -
      -

      kappa-sama updated:

      -
        -
      • super saiyan
      • -
      • ishotgun crafting recipe no longer requires plasteel and is slightly more convenient
      • -
      • ishotgun does 45 damage now instead of 40.5
      • -
      • s
      • -
      • A new spell for the wizard and his martial apprentices, the Inner Mantra technique. It makes you punch people really good and makes you durable, but drains your energy while it's active.
      • -
      • A self-buffing spell for valiant bubblegum slayers that is ultimately useless on lavaland and probably overpowered for miner antagonists. Go figure. At least all it does is let you punch hard while draining your health every second.
      • -
      • bubblegum now drops a book that makes you into an abusive father instead of a shotgun that plays like pre-nerf shotguns
      • -
      • a powerup and powerdown sound effect
      • -
      • two icons for two buff spells
      • -
      -

      keronshb updated:

      -
        -
      • Allows Energy Bola to be caught
      • -
      • This also allows them to be dropped/picked up.
      • -
      • Adds a reduced stamina buffer for SCarp users
      • -
      • Gives SCarp users a better parry
      • -
      • Adds the SCarp bundle which includes a bo staff
      • -
      • Lets Carp costumes carry Bo Staffs
      • -
      • reduces the stamina damage of scarp slightly
      • -
      • reduced the blockchance of the bo staff
      • -
      • Adds more room to northwest maint
      • -
      • Adds a bridge between Atmos and the Turbine.
      • -
      • Blob Resource Tower to 2 points per instead of 1 point per.
      • -
      • Blob Factory Towers can be placed 5 tiles apart instead of 7.
      • -
      • Fixes Blobbernaut Factories consuming Factories if no naut is chosen.
      • -
      • Fixes Reflective Blobs
      • -
      • Re-adds the Clown Car to the clown uplink
      • -
      • 15 >16 TC cost
      • -
      • bonks on external airlocks
      • -
      • Fixes the parry data for scarp
      • -
      -

      kittycat2002 updated:

      -
        -
      • set the name of /datum/reagent/consumable/ethanol/species_drink to Species Drink
      • -
      -

      kiwedespars updated:

      -
        -
      • balanced bone gauntlets.
      • -
      • the robust dildo weapon now has sound.
      • -
      -

      necromanceranne updated:

      -
        -
      • Fixes various sprites for bokken, as well as being unable to craft certain parts and duplicate entries.
      • -
      • Bokken now come in two lengths; full and wakizashi, and two varieties: wood and ironwood. They have different stats for all four.
      • -
      • Bokken require menu crafting and part construction, as well as more complicated materials.
      • -
      • Bokken (long and short) require wood, cloth and leather to craft with a hatchet and screwdriver.
      • -
      • Ironwood bokken (long and short) require ironcap logs, cloth and leather to craft with a hatchet, screwdriver and welder.
      • -
      • Twin sheathes can only fit a pair of blades (longsword + shortsword) or they can fit two shortswords.
      • -
      • Fixed a twin sheath runtime.
      • -
      • A lot of bokken related sprites received an overhaul. Added overlay sprites for weapons sheathed in the twin sheathes.
      • -
      • The extradimensional blade received improved sprites for inhands/back sprites.
      • -
      • You can now make all the variants of the bokken.
      • -
      • Removes a duplicate sprite.
      • -
      • Renames all instances of 'ironwood' to 'steelwood'.
      • -
      • Adds new roboticist labcoat sprites!
      • -
      -

      qwertyquerty updated:

      -
        -
      • Flash the screen on climax
      • -
      -

      raspy-on-osu updated:

      -
        -
      • salicylic acid
      • -
      • space heater heating range and power
      • -
      • windoor open length
      • -
      -

      shellspeed1 updated:

      -
        -
      • Wings from Cit RP have been ported over
      • -
      • Moth wings from cit have been ported over
      • -
      • Cleaned up some pixels on existing moth wings.
      • -
      • Organized the lists for wings by if they are for moths or not and than by alphabetical.
      • -
      • Lings now have infinite space for DNA.
      • -
      • All xenomorph types have been added as corpses for mapping purposes
      • -
      • The dead xenomorphs in the lavaland xenomorph hive now have more variety.
      • -
      • Floor bots are now buildable with all toolboxes.
      • -
      • Xenomorph hybrids can now select wings ~~add: Xenomorph hybrids can now speak xenomorph~~
      • -
      • Xenomorph tongues are available for customization.
      • -
      • Mining borgs can claim points again
      • -
      • Construction bags have been added, use them to carry all sorts of construction bits.
      • -
      • A recipe has been added to cloth stacks to make material and construction bags.
      • -
      • Material bags and construction bags are now available in engineering lockers.
      • -
      • Adds the disposable sentry gun from tg for 11tc each.
      • -
      • The exofab can now print prosthetic limbs
      • -
      • The exofab was missing access to multiple cybernetic organs. This has now been rectified.
      • -
      • A new recipe for a spicy has been given to us by a strange business man.
      • -
      • The bluespace navigation gigabeacon design has been added to shuttle research for those wanting to take their ships around space more.
      • -
      • Xenomorph powers now list plasma cost in their description.
      • -
      -

      silicons updated:

      -
        -
      • nanite resistances tweaked
      • -
      • new nanite programs added for locking the user out from being modified by consoles or antivirals.
      • -
      • anomalies no longer spawn in walls
      • -
      • Twitch Plays: Clown Car
      • -
      • pugilists can now parry
      • -
      • c4 can no longer gib mobs
      • -
      • medium screens are better now
      • -
      • text formatting now uses one character instead of two around the text to emphasize.
      • -
      • colormates
      • -
      • shoving yourself up now costs 50% more
      • -
      • dullahans enabled
      • -
      • tailed individuals can now target groin to intertwine tails on grab intent.
      • -
      • Clowns now have unpredictable effects on supermatter crystals when dusting from contact.
      • -
      • anyone new to the server is lucky enough to have their sprint default to toggle instead of hold
      • -
      • stamina crit is only removed when at or under 100 stamina, rather than 140. stamina crit threshold is still at 140.
      • -
      • luxury shuttle no longer has noteleport
      • -
      • now only poly gets a headset on spawn, not all birds.
      • -
      • the warp implant now actually warps you back 10 seconds. leaves a trail, though. now unlimited us.
      • -
      • things in DEATHCOMA do not deathgasp on death
      • -
      • Meth and changeling adrenals no longer ignore all slowdowns, rather damage slowdowns.
      • -
      • you can now be an angel using a magic mirror again
      • -
      • command headsets are 120% instead of 160%
      • -
      • no more emote italics
      • -
      • players can now respawn/return to lobby as a ghost after a 15 minute (default) delay and rejoin on another character with some/many restrictions
      • -
      • cryo now preserves everything
      • -
      • Magrifle ammo no longer glows.
      • -
      • temperature slowdown divisor nerfed to 35 from 20.
      • -
      • dna melt drops all items being destroying you
      • -
      • keybinds generate anti-collision bindings where necessary automatically now
      • -
      • changeling combat mutations rebalanced. most of them take chemicals to upkeep now.
      • -
      • set-pose has been added
      • -
      • temporary flavor text renamed to set pose, fully visible in examine
      • -
      • ninja gloves no longer hardstun
      • -
      • ninja gloves now cost half as much to use to compensate
      • -
      • simple mobs are now immune to radioactive contamination
      • -
      -

      timothyteakettle updated:

      -
        -
      • time for memory loss message to show up when being revived is now correctly 300 seconds, instead of 30
      • -
      • the load away mission verb won't crash the server now
      • -
      • roundstart slimes can turn into puddles now
      • -
      • all gas masks (but welding + glass) can be alt clicked to show/hide identity
      • -
      • autosurgeons from travelling trader rewards now only have one use
      • -
      • fixes held items proccing crossed when passing someone
      • -
      • you can now get a family heirlooms based off your species instead of job
      • -
      • changeling stings retract upon turning into a slime puddle
      • -
      • you cannot transform into a slime puddle with a no drop item in your hands
      • -
      • slime puddles are now transparent and their colour looks more natural in comparison to the user
      • -
      • slime puddles are now even slower
      • -
      • slime puddles now get no protection from worn clothing
      • -
      • removes two debug messages left in from my prior eye customization pr
      • -
      • adds unlockable loadout items, corresponding category in loadouts, etc
      • -
      • added in-game age verification as an alternative to access requests
      • -
      • disabling adminhelp noises no longer disables looc
      • -
      • apids render now
      • -
      • you can now only entwine tails with people who have a tail
      • -
      • custom eyes and tongues now properly carry across cloning
      • -
      • re-adds the holoform verb for people who want to use it over going through the char list
      • -
      • eye sprites should look normal once more
      • -
      • licking people washes pie off their face
      • -
      • you can now pick your eye sprites from customization
      • -
      • looking at loadout equips loadout items on your preview image instead of job items
      • -
      • custom holoforms are now accessible through an action instead of through verbs
      • -
      • AI holoforms can now emote
      • -
      • cloning now correctly copies your blood colour, body sprite type and eye type
      • -
      • species with NOTRANSSTING cannot have envy's knife used on them
      • -
      • avian/digitigrade legs have been added for slimes
      • -
      • you can teleport bread
      • -
      • slime puddles are no longer layered down one layer
      • -
      • you cannot tackle with two paralysed arms
      • -
      • tackling with a single paralysed arm lowers your tackle roll by 2
      • -
      • circuits get pin data proc is sanitized when text is returned as data
      • -
      • loadout now has save slot support and colour choosing/saving for polychromic items
      • -
      • polychromic maid outfit
      • -
      • you can rebind communication hotkeys and they're the default now
      • -
      • you can now customize your size from 90% to 130%, going below 100% makes you have 10 less max health
      • -
      • *squeak
      • -
      • anthromorphic synth species
      • -
      • improvements to the automatic age gate
      • -
      • antag items are now of critical importance and wont fail to be placed on the character
      • -
      • a tonne of fixes to colourisation of parts, too many to name, including some sprite fixes
      • -
      • things now have their own individual primary/(secondary)/(tertiary) colours as required, and these can be modified by you
      • -
      -

      uomo91 updated:

      -
        -
      • Fixed "Show All" tab in player panel logs being broken.
      • -
      • Whispers, OOC, and various other things display differently in logs, visually distinguishing them from say logs.
      • -
      • Player panel logs will now show all logs chronologically, so you'll see commingled say and attack logs if you're on the "Show All" tab, etc...
      • -
      -

      yorii updated:

      -
        -
      • fixed botany rounding error that caused grass and other plants to misbehave
      • -
      -

      zeroisthebiggay updated:

      -
        -
      • legion now drops chests
      • -
      • Traitor assistants can now purchase the patented POGBox! Put TC into it for even higher damage!
      • -
      • MEGAFAUNA DROPS ARE LAVAPROOF
      • -
      • cool codex cicatrix inhands
      • -
      • gravitokinetic stands from tg
      • -
      • buffs stands overall
      • -
      • protector stands no longer become tposing invisible apes sometimes
      • -
      • jacqueline spawns on boxstation
      • -
      • secsheath for your cool stunsword at your local security vendor. you gotta hack it first though.
      • -
      • fuck the r*d cr*ss
      • -
      • The legion megafauna has been reworked. The fight should now be both slightly harder and faster.
      • -
      • You can no longer cheese the colossus by being a sand golem and simply being immune.
      • -
    GoonStation 13 Development Team From 4edba9fb0373079314a224e93cf2992a15ad67db Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 26 Mar 2021 02:05:08 +0000 Subject: [PATCH 12/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index bbf1a17862..bb9dc98068 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -883,12 +883,6 @@
    • you can now shove yourself up in any intent, not just help.
    - -

    22 January 2021

    -

    Arturlang updated:

    -
      -
    • Adds a way to give items to people, you can combat mode rightclick to offer it to one person, right click on people without mode and click the give verb, or use the hotkey CTRL G to offer it to everyone around you
    • -
    GoonStation 13 Development Team From 03c75ce48a20273830cf376c0967d81fbd589d45 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 29 Mar 2021 00:26:42 +0000 Subject: [PATCH 13/43] Automatic changelog compile [ci skip] --- html/changelog.html | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index bb9dc98068..eb22377e01 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -863,26 +863,6 @@
  • blobs can use the 'me' verb
  • adminhelps and pms only sanitize once instead of twice
  • - -

    25 January 2021

    -

    MrJWhit updated:

    -
      -
    • Alien radio code
    • -
    • Microwave can now be cleaned by a damp rag as well as soap.
    • -
    • Removes some unused code, and improves some other code.
    • -
    • The AI has a verb to look up and down z-levels
    • -
    • Making a monkey into a human doesn't unanchor random things on the tile
    • -
    • Makes a few slight improvements to drinking code
    • -
    • Makes encryption keys be put in the hands of the user when able instead of being dropped on the floor when removed from headsets
    • -
    -

    raspy-on-osu updated:

    -
      -
    • ventcrawling
    • -
    -

    silicons updated:

    -
      -
    • you can now shove yourself up in any intent, not just help.
    • -
    GoonStation 13 Development Team From e58ad434780bd353d8f221a4179e8ca2f67f01e7 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 31 Mar 2021 00:20:53 +0000 Subject: [PATCH 14/43] Automatic changelog compile [ci skip] --- html/changelog.html | 53 --------------------------------------------- 1 file changed, 53 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index eb22377e01..4b2bd626cd 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -810,59 +810,6 @@
  • colormates can now paint some mobs.
  • 1 dev explosions shouldn't delete brains anymore
  • - -

    27 January 2021

    -

    ArcaneMusic, ported by Hatterhat updated:

    -
      -
    • Strike a hydroponics tray with a fully-charged floral somatoray to lock in a mutation.
    • -
    • Floral somatorays now have the ability to force a mutation in a plant. This should drain the cell in a single shot, but we'll see.
    • -
    • Somatorays now take uranium to craft instead of radium.
    • -
    -

    Arturlang updated:

    -
      -
    • Actually adds a right click give option
    • -
    • Revenants can now clickdrag to throw stuff at people, with some items doing various things at the same time.
    • -
    -

    DeltaFire15 updated:

    -
      -
    • The woundmending rite no longer causes runtimes.
    • -
    • Ratvarian borgs can now use their tier-0 spells.
    • -
    • Ratvarian borgs can always use their assigned spells, if there is enough power.
    • -
    • The heretic antag panel now shows their sacrifices & current sacrifice targets.
    • -
    • The heretic roundend report now shows their sacrifices and nonsacrificed targets.
    • -
    • Living hearts can no longer select the same target as another living heart, removing a certain problem.
    • -
    -

    Hatterhat updated:

    -
      -
    • Department budget cards have been readded. TO THE CODE. NOT LOCKERS.
    • -
    • Also budget cards now look more like every other ID - see tgstation#55001.
    • -
    • One of the contractor tablet's payouts has been raised from a small payout to a medium payout.
    • -
    • The free golem ship's GPSes no longer start on. They were never meant to, but they did.
    • -
    • Headsets can't be found on most legion corpses now.
    • -
    • The flash on the assistant corpse is gone, too.
    • -
    -

    MrJWhit updated:

    -
      -
    • Remaps some air alarms for sanity.
    • -
    -

    SandPoot updated:

    -
      -
    • The drop circuit can no longer drop things that are not inside it.
    • -
    -

    raspy-on-osu updated:

    -
      -
    • bespoke ventcrawling element not detaching due to malformed call
    • -
    -

    shellspeed1 updated:

    -
      -
    • Floorbots had had a software update, preventing them from dogpiling on their target as easily as they did before.
    • -
    • Floorbots will now play a small chime when stacked on top of each other to indicate that they're moving apart.
    • -
    -

    timothyteakettle updated:

    -
      -
    • blobs can use the 'me' verb
    • -
    • adminhelps and pms only sanitize once instead of twice
    • -
    GoonStation 13 Development Team From f2208f99648b8bf3d3db98adb3bc7e0bffbbc8ad Mon Sep 17 00:00:00 2001 From: Changelogs Date: Thu, 1 Apr 2021 00:26:52 +0000 Subject: [PATCH 15/43] Automatic changelog compile [ci skip] --- html/changelog.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 4b2bd626cd..46d9b16786 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -803,13 +803,6 @@
  • cowbell necklace happy 2021
  • shibari ropes & torn pantyhose
  • - -

    28 January 2021

    -

    silicons updated:

    -
      -
    • colormates can now paint some mobs.
    • -
    • 1 dev explosions shouldn't delete brains anymore
    • -
    GoonStation 13 Development Team From e101e55f7ab684852ea87804d93717f10729d06b Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 2 Apr 2021 00:34:59 +0000 Subject: [PATCH 16/43] Automatic changelog compile [ci skip] --- html/changelog.html | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 46d9b16786..34dfeced7a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -771,38 +771,6 @@
  • some more FUCKING hairs
  • uncodersprites the advanced extinguisher
  • - -

    29 January 2021

    -

    MrJWhit updated:

    -
      -
    • Ported the QM, Captain, CMO, and HoS cloaks from beestation.
    • -
    • Removes excess air alarms from boxstation
    • -
    -

    TripleShades updated:

    -
      -
    • fixes engineering secure storage being the wrong area because I fucked that up previously my bad
    • -
    • removes funny extra light switch under right surgery table in surgery oops
    • -
    • Added chairs to the corpse launch viewing area
    • -
    • Small garden plot for flowers for parity with other station Chapels
    • -
    • Plain Bible to glass tables in Chapel
    • -
    • Candles and Matchbox to glass tables in Chapel
    • -
    • More glass tables, with a chaplain figure and another spare bible.
    • -
    • Bookcase to Box Chapel for parity with other station Chapels
    • -
    • Minimoog to Box Chapel as substitute for a church organ
    • -
    • Holy department sign just below Chapel change: Expanded the corpse launching area to feel less congested change: Added windows to the corpse launch so you can look inside I guess? change: Moved flowers and burial garments to the corner next to the corpse launcher change: Box Chaplain's office door is moved over one change: Confessional is now connected to Chaplain's office for parity with other station Chapels change: Moved coffins over to old confessional location change: Box Chapel now has pews instead of stools change: Box Chapel Confessional is now lit instead of being nearly pitch black remove: Two coffins from Chapel
    • -
    -

    timothyteakettle updated:

    -
      -
    • the miner bedsheet will now increment its progress when you redeem points from the ORM
    • -
    • you can add custom names and descriptions to item's on the loadout now
    • -
    -

    zeroisthebiggay updated:

    -
      -
    • roundstart aesthetic sterile masks and roundstart paper masks
    • -
    • more accessory slot items
    • -
    • cowbell necklace happy 2021
    • -
    • shibari ropes & torn pantyhose
    • -
    GoonStation 13 Development Team From b675e57c0c06b6fd2b4c55e0a1cade55d50b3882 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sat, 3 Apr 2021 00:25:19 +0000 Subject: [PATCH 17/43] Automatic changelog compile [ci skip] --- html/changelog.html | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 34dfeced7a..bc507ca1c9 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -760,17 +760,6 @@
    • fermichem explosion EMPs don't cover the entire station
    - -

    30 January 2021

    -

    timothyteakettle updated:

    -
      -
    • adds 'clucks', 'caws' and 'gekkers' to the speech verb list
    • -
    -

    zeroisthebiggay updated:

    -
      -
    • some more FUCKING hairs
    • -
    • uncodersprites the advanced extinguisher
    • -
    GoonStation 13 Development Team From ecc38dff107076261cb585f01b726fe5ccb54075 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 4 Apr 2021 00:27:31 +0000 Subject: [PATCH 18/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index bc507ca1c9..1a6372d2a1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -754,12 +754,6 @@
  • pais can now be carried around piggybacking/fireman
  • Meth and Nuka Cola once again, speed you up.
  • - -

    31 January 2021

    -

    Putnam3145 updated:

    -
      -
    • fermichem explosion EMPs don't cover the entire station
    • -
    GoonStation 13 Development Team From dc9c1eb8bd95a7bd6c3e8ac43db006403c931214 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 6 Apr 2021 00:27:15 +0000 Subject: [PATCH 19/43] Automatic changelog compile [ci skip] --- html/changelog.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 1a6372d2a1..f8bc95fae5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -747,13 +747,6 @@
    • The green energy sabre's sprite now respects proper handedness.
    - -

    02 February 2021

    -

    silicons updated:

    -
      -
    • pais can now be carried around piggybacking/fireman
    • -
    • Meth and Nuka Cola once again, speed you up.
    • -
    GoonStation 13 Development Team From 3e257893b1236ca83c39d8f1b88bdee22dd28aac Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 7 Apr 2021 00:26:18 +0000 Subject: [PATCH 20/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index f8bc95fae5..ef4e9c596d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -741,12 +741,6 @@
    • dwarf facial hair is no longer randomised
    - -

    03 February 2021

    -

    Hatterhat updated:

    -
      -
    • The green energy sabre's sprite now respects proper handedness.
    • -
    GoonStation 13 Development Team From a216eeaf6ae7d3e7bfe444fc37f732223b00a935 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 9 Apr 2021 00:26:10 +0000 Subject: [PATCH 21/43] Automatic changelog compile [ci skip] --- html/changelog.html | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index ef4e9c596d..d457e4d823 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -715,32 +715,6 @@
    • syndicate ablative armwraps have been added.
    - -

    05 February 2021

    -

    SmArtKar updated:

    -
      -
    • The orbit menu now has an Auto-Observe button! No more sifting through the lame observe menu to snoop in people's backpacks! Also, orbit menu now refreshes.
    • -
    • KAs are no longer getting broken when fired by a circuit
    • -
    -

    keronshb updated:

    -
      -
    • Force and damage > 15 from 18/25
    • -
    • Knockdown put down to 5 from 30
    • -
    • Armor pen down to 10 from 100.
    • -
    • Makes cell chargers, charge faster.
    • -
    -

    raspy-on-osu updated:

    -
      -
    • alien royals can no longer ventcrawl
    • -
    -

    shellspeed1 updated:

    -
      -
    • There actually needs to be people for zombies to happen now.
    • -
    -

    timothyteakettle updated:

    -
      -
    • dwarf facial hair is no longer randomised
    • -
    GoonStation 13 Development Team From 40edd39c257a33273a4b4a88b12e1cc7fe7b3905 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 11 Apr 2021 00:29:44 +0000 Subject: [PATCH 22/43] Automatic changelog compile [ci skip] --- html/changelog.html | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index d457e4d823..9db74f4c8f 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -683,38 +683,6 @@
    • sentient viruses can now infect synths and ipcs
    - -

    07 February 2021

    -

    Thalpy updated:

    -
      -
    • Dispenser: Adds the ability to store a small amount of reagents in the machine itself for dispensing. Reacting recipies cannot be stored. Size of storage increases with bin size.
    • -
    • Dispenser: Allows reagents to be color coded by pH
    • -
    • Dispenser: Each reagent displays it's pH on hover
    • -
    • Dispenser: Allows the user to toggle between buttons and a radial dial
    • -
    • Dispenser: When the dispencer is upgraded it can dispense 5/3/2/1 volumes based on rating refactor: Dispenser: as it was before. This does not break recorded recipes.
    • -
    • Adds a round function to some numbers so they're not huge
    • -
    • The Chem master can now get purity for all reagents when analysed
    • -
    • Synthissue fixes
    • -
    • buffers now have a strong and weak variant. Weak can be dispensed, and strong can be created. Strong buffers are 6x more effective.
    • -
    • Some buffer pH edge calculation fixes
    • -
    -

    TyrianTyrell updated:

    -
      -
    • added a signed language, that can't be used over the radio but can be used if you're mute. also added the multilingual trait.
    • -
    • hopefully added an icon for the signed language.
    • -
    • changed how some traits function slightly.
    • -
    -

    dzahlus updated:

    -
      -
    • tweaked a few sounds
    • -
    • added a new weapon sounds
    • -
    • removed old weapon sounds
    • -
    • changed some sound related code
    • -
    -

    silicons updated:

    -
      -
    • syndicate ablative armwraps have been added.
    • -
    GoonStation 13 Development Team From d04f3dd4d4f1efc107210e6b89143783e7bc345f Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 13 Apr 2021 00:28:39 +0000 Subject: [PATCH 23/43] Automatic changelog compile [ci skip] --- html/changelog.html | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 9db74f4c8f..fbc944ec52 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -665,24 +665,6 @@
    • the aesthetic sterile mask no longer hides faces so you can cosplay egirls and keep flavortexts
    - -

    09 February 2021

    -

    Chiirno updated:

    -
      -
    • Adds clown waddle to clown shoes. Enhanced Clown Waddle Dampeners can be engaged in-hand with ctrl+click, _but why would you?_
    • -
    -

    MrJWhit updated:

    -
      -
    • Re-adds theater disposal outlet, and makes dorms disposal able to have things sent to it on boxstation.
    • -
    -

    TyrianTyrell updated:

    -
      -
    • made default tongue able to speak signed language.
    • -
    -

    timothyteakettle updated:

    -
      -
    • sentient viruses can now infect synths and ipcs
    • -
    GoonStation 13 Development Team From 96d154a618f84719cc9515920f3f70688ee94a88 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Thu, 15 Apr 2021 00:26:22 +0000 Subject: [PATCH 24/43] Automatic changelog compile [ci skip] --- html/changelog.html | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index fbc944ec52..fa345a43b7 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -632,39 +632,6 @@
    • Voice of God - sleep removed, stun staggers instead, knockdown is faster but does not do stamina damage, vomit is faster but doesn't stun
    - -

    11 February 2021

    -

    Adelphon updated:

    -
      -
    • Charismatic Suit
    • -
    • Urban Jacket
    • -
    -

    DeltaFire15 updated:

    -
      -
    • Added nanogel to the robodrobe.
    • -
    -

    Putnam3145 updated:

    -
      -
    • Config to keep unreadied players from mode voting
    • -
    -

    dzahlus updated:

    -
      -
    • fixes grenadelaunch.ogg being used where it shouldn't and makes mech weapons use correct sound
    • -
    -

    keronshb updated:

    -
      -
    • 10 > 30 second for Warp Implant cooldown
    • -
    • Comments out power sink objective.
    • -
    -

    timothyteakettle updated:

    -
      -
    • persistent blood should stop being invisible and alt clicking it shouldn't return the entire spritesheet
    • -
    • pickpocketing is now logged using log_combat
    • -
    -

    zeroisthebiggay updated:

    -
      -
    • the aesthetic sterile mask no longer hides faces so you can cosplay egirls and keep flavortexts
    • -
    GoonStation 13 Development Team From b5d720d3308884a5906b52065b8de45e7ad77c6f Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 16 Apr 2021 00:25:13 +0000 Subject: [PATCH 25/43] Automatic changelog compile [ci skip] --- html/changelog.html | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index fa345a43b7..9ff0a3e422 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -617,21 +617,6 @@
    • migration error to version 39+ of savefiles is now logged instead of messaging all online admins in the chat
    - -

    12 February 2021

    -

    Hatterhat updated:

    -
      -
    • The ATVs on SnowCabin.dmm have been replaced with snowmobiles.
    • -
    -

    MrJWhit updated:

    -
      -
    • Random deltastation fixes.
    • -
    • Gives boxstation vault door actual vault door access
    • -
    -

    silicons updated:

    -
      -
    • Voice of God - sleep removed, stun staggers instead, knockdown is faster but does not do stamina damage, vomit is faster but doesn't stun
    • -
    GoonStation 13 Development Team From e86accccec939b5198b8284c6447d1c4d7e9f784 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sat, 17 Apr 2021 00:25:22 +0000 Subject: [PATCH 26/43] Automatic changelog compile [ci skip] --- html/changelog.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 9ff0a3e422..6cbcc26219 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -607,16 +607,6 @@
    • added a define for multilingual granted languages, and changed the multilingual trait to use it.
    - -

    13 February 2021

    -

    Hatterhat updated:

    -
      -
    • Energy bolas now take 2.5 seconds to remove and dissipate on removal.
    • -
    -

    timothyteakettle updated:

    -
      -
    • migration error to version 39+ of savefiles is now logged instead of messaging all online admins in the chat
    • -
    GoonStation 13 Development Team From 230231a34bf08d192befec99dcddf91177038618 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 18 Apr 2021 00:26:47 +0000 Subject: [PATCH 27/43] Automatic changelog compile [ci skip] --- html/changelog.html | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 6cbcc26219..9fadfaf5a5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -589,24 +589,6 @@
  • people on the ground hit less hard in unarmed combat. rng miss remove from punches.
  • chat highlighting no longer drops half your entered words.
  • - -

    14 February 2021

    -

    DeltaFire15 updated:

    -
      -
    • The antag panel now correctly shows the names of cultist / clockcult datum subtypes.
    • -
    • Adding clock cultists via the admin panel now works correctly.
    • -
    • Xeno larvae should now be able to ventcrawl again.
    • -
    -

    Hatterhat updated:

    -
      -
    • Repairing sensors on jumpsuits now requires a fully-intact jumpsuit. Find some cloth.
    • -
    • Durathread armor kits now require you to have a fully-repaired jumpsuit, first, with no attachments.
    • -
    • Durathread armor kits now no longer weave the entirety of the jumpsuit armor universe into having armor.
    • -
    -

    TyrianTyrell updated:

    -
      -
    • added a define for multilingual granted languages, and changed the multilingual trait to use it.
    • -
    GoonStation 13 Development Team From 9df4eebbedd9ed5ed573c1586808a363921d67e2 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 19 Apr 2021 00:26:20 +0000 Subject: [PATCH 28/43] Automatic changelog compile [ci skip] --- html/changelog.html | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 9fadfaf5a5..fb0a74d395 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -561,34 +561,6 @@
    • sprint removal entry added, UI will revert to old UI while this is active.
    - -

    15 February 2021

    -

    Adelphon updated:

    -
      -
    • polychromatic shoes
    • -
    • polychromatic windbreaker
    • -
    • polychromatic canvas cloak
    • -
    • digitigrade charismatic suit texture
    • -
    -

    DeltaFire15 updated:

    -
      -
    • Kneecapped pugilist parries somewhat.
    • -
    • Slightly nerfed default unarmed parries.
    • -
    • Slightly nerfed traitor armwrap parries.
    • -
    • Pugilist parries now cannot perfectly defend against projectiles, as they were supposed to.
    • -
    • Some parrying numbers that one would think were in seconds didn't have the SECONDS. I added those.
    • -
    • Clock cultists now yell alot less when invoking scripture.
    • -
    -

    dzahlus updated:

    -
      -
    • Added new emote
    • -
    • added a new emote sound
    • -
    -

    silicons updated:

    -
      -
    • people on the ground hit less hard in unarmed combat. rng miss remove from punches.
    • -
    • chat highlighting no longer drops half your entered words.
    • -
    GoonStation 13 Development Team From 1f68d32295d3d09aff65abb2aa1e4f30e4879ebe Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 20 Apr 2021 00:26:20 +0000 Subject: [PATCH 29/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index fb0a74d395..1889c8fa85 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -555,12 +555,6 @@
    • priviledge --> privilege
    - -

    16 February 2021

    -

    silicons updated:

    -
      -
    • sprint removal entry added, UI will revert to old UI while this is active.
    • -
    GoonStation 13 Development Team From af8f15a729e47adddd7443baa4460b426b0867d4 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Thu, 22 Apr 2021 00:27:35 +0000 Subject: [PATCH 30/43] Automatic changelog compile [ci skip] --- html/changelog.html | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 1889c8fa85..528a37bc52 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -524,37 +524,6 @@
    • staring into pierced realities is now logged
    - -

    18 February 2021

    -

    BlueWildrose updated:

    -
      -
    • Admins now receive messages regarding certain holodeck actions.
    • -
    -

    Hatterhat updated:

    -
      -
    • Free Golem Ship GPSes now start as disabled. Like they were supposed to.
    • -
    -

    LetterN updated:

    -
      -
    • No more liver damage when you opt out of "hornychems"
    • -
    -

    SmArtKar updated:

    -
      -
    • Added a new TCG card game
    • -
    -

    dzahlus updated:

    -
      -
    • Removed maroon objective due to toxic gameplay behaviour
    • -
    -

    shellspeed1 updated:

    -
      -
    • floor bots place plating before tiles now.
    • -
    • gets rid of another tile duplication issue.
    • -
    -

    silicons updated:

    -
      -
    • priviledge --> privilege
    • -
    GoonStation 13 Development Team From 0b918a4a380e2445cfbe059bcb7a14d4279acdd8 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 23 Apr 2021 00:26:49 +0000 Subject: [PATCH 31/43] Automatic changelog compile [ci skip] --- html/changelog.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 528a37bc52..b5347f5415 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -514,16 +514,6 @@
    • stops people using Message All on PDAs when their cartridge doesn't allow it
    - -

    19 February 2021

    -

    Putnam3145 updated:

    -
      -
    • Buzz Fuzz's addiction threshold is now a can and a sip as intended.
    • -
    -

    timothyteakettle updated:

    -
      -
    • staring into pierced realities is now logged
    • -
    GoonStation 13 Development Team From 88a018df29c6be643f6e7760a721722f2ec375f2 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sat, 24 Apr 2021 00:27:30 +0000 Subject: [PATCH 32/43] Automatic changelog compile [ci skip] --- html/changelog.html | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index b5347f5415..592bf02e18 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -490,30 +490,6 @@
  • the query for checking mentors now gets properly deleted
  • vampires no longer burn in the chapel if they signed up as the chaplain
  • - -

    20 February 2021

    -

    Adelphon updated:

    -
      -
    • polychromic pants
    • -
    • urban coat made polychromic
    • -
    -

    Chiirno updated:

    -
      -
    • Synthflesh now unhusks with 100u instead of requiring 101u.
    • -
    -

    SmArtKar updated:

    -
      -
    • Added some QoL changes to TCG
    • -
    • Fixed TCG cards not saving
    • -
    -

    TyrianTyrell updated:

    -
      -
    • fixed the signed language so that you can actually use it, and that it's unusable when it's meant to be.
    • -
    -

    timothyteakettle updated:

    -
      -
    • stops people using Message All on PDAs when their cartridge doesn't allow it
    • -
    GoonStation 13 Development Team From 574a843d65467e2055700474175df49270345adf Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 25 Apr 2021 00:28:05 +0000 Subject: [PATCH 33/43] Automatic changelog compile [ci skip] --- html/changelog.html | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 592bf02e18..d5ddb64bcb 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -471,25 +471,6 @@
  • Added pain emote to getting wounded
  • added a new pain emote sounds
  • - -

    21 February 2021

    -

    Hatterhat updated:

    -
      -
    • Anomaly announcements and brand intelligence now always announce instead of having some ham-fisted chance of being a command report.
    • -
    -

    IronEleven updated:

    -
      -
    • Raises Space Vine Population Requirement from 10 to 20
    • -
    -

    MrJWhit updated:

    -
      -
    • Removes an unnecessary % on the seed extractor.
    • -
    -

    timothyteakettle updated:

    -
      -
    • the query for checking mentors now gets properly deleted
    • -
    • vampires no longer burn in the chapel if they signed up as the chaplain
    • -
    GoonStation 13 Development Team From 382ac96d2f4a478ee6a47273887ad9dd7f5f631b Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 26 Apr 2021 00:28:22 +0000 Subject: [PATCH 34/43] Automatic changelog compile [ci skip] --- html/changelog.html | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index d5ddb64bcb..7195987603 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -439,38 +439,6 @@
    • banning panel prioritises mobs with clients now when trying to find them if they're in the game
    - -

    22 February 2021

    -

    Putnam3145 updated:

    -
      -
    • (Hexa)crocin
    • -
    • (Hexa)camphor
    • -
    • Nymphomaniac quirk
    • -
    • All climaxes and arousals are now logged, as well as genital exposure.
    • -
    -

    SandPoot updated:

    -
      -
    • Cyborg tablets and it's special app for self-management.
    • -
    • In the case of a doomsday device being created outside of an AI it will delete itself.
    • -
    • Some sprites for it have been added and the borg's hud light toggles been changed to only on-off (made by yours truly)
    • -
    • A lot of borg code was changed
    • -
    • Tools no longer use istype checks and actually check for their behavior.
    • -
    -

    Vynzill updated:

    -
      -
    • cursed rice hat that's hard to find and obtain, along with a couple other hats
    • -
    • a replacement toy gun for donksoft lmg
    • -
    • gorillas to the jungle gateway, friendly, even when attacked.
    • -
    • couple mapping errors I noticed, most importantly a missing window in the chapel.
    • -
    • shotgun and donksoft lmg removed, captain coat nerfed armor values.
    • -
    • leaper healthpool from 450 to 550 hopefully making it more of a struggle, and gives it a name.
    • -
    • leaper pit is more wider. The hidden room south is now more obvious to find
    • -
    -

    dzahlus updated:

    -
      -
    • Added pain emote to getting wounded
    • -
    • added a new pain emote sounds
    • -
    GoonStation 13 Development Team From 1cf881470bb760bce137d7b816fd492645e97ad0 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 27 Apr 2021 00:25:58 +0000 Subject: [PATCH 35/43] Automatic changelog compile [ci skip] --- html/changelog.html | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index e3b9b14a1f..44ed1c8e5d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,24 +50,6 @@ -->
    -

    24 March 2021

    -

    Hatterhat updated:

    -
      -
    • The NOGUNS trait now takes precedence over the triggerguard checks.
    • -
    -

    ItzGabby updated:

    -
      -
    • Fluff Items with polychromic support
    • -
    • A new vendor called Bark box
    • -
    • A new form of snack with it's own box
    • -
    • Two harness, one of them being lewd
    • -
    • One new collar, with a ribbon. Classy.
    • -
    • More locked forms of collars
    • -
    • Purged old balls
    • -
    • Removed the funny buffs each colored tennis ball had, down with the powergame!
    • -
    • Added polychromic fluff icons, vendor icons, suit icons, snack icons, fancy box icons, and a polychromic version of Izzy's ball.
    • -
    • Deleted old balls, Izzy's Ball, except the rainbow one since it's special and as I did not go out of my way to get permission to touch.
    • -
    • Walked into vending.dm and glared for a moment at hydroponics' grammar.
    • 26 April 2021

      Trigg, stylemistake and SandPoot updated:

        @@ -384,11 +366,8 @@
      • The radioactive microlaser now calculates the strength of its delay effect using the intensity setting it had when you initially used it on your victim, not the intensity setting it currently has. This prevents people from "cheating out" its intensity 20 effect with only a 2 second delay and a 1 second cooldown.
      • Radioactive microlasers no longer contain twice as much metal as normal health analyzers do.
      -

      LetterN updated:

      +

      necromanceranne updated:

        -
      • fixed laptops pickability
      • -
      • fixed closets being unweldable
      • -
    • Replaces the useless bullet and laser shields with new Kinetic and Ablative shields, which do as they advertise.
    • Replaces the shield implants shield with a hardlight shield that can take large amounts of brute damage, but disintegrates when shot with disablers.
    • Fixes Fake Roman Shields being able to be used as normal riot shields.
    • @@ -828,17 +807,6 @@
      • xeno cube makes hostile xenos now, and drops a sentinel instead of a drone.
      - -

      23 February 2021

      -

      keronshb updated:

      -
        -
      • Hyperblade to uplink with poplock
      • -
      • Removes combination of two Dragon Tooth Swords while keeping it for regular eutactics.
      • -
      -

      timothyteakettle updated:

      -
        -
      • banning panel prioritises mobs with clients now when trying to find them if they're in the game
      • -
    GoonStation 13 Development Team From 02b5f70c10f625aad49eacd4e850266fdf89d396 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 28 Apr 2021 00:26:45 +0000 Subject: [PATCH 36/43] Automatic changelog compile [ci skip] --- html/changelog.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 44ed1c8e5d..fa46c13a87 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -797,16 +797,6 @@
    • Traitor / Ling objective amount should now be correct again.
    - -

    24 February 2021

    -

    SandPoot updated:

    -
      -
    • Regular crowbars no longer open powered airlocks.
    • -
    -

    silicons updated:

    -
      -
    • xeno cube makes hostile xenos now, and drops a sentinel instead of a drone.
    • -
    GoonStation 13 Development Team From dc05f23e9e450aa7f0a8b93fa5babbf1f7c76ec2 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Thu, 29 Apr 2021 00:26:16 +0000 Subject: [PATCH 37/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index fa46c13a87..9185892185 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -791,12 +791,6 @@
    • All machine-frame based tool-use actions now have state-checking callbacks.
    - -

    25 February 2021

    -

    DeltaFire15 updated:

    -
      -
    • Traitor / Ling objective amount should now be correct again.
    • -
    GoonStation 13 Development Team From dc02561b3601b1fac0a781e9895469f76f1a0c15 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Fri, 30 Apr 2021 00:13:45 +0000 Subject: [PATCH 38/43] Automatic changelog compile [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 9185892185..f9f94b6d37 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -785,12 +785,6 @@
    • chaplain arrythmic knives can no longer be abused for infinite speed.
    - -

    26 February 2021

    -

    DeltaFire15 updated:

    -
      -
    • All machine-frame based tool-use actions now have state-checking callbacks.
    • -
    GoonStation 13 Development Team From 4c8b1f2454cfe6e8be3a44dde2c40beb115a6e9a Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sat, 1 May 2021 00:15:03 +0000 Subject: [PATCH 39/43] Automatic changelog compile [ci skip] --- html/changelog.html | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index f9f94b6d37..12186a5fae 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -753,38 +753,6 @@
    • fixes toxinlovers dying from heretic stuff that should heal them instead
    - -

    27 February 2021

    -

    Hatterhat updated:

    -
      -
    • Lingfists (trait_mauler) now deal no stam damage and lost their 15(!!!) armor penetration.
    • -
    -

    Putnam3145 updated:

    -
      -
    • Tablets now protect their contents from rads.
    • -
    -

    TheObserver-sys updated:

    -
      -
    • Chems that should have been usable are now usable, try some cryoxadone on a plant today!!!
    • -
    -

    kappa-sama updated:

    -
      -
    • cards and card binders are now small-class items
    • -
    -

    keronshb updated:

    -
      -
    • 16 > 10 unlock cost for stronger abilities
    • -
    • Made nearly all other abilities for free.
    • -
    -

    kiwedespars updated:

    -
      -
    • reverted the pr that absolutely gutted pugilism and made it worse than base unarmed, also gives it a second long stagger
    • -
    • removed the ability to parry while horizontal, because that's dumb and makes it easy to just time the parries right.
    • -
    -

    silicons updated:

    -
      -
    • chaplain arrythmic knives can no longer be abused for infinite speed.
    • -
    GoonStation 13 Development Team From 16731b2475d57831d2d38d231bd06b3f7bf008e3 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 2 May 2021 00:18:09 +0000 Subject: [PATCH 40/43] Automatic changelog compile [ci skip] --- html/changelog.html | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 12186a5fae..342b1a63c9 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -734,25 +734,6 @@
    • cursed rice hat right in front of the jungle gateway's entrance is now removed from this dimensional plane
    - -

    28 February 2021

    -

    Putnam3145 updated:

    -
      -
    • Polychromic windbreaker's alt-click message is now coherent
    • -
    • Toggleable suits now have an on_toggle proc to be overridden.
    • -
    -

    R3dtail updated:

    -
      -
    • doubled max belly name length and quadrupled belly description length
    • -
    -

    SandPoot updated:

    -
      -
    • Body rejuvenation surgery will loop until the patient is completely healed.
    • -
    -

    dzahlus updated:

    -
      -
    • fixes toxinlovers dying from heretic stuff that should heal them instead
    • -
    GoonStation 13 Development Team From 59a8434d0cee25fe8cbba7e88a0843a0dfefda56 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 3 May 2021 00:16:49 +0000 Subject: [PATCH 41/43] Automatic changelog compile [ci skip] --- html/changelog.html | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 342b1a63c9..ab49f1731e 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -722,18 +722,6 @@
    • Changelings will actually become the person they want to be when using "human form" ability(after having used last resort).
    - -

    01 March 2021

    -

    SmArtKar updated:

    -
      -
    • Fixes decks breaking your screen
    • -
    • Fixes binders not saving cards
    • -
    • Fixes binders not saving multiple cards of the same type
    • -
    -

    Vynzill updated:

    -
      -
    • cursed rice hat right in front of the jungle gateway's entrance is now removed from this dimensional plane
    • -
    GoonStation 13 Development Team From 1fb05a12fade41aba811e888b23bcb27ec9cf38c Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 4 May 2021 00:10:22 +0000 Subject: [PATCH 42/43] Automatic changelog compile [ci skip] --- html/changelog.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index ab49f1731e..b7e25baa22 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -712,16 +712,6 @@
  • Kinetic Accelerator now properly reloads a charge to it's chamber instead of nulling the variable forever
  • Now pacifists won't be able to use Kinetic Accelerators if a non-pacifist shoots it first
  • - -

    02 March 2021

    -

    LetterN updated:

    -
      -
    • colorpainter: let's not dispense null
    • -
    -

    SandPoot updated:

    -
      -
    • Changelings will actually become the person they want to be when using "human form" ability(after having used last resort).
    • -
    GoonStation 13 Development Team From 1542785490c1620826ccfbbb1c8b951a4bfa6dae Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 5 May 2021 00:02:52 +0000 Subject: [PATCH 43/43] Automatic changelog compile [ci skip] --- html/changelog.html | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index b7e25baa22..96725ae8f8 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -681,37 +681,6 @@
    • removes bsql
    - -

    03 March 2021

    -

    MarinaGryphon updated:

    -
      -
    • The AOOC mute pref is now properly respected.
    • -
    • Muting adminhelp sounds no longer mutes AOOC.
    • -
    -

    Putnam3145 updated:

    -
      -
    • pAIs now have a policy config
    • -
    • "Supermatter surge" event, which might cause problems if the supermatter is not sufficiently cooled (i.e. the setup is messed up in some way)
    • -
    • Fusion can no longer be done in open air.
    • -
    • Valentine's day event no longer gives everyone a valentine's antag.
    • -
    -

    SandPoot updated:

    -
      -
    • Legions should now pass their type to the person they infect (if valid).
    • -
    -

    dzahlus updated:

    -
      -
    • Added new subtype to lesser ash drake balanced around player control
    • -
    • rebalanced dragon transformation to a 1 minute cooldown as well as using the new subtype of megafauna
    • -
    -

    qweq12yt updated:

    -
      -
    • fixed infectious zombies not being able to attack if host was pacifist
    • -
    • adds a way for species to have blacklisted quirks, the removal, and restoration of said quirks upon species changes
    • -
    • Now pacifists won't be able to use flamethrowers
    • -
    • Kinetic Accelerator now properly reloads a charge to it's chamber instead of nulling the variable forever
    • -
    • Now pacifists won't be able to use Kinetic Accelerators if a non-pacifist shoots it first
    • -
    GoonStation 13 Development Team