New Librarian traitor item: Haunted Magic Eightball (#24607)

* New Chaplain traitor item: Haunted Magic Eightball

🆑 coiax
add: Toy magic eightballs can now be found around the station in
maintenance and arcade machines. Ask your question aloud, and then
shake for guidance.
add: Adds new Chaplain traitor item, the Haunted Magic Eightball.
Although identical in appearence to the harmless toys, this occult
device reaches into the spirit world to find its answers. Be warned,
that spirits are often capricious or just little assholes.
/🆑

* Compiles, fixes the bugs

* Adds toy eightballs to loot, toys; adds haunted to uplink

* Every 3 minutes

* Noiseless, random haunt, limited stock

* Added sprites for eightball

* Removed notice to replace sprites

* Librarian only
This commit is contained in:
coiax
2017-03-07 23:14:44 +00:00
committed by oranges
parent f176e98fe6
commit 2d288690e1
10 changed files with 251 additions and 9 deletions

View File

@@ -40,7 +40,8 @@
/obj/item/stack/tile/fakepit/loaded = 2,
/obj/item/toy/toy_xeno = 2,
/obj/item/weapon/storage/box/actionfigure = 1,
/obj/item/weapon/restraints/handcuffs/fake = 2)
/obj/item/weapon/restraints/handcuffs/fake = 2,
/obj/item/toy/eightball = 2)
light_color = LIGHT_COLOR_GREEN

View File

@@ -158,6 +158,7 @@
/obj/item/clothing/shoes/laceup = 1,
/obj/item/weapon/storage/secure/briefcase = 3,
/obj/item/weapon/storage/toolbox/artistic = 2,
/obj/item/toy/eightball = 1,
"" = 3
)

View File

@@ -0,0 +1,200 @@
/obj/item/toy/eightball
name = "magic eightball"
desc = "A black ball with a stenciled number eight in white on the side. It seems full of dark liquid.\nThe instructions state that you should ask your question aloud, and then shake."
icon = 'icons/obj/toy.dmi'
icon_state = "eightball"
verb_say = "rattles"
var/shaking = FALSE
var/on_cooldown = FALSE
var/shake_time = 150
var/cooldown_time = 1800
var/static/list/possible_answers = list(
"It is certain",
"It is decidedly so",
"Without a doubt",
"Yes definitely",
"You may rely on it",
"As I see it, yes",
"Most likely",
"Outlook good",
"Yes",
"Signs point to yes",
"Reply hazy try again",
"Ask again later",
"Better not tell you now",
"Cannot predict now",
"Concentrate and ask again",
"Don't count on it",
"My reply is no",
"My sources say no",
"Outlook not so good",
"Very doubtful")
/obj/item/toy/eightball/Initialize(mapload)
..()
if(prob(1))
new /obj/item/toy/eightball/haunted(get_turf(src))
qdel(src)
/obj/item/toy/eightball/attack_self(mob/user)
if(shaking)
return
if(on_cooldown)
user << "<span class='warning'>[src] was shaken recently, it needs time to settle.</span>"
return
user.visible_message("<span class='notice'>[user] starts shaking [src].</span>", "<span class='notice'>You start shaking [src].</span>", "<span class='italics'>You hear shaking and sloshing.</span>")
shaking = TRUE
start_shaking(user)
if(do_after(user, shake_time, needhand=TRUE, target=src, progress=TRUE))
var/answer = get_answer()
say(answer)
on_cooldown = TRUE
addtimer(CALLBACK(src, .proc/clear_cooldown), cooldown_time)
shaking = FALSE
/obj/item/toy/eightball/proc/start_shaking(user)
return
/obj/item/toy/eightball/proc/get_answer()
return pick(possible_answers)
/obj/item/toy/eightball/proc/clear_cooldown()
on_cooldown = FALSE
// A broken magic eightball, it only says "YOU SUCK" over and over again.
/obj/item/toy/eightball/broken
name = "broken magic eightball"
desc = "A black ball with a stenciled number eight in white on the side. It is cracked and seems empty."
var/fixed_answer
/obj/item/toy/eightball/broken/Initialize(mapload)
..()
fixed_answer = pick(possible_answers)
/obj/item/toy/eightball/broken/get_answer()
return fixed_answer
// Haunted eightball is identical in description and function to toy,
// except it actually ASKS THE DEAD (wooooo)
/obj/item/toy/eightball/haunted
flags = HEAR
var/last_message
var/selected_message
var/list/votes
/obj/item/toy/eightball/haunted/Initialize(mapload)
..()
votes = list()
poi_list |= src
/obj/item/toy/eightball/haunted/Destroy()
poi_list -= src
. = ..()
/obj/item/toy/eightball/haunted/attack_ghost(mob/user)
if(!shaking)
user << "<span class='warning'>[src] is not currently being shaken.</span>"
return
interact(user)
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
last_message = raw_message
/obj/item/toy/eightball/haunted/start_shaking(mob/user)
// notify ghosts that someone's shaking a haunted eightball
// and inform them of the message, (hopefully a yes/no question)
selected_message = last_message
notify_ghosts("[user] is shaking [src], hoping to get an answer to \"[selected_message]\"", source=src, enter_link="<a href=?src=\ref[src];interact=1>(Click to help)</a>", action=NOTIFY_ATTACK)
/obj/item/toy/eightball/haunted/Topic(href, href_list)
if(href_list["interact"])
if(isobserver(usr))
interact(usr)
/obj/item/toy/eightball/haunted/proc/get_vote_tallies()
var/list/answers = list()
for(var/ckey in votes)
var/selected = votes[ckey]
if(selected in answers)
answers[selected]++
else
answers[selected] = 1
return answers
/obj/item/toy/eightball/haunted/get_answer()
if(!votes.len)
return pick(possible_answers)
var/list/tallied_votes = get_vote_tallies()
// I miss python sorting, then I wouldn't have to muck about with
// all this
var/most_popular_answer
var/most_amount = 0
// yes, if there is a tie, there is an arbitary decision
// but we never said the spirit world was fair
for(var/A in tallied_votes)
var/amount = tallied_votes[A]
if(amount > most_amount)
most_popular_answer = A
return most_popular_answer
/obj/item/toy/eightball/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state=observer_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "eightball", name, 400, 600, master_ui, state)
ui.open()
/obj/item/toy/eightball/haunted/ui_data(mob/user)
var/list/data = list()
data["shaking"] = shaking
data["question"] = selected_message
var/list/tallied_votes = get_vote_tallies()
data["answers"] = list()
for(var/pa in possible_answers)
var/list/L = list()
L["answer"] = pa
var/amount = 0
if(pa in tallied_votes)
amount = tallied_votes[pa]
L["amount"] = amount
var/selected = FALSE
if(votes[user.ckey] == pa)
selected = TRUE
L["selected"] = selected
data["answers"] += list(L)
return data
/obj/item/toy/eightball/haunted/ui_act(action, params)
if(..())
return
var/mob/user = usr
switch(action)
if("vote")
var/selected_answer = params["answer"]
if(!selected_answer in possible_answers)
return
else
votes[user.ckey] = selected_answer
. = TRUE

