[MIRROR] Adds a wizard Right and Wrong that lets the caster give one spell (or relic) to everyone on the station [MDB IGNORE] (#22637)

* Adds a wizard Right and Wrong that lets the caster give one spell (or relic) to everyone on the station (#76974)

## About The Pull Request

This PR adds a new wizard ritual (the kind that require 100 threat on
dynamic)

This ritual allows the wizard to select one spellbook entry (item or
spell), to which everyone on the station will be given or taught said
spell or item. If the spell requires a robe, the spell becomes robeless,
and if the item requires wizard to use, it makes it usable. Mostly.

- Want an epic sword fight? Give everyone a high-frequency blade

- One mindswap not enough shenanigans for you? Give out mindswap

- Fourth of July? Fireball would be pretty hilarious...

The wizard ritual costs 3 points plus the cost of whatever entry you are
giving out. So giving everyone fireball is 5 points.

It can only be cast once by a wizard, because I didn't want to go
through the effort to allow multiple in existence

## Why It's Good For The Game

Someone gave me the idea and I thought it sounded pretty funny as an
alternative to Summon Magic

Maybe I make this a Grand Finale ritual instead / in tandem? That's also
an idea.

## Changelog

🆑 Melbert
add: Wizards have a new Right and Wrong: Mass Teaching, allowing them to
grant everyone on the station one spell or relic of their choice!
/🆑

* Adds a wizard Right and Wrong that lets the caster give one spell (or relic) to everyone on the station

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-07-22 22:47:17 -04:00
committed by GitHub
co-authored by MrMelbert
parent ff2cdfd563
commit dcd2d0e418
13 changed files with 221 additions and 71 deletions
+2
View File
@@ -303,6 +303,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_ANTIMAGIC_NO_SELFBLOCK "anti_magic_no_selfblock"
/// This mob recently blocked magic with some form of antimagic
#define TRAIT_RECENTLY_BLOCKED_MAGIC "recently_blocked_magic"
/// The user can do things like use magic staffs without penalty
#define TRAIT_MAGICALLY_GIFTED "magically_gifted"
#define TRAIT_DEPRESSION "depression"
#define TRAIT_BLOOD_DEFICIENCY "blood_deficiency"
#define TRAIT_JOLLY "jolly"
@@ -33,7 +33,7 @@
if(!granted_action)
CRASH("Someone attempted to learn [type], which did not have an spell set.")
if(locate(granted_action) in user.actions)
if(IS_WIZARD(user))
if(HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED))
to_chat(user, span_warning("You're already far more versed in the spell [action_name] \
than this flimsy how-to book can provide!"))
else
+1 -1
View File
@@ -1107,7 +1107,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
bare_wound_bonus = 25
/obj/item/highfrequencyblade/wizard/attack_self(mob/user, modifiers)
if(!IS_WIZARD(user))
if(!HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED))
balloon_alert(user, "you're too weak!")
return
return ..()
@@ -1,12 +1,13 @@
//Returns MINDS of the assigned antags of given type/subtypes
/proc/get_antag_minds(antag_type,specific = FALSE)
/// Returns MINDS of the assigned antags of given type/subtypes
/// Supplying no antag type grants all minds with antag datums
/proc/get_antag_minds(antag_type, specific = FALSE)
RETURN_TYPE(/list/datum/mind)
. = list()
for(var/datum/antagonist/A in GLOB.antagonists)
if(!A.owner)
continue
if(!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type)
. += A.owner
. |= A.owner
/// From a list of players (minds, mobs or clients), finds the one with the highest playtime (either from a specific role or overall living) and returns it.
/proc/get_most_experienced(list/players, specific_role)
@@ -42,3 +42,11 @@
magic.owner = owner
objectives += magic
..()
/datum/antagonist/survivalist/magic/on_gain()
. = ..()
ADD_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
/datum/antagonist/survivalist/magic/on_removal()
REMOVE_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
return..()
@@ -271,7 +271,7 @@
/obj/structure/constructshell/examine(mob/user)
. = ..()
if(IS_CULTIST(user) || IS_WIZARD(user) || user.stat == DEAD)
if(IS_CULTIST(user) || HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED) || user.stat == DEAD)
. += {"<span class='cult'>A construct shell, used to house bound souls from a soulstone.\n
Placing a soulstone with a soul into this shell allows you to produce your choice of the following:\n
An <b>Artificer</b>, which can produce <b>more shells and soulstones</b>, as well as fortifications.\n
@@ -281,7 +281,7 @@
/obj/structure/constructshell/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/soulstone))
var/obj/item/soulstone/SS = O
if(!IS_CULTIST(user) && !IS_WIZARD(user) && !SS.theme == THEME_HOLY)
if(!IS_CULTIST(user) && !HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED) && !SS.theme == THEME_HOLY)
to_chat(user, span_danger("An overwhelming feeling of dread comes over you as you attempt to place [SS] into the shell. It would be wise to be rid of this quickly."))
if(isliving(user))
var/mob/living/living_user = user
@@ -79,9 +79,9 @@
* * user - the mob who's bought the spell
* * book - what book they've bought the spell from
*
* Return TRUE if the purchase was successful, FALSE otherwise
* Return truthy if the purchase was successful, FALSE otherwise
*/
/datum/spellbook_entry/proc/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
/datum/spellbook_entry/proc/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
var/datum/action/cooldown/spell/existing = locate(spell_type) in user.actions
if(existing)
var/before_name = existing.name
@@ -94,20 +94,23 @@
//we'll need to update the cooldowns for the spellbook
set_spell_info()
log_spellbook("[key_name(user)] improved their knowledge of [initial(existing.name)] to level [existing.spell_level] for [cost] points")
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[existing.spell_level]"))
log_purchase(user.key)
return TRUE
if(log_buy)
log_spellbook("[key_name(user)] improved their knowledge of [initial(existing.name)] to level [existing.spell_level] for [cost] points")
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[existing.spell_level]"))
log_purchase(user.key)
return existing
//No same spell found - just learn it
var/datum/action/cooldown/spell/new_spell = new spell_type(user.mind || user)
new_spell.Grant(user)
to_chat(user, span_notice("You have learned [new_spell.name]."))
log_spellbook("[key_name(user)] learned [new_spell] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
log_purchase(user.key)
return TRUE
if(log_buy)
log_spellbook("[key_name(user)] learned [new_spell] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
log_purchase(user.key)
return new_spell
/datum/spellbook_entry/proc/log_purchase(key)
if(!islist(GLOB.wizard_spellbook_purchases_by_key[key]))
@@ -194,12 +197,13 @@
/// Typepath of what item we create when purchased
var/obj/item/item_path
/datum/spellbook_entry/item/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
var/atom/spawned_path = new item_path(get_turf(user))
log_spellbook("[key_name(user)] bought [src] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
/datum/spellbook_entry/item/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
var/atom/spawned_path = new item_path(user.loc)
if(log_buy)
log_spellbook("[key_name(user)] bought [src] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
log_purchase(user.key)
try_equip_item(user, spawned_path)
log_purchase(user.key)
return spawned_path
/// Attempts to give the item to the buyer on purchase.
@@ -214,10 +218,11 @@
refundable = FALSE
buy_word = "Cast"
/datum/spellbook_entry/summon/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
log_spellbook("[key_name(user)] cast [src] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
log_purchase(user.key)
/datum/spellbook_entry/summon/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
if(log_buy)
log_spellbook("[key_name(user)] cast [src] for [cost] points")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
log_purchase(user.key)
book.update_static_data(user) // updates "times" var
return TRUE
@@ -44,7 +44,7 @@
var/was_equipped = user.equip_to_slot_if_possible(to_equip, ITEM_SLOT_BELT, disable_warning = TRUE)
to_chat(user, span_notice("\A [to_equip.name] has been summoned [was_equipped ? "on your waist" : "at your feet"]."))
/datum/spellbook_entry/item/soulstones/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
/datum/spellbook_entry/item/soulstones/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
. =..()
if(!.)
return
@@ -8,3 +8,6 @@
/datum/spellbook_entry/challenge/antiwizard
name = "Friendly Wizard Scum"
desc = "A \"Friendly\" Wizard will protect the station, and try to kill you. They get a spellbook much like you, but will use it for \"GOOD\"."
/datum/spellbook_entry/challenge/can_be_purchased()
return FALSE
@@ -9,7 +9,7 @@
and some will use their incredibly minor abilities to frustrate you."
cost = 0
/datum/spellbook_entry/summon/ghosts/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
/datum/spellbook_entry/summon/ghosts/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
summon_ghosts(user)
playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, TRUE)
return ..()
@@ -27,7 +27,7 @@
// Also must be config enabled
return !CONFIG_GET(flag/no_summon_guns)
/datum/spellbook_entry/summon/guns/buy_spell(mob/living/carbon/human/user,obj/item/spellbook/book)
/datum/spellbook_entry/summon/guns/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
summon_guns(user, 10)
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
return ..()
@@ -45,7 +45,7 @@
// Also must be config enabled
return !CONFIG_GET(flag/no_summon_magic)
/datum/spellbook_entry/summon/magic/buy_spell(mob/living/carbon/human/user,obj/item/spellbook/book)
/datum/spellbook_entry/summon/magic/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
summon_magic(user, 10)
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
return ..()
@@ -66,7 +66,7 @@
// Also, must be config enabled
return !CONFIG_GET(flag/no_summon_events)
/datum/spellbook_entry/summon/events/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
/datum/spellbook_entry/summon/events/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
summon_events(user)
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE)
return ..()
@@ -76,12 +76,73 @@
desc = "Curses the station, warping the minds of everyone inside, causing lasting traumas. Warning: this spell can affect you if not cast from a safe distance."
cost = 4
/datum/spellbook_entry/summon/curse_of_madness/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book)
/datum/spellbook_entry/summon/curse_of_madness/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
var/message = tgui_input_text(user, "Whisper a secret truth to drive your victims to madness", "Whispers of Madness")
if(!message)
if(!message || QDELETED(user) || QDELETED(book) || !can_buy(user, book))
return FALSE
curse_of_madness(user, message)
playsound(user, 'sound/magic/mandswap.ogg', 50, TRUE)
return ..()
/// A wizard ritual that allows the wizard to teach a specific spellbook enty to everyone on the station.
/// This includes item entries (which will be given to everyone) but disincludes other rituals like itself
/datum/spellbook_entry/summon/specific_spell
name = "Mass Wizard Teaching"
desc = "Teach a specific spell (or give a specific item) to everyone on the station. \
The cost of this is increased by the cost of the spell you choose. And don't worry - you, too, will learn the spell!"
cost = 3 // cheapest is 4 cost, most expensive is 7 cost
limit = 1
/datum/spellbook_entry/summon/specific_spell/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE)
var/list/spell_options = list()
for(var/datum/spellbook_entry/entry as anything in book.entries)
if(istype(entry, /datum/spellbook_entry/summon))
continue
if(!entry.can_be_purchased())
continue
spell_options[entry.name] = entry
sortTim(spell_options, GLOBAL_PROC_REF(cmp_text_asc))
var/chosen_spell_name = tgui_input_list(user, "Choose a spell (or item) to grant to everyone...", "Wizardly Teaching", spell_options)
if(isnull(chosen_spell_name) || QDELETED(user) || QDELETED(book))
return FALSE
if(GLOB.mass_teaching)
tgui_alert(user, "Someone's already cast [name]!", "Wizardly Teaching", list("Shame"))
return FALSE
var/datum/spellbook_entry/chosen_entry = spell_options[chosen_spell_name]
if(cost + chosen_entry.cost > book.uses)
tgui_alert(user, "You can't afford to grant everyone [chosen_spell_name]! ([cost] points needed)", "Wizardly Teaching", list("Shame"))
return FALSE
cost += chosen_entry.cost
if(!can_buy(user, book))
cost = initial(cost)
return FALSE
GLOB.mass_teaching = new(chosen_entry.type)
GLOB.mass_teaching.equip_all_affected()
var/item_entry = istype(chosen_entry, /datum/spellbook_entry/item)
to_chat(user, span_hypnophrase("You have [item_entry ? "granted everyone the power" : "taught everyone the ways"] of [chosen_spell_name]!"))
message_admins("[ADMIN_LOOKUPFLW(user)] gave everyone the [item_entry ? "item" : "spell"] \"[chosen_spell_name]\"!")
user.log_message("has gave everyone the [item_entry ? "item" : "spell"] \"[chosen_spell_name]\"!", LOG_GAME)
name = "[name]: [chosen_spell_name]"
return ..()
/datum/spellbook_entry/summon/specific_spell/can_buy(mob/living/carbon/human/user, obj/item/spellbook/book)
if(GLOB.mass_teaching)
return FALSE
return ..()
/datum/spellbook_entry/summon/specific_spell/can_be_purchased()
var/datum/game_mode/dynamic/mode = SSticker.mode
if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS)
return FALSE
if(GLOB.mass_teaching)
return FALSE
return ..()
#undef MINIMUM_THREAT_FOR_RITUALS
@@ -55,6 +55,11 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
/datum/antagonist/wizard_minion/on_gain()
create_objectives()
. = ..()
ADD_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
/datum/antagonist/wizard_minion/on_removal()
REMOVE_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
return ..()
/datum/antagonist/wizard_minion/proc/create_objectives()
@@ -81,6 +86,7 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
. = ..()
if(allow_rename)
rename_wizard()
ADD_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
/datum/antagonist/wizard/Destroy()
QDEL_NULL(ritual)
@@ -174,6 +180,7 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
qdel(spell)
owner.current.actions -= spell
REMOVE_TRAIT(owner, TRAIT_MAGICALLY_GIFTED, REF(src))
return ..()
/datum/antagonist/wizard/proc/equip_wizard()
+1 -4
View File
@@ -11,10 +11,7 @@
var/allow_intruder_use = FALSE
/obj/item/gun/magic/staff/proc/is_wizard_or_friend(mob/user)
if(!user?.mind?.has_antag_datum(/datum/antagonist/wizard) \
&& !user.mind.has_antag_datum(/datum/antagonist/survivalist/magic) \
&& !user.mind.has_antag_datum(/datum/antagonist/wizard_minion) \
&& !allow_intruder_use)
if(!HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED) && !allow_intruder_use)
return FALSE
return TRUE
@@ -1,8 +1,12 @@
//In this file: Summon Magic/Summon Guns/Summon Events
//and corresponding datum controller for them
GLOBAL_DATUM(summon_guns, /datum/summon_things_controller)
GLOBAL_DATUM(summon_magic, /datum/summon_things_controller)
/// A global singleton datum used to store a "summon things controller" for Summon Guns, to grant random guns to stationgoers and latejoiners
GLOBAL_DATUM(summon_guns, /datum/summon_things_controller/item)
/// A global singleton datum used to store a "summon things controller" for Summon Magic, to grant random magical items to stationgoers and latejoiners
GLOBAL_DATUM(summon_magic, /datum/summon_things_controller/item)
/// A global singleton datum used to store a "summon things controller" for Mass Teaching, to grant a specific spellbook entry to stationgoers and latejoiners
GLOBAL_DATUM(mass_teaching, /datum/summon_things_controller/spellbook_entry)
// 1 in 50 chance of getting something really special.
#define SPECIALIST_MAGIC_PROB 2
@@ -136,7 +140,7 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
CRASH("give_magic() was called without a summon magic global datum!")
if(to_equip.stat == DEAD || !to_equip.client || !to_equip.mind)
return
if(IS_WIZARD(to_equip) || to_equip.mind.has_antag_datum(/datum/antagonist/survivalist/guns))
if(IS_WIZARD(to_equip) || to_equip.mind.has_antag_datum(/datum/antagonist/survivalist/magic))
return
if(!length(to_equip.mind.antag_datums) && prob(GLOB.summon_magic.survivor_probability))
@@ -154,7 +158,7 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
if(magic_type in GLOB.summoned_special_magic)
to_chat(to_equip, span_notice("You feel incredibly lucky."))
/*
/**
* Triggers Summon Ghosts from [user].
*/
/proc/summon_ghosts(mob/user)
@@ -174,7 +178,7 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
if(user)
to_chat(user, span_warning("You... try to summon ghosts, but nothing seems to happen. Shame."))
/*
/**
* Triggers Summon Magic from [user].
* Can optionally be passed [survivor_probability], to set the chance of creating survivalists.
* If Summon Magic has already been triggered, gives out magic to everyone again.
@@ -191,10 +195,10 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
if(GLOB.summon_magic)
GLOB.summon_magic.survivor_probability = survivor_probability
else
GLOB.summon_magic = new /datum/summon_things_controller(/proc/give_magic, survivor_probability)
GLOB.summon_magic.give_out_gear()
GLOB.summon_magic = new /datum/summon_things_controller(survivor_probability, GLOBAL_PROC_REF(give_magic))
GLOB.summon_magic.equip_all_affected()
/*
/**
* Triggers Summon Guns from [user].
* Can optionally be passed [survivor_probability], to set the chance of creating survivalists.
* If Summon Guns has already been triggered, gives out guns to everyone again.
@@ -211,10 +215,10 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
if(GLOB.summon_guns)
GLOB.summon_guns.survivor_probability = survivor_probability
else
GLOB.summon_guns = new /datum/summon_things_controller(/proc/give_guns, survivor_probability)
GLOB.summon_guns.give_out_gear()
GLOB.summon_guns = new /datum/summon_things_controller(survivor_probability, GLOBAL_PROC_REF(give_guns))
GLOB.summon_guns.equip_all_affected()
/*
/**
* Triggers Summon Events from [user].
* If Summon Events has already been triggered, speeds up the event timer.
*/
@@ -258,12 +262,56 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
/datum/summon_things_controller
/// Prob. chance someone who is given things will be made a survivalist antagonist.
var/survivor_probability = 0
/datum/summon_things_controller/New()
RegisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED, PROC_REF(on_latejoin))
/datum/summon_things_controller/Destroy(force, ...)
. = ..()
UnregisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED)
/// Determins if the mob is valid to be given whatever we're handing out.
/datum/summon_things_controller/proc/can_give_to(mob/who)
return ishuman(who)
/// Returns a list of minds of all mobs affected by what we're giving out.
/datum/summon_things_controller/proc/get_affected_minds()
RETURN_TYPE(/list/datum/mind)
var/list/affected = list()
for(var/datum/mind/maybe_affected as anything in get_crewmember_minds() | get_antag_minds())
if(!can_give_to(maybe_affected.current))
continue
var/turf/affected_turf = get_turf(maybe_affected.current)
if(!is_station_level(affected_turf?.z) && !is_mining_level(affected_turf?.z))
continue
affected += maybe_affected
return affected
/// Signal proc from [COMSIG_GLOB_CREWMEMBER_JOINED].
/// Calls give_proc_path on latejoiners a number of times (based on num_to_give_to_latejoiners)
/datum/summon_things_controller/proc/on_latejoin(datum/source, mob/living/new_crewmember, rank)
SIGNAL_HANDLER
if(!can_give_to(new_crewmember))
return
equip_latejoiner(new_crewmember)
/// Called manually to give out our things to all minds returned by [proc/get_affected_minds()]
/datum/summon_things_controller/proc/equip_all_affected()
CRASH("[type] did not implement equip_all_affected()!")
/// Called via signal to equip latejoin crewmembers
/datum/summon_things_controller/proc/equip_latejoiner(mob/living/carbon/human/new_crewmember)
CRASH("[type] did not implement equip_latejoiner()!")
/datum/summon_things_controller/item
/// The proc path we call on someone to equip them with stuff. Cannot function without it.
var/give_proc_path
/// The number of equipment we give to latejoiners, to make sure they catch up if it was casted multiple times.
var/num_to_give_to_latejoiners = 0
/datum/summon_things_controller/New(give_proc_path, survivor_probability = 0)
/datum/summon_things_controller/item/New(survivor_probability = 0, give_proc_path)
. = ..()
if(isnull(give_proc_path))
CRASH("[type] was created without a give_proc_path (the proc that gives people stuff)!")
@@ -271,28 +319,46 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
src.survivor_probability = survivor_probability
src.give_proc_path = give_proc_path
RegisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED, PROC_REF(gear_up_new_crew))
/datum/summon_things_controller/Destroy(force, ...)
. = ..()
UnregisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED)
/// Calls our give_proc_path on all humans in the player list.
/datum/summon_things_controller/proc/give_out_gear()
num_to_give_to_latejoiners++
for(var/mob/living/carbon/human/to_equip in GLOB.player_list)
var/turf/turf_check = get_turf(to_equip)
if(turf_check && is_away_level(turf_check.z))
continue
INVOKE_ASYNC(GLOBAL_PROC, give_proc_path, to_equip)
/// Signal proc from [COMSIG_GLOB_CREWMEMBER_JOINED].
/// Calls give_proc_path on latejoiners a number of times (based on num_to_give_to_latejoiners)
/datum/summon_things_controller/proc/gear_up_new_crew(datum/source, mob/living/new_crewmember, rank)
SIGNAL_HANDLER
if(!ishuman(new_crewmember))
return
/datum/summon_things_controller/item/equip_all_affected()
num_to_give_to_latejoiners += 1
for(var/datum/mind/crewmember_mind as anything in get_affected_minds())
INVOKE_ASYNC(GLOBAL_PROC, give_proc_path, crewmember_mind.current)
/datum/summon_things_controller/item/equip_latejoiner(mob/living/carbon/human/new_crewmember)
for(var/i in 1 to num_to_give_to_latejoiners)
INVOKE_ASYNC(GLOBAL_PROC, give_proc_path, new_crewmember)
/datum/summon_things_controller/spellbook_entry
/// Spellbook entry instance to hand out
var/datum/spellbook_entry/used_entry
/datum/summon_things_controller/spellbook_entry/can_give_to(mob/who)
return istype(used_entry, /datum/spellbook_entry/item) ? ishuman(who) : isliving(who)
/datum/summon_things_controller/spellbook_entry/get_affected_minds()
// The wizards get in on this too, wherever they may be
return ..() | get_antag_minds(/datum/antagonist/wizard)
/datum/summon_things_controller/spellbook_entry/New(entry_type)
. = ..()
if(!ispath(entry_type, /datum/spellbook_entry))
CRASH("[type] was created with an invalid entry type (must be a spellbook entry typepath)!")
used_entry = new entry_type()
/datum/summon_things_controller/spellbook_entry/equip_all_affected()
for(var/datum/mind/crewmember_mind as anything in get_affected_minds())
INVOKE_ASYNC(src, PROC_REF(grant_entry), crewmember_mind.current)
/datum/summon_things_controller/spellbook_entry/equip_latejoiner(mob/living/carbon/human/new_crewmember)
grant_entry(new_crewmember)
/datum/summon_things_controller/spellbook_entry/proc/grant_entry(mob/to_who)
var/gained = used_entry.buy_spell(to_who, log_buy = FALSE)
// Make spells castable without robes
if(istype(gained, /datum/action/cooldown/spell))
var/datum/action/cooldown/spell/given_out = gained
given_out.spell_requirements &= ~SPELL_REQUIRES_WIZARD_GARB
// Makes staffs and related items usable without penalty
ADD_TRAIT(to_who.mind, TRAIT_MAGICALLY_GIFTED, INNATE_TRAIT)