Cleans up + Improves bows, Sorts files, Adds the Divine Archer clothing, weapon, rite (#74811)

## About The Pull Request

### Divine Archer 🏹 


![image](https://user-images.githubusercontent.com/40974010/232647927-aace69ea-bda8-4ec9-9bf1-60140034fbb3.png)

Adds a new chaplain weapon and suit of armor, the divine archer. It's an
orderable set of armor, but provides less armor than the rest, but you
get more pieces of armor (boots, bracer, undersuit).

The divine bow comes with a quiver that holds holy arrows. The holy
arrows come with bane support, dealing critical damage to revenants.

### Bow Features  

- arrows can now be dipped in poison

### Bow Improvements 🔧 

- bows now drop their arrow when you put them on your back while nocking
a bow
- bows give feedback for trying to draw without a nocked arrow
- codewise, bows support subtypes much better. They still have
hard-sprited loaded arrows, but one day that'll change.

## Why It's Good For The Game

Yeah, we could add null rod #2342 that does almost the same as the
others, or we could have a unique bow weapon!

Player Dev Project thread:
https://discord.com/channels/326822144233439242/1093521091957370940/1093521091957370940

## Changelog
🆑 tralezab code, Drag for the commission and player project, cre#0484
for their spritework
add: Divine Archer Armor and Weapon
qol: Bows give more feedback when you're doing something wrong, like
trying to draw without a nocked arrow
code: Sorted files, cleaned bow code up to allow subtypes
/🆑
This commit is contained in:
tralezab
2023-04-29 02:07:44 +00:00
committed by GitHub
parent e5cf268dd5
commit bc813ab93d
57 changed files with 678 additions and 293 deletions
@@ -80,3 +80,6 @@
/// Global signal called after the station changes its name.
/// (new_name, old_name)
#define COMSIG_GLOB_STATION_NAME_CHANGED "!station_name_changed"
/// global signal when a global nullrod type is picked
#define COMSIG_GLOB_NULLROD_PICKED "!nullrod_picked"
+2 -2
View File
@@ -321,9 +321,9 @@
// /obj/projectile signals (sent to the firer)
///from base of /obj/projectile/proc/on_hit(), like COMSIG_PROJECTILE_ON_HIT but on the projectile itself and with the hit limb (if any): (atom/movable/firer, atom/target, Angle, hit_limb)
///from base of /obj/projectile/proc/on_hit(), like COMSIG_PROJECTILE_ON_HIT but on the projectile itself and with the hit limb (if any): (atom/movable/firer, atom/target, angle, hit_limb)
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit"
///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, angle, hit_limb)
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit"
///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target)
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire"
+76
View File
@@ -0,0 +1,76 @@
/**
* ## On Hit Effect Component!
*
* Component for other elements/components to rely on for on-hit effects without duplicating the on-hit code.
* See Lifesteal, or bane for examples.
*
* THIS COULD EASILY SUPPORT COMPONENT_DUPE_ALLOWED but the getcomponent makes it throw errors. if you can figure that out feel free to readd the dupe types
*/
/datum/component/on_hit_effect
///callback used by other components to apply effects
var/datum/callback/on_hit_callback
///callback optionally used for more checks
var/datum/callback/extra_check_callback
/datum/component/on_hit_effect/Initialize(on_hit_callback, extra_check_callback)
src.on_hit_callback = on_hit_callback
src.extra_check_callback = extra_check_callback
if(!(ismachinery(parent) || isstructure(parent) || isgun(parent) || isprojectilespell(parent) || isitem(parent) || isanimal_or_basicmob(parent) || isprojectile(parent)))
return ELEMENT_INCOMPATIBLE
/datum/component/on_hit_effect/RegisterWithParent()
if(ismachinery(parent) || isstructure(parent) || isgun(parent) || isprojectilespell(parent))
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, PROC_REF(on_projectile_hit))
else if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(item_afterattack))
else if(isanimal_or_basicmob(parent))
RegisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget))
else if(isprojectile(parent))
RegisterSignal(parent, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(on_projectile_self_hit))
/datum/component/on_hit_effect/UnregisterFromParent()
UnregisterSignal(parent, list(
COMSIG_PROJECTILE_ON_HIT,
COMSIG_ITEM_AFTERATTACK,
COMSIG_HOSTILE_POST_ATTACKINGTARGET,
COMSIG_PROJECTILE_SELF_ON_HIT,
))
/datum/component/on_hit_effect/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!proximity_flag)
return
if(extra_check_callback)
if(!extra_check_callback.Invoke(user, target))
return
on_hit_callback.Invoke(source, user, target, user.zone_selected)
return COMPONENT_AFTERATTACK_PROCESSED_ITEM
/datum/component/on_hit_effect/proc/hostile_attackingtarget(mob/living/attacker, atom/target, success)
SIGNAL_HANDLER
if(!success)
return
if(extra_check_callback)
if(!extra_check_callback.Invoke(attacker, target))
return
on_hit_callback.Invoke(attacker, attacker, target, attacker.zone_selected)
/datum/component/on_hit_effect/proc/on_projectile_hit(datum/fired_from, atom/movable/firer, atom/target, angle, obj/item/bodypart/hit_limb)
SIGNAL_HANDLER
if(extra_check_callback)
if(!extra_check_callback.Invoke(firer, target))
return
on_hit_callback.Invoke(fired_from, firer, target, hit_limb.body_zone)
/datum/component/on_hit_effect/proc/on_projectile_self_hit(datum/source, mob/firer, atom/target, angle, obj/item/bodypart/hit_limb)
SIGNAL_HANDLER
if(extra_check_callback)
if(!extra_check_callback.Invoke(firer, target))
return
on_hit_callback.Invoke(source, firer, target, hit_limb.body_zone)
+1 -1
View File
@@ -120,7 +120,7 @@
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.")
to_chat(user, span_warning("You are not the high priest, and therefore cannot select a religious sect."))
return
if(!user.can_perform_action(parent, FORBID_TELEKINESIS_REACH))
to_chat(user,span_warning("You cannot select a sect at this time."))
@@ -0,0 +1,35 @@
/**
* sect nullrod bonus component; for sekret rite combos
*
* Good example is the bow and pyre sect. pick the bow, get a special rite in the pyre sect.
*/
/datum/component/sect_nullrod_bonus
/// assoc list of nullrod type -> rites it unlocks
var/list/bonus_rites
/// has this component given the bonus yet
var/bonus_applied = FALSE
/datum/component/sect_nullrod_bonus/Initialize(list/bonus_rites)
if(!istype(parent, /datum/religion_sect))
return COMPONENT_INCOMPATIBLE
src.bonus_rites = bonus_rites
check_bonus_rites()
/datum/component/sect_nullrod_bonus/RegisterWithParent()
RegisterSignal(SSdcs, COMSIG_GLOB_NULLROD_PICKED, PROC_REF(on_nullrod_picked))
/datum/component/sect_nullrod_bonus/UnregisterFromParent()
UnregisterSignal(SSdcs, COMSIG_GLOB_NULLROD_PICKED)
/datum/component/sect_nullrod_bonus/proc/on_nullrod_picked(datum/source)
SIGNAL_HANDLER
check_bonus_rites()
/datum/component/sect_nullrod_bonus/proc/check_bonus_rites()
if(bonus_applied || !GLOB.holy_weapon_type)
return
var/list/unlocked_rites = bonus_rites[GLOB.holy_weapon_type]
if(!unlocked_rites)
return
GLOB.religious_sect.rites_list.Add(unlocked_rites)
bonus_applied = TRUE
+45 -36
View File
@@ -18,14 +18,8 @@
/datum/element/bane/Attach(datum/target, target_type = /mob/living, mob_biotypes = NONE, damage_multiplier=1, added_damage = 0, requires_combat_mode = TRUE)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
if(ispath(target_type, /mob/living))
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(mob_check))
else if(ispath(target_type, /datum/species))
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(species_check))
else
if(!ispath(target_type, /mob/living) && !ispath(target_type, /datum/species))
return ELEMENT_INCOMPATIBLE
src.target_type = target_type
@@ -33,39 +27,54 @@
src.added_damage = added_damage
src.requires_combat_mode = requires_combat_mode
src.mob_biotypes = mob_biotypes
target.AddComponent(/datum/component/on_hit_effect, CALLBACK(src, PROC_REF(do_bane)), CALLBACK(src, PROC_REF(check_bane)))
/datum/element/bane/Detach(datum/source)
UnregisterSignal(source, COMSIG_ITEM_AFTERATTACK)
/datum/element/bane/Detach(datum/target)
qdel(target.GetComponent(/datum/component/on_hit_effect))
return ..()
/datum/element/bane/proc/species_check(obj/item/source, mob/living/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!proximity_flag || !istype(target) || !is_species(target, target_type))
/datum/element/bane/proc/check_bane(mob/living/bane_applier, atom/target)
if(!isliving(target))
return
var/is_correct_biotype = target.mob_biotypes & mob_biotypes
var/mob/living/living_target = target
if(bane_applier)
if(requires_combat_mode && !bane_applier.combat_mode)
return
var/is_correct_biotype = living_target.mob_biotypes & mob_biotypes
if(mob_biotypes && !(is_correct_biotype))
return FALSE
if(ispath(target_type, /mob/living))
return istype(living_target, target_type)
else //species type
return is_species(living_target, target_type)
/datum/element/bane/proc/do_bane(datum/element_owner, mob/living/bane_applier, mob/living/baned_target, hit_zone)
var/force_boosted
var/applied_dam_type
if(isitem(element_owner))
var/obj/item/item_owner = element_owner
force_boosted = item_owner.force
applied_dam_type = item_owner.damtype
else if(isprojectile(element_owner))
var/obj/projectile/projectile_owner = element_owner
force_boosted = projectile_owner.damage
applied_dam_type = projectile_owner.damage_type
else if (isliving(element_owner))
var/mob/living/living_owner = element_owner
force_boosted = (living_owner.melee_damage_lower + living_owner.melee_damage_upper) / 2
//commence crying. yes, these really are the same check. FUCK.
if(isbasicmob(living_owner))
var/mob/living/basic/basic_owner = living_owner
applied_dam_type = basic_owner.melee_damage_type
else if(isanimal(living_owner))
var/mob/living/simple_animal/simple_owner = living_owner
applied_dam_type = simple_owner.melee_damage_type
else
return
else
return
activate(source, target, user)
/datum/element/bane/proc/mob_check(obj/item/source, mob/living/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!proximity_flag || !istype(target, target_type))
return
var/is_correct_biotype = target.mob_biotypes & mob_biotypes
if(mob_biotypes && !(is_correct_biotype))
return
activate(source, target, user)
/datum/element/bane/proc/activate(obj/item/source, mob/living/target, mob/living/attacker)
if(requires_combat_mode && !attacker.combat_mode)
return
var/extra_damage = max(0, (source.force * damage_multiplier) + added_damage)
target.apply_damage(extra_damage, source.damtype, attacker.zone_selected)
SEND_SIGNAL(target, COMSIG_LIVING_BANED, source, attacker) // for extra effects when baned.
var/extra_damage = max(0, (force_boosted * damage_multiplier) + added_damage)
baned_target.apply_damage(extra_damage, applied_dam_type, hit_zone)
SEND_SIGNAL(baned_target, COMSIG_LIVING_BANED, bane_applier, baned_target) // for extra effects when baned.
@@ -0,0 +1,57 @@
/**
* ### envenomable caseless element!
*
* Non bespoke element (1 in existence) that lets caseless bullets be dippable.
* When you fire the bullet, it will gain venomous. The casing itself isn't venomous to prevent bullshit
*/
/datum/element/envenomable_casing
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// how much reagent can you dip the caseless in?
var/amount_allowed
/datum/element/envenomable_casing/Attach(datum/target, amount_allowed = 5)
. = ..()
if(!istype(target, /obj/item/ammo_casing))
return ELEMENT_INCOMPATIBLE
src.amount_allowed = amount_allowed
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack))
RegisterSignal(target, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
/datum/element/envenomable_casing/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_ITEM_AFTERATTACK, COMSIG_PARENT_EXAMINE))
///signal called on the parent attacking an item
/datum/element/envenomable_casing/proc/on_afterattack(obj/item/ammo_casing/casing, atom/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!is_reagent_container(target))
return
var/obj/item/reagent_containers/venom_container = target
if(!casing.loaded_projectile)
user.balloon_alert(user, "casing is already spent!")
return
if(!(venom_container.reagent_flags & OPENCONTAINER))
user.balloon_alert(user, "open the container!")
return
var/datum/reagent/venom_applied = venom_container.reagents.get_master_reagent()
if(!venom_applied)
return
var/amount_applied = min(venom_applied.volume, amount_allowed)
casing.loaded_projectile.AddComponent(/datum/element/venomous, venom_applied.type, amount_applied)
to_chat(user, span_notice("You coat [casing] in [venom_applied]."))
venom_container.reagents.remove_reagent(venom_applied.type, amount_applied)
///stops further poison application
UnregisterSignal(casing, COMSIG_ITEM_AFTERATTACK)
///signal called on parent being examined
/datum/element/envenomable_casing/proc/on_examine(obj/item/ammo_casing/casing, mob/user, list/examine_list)
SIGNAL_HANDLER
if(!casing.loaded_projectile)
return
if(casing.loaded_projectile.GetComponent(/datum/element/venomous))
examine_list += span_warning("It's coated in some kind of chemical...")
else
examine_list += span_notice("You can dip it in a chemical to deliver a poisonous kick.")
+6 -33
View File
@@ -7,46 +7,19 @@
argument_hash_start_idx = 2
/// heals a constant amount every time a hit occurs
var/flat_heal
/// static list shared that tells which order of damage types to prioritize
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
/datum/element/lifesteal/Attach(datum/target, flat_heal)
/datum/element/lifesteal/Attach(datum/target, flat_heal = 10)
. = ..()
if(ismachinery(target) || isstructure(target) || isgun(target) || isprojectilespell(target))
RegisterSignal(target, COMSIG_PROJECTILE_ON_HIT, PROC_REF(projectile_hit))
else if(isitem(target))
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(item_afterattack))
else if(ishostile(target))
RegisterSignal(target, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget))
else
return ELEMENT_INCOMPATIBLE
src.flat_heal = flat_heal
target.AddComponent(/datum/component/on_hit_effect, CALLBACK(src, PROC_REF(do_lifesteal)))
/datum/element/lifesteal/Detach(datum/source)
UnregisterSignal(source, list(COMSIG_PROJECTILE_ON_HIT, COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_POST_ATTACKINGTARGET))
/datum/element/lifesteal/Detach(datum/target)
qdel(target.GetComponent(/datum/component/on_hit_effect))
return ..()
/datum/element/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!proximity_flag)
return
do_lifesteal(user, target)
return COMPONENT_AFTERATTACK_PROCESSED_ITEM
/datum/element/lifesteal/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success)
SIGNAL_HANDLER
if(!success)
return
do_lifesteal(attacker, target)
/datum/element/lifesteal/proc/projectile_hit(datum/fired_from, atom/movable/firer, atom/target, Angle)
SIGNAL_HANDLER
do_lifesteal(firer, target)
/datum/element/lifesteal/proc/do_lifesteal(atom/heal_target, atom/damage_target)
/datum/element/lifesteal/proc/do_lifesteal(datum/element_owner, atom/heal_target, atom/damage_target, hit_zone)
if(isliving(heal_target) && isliving(damage_target))
var/mob/living/healing = heal_target
var/mob/living/damaging = damage_target
+3 -32
View File
@@ -13,44 +13,15 @@
/datum/element/venomous/Attach(datum/target, poison_type, amount_added)
. = ..()
if(ismachinery(target) || isstructure(target) || isgun(target) || isprojectilespell(target))
RegisterSignal(target, COMSIG_PROJECTILE_ON_HIT, PROC_REF(projectile_hit))
else if(isitem(target))
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(item_afterattack))
else if(ishostile(target) || isbasicmob(target))
RegisterSignal(target, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget))
else
return ELEMENT_INCOMPATIBLE
src.poison_type = poison_type
src.amount_added = amount_added
target.AddComponent(/datum/component/on_hit_effect, CALLBACK(src, PROC_REF(do_venom)))
/datum/element/venomous/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_PROJECTILE_ON_HIT, COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_POST_ATTACKINGTARGET))
qdel(target.GetComponent(/datum/component/on_hit_effect))
return ..()
/datum/element/venomous/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
SIGNAL_HANDLER
add_reagent(target)
/datum/element/venomous/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if(!proximity_flag)
return
add_reagent(target)
return COMPONENT_AFTERATTACK_PROCESSED_ITEM
/datum/element/venomous/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success)
SIGNAL_HANDLER
if(!success)
return
add_reagent(target)
/datum/element/venomous/proc/add_reagent(mob/living/target)
/datum/element/venomous/proc/do_venom(datum/element_owner, atom/venom_source, mob/living/target, hit_zone)
if(!istype(target))
return
if(target.stat == DEAD)
+1
View File
@@ -542,6 +542,7 @@
/obj/item/storage/bag/harpoon_quiver
name = "harpoon quiver"
desc = "A quiver for holding harpoons."
icon = 'icons/obj/weapons/guns/bows/quivers.dmi'
icon_state = "quiver"
inhand_icon_state = null
worn_icon_state = "harpoon_quiver"
@@ -186,3 +186,13 @@
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
new /obj/item/clothing/suit/hooded/chaplain_hoodie/leader(src)
/obj/item/storage/box/holy/divine_archer
name = "Divine Archer Kit"
typepath_for_preview = /obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer
/obj/item/storage/box/holy/divine_archer/PopulateContents()
new /obj/item/clothing/under/rank/civilian/chaplain/divine_archer(src)
new /obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer(src)
new /obj/item/clothing/gloves/divine_archer(src)
new /obj/item/clothing/shoes/divine_archer(src)
+3 -1
View File
@@ -8,6 +8,8 @@
var/alternative_mode = FALSE
///Whether the hood is flipped up
var/hood_up = FALSE
/// What should be added to the end of the icon state when the hood is up? Set to "" for the suit sprite to not change at all
var/hood_up_affix = "_t"
/// Are we zipped? Mostly relevant for wintercoats, leaving this here to simplify logic and so someone else can extend it if they ever wish to.
var/zipped = FALSE
@@ -86,7 +88,7 @@
RemoveHood()
return
hood_up = TRUE
icon_state = "[initial(icon_state)]_t"
icon_state = "[initial(icon_state)][hood_up_affix]"
worn_icon_state = icon_state
zipped = TRUE // Just to maintain the same behavior, and so we avoid any bugs that otherwise relied on this behavior of zipping the jacket when bringing up the hood
H.update_worn_oversuit()
@@ -0,0 +1,63 @@
// this costume has so many fugging parts 😭. fuck it, it's a file.
//in fact, we should strive to make the chaplain kits of this quality, moreso than the other way around.
/// undersuit
/obj/item/clothing/under/rank/civilian/chaplain/divine_archer
name = "divine archer's garb"
desc = "Inner garb for divine archers."
icon_state = "archergarb"
inhand_icon_state = "archergarb"
can_adjust = TRUE
/// suit
/obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer
name = "divine archer coat"
desc = "Outer coat for divine archers. Offers some protection."
icon_state = "archercoat"
inhand_icon_state = "archercoat"
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
armor_type = /datum/armor/chaplainsuit_armor_weaker
clothing_flags = BLOCKS_SHOVE_KNOCKDOWN
strip_delay = 80
equip_delay_other = 60
hoodtype = /obj/item/clothing/head/hooded/chaplain_hood/divine_archer
hood_up_affix = ""
/datum/armor/chaplainsuit_armor_weaker
melee = 40
bullet = 5
laser = 5
energy = 5
fire = 60
acid = 60
wound = 10
/// hood
/obj/item/clothing/head/hooded/chaplain_hood/divine_archer
name = "divine archer hood"
desc = "A divine hood included, because have you ever got the sun in your eyes during archery? Oh, it's just the worst."
icon_state = "archerhood"
/// gloves
/obj/item/clothing/gloves/divine_archer
name = "divine archer bracers"
desc = "Bracers, a wise choice for archers who do not want their outfit to get in the way of drawing and firing their weapon."
icon_state = "archerbracers"
inhand_icon_state = "archerbracers"
strip_delay = 40
equip_delay_other = 20
resistance_flags = NONE
/// boots
/obj/item/clothing/shoes/divine_archer
name = "divine archer boots"
desc = "Boots, For steady footing while aiming."
icon_state = "archerboots"
inhand_icon_state = "archerboots"
strip_delay = 30
equip_delay_other = 50
resistance_flags = NONE
can_be_tied = FALSE
@@ -29,8 +29,8 @@
success_forcesay = "BEGONE FOUL MAGIKS!!", \
tip_text = "Clear rune", \
on_clear_callback = CALLBACK(src, PROC_REF(on_cult_rune_removed)), \
effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune, /obj/effect/cosmic_rune))
effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune, /obj/effect/cosmic_rune), \
)
AddElement(/datum/element/bane, target_type = /mob/living/simple_animal/revenant, damage_multiplier = 0, added_damage = 25, requires_combat_mode = FALSE)
if(!GLOB.holy_weapon_type && type == /obj/item/nullrod)
@@ -39,10 +39,13 @@
if(!initial(nullrod_type.chaplain_spawnable))
continue
rods[nullrod_type] = initial(nullrod_type.menu_description)
//special non-nullrod subtyped shit
rods[/obj/item/gun/ballistic/bow/divine/with_quiver] = "A divine bow and 10 quivered holy arrows."
AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, PROC_REF(on_holy_weapon_picked)))
/obj/item/nullrod/proc/on_holy_weapon_picked(obj/item/nullrod/holy_weapon_type)
GLOB.holy_weapon_type = holy_weapon_type
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NULLROD_PICKED)
SSblackbox.record_feedback("tally", "chaplain_weapon", 1, "[initial(holy_weapon_type.name)]")
/obj/item/nullrod/proc/on_cult_rune_removed(obj/effect/target, mob/living/user)
@@ -1,10 +1,11 @@
/obj/item/gun/ballistic/bow
name = "longbow"
desc = "While pretty finely crafted, surely you can find something better to use in the current year."
icon = 'icons/obj/weapons/guns/ballistic.dmi'
icon = 'icons/obj/weapons/guns/bows/bows.dmi'
lefthand_file = 'icons/mob/inhands/weapons/bows_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/bows_righthand.dmi'
icon_state = "bow"
inhand_icon_state = "bow"
base_icon_state = "bow"
load_sound = null
fire_sound = null
mag_type = /obj/item/ammo_box/magazine/internal/bow
@@ -16,11 +17,12 @@
internal_magazine = TRUE
cartridge_wording = "arrow"
bolt_type = BOLT_TYPE_NO_BOLT
/// whether the bow is drawn back
var/drawn = FALSE
/obj/item/gun/ballistic/bow/update_icon_state()
. = ..()
icon_state = chambered ? "bow_[drawn]" : "bow"
icon_state = chambered ? "[base_icon_state]_[drawn ? "drawn" : "nocked"]" : "[base_icon_state]"
/obj/item/gun/ballistic/bow/proc/drop_arrow()
drawn = FALSE
@@ -38,7 +40,9 @@
chambered.forceMove(src)
/obj/item/gun/ballistic/bow/attack_self(mob/user)
if(chambered)
if(!chambered)
balloon_alert(user, "no arrow nocked!")
else
balloon_alert(user, "[drawn ? "string released" : "string drawn"]")
drawn = !drawn
update_appearance()
@@ -56,8 +60,16 @@
. = ..() //fires, removing the arrow
update_appearance()
/obj/item/gun/ballistic/bow/equipped(mob/user, slot, initial)
. = ..()
if(slot == ITEM_SLOT_BACK && chambered)
balloon_alert(user, "the arrow falls out!")
drop_arrow()
drawn = FALSE
update_appearance()
/obj/item/gun/ballistic/bow/shoot_with_empty_chamber(mob/living/user)
return //so clicking sounds please
return //no clicking sounds please
/obj/item/ammo_box/magazine/internal/bow
name = "bowstring"
@@ -65,58 +77,3 @@
max_ammo = 1
start_empty = TRUE
caliber = CALIBER_ARROW
/obj/item/ammo_casing/caseless/arrow
name = "arrow"
desc = "Stabby Stabman!"
icon_state = "arrow"
inhand_icon_state = "arrow"
flags_1 = NONE
throwforce = 1
projectile_type = /obj/projectile/bullet/reusable/arrow
firing_effect_type = null
caliber = CALIBER_ARROW
heavy_metal = FALSE
/obj/item/ammo_casing/caseless/arrow/despawning/dropped()
. = ..()
addtimer(CALLBACK(src, PROC_REF(floor_vanish)), 5 SECONDS)
/obj/item/ammo_casing/caseless/arrow/despawning/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/obj/projectile/bullet/reusable/arrow
name = "arrow"
desc = "Ow! Get it out of me!"
ammo_type = /obj/item/ammo_casing/caseless/arrow
damage = 50
speed = 1
range = 25
/obj/item/storage/bag/quiver
name = "quiver"
desc = "Holds arrows for your bow. Good, because while pocketing arrows is possible, it surely can't be pleasant."
icon_state = "quiver"
inhand_icon_state = null
worn_icon_state = "harpoon_quiver"
var/arrow_path = /obj/item/ammo_casing/caseless/arrow
/obj/item/storage/bag/quiver/Initialize(mapload)
. = ..()
atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
atom_storage.max_slots = 40
atom_storage.max_total_storage = 100
atom_storage.set_holdable(list(
/obj/item/ammo_casing/caseless/arrow
))
/obj/item/storage/bag/quiver/PopulateContents()
. = ..()
for(var/i in 1 to 10)
new arrow_path(src)
/obj/item/storage/bag/quiver/despawning
arrow_path = /obj/item/ammo_casing/caseless/arrow/despawning
@@ -0,0 +1,94 @@
///base arrow
/obj/item/ammo_casing/caseless/arrow
name = "arrow"
desc = "Stabby Stabman!"
icon = 'icons/obj/weapons/guns/bows/arrows.dmi'
icon_state = "arrow"
inhand_icon_state = "arrow"
projectile_type = /obj/projectile/bullet/reusable/arrow
flags_1 = NONE
throwforce = 1
firing_effect_type = null
caliber = CALIBER_ARROW
heavy_metal = FALSE
/obj/item/ammo_casing/caseless/arrow/Initialize(mapload)
. = ..()
AddComponent(/datum/element/envenomable_casing)
///base arrow projectile
/obj/projectile/bullet/reusable/arrow
name = "arrow"
desc = "Ow! Get it out of me!"
icon = 'icons/obj/weapons/guns/bows/arrows.dmi'
icon_state = "arrow_projectile"
ammo_type = /obj/item/ammo_casing/caseless/arrow
damage = 50
speed = 1
range = 25
///*sigh* NON-REUSABLE base arrow projectile. In the future: let's componentize the reusable subtype, jesus
/obj/projectile/bullet/arrow
name = "arrow"
desc = "Ow! Get it out of me!"
icon = 'icons/obj/weapons/guns/bows/arrows.dmi'
icon_state = "arrow_projectile"
damage = 50
speed = 1
range = 25
/// despawning arrow type
/obj/item/ammo_casing/caseless/arrow/despawning/dropped()
. = ..()
addtimer(CALLBACK(src, PROC_REF(floor_vanish)), 5 SECONDS)
/obj/item/ammo_casing/caseless/arrow/despawning/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/// holy arrows
/obj/item/ammo_casing/caseless/arrow/holy
name = "holy arrow"
desc = "A holy diver seeking its target."
icon_state = "holy_arrow"
inhand_icon_state = "holy_arrow"
projectile_type = /obj/projectile/bullet/reusable/arrow/holy
/// holy arrow projectile
/obj/projectile/bullet/reusable/arrow/holy
name = "holy arrow"
desc = "Here it comes, cultist scum!"
icon_state = "holy_arrow_projectile"
ammo_type = /obj/item/ammo_casing/caseless/arrow/holy
damage = 20 //still a lot but this is roundstart gear so far less
/obj/projectile/bullet/reusable/arrow/holy/Initialize(mapload)
. = ..()
//50 damage to revenants
AddElement(/datum/element/bane, target_type = /mob/living/simple_animal/revenant, damage_multiplier = 0, added_damage = 30)
/// special pyre sect arrow
/// in the future, this needs a special sprite, but bows don't support non-hardcoded arrow sprites
/obj/item/ammo_casing/caseless/arrow/holy/blazing
name = "blazing star arrow"
desc = "A holy diver seeking its target, blessed with fire. Will ignite on hit, destroying the arrow. But if you hit an already ignited target...?"
projectile_type = /obj/projectile/bullet/arrow/blazing
/obj/projectile/bullet/arrow/blazing
name = "blazing arrow"
desc = "THE UNMATCHED POWER OF THE SUN"
icon_state = "holy_arrow_projectile"
damage = 20
/obj/projectile/bullet/arrow/blazing/on_hit(atom/target, blocked, pierce_hit)
. = ..()
if(!ishuman(target))
return
var/mob/living/carbon/human/human_target = target
if(!human_target.on_fire)
to_chat(human_target, span_danger("[src] explodes into flames which quickly envelop you!"))
human_target.adjust_fire_stacks(2)
human_target.ignite_mob()
return
to_chat(human_target, span_danger("[src] reacts with the flames on y-"))
explosion(src, light_impact_range = 1, flame_range = 2) //ow
@@ -0,0 +1,35 @@
/obj/item/storage/bag/quiver
name = "quiver"
desc = "Holds arrows for your bow. Good, because while pocketing arrows is possible, it surely can't be pleasant."
icon = 'icons/obj/weapons/guns/bows/quivers.dmi'
icon_state = "quiver"
inhand_icon_state = null
worn_icon_state = "harpoon_quiver"
/// type of arrow the quivel should hold
var/arrow_path = /obj/item/ammo_casing/caseless/arrow
/obj/item/storage/bag/quiver/Initialize(mapload)
. = ..()
atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
atom_storage.max_slots = 40
atom_storage.max_total_storage = 100
atom_storage.set_holdable(list(
/obj/item/ammo_casing/caseless/arrow,
))
/obj/item/storage/bag/quiver/PopulateContents()
. = ..()
for(var/i in 1 to 10)
new arrow_path(src)
/obj/item/storage/bag/quiver/despawning
arrow_path = /obj/item/ammo_casing/caseless/arrow/despawning
/obj/item/storage/bag/quiver/holy
name = "divine quiver"
desc = "Holds arrows for your divine bow, where they wait to find their target."
icon_state = "holyquiver"
inhand_icon_state = "holyquiver"
worn_icon_state = "holyquiver"
arrow_path = /obj/item/ammo_casing/caseless/arrow/holy
@@ -0,0 +1,47 @@
///basic bow, used for medieval sim
/obj/item/gun/ballistic/bow/longbow
name = "longbow"
desc = "While pretty finely crafted, surely you can find something better to use in the current year."
///chaplain's divine archer bow
/obj/item/gun/ballistic/bow/divine
name = "divine bow"
desc = "Holy armament to pierce the souls of sinners."
icon_state = "holybow"
inhand_icon_state = "holybow"
base_icon_state = "holybow"
worn_icon_state = "holybow"
slot_flags = ITEM_SLOT_BACK
mag_type = /obj/item/ammo_box/magazine/internal/bow/holy
/obj/item/ammo_box/magazine/internal/bow/holy
name = "divine bowstring"
ammo_type = /obj/item/ammo_casing/caseless/arrow/holy
/obj/item/gun/ballistic/bow/divine/Initialize(mapload)
. = ..()
AddComponent(/datum/component/anti_magic, MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY)
AddComponent(/datum/component/effect_remover, \
success_feedback = "You disrupt the magic of %THEEFFECT with %THEWEAPON.", \
success_forcesay = "BOW-GONE FOUL MAGIKS!!", \
tip_text = "Clear rune", \
on_clear_callback = CALLBACK(src, PROC_REF(on_cult_rune_removed)), \
effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune) \
)
AddElement(/datum/element/bane, target_type = /mob/living/simple_animal/revenant, damage_multiplier = 0, added_damage = 25, requires_combat_mode = FALSE)
/obj/item/gun/ballistic/bow/divine/proc/on_cult_rune_removed(obj/effect/target, mob/living/user)
SIGNAL_HANDLER
if(!istype(target, /obj/effect/rune))
return
var/obj/effect/rune/target_rune = target
if(target_rune.log_when_erased)
user.log_message("erased [target_rune.cultist_name] rune using a null rod", LOG_GAME)
message_admins("[ADMIN_LOOKUPFLW(user)] erased a [target_rune.cultist_name] rune with a null rod.")
SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_NARNAR] = TRUE
/obj/item/gun/ballistic/bow/divine/with_quiver/Initialize(mapload)
. = ..()
new /obj/item/storage/bag/quiver/holy(loc)
+2 -2
View File
@@ -242,14 +242,14 @@
* pierce_hit - are we piercing through or regular hitting
*/
/obj/projectile/proc/on_hit(atom/target, blocked = FALSE, pierce_hit)
if(fired_from)
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle)
// i know that this is probably more with wands and gun mods in mind, but it's a bit silly that the projectile on_hit signal doesn't ping the projectile itself.
// maybe we care what the projectile thinks! See about combining these via args some time when it's not 5AM
var/obj/item/bodypart/hit_limb
if(isliving(target))
var/mob/living/L = target
hit_limb = L.check_limb_hit(def_zone)
if(fired_from)
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle, hit_limb)
SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb)
if(QDELETED(src)) // in case one of the above signals deleted the projectile for whatever reason
@@ -128,7 +128,7 @@
var/obj/item/paper/autograph = writ_target
var/turf/tool_turf = get_turf(religious_tool)
writ_target = null
if(QDELETED(autograph) || !(tool_turf == autograph.loc)) //check if the same food is still there
if(QDELETED(autograph) || !(tool_turf == autograph.loc)) //check if the paper is still there
to_chat(user, span_warning("Your target left the altar!"))
return FALSE
autograph.visible_message(span_notice("Words magically form on [autograph]!"))
+151
View File
@@ -0,0 +1,151 @@
///apply a bunch of fire immunity effect to clothing
/datum/religion_rites/fireproof/proc/apply_fireproof(obj/item/clothing/fireproofed)
fireproofed.name = "unmelting [fireproofed.name]"
fireproofed.max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
fireproofed.heat_protection = chosen_clothing.body_parts_covered
fireproofed.resistance_flags |= FIRE_PROOF
/datum/religion_rites/fireproof
name = "Unmelting Protection"
desc = "Grants fire immunity to any piece of clothing."
ritual_length = 15 SECONDS
ritual_invocations = list("And so to support the holder of the Ever-Burning candle...",
"... allow this unworthy apparel to serve you ...",
"... make it strong enough to burn a thousand time and more ...")
invoke_msg = "... Come forth in your new form, and join the unmelting wax of the one true flame!"
favor_cost = 1000
///the piece of clothing that will be fireproofed, only one per rite
var/obj/item/clothing/chosen_clothing
/datum/religion_rites/fireproof/perform_rite(mob/living/user, atom/religious_tool)
for(var/obj/item/clothing/apparel in get_turf(religious_tool))
if(apparel.max_heat_protection_temperature >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
continue //we ignore anything that is already fireproof
chosen_clothing = apparel //the apparel has been chosen by our lord and savior
return ..()
return FALSE
/datum/religion_rites/fireproof/invoke_effect(mob/living/user, atom/religious_tool)
..()
if(!QDELETED(chosen_clothing) && get_turf(religious_tool) == chosen_clothing.loc) //check if the same clothing is still there
if(istype(chosen_clothing,/obj/item/clothing/suit/hooded))
for(var/obj/item/clothing/head/integrated_helmet in chosen_clothing.contents) //check if the clothing has a hood/helmet integrated and fireproof it if there is one.
apply_fireproof(integrated_helmet)
apply_fireproof(chosen_clothing)
playsound(get_turf(religious_tool), 'sound/magic/fireball.ogg', 50, TRUE)
chosen_clothing = null //our lord and savior no longer cares about this apparel
return TRUE
chosen_clothing = null
to_chat(user, span_warning("The clothing that was chosen for the rite is no longer on the altar!"))
return FALSE
/datum/religion_rites/burning_sacrifice
name = "Burning Offering"
desc = "Sacrifice a buckled burning corpse for favor, the more burn damage the corpse has the more favor you will receive."
ritual_length = 20 SECONDS
ritual_invocations = list("Burning body ...",
"... cleansed by the flame ...",
"... we were all created from fire ...",
"... and to it ...")
invoke_msg = "... WE RETURN! "
///the burning corpse chosen for the sacrifice of the rite
var/mob/living/carbon/chosen_sacrifice
/datum/religion_rites/burning_sacrifice/perform_rite(mob/living/user, atom/religious_tool)
if(!ismovable(religious_tool))
to_chat(user, span_warning("This rite requires a religious device that individuals can be buckled to."))
return FALSE
var/atom/movable/movable_reltool = religious_tool
if(!movable_reltool)
return FALSE
if(!LAZYLEN(movable_reltool.buckled_mobs))
to_chat(user, span_warning("Nothing is buckled to the altar!"))
return FALSE
for(var/corpse in movable_reltool.buckled_mobs)
if(!iscarbon(corpse))// only works with carbon corpse since most normal mobs can't be set on fire.
to_chat(user, span_warning("Only carbon lifeforms can be properly burned for the sacrifice!"))
return FALSE
chosen_sacrifice = corpse
if(chosen_sacrifice.stat != DEAD)
to_chat(user, span_warning("You can only sacrifice dead bodies, this one is still alive!"))
return FALSE
if(!chosen_sacrifice.on_fire)
to_chat(user, span_warning("This corpse needs to be on fire to be sacrificed!"))
return FALSE
return ..()
/datum/religion_rites/burning_sacrifice/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
if(!(chosen_sacrifice in religious_tool.buckled_mobs)) //checks one last time if the right corpse is still buckled
to_chat(user, span_warning("The right sacrifice is no longer on the altar!"))
chosen_sacrifice = null
return FALSE
if(!chosen_sacrifice.on_fire)
to_chat(user, span_warning("The sacrifice is no longer on fire, it needs to burn until the end of the rite!"))
chosen_sacrifice = null
return FALSE
if(chosen_sacrifice.stat != DEAD)
to_chat(user, span_warning("The sacrifice has to stay dead for the rite to work!"))
chosen_sacrifice = null
return FALSE
var/favor_gained = 100 + round(chosen_sacrifice.getFireLoss())
GLOB.religious_sect.adjust_favor(favor_gained, user)
to_chat(user, span_notice("[GLOB.deity] absorbs the burning corpse and any trace of fire with it. [GLOB.deity] rewards you with [favor_gained] favor."))
chosen_sacrifice.dust(force = TRUE)
playsound(get_turf(religious_tool), 'sound/effects/supermatter.ogg', 50, TRUE)
chosen_sacrifice = null
return TRUE
/datum/religion_rites/infinite_candle
name = "Immortal Candles"
desc = "Creates 5 candles that never run out of wax."
ritual_length = 10 SECONDS
invoke_msg = "Burn bright, little candles, for you will only extinguish along with the universe."
favor_cost = 200
/datum/religion_rites/infinite_candle/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
var/altar_turf = get_turf(religious_tool)
for(var/i in 1 to 5)
new /obj/item/flashlight/flare/candle/infinite(altar_turf)
playsound(altar_turf, 'sound/magic/fireball.ogg', 50, TRUE)
return TRUE
/datum/religion_rites/blazing_star
name = "Blazing Star"
desc = "Enchants a holy arrow to set someone on fire on hit, or if the victim is already on fire... note, this consumes the arrow."
ritual_length = 15 SECONDS
ritual_invocations = list(
"And so to keep the Ever-Burning candle protected ...",
"... grant this feeble bolt your blessing ...",
"... make it burn bright ...",
)
invoke_msg = "... a blazing star is born!"
favor_cost = 2000
///arrow to enchant
var/obj/item/ammo_casing/caseless/arrow/holy/enchant_target
/datum/religion_rites/blazing_star/perform_rite(mob/living/user, atom/religious_tool)
for(var/obj/item/ammo_casing/caseless/arrow/holy/can_enchant in get_turf(religious_tool))
if(istype(can_enchant, /obj/item/ammo_casing/caseless/arrow/holy/blazing))
continue
enchant_target = can_enchant
return ..()
to_chat(user, span_warning("You need to place a holy arrow on [religious_tool] to do this!"))
return FALSE
/datum/religion_rites/blazing_star/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
var/obj/item/ammo_casing/caseless/arrow/holy/enchanting = enchant_target
var/turf/tool_turf = get_turf(religious_tool)
enchant_target = null
if(QDELETED(enchanting) || !(tool_turf == enchanting.loc)) //check if the arrow is still there
to_chat(user, span_warning("Your target left the altar!"))
return FALSE
enchanting.visible_message(span_notice("[enchant_target] is blessed by holy fire!"))
playsound(tool_turf, 'sound/effects/pray.ogg', 50, TRUE)
new /obj/item/ammo_casing/caseless/arrow/holy/blazing(tool_turf)
qdel(enchanting)
return TRUE
+8
View File
@@ -208,6 +208,14 @@
rites_list = list(/datum/religion_rites/fireproof, /datum/religion_rites/burning_sacrifice, /datum/religion_rites/infinite_candle)
altar_icon_state = "convertaltar-red"
/datum/religion_sect/pyre/on_select()
. = ..()
AddComponent(/datum/component/sect_nullrod_bonus, list(
/obj/item/gun/ballistic/bow/divine/with_quiver = list(
/datum/religion_rites/blazing_star,
),
))
//candle sect bibles don't heal or do anything special apart from the standard holy water blessings
/datum/religion_sect/pyre/sect_bless(mob/living/target, mob/living/chap)
return TRUE
-118
View File
@@ -139,124 +139,6 @@
new blessing(altar_turf)
return TRUE
/**** Pyre God ****/
///apply a bunch of fire immunity effect to clothing
/datum/religion_rites/fireproof/proc/apply_fireproof(obj/item/clothing/fireproofed)
fireproofed.name = "unmelting [fireproofed.name]"
fireproofed.max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
fireproofed.heat_protection = chosen_clothing.body_parts_covered
fireproofed.resistance_flags |= FIRE_PROOF
/datum/religion_rites/fireproof
name = "Unmelting Protection"
desc = "Grants fire immunity to any piece of clothing."
ritual_length = 15 SECONDS
ritual_invocations = list("And so to support the holder of the Ever-Burning candle...",
"... allow this unworthy apparel to serve you ...",
"... make it strong enough to burn a thousand time and more ...")
invoke_msg = "... Come forth in your new form, and join the unmelting wax of the one true flame!"
favor_cost = 1000
///the piece of clothing that will be fireproofed, only one per rite
var/obj/item/clothing/chosen_clothing
/datum/religion_rites/fireproof/perform_rite(mob/living/user, atom/religious_tool)
for(var/obj/item/clothing/apparel in get_turf(religious_tool))
if(apparel.max_heat_protection_temperature >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
continue //we ignore anything that is already fireproof
chosen_clothing = apparel //the apparel has been chosen by our lord and savior
return ..()
return FALSE
/datum/religion_rites/fireproof/invoke_effect(mob/living/user, atom/religious_tool)
..()
if(!QDELETED(chosen_clothing) && get_turf(religious_tool) == chosen_clothing.loc) //check if the same clothing is still there
if(istype(chosen_clothing,/obj/item/clothing/suit/hooded))
for(var/obj/item/clothing/head/integrated_helmet in chosen_clothing.contents) //check if the clothing has a hood/helmet integrated and fireproof it if there is one.
apply_fireproof(integrated_helmet)
apply_fireproof(chosen_clothing)
playsound(get_turf(religious_tool), 'sound/magic/fireball.ogg', 50, TRUE)
chosen_clothing = null //our lord and savior no longer cares about this apparel
return TRUE
chosen_clothing = null
to_chat(user, span_warning("The clothing that was chosen for the rite is no longer on the altar!"))
return FALSE
/datum/religion_rites/burning_sacrifice
name = "Burning Offering"
desc = "Sacrifice a buckled burning corpse for favor, the more burn damage the corpse has the more favor you will receive."
ritual_length = 20 SECONDS
ritual_invocations = list("Burning body ...",
"... cleansed by the flame ...",
"... we were all created from fire ...",
"... and to it ...")
invoke_msg = "... WE RETURN! "
///the burning corpse chosen for the sacrifice of the rite
var/mob/living/carbon/chosen_sacrifice
/datum/religion_rites/burning_sacrifice/perform_rite(mob/living/user, atom/religious_tool)
if(!ismovable(religious_tool))
to_chat(user, span_warning("This rite requires a religious device that individuals can be buckled to."))
return FALSE
var/atom/movable/movable_reltool = religious_tool
if(!movable_reltool)
return FALSE
if(!LAZYLEN(movable_reltool.buckled_mobs))
to_chat(user, span_warning("Nothing is buckled to the altar!"))
return FALSE
for(var/corpse in movable_reltool.buckled_mobs)
if(!iscarbon(corpse))// only works with carbon corpse since most normal mobs can't be set on fire.
to_chat(user, span_warning("Only carbon lifeforms can be properly burned for the sacrifice!"))
return FALSE
chosen_sacrifice = corpse
if(chosen_sacrifice.stat != DEAD)
to_chat(user, span_warning("You can only sacrifice dead bodies, this one is still alive!"))
return FALSE
if(!chosen_sacrifice.on_fire)
to_chat(user, span_warning("This corpse needs to be on fire to be sacrificed!"))
return FALSE
return ..()
/datum/religion_rites/burning_sacrifice/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
if(!(chosen_sacrifice in religious_tool.buckled_mobs)) //checks one last time if the right corpse is still buckled
to_chat(user, span_warning("The right sacrifice is no longer on the altar!"))
chosen_sacrifice = null
return FALSE
if(!chosen_sacrifice.on_fire)
to_chat(user, span_warning("The sacrifice is no longer on fire, it needs to burn until the end of the rite!"))
chosen_sacrifice = null
return FALSE
if(chosen_sacrifice.stat != DEAD)
to_chat(user, span_warning("The sacrifice has to stay dead for the rite to work!"))
chosen_sacrifice = null
return FALSE
var/favor_gained = 100 + round(chosen_sacrifice.getFireLoss())
GLOB.religious_sect.adjust_favor(favor_gained, user)
to_chat(user, span_notice("[GLOB.deity] absorbs the burning corpse and any trace of fire with it. [GLOB.deity] rewards you with [favor_gained] favor."))
chosen_sacrifice.dust(force = TRUE)
playsound(get_turf(religious_tool), 'sound/effects/supermatter.ogg', 50, TRUE)
chosen_sacrifice = null
return TRUE
/datum/religion_rites/infinite_candle
name = "Immortal Candles"
desc = "Creates 5 candles that never run out of wax."
ritual_length = 10 SECONDS
invoke_msg = "Burn bright, little candles, for you will only extinguish along with the universe."
favor_cost = 200
/datum/religion_rites/infinite_candle/invoke_effect(mob/living/user, atom/movable/religious_tool)
..()
var/altar_turf = get_turf(religious_tool)
for(var/i in 1 to 5)
new /obj/item/flashlight/flare/candle/infinite(altar_turf)
playsound(altar_turf, 'sound/magic/fireball.ogg', 50, TRUE)
return TRUE
/*********Greedy God**********/
///all greed rites cost money instead
Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 133 KiB

+12 -4
View File
@@ -949,6 +949,7 @@
#include "code\datums\components\mutant_hands.dm"
#include "code\datums\components\nuclear_bomb_operator.dm"
#include "code\datums\components\omen.dm"
#include "code\datums\components\on_hit_effect.dm"
#include "code\datums\components\onwear_mood.dm"
#include "code\datums\components\orbiter.dm"
#include "code\datums\components\overlay_lighting.dm"
@@ -973,6 +974,7 @@
#include "code\datums\components\rotation.dm"
#include "code\datums\components\scope.dm"
#include "code\datums\components\seclight_attachable.dm"
#include "code\datums\components\sect_nullrod_bonus.dm"
#include "code\datums\components\seethrough.dm"
#include "code\datums\components\shell.dm"
#include "code\datums\components\shielded.dm"
@@ -1176,6 +1178,7 @@
#include "code\datums\elements\effect_trail.dm"
#include "code\datums\elements\embed.dm"
#include "code\datums\elements\empprotection.dm"
#include "code\datums\elements\envenomable_casing.dm"
#include "code\datums\elements\eyestab.dm"
#include "code\datums\elements\falling_hazard.dm"
#include "code\datums\elements\firestacker.dm"
@@ -1823,7 +1826,6 @@
#include "code\game\objects\items\handcuffs.dm"
#include "code\game\objects\items\his_grace.dm"
#include "code\game\objects\items\holosign_creator.dm"
#include "code\game\objects\items\holy_weapons.dm"
#include "code\game\objects\items\hot_potato.dm"
#include "code\game\objects\items\hourglass.dm"
#include "code\game\objects\items\inducer.dm"
@@ -3170,7 +3172,6 @@
#include "code\modules\clothing\suits\ablativecoat.dm"
#include "code\modules\clothing\suits\armor.dm"
#include "code\modules\clothing\suits\bio.dm"
#include "code\modules\clothing\suits\chaplainsuits.dm"
#include "code\modules\clothing\suits\cloaks.dm"
#include "code\modules\clothing\suits\costume.dm"
#include "code\modules\clothing\suits\ethereal.dm"
@@ -3576,7 +3577,6 @@
#include "code\modules\jobs\job_types\botanist.dm"
#include "code\modules\jobs\job_types\captain.dm"
#include "code\modules\jobs\job_types\cargo_technician.dm"
#include "code\modules\jobs\job_types\chaplain.dm"
#include "code\modules\jobs\job_types\chemist.dm"
#include "code\modules\jobs\job_types\chief_engineer.dm"
#include "code\modules\jobs\job_types\chief_medical_officer.dm"
@@ -3625,6 +3625,10 @@
#include "code\modules\jobs\job_types\antagonists\space_wizard.dm"
#include "code\modules\jobs\job_types\antagonists\wizard_apprentice.dm"
#include "code\modules\jobs\job_types\antagonists\xenomorph.dm"
#include "code\modules\jobs\job_types\chaplain\chaplain.dm"
#include "code\modules\jobs\job_types\chaplain\chaplain_costumes.dm"
#include "code\modules\jobs\job_types\chaplain\chaplain_divine_archer.dm"
#include "code\modules\jobs\job_types\chaplain\chaplain_nullrod.dm"
#include "code\modules\jobs\job_types\ert\ert_generic.dm"
#include "code\modules\jobs\job_types\event\admin.dm"
#include "code\modules\jobs\job_types\event\fugitive.dm"
@@ -4526,13 +4530,16 @@
#include "code\modules\projectiles\guns\energy.dm"
#include "code\modules\projectiles\guns\magic.dm"
#include "code\modules\projectiles\guns\ballistic\automatic.dm"
#include "code\modules\projectiles\guns\ballistic\bow.dm"
#include "code\modules\projectiles\guns\ballistic\launchers.dm"
#include "code\modules\projectiles\guns\ballistic\pistol.dm"
#include "code\modules\projectiles\guns\ballistic\revolver.dm"
#include "code\modules\projectiles\guns\ballistic\rifle.dm"
#include "code\modules\projectiles\guns\ballistic\shotgun.dm"
#include "code\modules\projectiles\guns\ballistic\toy.dm"
#include "code\modules\projectiles\guns\ballistic\bows\_bow.dm"
#include "code\modules\projectiles\guns\ballistic\bows\bow_arrows.dm"
#include "code\modules\projectiles\guns\ballistic\bows\bow_quivers.dm"
#include "code\modules\projectiles\guns\ballistic\bows\bow_types.dm"
#include "code\modules\projectiles\guns\energy\beam_rifle.dm"
#include "code\modules\projectiles\guns\energy\dueling.dm"
#include "code\modules\projectiles\guns\energy\energy_gun.dm"
@@ -4668,6 +4675,7 @@
#include "code\modules\recycling\disposal\outlet.dm"
#include "code\modules\recycling\disposal\pipe.dm"
#include "code\modules\recycling\disposal\pipe_sorting.dm"
#include "code\modules\religion\pyre_rites.dm"
#include "code\modules\religion\religion_sects.dm"
#include "code\modules\religion\religion_structures.dm"
#include "code\modules\religion\rites.dm"