Skip to content

Commit

Permalink
[MIRROR] Festival Sect Expansion: New Tunes, New Rites, Cogitandi Fid…
Browse files Browse the repository at this point in the history
…is [MDB IGNORE] (#25404)

* Festival Sect Expansion: New Tunes, New Rites, Cogitandi Fidis (#80032)

Creates a holy violin that gives an analysis of songs played on it. This
lets you check how long the song is for final effects, to make sure they
trigger without the hassle of trying a rite with a song until you get
one that works. 20 Favor, looks neat too!

Rite to empower an instrument with the ability to invoke specifically
song tuning rites, 5 charges before you need to go back to a proper
altar. Helps a chaplain stay on the move, since songs are interruptable
and sometimes an altar can be incredibly far. 10 Favor for 5 charges.

![image](https://github.com/tgstation/tgstation/assets/40974010/9dddc60a-92e3-4e42-bf7b-423e9ac25c7c)

New free invocation that lets you light up the way with your music! The
finishing effect applies a weaker glow to all listeners for a minute.

The threshold for getting a final effect on a song is now lower, 220 ->
170. As a reminder, this threshold is lines * tempo. I think the
threshold was simply too high

Changes were made from
https://tgstation13.org/phpBB/viewtopic.php?f=10&t=35381 statistics and
feedback about sects. I think, overall, Festival Sect is in a very good
place and doesn't need a whole lot but a few rites that help with a
quality of life would really cut down on the amount of time a chappy is
spending doing nothing but running allllll the way back to the chapel to
load up some new songs

:cl:
add: Festival Sect has 3 new rites: Cogitandi Fidis, Portable Song
Tuning, and Illuminating Solo.
balance: lowers threshold for triggering a final effect. Consult your
Cogitandi Fidis for more information
/:cl:

* Festival Sect Expansion: New Tunes, New Rites, Cogitandi Fidis

---------

Co-authored-by: tralezab <[email protected]>
  • Loading branch information
2 people authored and FFMirrorBot committed Dec 3, 2023
1 parent 3102af3 commit f6e4d8e
Show file tree
Hide file tree
Showing 16 changed files with 205 additions and 25 deletions.
2 changes: 1 addition & 1 deletion code/__DEFINES/dcs/signals/signals_music.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// /datum/song signals

///sent to the instrument when a song starts playing
///sent to the instrument when a song starts playing: (datum/starting_song, atom/player)
#define COMSIG_INSTRUMENT_START "instrument_start"
///sent to the instrument when a song stops playing
#define COMSIG_INSTRUMENT_END "instrument_end"
Expand Down
9 changes: 9 additions & 0 deletions code/__DEFINES/religion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
#define ALIGNMENT_NEUT "neutral"
#define ALIGNMENT_EVIL "evil"

<<<<<<< HEAD

Check failure on line 12 in code/__DEFINES/religion.dm

View workflow job for this annotation

GitHub Actions / Run Linters

got '<<', expected one of: newline, '/', identifier
=======
///how many lines multiplied by tempo should at least be higher than this. Makes people have to choose a long enough song to get the final effect.
#define FESTIVAL_SONG_LONG_ENOUGH 170

/// the probability, when not overridden by sects, for a bible's bless effect to trigger on a smack
#define DEFAULT_SMACK_CHANCE 60

>>>>>>> 4eb17420b ([MIRROR] Festival Sect Expansion: New Tunes, New Rites, Cogitandi Fidis [MDB IGNORE] (#25404))
//## which weapons should we use?

// unused but for clarity
Expand Down
50 changes: 35 additions & 15 deletions code/datums/components/religious_tool.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
*/
/datum/component/religious_tool
dupe_mode = COMPONENT_DUPE_UNIQUE
dupe_mode = COMPONENT_DUPE_HIGHLANDER
/// Enables access to the global sect directly
var/datum/religion_sect/easy_access_sect
/// Prevents double selecting sects
Expand All @@ -14,19 +14,32 @@
/// The rite currently being invoked
var/datum/religion_rites/performing_rite
///Sets the type for catalyst
var/catalyst_type = /obj/item/book/bible
var/obj/item/catalyst_type = /obj/item/book/bible
///Enables overide of COMPONENT_NO_AFTERATTACK, not recommended as it means you can potentially cause damage to the item using the catalyst.
var/force_catalyst_afterattack = FALSE
///Callback provided to the tool for after a sect is chosen
var/datum/callback/after_sect_select_cb
///Optional argument. If a positive value, each invocation will lower charges, and the component will delete without any more charges
var/charges
///If a typecache is provided, only types of rites in the cache can be invoked.
var/list/rite_types_allowlist

/datum/component/religious_tool/Initialize(_flags = ALL, _force_catalyst_afterattack = FALSE, _after_sect_select_cb, override_catalyst_type)
/datum/component/religious_tool/Initialize(
operation_flags = ALL,
force_catalyst_afterattack = FALSE,
after_sect_select_cb = null,
catalyst_type = /obj/item/book/bible,
charges = -1,
rite_types_allowlist = null,
)
. = ..()
SetGlobalToLocal() //attempt to connect on start in case one already exists!
operation_flags = _flags
force_catalyst_afterattack = _force_catalyst_afterattack
after_sect_select_cb = _after_sect_select_cb
if(override_catalyst_type)
catalyst_type = override_catalyst_type
src.operation_flags = operation_flags
src.force_catalyst_afterattack = force_catalyst_afterattack
src.after_sect_select_cb = after_sect_select_cb
src.catalyst_type = catalyst_type
src.charges = charges
src.rite_types_allowlist = rite_types_allowlist
RegisterSignal(SSdcs, COMSIG_RELIGIOUS_SECT_CHANGED, PROC_REF(SetGlobalToLocal))
RegisterSignal(SSdcs, COMSIG_RELIGIOUS_SECT_RESET, PROC_REF(on_sect_reset))

Expand Down Expand Up @@ -150,6 +163,9 @@
else
to_chat(user, "<span class='warning'>You are not holy, and therefore cannot perform rites.")
return
if(rite_types_allowlist && !is_path_in_list(path, rite_types_allowlist))
to_chat(user, span_warning("This cannot perform that kind of rite."))
return
if(performing_rite)
to_chat(user, "<span class='notice'>There is a rite currently being performed here already.")
return
Expand All @@ -159,13 +175,17 @@
performing_rite = new path(parent)
if(!performing_rite.perform_rite(user, parent))
QDEL_NULL(performing_rite)
return
performing_rite.invoke_effect(user, parent)
easy_access_sect.adjust_favor(-performing_rite.favor_cost)
if(performing_rite.auto_delete)
QDEL_NULL(performing_rite)
else
performing_rite.invoke_effect(user, parent)
easy_access_sect.adjust_favor(-performing_rite.favor_cost)
if(performing_rite.auto_delete)
QDEL_NULL(performing_rite)
else
performing_rite = null
performing_rite = null
if(charges)
charges--
if(!charges)
qdel(src)

/**
* Generates a list of available sects to the user. Intended to support custom-availability sects.
Expand Down Expand Up @@ -231,7 +251,7 @@

if(!can_i_see)
return
examine_list += span_notice("Use a bible to interact with this.")
examine_list += span_notice("Use a [catalyst_type::name] to interact with this.")
if(isnull(easy_access_sect))
if(operation_flags & RELIGION_TOOL_SECTSELECT)
examine_list += span_notice("This looks like it can be used to select a sect.")
Expand Down
9 changes: 3 additions & 6 deletions code/datums/components/smooth_tunes.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
///how many lines multiplied by tempo should at least be higher than this.
#define LONG_ENOUGH_SONG 220

///Smooth tunes component! Applied to musicians to give the songs they play special effects, according to a rite!
///Comes with BARTICLES!!!
/datum/component/smooth_tunes
Expand Down Expand Up @@ -47,7 +44,7 @@
if(istype(starting_song.parent, /obj/structure/musician))
return //TODO: make stationary instruments work with no hiccups

if(starting_song.lines.len * starting_song.tempo > LONG_ENOUGH_SONG)
if(starting_song.lines.len * starting_song.tempo > FESTIVAL_SONG_LONG_ENOUGH)
viable_for_final_effect = TRUE
else
to_chat(parent, span_warning("This song is too short, so it won't include the song finishing effect."))
Expand All @@ -56,6 +53,8 @@
if(linked_songtuner_rite.song_start_message)
starting_song.parent.visible_message(linked_songtuner_rite.song_start_message)

linked_songtuner_rite.performer_start_effect(parent, starting_song)

///prevent more songs from being blessed concurrently, mob signal
UnregisterSignal(parent, COMSIG_ATOM_STARTING_INSTRUMENT)
///and hook into the instrument this time, preventing other weird exploity stuff.
Expand Down Expand Up @@ -112,5 +111,3 @@
linked_songtuner_rite.song_effect(listener, parent)
else
stop_singing()

#undef LONG_ENOUGH_SONG
19 changes: 19 additions & 0 deletions code/datums/status_effects/song_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,22 @@

/datum/status_effect/song/antimagic/get_examine_text()
return span_notice("[owner.p_They()] seem[owner.p_s()] to be covered in a dull, grey aura.")

/datum/status_effect/song/light
id = "light_song"
status_type = STATUS_EFFECT_REFRESH
duration = 1 MINUTES
aura_desc = "bright"
/// lighting object that makes owner glow
var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj

/datum/status_effect/song/light/on_apply()
mob_light_obj = owner.mob_light(3, color = LIGHT_COLOR_DIM_YELLOW)
playsound(owner, 'sound/weapons/fwoosh.ogg', 75, FALSE)
return TRUE

/datum/status_effect/song/light/on_remove()
QDEL_NULL(mob_light_obj)

/datum/status_effect/song/light_song/get_examine_text()
return span_notice("[owner.p_They()] seem[owner.p_s()] to be covered in a glowing aura.")
15 changes: 15 additions & 0 deletions code/game/objects/effects/particles/note_particles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,18 @@
"sleepy_9" = 2, //sleepy theme specific
"sleepy_10" = 2, //sleepy theme specific
)

/particles/musical_notes/light
icon = 'icons/effects/particles/notes/note_light.dmi'
icon_state = list(
"power_1" = 1,
"power_2" = 1,
"power_3" = 1,
"power_4" = 1,
"power_5" = 1,
"power_6" = 1,
"power_7" = 1,
"power_8" = 1,
"power_9" = 2, //light theme specific
"power_10" = 2, //light theme specific
)
4 changes: 2 additions & 2 deletions code/modules/instruments/piano_synth.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
RegisterSignal(src, COMSIG_INSTRUMENT_END, PROC_REF(update_icon_for_playing_music))

// Called by a component signal to update musical note VFX for songs playing while worn.
/obj/item/instrument/piano_synth/headphones/proc/update_icon_for_playing_music()
/obj/item/instrument/piano_synth/headphones/proc/update_icon_for_playing_music(datum/source, datum/starting_song, atom/player)
SIGNAL_HANDLER
update_appearance()

Expand Down Expand Up @@ -129,7 +129,7 @@
/obj/item/circuit_component/synth/proc/start_playing(datum/port/input/port)
synth.song.start_playing(src)

/obj/item/circuit_component/synth/proc/on_song_start()
/obj/item/circuit_component/synth/proc/on_song_start(datum/source, datum/starting_song, atom/player)
SIGNAL_HANDLER
is_playing.set_output(TRUE)
started_playing.set_output(COMPONENT_SIGNAL)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/instruments/songs/_song.dm
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
//we can not afford to runtime, since we are going to be doing sound channel reservations and if we runtime it means we have a channel allocation leak.
//wrap the rest of the stuff to ensure stop_playing() is called.
do_hearcheck()
SEND_SIGNAL(parent, COMSIG_INSTRUMENT_START, src)
SEND_SIGNAL(parent, COMSIG_INSTRUMENT_START, src, user)
SEND_SIGNAL(user, COMSIG_ATOM_STARTING_INSTRUMENT, src)
elapsed_delay = 0
delay_by = 0
Expand Down
29 changes: 29 additions & 0 deletions code/modules/religion/festival/festival_violin.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/obj/item/instrument/violin/festival
name = "Cogitandi Fidis"
desc = "A violin that holds a special interest in the songs played from its strings."
icon_state = "holy_violin"
inhand_icon_state = "holy_violin"

/obj/item/instrument/violin/festival/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_INSTRUMENT_START, PROC_REF(on_instrument_start))

/// signal fired when the festival instrument starts to play.
/obj/item/instrument/violin/festival/proc/on_instrument_start(datum/source, datum/song/starting_song, atom/player)
SIGNAL_HANDLER

if(!starting_song || !isliving(player))
return
analyze_song(starting_song, player)

///Reports some relevant information when the song begins playing.
/obj/item/instrument/violin/festival/proc/analyze_song(datum/song/song, mob/living/playing_song)
var/list/analysis = list()
//check tempo and lines
var/song_length = song.lines.len * song.tempo
analysis += span_revenbignotice("[src] speaks to you...")
analysis += span_revennotice("\"This song has <b>[song.lines.len]</b> lines and a tempo of <b>[song.tempo]</b>.\"")
analysis += span_revennotice("\"Multiplying these together gives a song length of <b>[song_length]</b>.\"")
analysis += span_revennotice("\"To get a bonus effect from [GLOB.deity] upon finishing a performance, you need a song length of <b>[FESTIVAL_SONG_LONG_ENOUGH]</b>.\"")

to_chat(playing_song, analysis.Join("\n"))
87 changes: 87 additions & 0 deletions code/modules/religion/festival/instrument_rites.dm
Original file line number Diff line number Diff line change
@@ -1,9 +1,64 @@
/datum/religion_rites/holy_violin
name = "Cogitandi Fidis"
desc = "Creates a holy violin that can analyze songs played from it."
ritual_length = 6 SECONDS
ritual_invocations = list("A servant of jubilee is needed ...")
invoke_msg = "... A great mind for musical matters!"
favor_cost = 20 //you only need one

/datum/religion_rites/holy_violin/invoke_effect(mob/living/user, atom/religious_tool)
. = ..()
var/turf/tool_turf = get_turf(religious_tool)
var/obj/item/instrument/violin/fidis = new /obj/item/instrument/violin/festival(get_turf(religious_tool))
fidis.visible_message(span_notice("[fidis] appears!"))
playsound(tool_turf, 'sound/effects/pray.ogg', 50, TRUE)

/datum/religion_rites/portable_song_tuning
name = "Portable Song Tuning"
desc = "Empowers an instrument on the table to work as a portable altar for tuning songs. Will need to be recharged after 5 rites."
ritual_length = 6 SECONDS
ritual_invocations = list("Allow me to bring your holy inspirations ...")
invoke_msg = "... And send them with the winds my tunes ride with!"
favor_cost = 10
///instrument to empower
var/obj/item/instrument/instrument_target

/datum/religion_rites/portable_song_tuning/perform_rite(mob/living/user, atom/religious_tool)
for(var/obj/item/instrument/could_empower in get_turf(religious_tool))
instrument_target = could_empower
return ..()
to_chat(user, span_warning("You need to place an instrument on [religious_tool] to do this!"))
return FALSE

/datum/religion_rites/portable_song_tuning/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
var/obj/item/instrument/empower_target = instrument_target
var/turf/tool_turf = get_turf(religious_tool)
instrument_target = null
if(QDELETED(empower_target) || !(tool_turf == empower_target.loc)) //check if the instrument is still there
to_chat(user, span_warning("Your target left the altar!"))
return FALSE
empower_target.visible_message(span_notice("[empower_target] glows for a moment."))
playsound(tool_turf, 'sound/effects/pray.ogg', 50, TRUE)
var/list/allowed_rites_from_bible = subtypesof(/datum/religion_rites/song_tuner)
empower_target.AddComponent( \
/datum/component/religious_tool, \
operation_flags = RELIGION_TOOL_INVOKE, \
force_catalyst_afterattack = FALSE, \
after_sect_select_cb = null, \
catalyst_type = /obj/item/book/bible, \
charges = 5, \
rite_types_allowlist = allowed_rites_from_bible, \
)
return TRUE

///prototype for rites that tune a song.
/datum/religion_rites/song_tuner
name = "Tune Song"
desc = "this is a prototype."
ritual_length = 10 SECONDS
favor_cost = 10
auto_delete = FALSE
///if repeats count as continuations instead of a song's end, TRUE
var/repeats_okay = TRUE
///personal message sent to the chaplain as feedback for their chosen song
Expand All @@ -20,6 +75,16 @@
to_chat(user, span_notice(song_invocation_message))
user.AddComponent(/datum/component/smooth_tunes, src, repeats_okay, particles_path, glow_color)

/**
* Song effect applied when the performer starts playing.
*
* Arguments:
* * performer - A human starting the song
* * song_source - parent of the smooth_tunes component. This is limited to the compatible items of said component, which currently includes mobs and objects so we'll have to type appropriately.
*/
/datum/religion_rites/song_tuner/proc/performer_start_effect(mob/living/carbon/human/performer, atom/song_source)
return

/**
* Perform the song effect.
*
Expand Down Expand Up @@ -60,6 +125,28 @@
/datum/religion_rites/song_tuner/evangelism/finish_effect(mob/living/carbon/human/listener, atom/song_source)
listener.add_mood_event("blessing", /datum/mood_event/blessing)

/datum/religion_rites/song_tuner/light
name = "Illuminating Solo"
desc = "Sing a bright song, lighting up the area around you. At the end of the song, you'll give some illumination to listeners."
particles_path = /particles/musical_notes/light
song_invocation_message = "You've prepared a bright song!"
song_start_message = span_notice("This music simply glows!")
glow_color = "#fcff44"
repeats_okay = FALSE
favor_cost = 0
/// lighting object that makes chaplain glow
var/obj/effect/dummy/lighting_obj/moblight/performer_light_obj

/datum/religion_rites/song_tuner/light/performer_start_effect(mob/living/carbon/human/performer, atom/song_source)
performer_light_obj = performer.mob_light(8, color = LIGHT_COLOR_DIM_YELLOW)

/datum/religion_rites/song_tuner/light/Destroy()
QDEL_NULL(performer_light_obj)
. = ..()

/datum/religion_rites/song_tuner/light/finish_effect(mob/living/carbon/human/listener, atom/song_source)
listener.apply_status_effect(/datum/status_effect/song/light)

/datum/religion_rites/song_tuner/nullwave
name = "Nullwave Vibrato"
desc = "Sing a dull song, protecting those who listen from magic."
Expand Down
3 changes: 3 additions & 0 deletions code/modules/religion/religion_sects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,10 @@
alignment = ALIGNMENT_GOOD
candle_overlay = FALSE
rites_list = list(
/datum/religion_rites/holy_violin,
/datum/religion_rites/portable_song_tuning,
/datum/religion_rites/song_tuner/evangelism,
/datum/religion_rites/song_tuner/light,
/datum/religion_rites/song_tuner/nullwave,
/datum/religion_rites/song_tuner/pain,
/datum/religion_rites/song_tuner/lullaby,
Expand Down
Binary file added icons/effects/particles/notes/note_light.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/equipment/instruments_lefthand.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/equipment/instruments_righthand.dmi
Binary file not shown.
Binary file modified icons/obj/art/musician.dmi
Binary file not shown.
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -5468,6 +5468,7 @@
#include "code\modules\religion\rites.dm"
#include "code\modules\religion\burdened\burdened_trauma.dm"
#include "code\modules\religion\burdened\psyker.dm"
#include "code\modules\religion\festival\festival_violin.dm"
#include "code\modules\religion\festival\instrument_rites.dm"
#include "code\modules\religion\honorbound\honorbound_rites.dm"
#include "code\modules\religion\honorbound\honorbound_trauma.dm"
Expand Down

0 comments on commit f6e4d8e

Please sign in to comment.