Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ports the new ritual from TG and fixes chuunibyou casting #224

Merged
2 changes: 2 additions & 0 deletions code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_HOLY "holy"
/// This allows a person who has antimagic to cast spells without getting blocked
#define TRAIT_ANTIMAGIC_NO_SELFBLOCK "anti_magic_no_selfblock"
/// 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"
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/granters/magic/_spell_granter.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/weaponry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,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 ..()
7 changes: 4 additions & 3 deletions code/modules/antagonists/_common/antag_helpers.dm
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
8 changes: 8 additions & 0 deletions code/modules/antagonists/survivalist/survivalist.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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..()
7 changes: 5 additions & 2 deletions code/modules/antagonists/wizard/equipment/chuunibyou_spell.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
if(ishuman(cast_on))
var/mob/living/carbon/human/human_cast_on = cast_on
human_cast_on.dropItemToGround(human_cast_on.glasses)
var/obj/item/clothing/head/wizard/wizhat = human_cast_on.head
//monkestation removal start
/* var/obj/item/clothing/head/wizard/wizhat = human_cast_on.head
if(istype(wizhat))
to_chat(human_cast_on, span_notice("Your [wizhat] transforms into an eyepatch."))
qdel(wizhat)
else
to_chat(human_cast_on, span_notice("An eyepatch pops into existence over one of your eyes."))
to_chat(human_cast_on, span_notice("An eyepatch pops into existence over one of your eyes.")) */
//monkestation removal end
to_chat(human_cast_on, span_notice("An eyepatch pops into existence over one of your eyes.")) //monkestation edit: makes it not remove your wizard hat
human_cast_on.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch/medical/chuuni(human_cast_on), ITEM_SLOT_EYES)

qdel(src)
4 changes: 2 additions & 2 deletions code/modules/antagonists/wizard/equipment/soulstone.dm
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,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
Expand All @@ -276,7 +276,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,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
Expand All @@ -96,20 +96,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]))
Expand Down Expand Up @@ -196,12 +199,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.
Expand All @@ -216,10 +220,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)
return TRUE

/// Non-purchasable flavor spells to populate the spell book with, for style.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() //im pretty sure this makes these not show up, kinda removing the point of them
return FALSE
Original file line number Diff line number Diff line change
Expand Up @@ -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 ..()
Expand All @@ -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 ..()
Expand All @@ -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 ..()
Expand All @@ -67,7 +67,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)
var/turf/user_turf = get_turf(user) //monkestation edit: you need to be on station to cast summon events to make sure you will also feel the effects
if(user_turf && !is_station_level(user_turf.z)) //monkestation edit
to_chat(user, span_warning("You need to be on the station!")) //monkestation edit
Expand All @@ -81,12 +81,71 @@
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()
if(get_active_player_count() < MINIMUM_POP_FOR_RITUALS)
return FALSE
// Also, must be config enabled
return !CONFIG_GET(flag/no_summon_events)

#undef MINIMUM_POP_FOR_RITUALS
7 changes: 7 additions & 0 deletions code/modules/antagonists/wizard/wizard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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()
Expand All @@ -83,6 +88,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/create_team(datum/team/wizard/new_team)
if(!new_team)
Expand Down Expand Up @@ -172,6 +178,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()
Expand Down
2 changes: 0 additions & 2 deletions code/modules/mob/dead/new_player/new_player.dm
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,6 @@

log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)

SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CREWMEMBER_JOINED, character, rank)

if(humanc)
for(var/datum/loadout_item/item as anything in loadout_list_to_datums(humanc?.client?.prefs?.loadout_list))
if (item.restricted_roles && length(item.restricted_roles) && !(job.title in item.restricted_roles))
Expand Down
7 changes: 2 additions & 5 deletions code/modules/projectiles/guns/magic/staff.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -87,7 +84,7 @@
if(!is_wizard_or_friend(user))
to_chat(user, span_hypnophrase("<span style='font-size: 24px'>The staff feels weaker as you touch it</span>"))
user.balloon_alert(user, "the staff feels weaker as you touch it")

/obj/item/gun/magic/staff/healing/examine(mob/user)
. = ..()
if(!is_wizard_or_friend(user))
Expand Down
2 changes: 1 addition & 1 deletion code/modules/spells/spell.dm
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
if(feedback)
to_chat(owner, span_warning("You don't feel strong enough without your robe!"))
return FALSE
if(!(human_owner.head?.clothing_flags & CASTING_CLOTHES) || (human_owner.glasses?.clothing_flags & CASTING_CLOTHES))
if(!(human_owner.head?.clothing_flags & CASTING_CLOTHES) && !(human_owner.glasses?.clothing_flags & CASTING_CLOTHES))
if(feedback)
to_chat(owner, span_warning("You don't feel strong enough without your hat!"))
return FALSE
Expand Down
Loading
Loading