mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 00:29:02 +01:00
Cleans up + Improves bows, Sorts files, Adds the Divine Archer clothing, weapon, rite (#74811)
## About The Pull Request ### Divine Archer 🏹  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:
+18
-61
@@ -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)
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user