diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index e032701468e..328f61d6212 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -182,10 +182,7 @@ dump_contents() update_icon() -/** - * Drops all contents of the unit onto the ground. -*/ -/obj/machinery/suit_storage_unit/proc/dump_contents() +/obj/machinery/suit_storage_unit/dump_contents() dropContents() helmet = null suit = null diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 8aa4067e68c..da24dc47822 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -90,6 +90,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ null, \ new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("floodlight frame", /obj/structure/floodlight_frame, 5, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("voting box", /obj/structure/votebox, 15, time = 50) )) /obj/item/stack/sheet/metal diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 9b734bfb1ad..ebb172a29f1 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -327,3 +327,8 @@ /obj/proc/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) return + +// Should move all contained objects to it's location. +/obj/proc/dump_contents() + CRASH("Unimplemented.") + return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index bfc878f9035..2920d57904d 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -120,7 +120,7 @@ return FALSE return TRUE -/obj/structure/closet/proc/dump_contents() +/obj/structure/closet/dump_contents() var/atom/L = drop_location() for(var/atom/movable/AM in src) AM.forceMove(L) diff --git a/code/game/objects/structures/votingbox.dm b/code/game/objects/structures/votingbox.dm new file mode 100644 index 00000000000..4d9fc14d9b6 --- /dev/null +++ b/code/game/objects/structures/votingbox.dm @@ -0,0 +1,194 @@ +/obj/structure/votebox + name = "voting box" + desc = "A automatic voting box." + + icon = 'icons/obj/votebox.dmi' + icon_state = "votebox_maint" + + anchored = TRUE + + var/obj/item/card/id/owner //Slapping the box with this ID starts/ends the vote. + + var/voting_active = FALSE //Voting or Maintenance Mode + var/id_auth = FALSE //One vote per ID. + var/vote_description = "" + + var/list/voted //List of ID's that already voted. + +/obj/structure/votebox/attackby(obj/item/I, mob/living/user, params) + if(istype(I,/obj/item/card/id)) + if(!owner) + register_owner(I,user) + return + if(istype(I,/obj/item/paper)) + if(voting_active) + apply_vote(I,user) + else + to_chat(user,"[src] is in maintenance mode. Voting is not possible at the moment.") + return + return ..() + +/obj/structure/votebox/interact(mob/user) + ..() + ui_interact(user) + +/obj/structure/votebox/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/ui_state/state) + . = ..() + + var/list/dat = list() + if(!owner) + dat += "

Unregistered. Swipe ID card to register as voting box operator

" + dat += "

[vote_description]

