mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-04 05:51:54 +00:00
* Psykers (#71566) ## About The Pull Request Finishes #66471 At burden level nine (or through a deadly genetic breakdown), you now turn into a psyker. This splits your skull in half and transforms it into a weird fleshy mass. You become blind, but your skull is perfectly suited for sending out psychic waves. You get potent psy abilities. First one is brainwave echolocation, inspired by Gehennites (but not as laggy). Secondly, you get the ability of Psychic Walls, which act similarly to wizard ones, but last shorter, and cause projectiles to ricochet off them. Thirdly, you get a projectile boost ability, this temporarily lets you fire guns twice as fast and gives them homing to the target you clicked. Lastly, you get the ability of psychic projection. This terrifies the victim, fucking their screen up and causing them to rapidfire any gun they have in their general direction (they'll probably miss you) With most of the abilities being based around guns, a burden level nine chaplain now gets a new rite, Transmogrify. This lets them turn their null rod into a 5-shot 18 damage .77 revolver. The revolver possesses a weaker version of antimagic (protects against mind and unholy spells, but not wizard/cult ones). It is reloaded by a prayer action (can also only be performed by a max burdened person). General Video: https://streamable.com/w3kkrk Psychic Projection Video: https://streamable.com/4ibu7o  ## Why It's Good For The Game Rewards the burdened chaplain with some pretty cool stuff for going through hell like losing half his limbs, cause the current psychics dont cut it as much as probably necessary, adds echolocation which can be used for neat stuff in the future (bat organs for DNA infuser for example). ## Changelog 🆑 Fikou, sprites from Halcyon, some old code from Basilman and Armhulen. refactor: Honorbound and Burdened mutations are brain traumas now. add: Psykers. Become a psyker through the path of the burdened, or a genetic breakdown. add: Echolocation Component. /🆑 Co-authored-by: tralezab <spamqetuo2@ gmail.com> Co-authored-by: tralezab <40974010+tralezab@ users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@ users.noreply.github.com> * Psykers * commented out stuff is now in Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com> Co-authored-by: tralezab <spamqetuo2@ gmail.com> Co-authored-by: tralezab <40974010+tralezab@ users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@ users.noreply.github.com> Co-authored-by: John Doe <gamingskeleton3@gmail.com>
242 lines
9.4 KiB
Plaintext
242 lines
9.4 KiB
Plaintext
/**
|
|
*
|
|
* Allows the parent to act similarly to the Altar of Gods with modularity. Invoke and Sect Selection is done via attacking with a bible. This means you cannot sacrifice Bibles (you shouldn't want to do this anyways although now that I mentioned it you probably will want to).
|
|
*
|
|
*/
|
|
/datum/component/religious_tool
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE
|
|
/// Enables access to the global sect directly
|
|
var/datum/religion_sect/easy_access_sect
|
|
/// Prevents double selecting sects
|
|
var/selecting_sect = FALSE
|
|
/// What extent do we want this religious tool to act? In case you don't want full access to the list. Generated on New
|
|
var/operation_flags
|
|
/// The rite currently being invoked
|
|
var/datum/religion_rites/performing_rite
|
|
///Sets the type for catalyst
|
|
var/catalyst_type = /obj/item/storage/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
|
|
var/datum/callback/after_sect_select_cb
|
|
|
|
/datum/component/religious_tool/Initialize(_flags = ALL, _force_catalyst_afterattack = FALSE, _after_sect_select_cb, override_catalyst_type)
|
|
. = ..()
|
|
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
|
|
|
|
/datum/component/religious_tool/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(AttemptActions))
|
|
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
|
|
|
|
/datum/component/religious_tool/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE))
|
|
|
|
/**
|
|
* Sets the easy access variable to the global if it exists.
|
|
*/
|
|
/datum/component/religious_tool/proc/SetGlobalToLocal()
|
|
if(easy_access_sect)
|
|
return TRUE
|
|
if(!GLOB.religious_sect)
|
|
return FALSE
|
|
easy_access_sect = GLOB.religious_sect
|
|
if(after_sect_select_cb)
|
|
after_sect_select_cb.Invoke()
|
|
return TRUE
|
|
|
|
/**
|
|
* Since all of these involve attackby, we require mega proc. Handles Invocation, Sacrificing, And Selection of Sects.
|
|
*/
|
|
/datum/component/religious_tool/proc/AttemptActions(datum/source, obj/item/the_item, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(istype(the_item, catalyst_type))
|
|
INVOKE_ASYNC(src, TYPE_PROC_REF(/datum, ui_interact), user) //asynchronous to avoid sleeping in a signal
|
|
|
|
/**********Sacrificing**********/
|
|
else if(operation_flags & RELIGION_TOOL_SACRIFICE)
|
|
if(!easy_access_sect?.can_sacrifice(the_item,user))
|
|
return
|
|
easy_access_sect.on_sacrifice(the_item,user)
|
|
return COMPONENT_NO_AFTERATTACK
|
|
|
|
/datum/component/religious_tool/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ReligiousTool")
|
|
ui.open()
|
|
return COMPONENT_NO_AFTERATTACK
|
|
|
|
/datum/component/religious_tool/ui_state(mob/user)
|
|
if(!iscarbon(usr))
|
|
return GLOB.never_state
|
|
var/mob/living/carbon/carbon = usr
|
|
if(!carbon.is_holding_item_of_type(catalyst_type))
|
|
return GLOB.never_state
|
|
return GLOB.default_state
|
|
|
|
/datum/component/religious_tool/ui_data(mob/user)
|
|
var/list/data = list()
|
|
//cannot find global vars, so lets offer options
|
|
if(!SetGlobalToLocal())
|
|
data["sects"] = generate_available_sects(user)
|
|
data["alignment"] = ALIGNMENT_NEUT //neutral theme if you have no sect
|
|
else
|
|
data["sects"] = null
|
|
data["name"] = easy_access_sect.name
|
|
data["desc"] = easy_access_sect.desc
|
|
data["quote"] = easy_access_sect.quote
|
|
data["alignment"] = easy_access_sect.alignment
|
|
data["icon"] = easy_access_sect.tgui_icon
|
|
data["favordesc"] = easy_access_sect.tool_examine(user)
|
|
data["favor"] = easy_access_sect.favor
|
|
data["deity"] = GLOB.deity
|
|
data["rites"] = generate_available_rites()
|
|
data["wanted"] = generate_sacrifice_list()
|
|
|
|
var/atom/atom_parent = parent
|
|
data["toolname"] = atom_parent.name
|
|
data["can_select_sect"] = (operation_flags & RELIGION_TOOL_SECTSELECT)
|
|
data["can_invoke_rite"] = (operation_flags & RELIGION_TOOL_INVOKE)
|
|
data["can_sacrifice_item"] = (operation_flags & RELIGION_TOOL_SACRIFICE)
|
|
return data
|
|
|
|
/datum/component/religious_tool/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
switch(action)
|
|
if("sect_select")
|
|
select_sect(usr, params["path"])
|
|
return TRUE //they picked a sect lets update so some weird spammy shit doesn't happen
|
|
if("perform_rite")
|
|
perform_rite(usr, params["path"])
|
|
|
|
/// Select the sect, called from [/datum/component/religious_tool/proc/AttemptActions]
|
|
/datum/component/religious_tool/proc/select_sect(mob/living/user, path)
|
|
if(!ispath(text2path(path), /datum/religion_sect))
|
|
message_admins("[ADMIN_LOOKUPFLW(usr)] has tried to spawn an item when selecting a sect.")
|
|
return
|
|
if(user.mind.holy_role != HOLY_ROLE_HIGHPRIEST)
|
|
to_chat(user, "<span class='warning'>You are not the high priest, and therefore cannot select a religious sect.")
|
|
return
|
|
if(!user.canUseTopic(parent, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE))
|
|
to_chat(user,span_warning("You cannot select a sect at this time."))
|
|
return
|
|
if(GLOB.religious_sect)
|
|
return
|
|
GLOB.religious_sect = new path()
|
|
for(var/i in GLOB.player_list)
|
|
if(!isliving(i))
|
|
continue
|
|
var/mob/living/am_i_holy_living = i
|
|
if(!am_i_holy_living.mind?.holy_role)
|
|
continue
|
|
GLOB.religious_sect.on_conversion(am_i_holy_living)
|
|
easy_access_sect = GLOB.religious_sect
|
|
after_sect_select_cb.Invoke()
|
|
|
|
/// Perform the rite, called from [/datum/component/religious_tool/proc/AttemptActions]
|
|
/datum/component/religious_tool/proc/perform_rite(mob/living/user, path)
|
|
if(!ispath(text2path(path), /datum/religion_rites))
|
|
message_admins("[ADMIN_LOOKUPFLW(usr)] has tried to spawn an item when performing a rite.")
|
|
return
|
|
if(user.mind.holy_role < HOLY_ROLE_PRIEST)
|
|
if(user.mind.holy_role == HOLY_ROLE_DEACON)
|
|
to_chat(user, "<span class='warning'>You are merely a deacon of [GLOB.deity], and therefore cannot perform rites.")
|
|
else
|
|
to_chat(user, "<span class='warning'>You are not holy, and therefore cannot perform rites.")
|
|
return
|
|
if(performing_rite)
|
|
to_chat(user, "<span class='notice'>There is a rite currently being performed here already.")
|
|
return
|
|
if(!user.canUseTopic(parent, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE))
|
|
to_chat(user,span_warning("You are not close enough to perform the rite."))
|
|
return
|
|
performing_rite = new path(parent)
|
|
if(!performing_rite.perform_rite(user, parent))
|
|
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
|
|
|
|
/**
|
|
* Generates a list of available sects to the user. Intended to support custom-availability sects.
|
|
*/
|
|
/datum/component/religious_tool/proc/generate_available_sects(mob/user)
|
|
var/list/sects_to_pick = list()
|
|
for(var/path in subtypesof(/datum/religion_sect))
|
|
var/list/sect = list()
|
|
var/datum/religion_sect/not_a_real_instance_rs = path
|
|
sect["name"] = initial(not_a_real_instance_rs.name)
|
|
sect["desc"] = initial(not_a_real_instance_rs.desc)
|
|
sect["alignment"] = initial(not_a_real_instance_rs.alignment)
|
|
sect["quote"] = initial(not_a_real_instance_rs.quote)
|
|
sect["icon"] = initial(not_a_real_instance_rs.tgui_icon)
|
|
sect["path"] = path
|
|
sects_to_pick += list(sect)
|
|
return sects_to_pick
|
|
|
|
/**
|
|
* Generates available rites to pick from. It expects the sect to be picked by the time it was called (by tgui data)
|
|
*/
|
|
/datum/component/religious_tool/proc/generate_available_rites()
|
|
var/list/rites_to_pick = list()
|
|
for(var/path in easy_access_sect.rites_list)
|
|
///checks to invalidate
|
|
var/list/rite = list()
|
|
var/datum/religion_rites/rite_type = path
|
|
rite["name"] = initial(rite_type.name)
|
|
rite["desc"] = initial(rite_type.desc)
|
|
var/cost = initial(rite_type.favor_cost)
|
|
rite["favor"] = cost
|
|
rite["can_cast"] = cost > easy_access_sect.favor
|
|
rite["path"] = path
|
|
rites_to_pick += list(rite)
|
|
return rites_to_pick
|
|
|
|
/**
|
|
* Generates an english list (so string) of wanted sac items. Returns null if no targets!
|
|
*/
|
|
/datum/component/religious_tool/proc/generate_sacrifice_list()
|
|
if(!easy_access_sect.desired_items)
|
|
return //specifically null so the data sends as such
|
|
var/list/item_names = list()
|
|
for(var/atom/sac_type as anything in easy_access_sect.desired_items)
|
|
var/append = easy_access_sect.desired_items[sac_type]
|
|
var/entry = "[initial(sac_type.name)]s [append]"
|
|
item_names += entry
|
|
return english_list(item_names)
|
|
|
|
/**
|
|
* Appends to examine so the user knows it can be used for religious purposes.
|
|
*/
|
|
/datum/component/religious_tool/proc/on_examine(datum/source, mob/user, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
|
|
var/can_i_see = FALSE
|
|
if(isobserver(user))
|
|
can_i_see = TRUE
|
|
else if(isliving(user))
|
|
var/mob/living/L = user
|
|
if(L.mind?.holy_role)
|
|
can_i_see = TRUE
|
|
|
|
if(!can_i_see)
|
|
return
|
|
examine_list += span_notice("Use a bible to interact with this.")
|
|
if(!easy_access_sect)
|
|
if(operation_flags & RELIGION_TOOL_SECTSELECT)
|
|
examine_list += span_notice("This looks like it can be used to select a sect.")
|
|
return
|
|
if(operation_flags & RELIGION_TOOL_SACRIFICE)//this can be moved around if things change but usually no rites == no sacrifice
|
|
examine_list += span_notice("Desired items can be used on this to increase favor.")
|
|
if(easy_access_sect.rites_list && operation_flags & RELIGION_TOOL_INVOKE)
|
|
examine_list += span_notice("You can invoke rites from this.")
|