View File

@@ -1577,6 +1577,7 @@
/datum/supply_pack/misc/randomised/toys
name = "Toy Crate"
cost = 5000 // or play the arcade machines ya lazy bum
// TODO make this actually just use the arcade machine loot list
num_contained = 5
contains = list(/obj/item/toy/spinningtoy,
/obj/item/toy/sword,
@@ -1591,7 +1592,8 @@
/obj/item/weapon/coin/antagtoken,
/obj/item/stack/tile/fakespace/loaded,
/obj/item/weapon/gun/ballistic/shotgun/toy/crossbow,
/obj/item/toy/redbutton)
/obj/item/toy/redbutton,
/obj/item/toy/eightball)
crate_name = "toy crate"
/datum/supply_pack/misc/autodrobe

View File

@@ -0,0 +1,13 @@
/**
* tgui state: observer_state
*
* Checks that the user is an observer/ghost.
**/
/var/global/datum/ui_state/observer_state/observer_state = new()
/datum/ui_state/observer_state/can_use_topic(src_object, mob/user)
if(isobserver(user))
return UI_INTERACTIVE
return UI_CLOSE

View File

@@ -1216,6 +1216,7 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
cost = 20
restricted_roles = list("Chaplain")
surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
/datum/uplink_item/role_restricted/ancient_jumpsuit
name = "Ancient Jumpsuit"
desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
@@ -1224,6 +1225,14 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
surplus = 0
restricted_roles = list("Assistant")
/datum/uplink_item/role_restricted/haunted_magic_eightball
name = "Haunted Magic Eightball"
desc = "Most magic eightballs are toys with dice inside. Although identical in appearance to the harmless toys, this occult device reaches into the spirit world to find its answers. Be warned, that spirits are often capricious or just little assholes. To use, simply speak your question aloud, then begin shaking."
item = /obj/item/toy/eightball/haunted
cost = 2
restricted_roles = list("Librarian")
limited_stock = 1 // please don't spam deadchat
// Pointless
/datum/uplink_item/badass
category = "(Pointless) Badassery"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -683,6 +683,7 @@
#include "code\game\objects\items\crayons.dm"
#include "code\game\objects\items\dehy_carp.dm"
#include "code\game\objects\items\documents.dm"
#include "code\game\objects\items\eightball.dm"
#include "code\game\objects\items\latexballoon.dm"
#include "code\game\objects\items\nuke_tools.dm"
#include "code\game\objects\items\religion.dm"
@@ -2034,6 +2035,7 @@
#include "code\modules\tgui\states\inventory.dm"
#include "code\modules\tgui\states\not_incapacitated.dm"
#include "code\modules\tgui\states\notcontained.dm"
#include "code\modules\tgui\states\observer.dm"
#include "code\modules\tgui\states\physical.dm"
#include "code\modules\tgui\states\self.dm"
#include "code\modules\tgui\states\zlevel.dm"

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
{{#if data.shaking}}
<ui-display title={{data.question}}>
<ui-section>
{{#each data.answers}}
<ui-button
action='vote' params='{"answer": "{{answer}}"}'
style='{{selected ? "selected" : null}}' >{{answer}} ({{amount}})
</ui-button>
{{/each}}
</ui-section>
</ui-display>
{{else}}
<ui-notice>The eightball is not currently being shaken.</ui-notice>
{{/if}}