" + if(is_operator(user)) + dat += "Voting: [voting_active ? "Active" : "Maintenance Mode"]
" + dat += "Set Description: Set Description
" + dat += "One vote per ID: [id_auth ? "Yes" : "No"]
" + dat += "Reset voted ID's: Reset
" + dat += "Draw random vote: Raffle
" + dat += "Shred votes: Shred
" + dat += "Tally votes: Tally
" + + var/datum/browser/popup = new(user, "votebox", "Voting Box", 300, 300) + popup.set_content(dat.Join()) + popup.open() + +/obj/structure/votebox/Topic(href, href_list) + if(..()) + return + + var/mob/user = usr + if(!is_operator(user)) + to_chat(user,"Voting box operator authorization required.") + return + + if(href_list["act"]) + switch(href_list["act"]) + if("toggle_vote") + voting_active = !voting_active + update_icon() + if("toggle_auth") + id_auth = !id_auth + if("reset_voted") + if(voted) + voted.Cut() + to_chat(user,"You reset the voter buffer. Everyone can vote again.") + if("raffle") + raffle(user) + if("shred") + shred(user) + if("tally") + print_tally(user) + if("set_desc") + set_description(user) + interact(user) + +/obj/structure/votebox/proc/register_owner(obj/item/card/id/I,mob/living/user) + owner = I + to_chat(user,"You register [src] to your ID card.") + ui_interact(user) + +/obj/structure/votebox/proc/set_description(mob/user) + var/new_description = stripped_multiline_input(user,"Enter new description","Vote Description",vote_description) + if(new_description) + vote_description = new_description + +/obj/structure/votebox/proc/is_operator(mob/user) + return user?.get_idcard() == owner + +/obj/structure/votebox/proc/apply_vote(obj/item/paper/I,mob/living/user) + var/obj/item/card/id/voter_card = user.get_idcard() + if(id_auth) + if(!voter_card) + to_chat(user,"[src] requires a valid id card to vote!") + return + if(voted && (voter_card in voted)) + to_chat(user,"[src] allows only one vote per person.") + return + if(user.transferItemToLoc(I,src)) + if(!voted) + voted = list() + voted += voter_card + to_chat(user,"You cast your vote.") + +/obj/structure/votebox/proc/shred(mob/user) + for(var/obj/item/paper/P in contents) + qdel(P) + to_chat(user,"You shred the current votes.") + +/obj/structure/votebox/wrench_act(mob/living/user, obj/item/I) + . = ..() + default_unfasten_wrench(user, I, 40) + return TRUE + +/obj/structure/votebox/crowbar_act(mob/living/user, obj/item/I) + . = ..() + if(voting_active) + to_chat(user,"You can only retrieve votes if maintenance mode is active.") + return FALSE + dump_contents() + to_chat(user,"You open vote retrieval hatch and dump all the votes.") + return TRUE + +/obj/structure/votebox/dump_contents() + var/atom/droppoint = drop_location() + for(var/atom/movable/AM in contents) + AM.forceMove(droppoint) + +/obj/structure/votebox/deconstruct(disassembled) + dump_contents() + . = ..() + +/obj/structure/votebox/proc/raffle(mob/user) + var/list/options = list() + for(var/obj/item/paper/P in contents) + options += P + if(!length(options)) + to_chat(user,"[src] pops out random vote.") + +/obj/structure/votebox/proc/print_tally(mob/user) + var/list/results = list() + for(var/obj/item/paper/P in contents) + var/text = P.info + if(!results[text]) + results[text] = 1 + else + results[text] += 1 + sortTim(results, cmp=/proc/cmp_numeric_dsc, associative = TRUE) + + var/obj/item/paper/P = new(drop_location()) + var/list/tally = list() + tally += "

Voting Results:


    " + for(var/option in results) + tally += "
  1. \"
    [option]
    \" - [results[option]] Vote[results[option] > 1 ? "s" : ""].
  2. " + tally += "
" + P.extra_headers = {" + + "} + P.info = tally.Join() + P.name = "Voting Results" + P.update_icon() + user.put_in_hands(P) + to_chat(user,"[src] prints out the voting tally") + +/obj/structure/votebox/update_icon() + . = ..() + icon_state = "votebox_[voting_active ? "active" : "maint"]" \ No newline at end of file diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 8394c8ea91b..279e8c46e56 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -22,6 +22,9 @@ max_integrity = 50 dog_fashion = /datum/dog_fashion/head + + var/extra_headers //For additional styling or other js features. + var/info //What's actually written on the paper. var/info_links //A different version of the paper which includes html links at fields and EOF var/stamps //The (text for the) stamps on the paper. @@ -69,10 +72,10 @@ if(in_range(user, src) || isobserver(user)) if(user.is_literate()) - user << browse("[name][info]
[stamps]", "window=[name]") + user << browse("[name][extra_headers][info]
[stamps]", "window=[name]") onclose(user, "[name]") else - user << browse("[name][stars(info)]
[stamps]", "window=[name]") + user << browse("[name][extra_headers][stars(info)]
[stamps]", "window=[name]") onclose(user, "[name]") else . += "You're too far away to read it!" diff --git a/icons/obj/votebox.dmi b/icons/obj/votebox.dmi new file mode 100644 index 00000000000..7bc1342c836 Binary files /dev/null and b/icons/obj/votebox.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 08b45d8d65a..ebf27384806 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1080,6 +1080,7 @@ #include "code\game\objects\structures\tank_dispenser.dm" #include "code\game\objects\structures\target_stake.dm" #include "code\game\objects\structures\traps.dm" +#include "code\game\objects\structures\votingbox.dm" #include "code\game\objects\structures\watercloset.dm" #include "code\game\objects\structures\windoor_assembly.dm" #include "code\game\objects\structures\window.dm"