diff --git a/__DEFINES/_macros.dm b/__DEFINES/_macros.dm
index 2d9ae93e89ac..205e10e70ee0 100644
--- a/__DEFINES/_macros.dm
+++ b/__DEFINES/_macros.dm
@@ -206,7 +206,11 @@
#define isgripper(G) (istype(G, /obj/item/weapon/gripper))
-#define isholyweapon(I) (istype(I, /obj/item/weapon/nullrod) || istype(I, /obj/item/weapon/gun/hookshot/whip/vampkiller))
+#define isholyweapon(I) (istype(I, /obj/item/weapon/storage/bible)\
+ || istype(I, /obj/item/weapon/nullrod)\
+ || istype(I, /obj/item/weapon/gun/hookshot/whip/vampkiller/true)\
+ || istype(I, /obj/item/projectile/hookshot/whip/vampkiller/true)\
+ || istype(I, /obj/item/weapon/boomerang/cross))
#define isholyprotection(I) (istype(I, /obj/item/weapon/nullrod))
diff --git a/__DEFINES/reagents.dm b/__DEFINES/reagents.dm
index 02f91b12ad57..893f4091ddf1 100644
--- a/__DEFINES/reagents.dm
+++ b/__DEFINES/reagents.dm
@@ -38,6 +38,7 @@
#define STOXIN "stoxin"
#define INAPROVALINE "inaprovaline"
#define HOLYWATER "holywater"
+#define SACREDWATER "sacredwater"
#define SEROTROTIUM "serotrotium"
#define SILICATE "silicate"
#define OXYGEN "oxygen"
diff --git a/__DEFINES/setup.dm b/__DEFINES/setup.dm
index df1c4a54ba0d..603b560b8af8 100644
--- a/__DEFINES/setup.dm
+++ b/__DEFINES/setup.dm
@@ -1977,6 +1977,11 @@ var/list/weekend_days = list("Friday", "Saturday", "Sunday")
#define PS_NARSIEHASRISEN3 "Nar-SieHasRisen3"
#define PS_ZAS_DUST "ZAS Dust"
#define PS_DANDELIONS "Dandelions"
+#define PS_CROSS_DUST "Cross Dust"
+#define PS_CROSS_ORB "Cross Orb"
+#define PS_SACRED_FLAME "Sacred Flame"
+#define PS_SACRED_FLAME2 "Sacred Flame2"
+#define PS_BIBLE_PAGE "Bible Page"
//Particles variable defines
#define PVAR_SPAWNING "spawning"
diff --git a/code/datums/gamemode/factions/bloodcult/bloodcult_effects.dm b/code/datums/gamemode/factions/bloodcult/bloodcult_effects.dm
index 138915e8d621..702bf66957e4 100644
--- a/code/datums/gamemode/factions/bloodcult/bloodcult_effects.dm
+++ b/code/datums/gamemode/factions/bloodcult/bloodcult_effects.dm
@@ -110,17 +110,23 @@
/obj/effect/afterimage/black
image_color = "black"
-/obj/effect/afterimage/New(var/turf/loc, var/atom/model, var/fadout = 5)
+/obj/effect/afterimage/richter_tackle/New()
+ ..()
+ transform = matrix()
+ pixel_x = 0
+ pixel_y = 0
+
+/obj/effect/afterimage/New(var/turf/loc, var/atom/model, var/fadout = 5, var/initial_alpha = 255, var/lay = NARSIE_GLOW, var/pla = ABOVE_LIGHTING_PLANE)
..()
if(model)
- src.appearance = model.appearance
+ appearance = model.appearance
invisibility = 0
- alpha = 255
+ alpha = initial_alpha
dir = model.dir
if (image_color)
color = image_color
- layer = NARSIE_GLOW
- plane = ABOVE_LIGHTING_PLANE
+ layer = lay
+ plane = pla
animate(src,alpha = 0, time = fadout)
spawn(fadout)
qdel(src)
diff --git a/code/datums/gamemode/factions/bloodcult/bloodcult_mobs_and_constructs.dm b/code/datums/gamemode/factions/bloodcult/bloodcult_mobs_and_constructs.dm
index 09fd6fdf1eef..992afc8959af 100644
--- a/code/datums/gamemode/factions/bloodcult/bloodcult_mobs_and_constructs.dm
+++ b/code/datums/gamemode/factions/bloodcult/bloodcult_mobs_and_constructs.dm
@@ -13,6 +13,13 @@
var/turf/crashing = null
spell_on_use_inhand = /spell/juggerdash //standard jug gets forcewall, but this seems better for perfect
+/mob/living/simple_animal/construct/armoured/perfect/special_thrown_behaviour()
+ dash_dir = dir
+ throwing = 2//dashing through windows and grilles
+
+/mob/living/simple_animal/construct/armoured/perfect/get_afterimage()
+ return "red"
+
/mob/living/simple_animal/construct/armoured/perfect/to_bump(var/atom/obstacle)
if(src.throwing)
var/breakthrough = 0
diff --git a/code/datums/gamemode/role/cultist.dm b/code/datums/gamemode/role/cultist.dm
index c95dc11e4d17..408b0b13280a 100644
--- a/code/datums/gamemode/role/cultist.dm
+++ b/code/datums/gamemode/role/cultist.dm
@@ -552,7 +552,7 @@
H.stuttering = max(H.stuttering, 12)
H.Jitter(12)
-/datum/role/cultist/handle_splashed_reagent(var/reagent_id)//also proc'd when holy water is drinked or ingested in any way
+/datum/role/cultist/handle_splashed_reagent(var/reagent_id, var/method, var/volume)//also proc'd when holy water is drinked or ingested in any way
var/mob/living/carbon/human/H = antag.current
if (!istype(H))
return
@@ -561,11 +561,17 @@
holywarning_cooldown = 5
to_chat(H, "The cold touch of holy water makes your head spin, you're having trouble walking straight.")
- if (reagent_id == HOLYWATER || reagent_id == INCENSE_HAREBELLS)
- H.eye_blurry = max(H.eye_blurry, 12)
- H.Dizzy(12)
- H.stuttering = max(H.stuttering, 12)
- H.Jitter(12)
+ if (reagent_id == SACREDWATER)
+ if (holywarning_cooldown <= 0)
+ holywarning_cooldown = 5
+ to_chat(H, "The burning touch of sacred water sears your skin.")
+
+ switch(reagent_id)
+ if (HOLYWATER,INCENSE_HAREBELLS,SACREDWATER)
+ H.eye_blurry = max(H.eye_blurry, 12)
+ H.Dizzy(12)
+ H.stuttering = max(H.stuttering, 12)
+ H.Jitter(12)
/datum/role/cultist/proc/write_rune(var/word_to_draw)
var/mob/living/user = antag.current
diff --git a/code/datums/gamemode/role/role.dm b/code/datums/gamemode/role/role.dm
index a73b10868f2f..b623f9d45b0b 100644
--- a/code/datums/gamemode/role/role.dm
+++ b/code/datums/gamemode/role/role.dm
@@ -579,7 +579,7 @@
/datum/role/proc/handle_reagent(var/reagent_id)
return
-/datum/role/proc/handle_splashed_reagent(var/reagent_id)
+/datum/role/proc/handle_splashed_reagent(var/reagent_id, var/method, var/volume)
return
//Does the role have special clothing restrictions?
diff --git a/code/datums/gamemode/role/vampire_role.dm b/code/datums/gamemode/role/vampire_role.dm
index 71f001c9ed2a..a28726504e5f 100644
--- a/code/datums/gamemode/role/vampire_role.dm
+++ b/code/datums/gamemode/role/vampire_role.dm
@@ -424,7 +424,7 @@
/datum/role/vampire/handle_reagent(var/reagent_id)
switch(reagent_id)
- if (HOLYWATER,INCENSE_HAREBELLS)
+ if (HOLYWATER,INCENSE_HAREBELLS,SACREDWATER)
var/mob/living/carbon/human/H = antag.current
if (!istype(H))
return
@@ -436,12 +436,9 @@
to_chat(H, "A freezing liquid permeates your bloodstream. You're still too human to be smited!")
smitecounter += 2 //Basically nothing, unless you drank multiple bottles of holy water (250 units to catch on fire !)
-/*
- Commented out for now.
-
-/datum/role/vampire/handle_splashed_reagent(var/reagent_id)
+/datum/role/vampire/handle_splashed_reagent(var/reagent_id, var/method, var/volume)
switch (reagent_id)
- if (HOLYWATER)
+ if (HOLYWATER,SACREDWATER)
var/mob/living/carbon/human/H = antag.current
if (!istype(H))
return
@@ -483,8 +480,6 @@
H.take_organ_damage(min(15, volume * 2))
smitecounter += 5
-*/
-
/*
-- Helpers --
*/
diff --git a/code/datums/religions.dm b/code/datums/religions.dm
index 84acf1485855..fc91c78489c1 100755
--- a/code/datums/religions.dm
+++ b/code/datums/religions.dm
@@ -67,12 +67,15 @@ var/list/tgui_religion_data
var/datum/religion/religion = new path
var/obj/item/weapon/storage/fancy/incensebox/incensebox_path = religion.preferred_incense
var/incense_fragrance = initial(incensebox_path.fragrance)
+ var/list/bible_style = all_bible_styles[religion.bookstyle]
+ if (islist(bible_style))
+ bible_style = bible_style["icon"]
data_religions += list(list(
"name" = religion.name,
"keywords" = religion.keys,
"deityName" = religion.deity_name,
"bibleStyle" = religion.bookstyle,
- "bibleStyleIcon" = all_bible_styles[religion.bookstyle],
+ "bibleStyleIcon" = bible_style,
"bibleName" = religion.bible_name,
"maleAdept" = religion.male_adept,
"femaleAdept" = religion.female_adept,
@@ -82,7 +85,6 @@ var/list/tgui_religion_data
"preferredIncense" = incense_fragrance,
"notes" = religion.ui_notes(),
))
-
var/list/data_bible_styles = data["bibleStyles"]
for(var/name in all_bible_styles)
var/icon_name = all_bible_styles[name]
@@ -1429,8 +1431,10 @@ var/list/all_bible_styles = list(
bookstyle = "Holy Grimoire"
/datum/religion/belmont/equip_chaplain(var/mob/living/carbon/human/H)
- H.equip_or_collect(new /obj/item/clothing/suit/vamphunter, slot_w_uniform)
- H.equip_or_collect(new /obj/item/clothing/head/vamphunter, slot_shoes)
+ H.collect_in_backpack(new /obj/item/clothing/suit/vamphunter)
+ H.collect_in_backpack(new /obj/item/clothing/head/vamphunter)
+ H.collect_in_backpack(new /obj/item/weapon/storage/box/castlevania(H))
+ H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/sacredwater, slot_r_store)
/datum/religion/esports
name = "E-Sports"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 726282d220a7..16f31f87ee81 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -156,8 +156,10 @@ var/global/list/ghdel_profiling = list()
/atom/proc/throw_impact(atom/hit_atom, var/speed, mob/user, var/list/impact_whitelist)
if(istype(hit_atom,/mob/living))
var/mob/living/M = hit_atom
- playsound(src, src.throw_impact_sound, 80, 1)
- M.hitby(src,speed,src.dir,impact_whitelist)
+ if (M.hitby(src,speed,src.dir,impact_whitelist))
+ playsound(loc,'sound/effects/slap2.ogg', 15, 1)//grabbed the item
+ else
+ playsound(src, src.throw_impact_sound, 80, 1)
log_attack("[hit_atom] ([M ? M.ckey : "what"]) was hit by [src] thrown by [user] ([user ? user.ckey : "what"])")
else if(isobj(hit_atom))
@@ -170,8 +172,9 @@ var/global/list/ghdel_profiling = list()
else if(isturf(hit_atom) && !istype(src,/obj/mecha))//heavy mechs don't just bounce off walls, also it can fuck up rocket dashes
var/turf/T = hit_atom
if(T.density)
- spawn(2)
- step(src, turn(src.dir, 180))
+ if (isturf(loc))
+ spawn(2)
+ step(src, turn(src.dir, 180))
if(istype(src,/mob/living))
var/mob/living/M = src
M.take_organ_damage(10)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index def3709762f7..eccf6f4cb6ec 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -576,6 +576,20 @@
throwing = 0
. = 0
+/atom/movable/proc/special_thrown_behaviour()
+ return
+
+/atom/movable/proc/get_afterimage()
+ return ""
+
+/atom/movable/proc/spawn_afterimage(var/afterimage,var/afterimage_step)
+ switch(afterimage)
+ if ("red")
+ new /obj/effect/afterimage/red(loc,src)
+ if ("richter tackle")
+ var/obj/effect/afterimage/richter_tackle/RT = new (loc,src)
+ RT.overlays += image('icons/effects/effects.dmi', src, "castlevania_tackle", dir = turn(SOUTH, 90 * afterimage_step))
+
/atom/movable/proc/throw_at(atom/target, range, speed, override = TRUE, var/fly_speed = 0, var/list/whitelist) //fly_speed parameter: if 0, does nothing. Otherwise, changes how fast the object flies WITHOUT affecting damage!
set waitfor = FALSE
if(!target || !src)
@@ -596,22 +610,9 @@
if(M_HULK in usr.mutations)
src.throwing = 2 // really strong throw!
- if(istype(src,/obj/mecha))
- var/obj/mecha/M = src
- M.dash_dir = dir
- src.throwing = 2// mechas will crash through windows, grilles, tables, people, you name it
-
- if(istype(src,/mob/living/simple_animal/hostile/humanoid/nurseunit))
- var/mob/living/simple_animal/hostile/humanoid/nurseunit/M = src
- M.dash_dir = dir
- src.throwing = 2
-
- var/afterimage = 0
- if(istype(src,/mob/living/simple_animal/construct/armoured/perfect))
- var/mob/living/simple_animal/construct/armoured/perfect/M = src
- M.dash_dir = dir
- src.throwing = 2
- afterimage = 1
+ special_thrown_behaviour()
+ var/afterimage = get_afterimage()
+ var/afterimage_step = 0
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
@@ -651,8 +652,8 @@
if(kinetic_acceleration>kinetic_sum)
fly_speed += kinetic_acceleration-kinetic_sum
kinetic_sum = kinetic_acceleration
- if(afterimage)
- new /obj/effect/afterimage/red(loc,src)
+ spawn_afterimage(afterimage,afterimage_step)
+ afterimage_step++
if(error < 0)
var/atom/step = get_step(src, dy)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
@@ -692,8 +693,8 @@
if(kinetic_acceleration>0)
fly_speed += kinetic_acceleration
kinetic_acceleration = 0
- if(afterimage)
- new /obj/effect/afterimage/red(loc,src)
+ spawn_afterimage(afterimage,afterimage_step)
+ afterimage_step++
if(error < 0)
var/atom/step = get_step(src, dx)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 4124d52ce8b8..c3c96fe40518 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -194,6 +194,10 @@
selected = null
..()
+/obj/mecha/special_thrown_behaviour()
+ dash_dir = dir
+ throwing = 2//dashing through windows and grilles
+
/obj/mecha/can_apply_inertia()
return 1 //No anchored check - so that mechas can fly off into space
@@ -802,7 +806,7 @@
if(equipment.len >= max_equip)
return 0
return max_equip - equipment.len
-
+
/obj/mecha/proc/is_killdozer()
for(var/obj/I in equipment)
if(istype(I, /obj/item/mecha_parts/mecha_equipment/passive/killdozer_kit))
diff --git a/code/game/objects/effects/particles_system.dm b/code/game/objects/effects/particles_system.dm
index 54ed151a715a..6f2a82ccc50c 100644
--- a/code/game/objects/effects/particles_system.dm
+++ b/code/game/objects/effects/particles_system.dm
@@ -178,6 +178,11 @@ var/list/particle_string_to_type = list(
PS_NARSIEHASRISEN3 = /particles/narsie_has_risen/last,
PS_ZAS_DUST = /particles/zas_dust,
PS_DANDELIONS = /particles/dandelions,
+ PS_CROSS_DUST = /particles/cross_dust,
+ PS_CROSS_ORB = /particles/cross_orb,
+ PS_SACRED_FLAME = /particles/sacred_flame,
+ PS_SACRED_FLAME2 = /particles/sacred_flame/alt,
+ PS_BIBLE_PAGE = /particles/bible_page,
)
/particles
@@ -486,3 +491,81 @@ var/list/particle_string_to_type = list(
spawn(SSair.wait)
if (last_pollen_time == this_pollen_time)
adjust_particles(PVAR_SPAWNING, 0, pollen)
+
+//CROSS DUST & ORBB
+/particles/cross_dust
+ width = 64
+ height = 64
+ count = 10
+
+ lifespan = 10
+ fade = 2
+ spawning = 1.5
+
+ icon = 'icons/effects/effects_particles.dmi'
+ icon_state = list("cross_dust_1","cross_dust_2","cross_dust_3")
+ position = generator("box", list(-12,-12), list(12,12))
+ velocity = list(0,-2)
+ drift = generator("box", list(-0.2,-0.2), list(0.2,0.2))
+
+ appearance_flags = RESET_COLOR|RESET_ALPHA
+ blend_mode = BLEND_ADD
+ plane = ABOVE_LIGHTING_PLANE
+
+
+/particles/cross_orb
+ count = 2
+
+ lifespan = 10
+ spawning = 0.5
+
+ icon = 'icons/effects/effects_particles.dmi'
+ icon_state = list("cross_orb")
+ position = generator("box", list(-12,-12), list(12,12))
+ velocity = list(0,-2)
+ friction = 0.1
+ drift = generator("box", list(-0.2,-0.2), list(0.2,0.2))
+ grow = list(-0.2, -0.2)
+
+ appearance_flags = RESET_COLOR|RESET_ALPHA
+ plane = ABOVE_LIGHTING_PLANE
+
+//SACRED FLAME
+/particles/sacred_flame
+ width = 96
+ height = 96
+ count = 30
+
+ lifespan = 10
+ fade = 5
+ spawning = 1.5
+
+ icon = 'icons/effects/effects_particles.dmi'
+ icon_state = "sacred_flame"
+ position = generator("box", list(-15,-15), list(15,15))
+ friction = 0.1
+ drift = generator("box", list(-0.2,-0.2), list(0.2,0.2))
+ scale = list(0.6, 0.6)
+ grow = list(0.1, 0.1)
+
+/particles/sacred_flame/alt
+ plane = LIGHTING_PLANE
+
+//BIBLE PAGE
+/particles/bible_page
+ width = 96
+ height = 96
+ count = 1
+
+ lifespan = 10
+ fade = 5
+ spawning = 0//we set the spawning after velocity has been adjusted
+
+ icon = 'icons/effects/effects_particles.dmi'
+ icon_state = "bible_page"
+ rotation = generator("num", 0,360)
+ spin = 10
+ grow = generator("box", list(-0.3,-0.3), list(0,0))
+
+ appearance_flags = RESET_COLOR|RESET_ALPHA
+ plane = ABOVE_LIGHTING_PLANE
diff --git a/code/game/objects/effects/trackers.dm b/code/game/objects/effects/trackers.dm
index 3142f914144d..e0ef687ef38e 100644
--- a/code/game/objects/effects/trackers.dm
+++ b/code/game/objects/effects/trackers.dm
@@ -8,6 +8,7 @@
icon_state = "soul2"
mouse_opacity = 0
animate_movement = 0
+ density = 0
var/absolute_X = 0
var/absolute_Y = 0
var/atom/target = null
@@ -33,6 +34,9 @@
color = "red"
/obj/effect/tracker/proc/process_step()
+ set waitfor = 0
+ if (gcDestroyed)
+ return
if(!target)
target = pick(player_list)
return
@@ -48,9 +52,11 @@
var/dist = sqrt(abs(dx)**2 + abs(dy)**2)
if(dist > maxdist)
+ on_expire(FALSE)
qdel(src)
return
else if(dist < 16)
+ on_expire(FALSE)
qdel(src)
return
@@ -70,9 +76,32 @@
speed += acceleration
- x = absolute_X/WORLD_ICON_SIZE
- y = absolute_Y/WORLD_ICON_SIZE
+ var/next_x = absolute_X/WORLD_ICON_SIZE
+ var/next_y = absolute_Y/WORLD_ICON_SIZE
+
+ if (density && ((x != next_x) || (y != next_y)))//changing tile, let's check for collisions if enabled
+ var/turf/T_old = locate(x,y,z)
+ var/turf/T_new = locate(next_x,next_y,z)
+ if (!T_new.Cross(src,T_old))
+ if (to_bump(T_new))
+ on_expire(TRUE)
+ qdel(src)
+ return
+ for (var/atom/A in T_new)
+ if (A == src)
+ continue
+ if (!A.Cross(src,T_old))
+ if (to_bump(A))
+ on_expire(TRUE)
+ qdel(src)
+ return
+
+ if (!gcDestroyed)
+ x = next_x
+ y = next_y
+
update_icon()
+ on_step()
sleep(refresh)
process_step()
@@ -91,6 +120,16 @@
/obj/effect/tracker/singularity_pull()
return
+/obj/effect/tracker/proc/on_expire(var/bumped_atom = FALSE)
+ return
+
+/obj/effect/tracker/proc/on_step()
+ return
+
+//used by dense trakers such as boomerangs
+/obj/effect/tracker/to_bump(var/atom/Obstacle)
+ return FALSE
+
/proc/make_tracker_effects(tr_source, tr_destination, var/tr_number = 10, var/custom_icon_state = "soul", var/number_of_icons = 3, var/tr_type = /obj/effect/tracker/soul, var/force_size)
spawn()
var/list/possible_icons = list()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index a63d0e47abf0..ae608f96c06b 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1644,7 +1644,7 @@ var/global/objects_thrown_when_explode = FALSE
usr.put_in_hand(OI.hand_index, src)
add_fingerprint(usr)
-/obj/item/proc/pre_throw(atom/movable/target)
+/obj/item/proc/pre_throw(var/atom/movable/target,var/mob/living/user)
return
/obj/item/proc/recharger_process(var/obj/machinery/recharger/charger)
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index a6bb0860e5a3..14181830098a 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -319,6 +319,8 @@ var/list/datum/stack_recipe/silver_recipes = list ( \
new/datum/stack_recipe/dorf("chain", /obj/item/stack/chains, 2, 1, 20, 5, inherit_material = TRUE),
null,
blacksmithing_recipes,
+ null,
+ new/datum/stack_recipe/blacksmithing("battle cross", /obj/item/weapon/boomerang/cross, 16, time = 8 SECONDS, required_strikes = 20),
)
/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null)
diff --git a/code/game/objects/items/weapons/boomerang.dm b/code/game/objects/items/weapons/boomerang.dm
index 9c0606abfba2..6721ea862983 100644
--- a/code/game/objects/items/weapons/boomerang.dm
+++ b/code/game/objects/items/weapons/boomerang.dm
@@ -1,25 +1,286 @@
+
+//////////////////////////////BOOMERANG ITEM////////////////////////////////
+
/obj/item/weapon/boomerang
name = "boomerang"
desc = "A heavy, curved piece of wood used by Space Australians for hunting, sport, entertainment, cooking, religious rituals and warfare. When thrown, it will either deal a devastating blow to somebody's head, or return back to the thrower." //also used for shitposting
+ icon = 'icons/obj/boomerang.dmi'
icon_state = "boomerang"
+ item_state = null
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/boomerang.dmi', "right_hand" = 'icons/mob/in-hand/right/boomerang.dmi')
w_class = W_CLASS_MEDIUM
-
- throwforce = 16
+ force = 7
+ throwforce = 10
throw_range = 7
throw_speed = 5
- force = 7
-
starting_materials = list(MAT_WOOD = CC_PER_SHEET_WOOD * 6)
w_type = RECYK_WOOD
flammable = TRUE
-/obj/item/weapon/boomerang/Destroy()
+ var/mob/living/carbon/originator = null
+ var/thrown = FALSE
+ var/throw_mult = 1
+ var/stun = 0
+ var/weaken = 2
+ var/sound_throw = 'sound/weapons/boomerang_start.ogg'
+ var/sound_loop = 'sound/weapons/boomerang_loop.ogg'
+ var/sound_bump = 'sound/weapons/kick.ogg'
+ var/last_sound_loop = 0
+
+/obj/item/weapon/boomerang/proc/on_step(var/obj/O)
+ if (world.time > (last_sound_loop+10))
+ last_sound_loop = world.time
+ playsound(loc,sound_loop, 35, 0)
+
+/obj/item/weapon/boomerang/proc/return_check()//lets you add conditions for the boomerang to come back
+ return TRUE
+
+/obj/item/weapon/boomerang/proc/apply_status_effects(var/mob/living/carbon/C, var/minimal_effect = 0)
+ var/obj/item/I = null
+ if (ishuman(C))
+ var/mob/living/carbon/human/H = C
+ I = H.head
+ else if (ismonkey(C))
+ var/mob/living/carbon/monkey/M = C
+ I = M.hat
+ if (istype(I) && (I.armor["melee"] > 0 || I.armor["bullet"] > 0))
+ return
+ C.Stun(max(minimal_effect,stun))
+ C.Knockdown(max(minimal_effect,weaken))
+
+/obj/item/weapon/boomerang/proc/on_return()
+ if (istype(originator) && clumsy_check(originator) && prob(30))
+ to_chat(originator, "Your clumsy hands fail to catch \the [src]!")
+ apply_status_effects(originator,1)
+ playsound(src, throw_impact_sound, 80, 1)
+ log_attack("[originator] ([originator ? originator.ckey : "what"]) was hit by [src] thrown by themselves because they're just that clumsy.")
+ return TRUE
+ return (istype(originator) && originator.can_catch(src, throw_speed*throw_mult) && originator.put_in_hands(src))
+
+/obj/item/weapon/boomerang/pickup(var/mob/user)
+ thrown = FALSE
+
+/obj/item/weapon/boomerang/dropped(var/mob/user)
+ reset_plane_and_layer()
+
+/obj/item/weapon/boomerang/attack_self(var/mob/living/user)
+ if (!user.in_throw_mode)
+ user.throw_mode_on()
+
+/obj/item/weapon/boomerang/pre_throw(var/atom/movable/target, var/mob/living/user)
+ thrown = TRUE
+ throw_mult = 1
+ playsound(loc,sound_throw, 70, 0)
+ if (user)
+ originator = user
+ if(ishuman(originator))
+ var/mob/living/carbon/human/H = originator
+ throw_mult = H.species.throw_mult
+ throw_mult += (H.get_strength()-1)/2 //For each level of strength above 1, add 0.5
+ return ..()
+
+/obj/item/weapon/boomerang/throw_at(var/atom/targ, var/range, var/speed, var/override = 1, var/fly_speed = 0)
+ var/turf/starting = get_turf(src)
+ var/turf/target = get_turf(targ)
+ var/obj/item/projectile/boomerang/B = new (starting)
+ B.name = name
+ B.desc = desc
+ B.original = target
+ B.target = target
+ B.current = starting
+ B.starting = starting
+ B.yo = target.y - starting.y
+ B.xo = target.x - starting.x
+ //B.damage = throwforce //Actual damage is down by calls to throw_impact(). The projectile damage should remain at zero unless you want to break open crates with it
+ B.projectile_speed = 0.66/throw_mult
+ B.icon_state = "[icon_state]-spin"
+ B.overlays += overlays
+ B.plane = plane
+ B.color = color
+ B.luminosity = luminosity
+ B.firer = originator
+ B.stun = stun
+ B.kill_count = throw_range
+ B.weaken = weaken
+ B.OnFired()
+ B.process()
+ B.boomerang = src
+ forceMove(B)
+
+/obj/item/weapon/boomerang/apply_inertia(direction)
+ if (!thrown)
+ return ..()
+
+//////////////////////////////BOOMERANG PROJECTILE - INITIAL////////////////////////////////
+
+/obj/item/projectile/boomerang
+ name = "boomerang"
+ icon = 'icons/obj/boomerang.dmi'
+ icon_state = "boomerang-spin"
+ damage = 0
+ flag = "energy"
+ custom_impact = 1
+ projectile_speed = 0.66
+ lock_angle = 1
+ kill_count = 7
+ grillepasschance = 0
+ var/obj/item/weapon/boomerang/boomerang
+ var/list/hit_atoms = list()
+
+/obj/item/projectile/boomerang/to_bump(var/atom/A)
+ if (!(A in hit_atoms))
+ hit_atoms += A
+ if (boomerang)
+ boomerang.throw_impact(A,boomerang.throw_speed*boomerang.throw_mult,boomerang.originator)
+ if (boomerang.loc != src)//boomerang got grabbed most likely
+ boomerang.originator = null
+ boomerang = null
+ qdel(src)
+ return
+ else if (iscarbon(A))
+ boomerang.apply_status_effects(A)
+ forceMove(A.loc)
+ A.Bumped(boomerang)
+ bumped = TRUE
+ bullet_die()
+ return
+ A.Bumped(boomerang)
+ return ..(A)
+
+/obj/item/projectile/boomerang/OnDeath()
+ if (boomerang && bumped)
+ playsound(loc,boomerang.sound_bump, 50, 1)
+ return_to_sender()
+
+/obj/item/projectile/boomerang/on_step()
+ if (boomerang && !boomerang.gcDestroyed)
+ boomerang.on_step(src)
+ else
+ bullet_die()
+
+/obj/item/projectile/boomerang/proc/return_to_sender()
+ if (!boomerang)
+ qdel(src)
+ return
+ var/turf/T = get_turf(src)
+ if (!boomerang.return_check())
+ boomerang.forceMove(T)
+ boomerang.thrown = FALSE
+ boomerang.dropped()
+ boomerang = null
+ return
+ //if there is no air, no return trip
+ var/datum/gas_mixture/current_air = T.return_air()
+ var/atmosphere = 0
+ if(current_air)
+ atmosphere = current_air.return_pressure()
+
+ if (atmosphere < ONE_ATMOSPHERE/2)
+ visible_message("\The [boomerang] dramatically fails to come back due to the lack of air pressure.")
+ boomerang.forceMove(T)
+ boomerang.thrown = FALSE
+ boomerang.dropped()
+ boomerang = null
+ return
+
+ var/atom/return_target
+ if (firer)
+ if (isturf(firer.loc) && (firer.z == z) && (get_dist(firer,src) <= 26))
+ return_target = firer
+
+ if (!return_target)
+ return_target = starting
+
+ var/obj/effect/tracker/boomerang/Tr = new (T)
+ Tr.target = return_target
+ Tr.appearance = appearance
+ Tr.refresh = projectile_speed
+ Tr.luminosity = luminosity
+ Tr.boomerang = boomerang
+ Tr.hit_atoms = hit_atoms.Copy()
+ boomerang.forceMove(Tr)
+ boomerang = null
+
+//////////////////////////////BOOMERANG TRACKER - RETURN////////////////////////////////
+
+/obj/effect/tracker/boomerang
+ name = "boomerang"
+ icon = 'icons/obj/boomerang.dmi'
+ icon_state = "boomerang-spin"
+ mouse_opacity = 1
+ density = 1
+ pass_flags = PASSTABLE | PASSRAILING
+ var/obj/item/weapon/boomerang/boomerang
+ var/list/hit_atoms = list()
+
+/obj/effect/tracker/boomerang/Destroy()
+ var/turf/T = get_turf(src)
+ if (T && boomerang)
+ boomerang.forceMove(T)
+ boomerang.thrown = FALSE
+ boomerang.dropped()
+ boomerang.originator = null
+ boomerang = null
..()
- throwing = 0
+/obj/effect/tracker/boomerang/on_step()
+ if (boomerang && !boomerang.gcDestroyed)
+ boomerang.on_step(src)
+ else
+ qdel(src)
+
+/obj/effect/tracker/boomerang/Bumped(var/atom/movable/AM)
+ make_contact(AM)
+
+/obj/effect/tracker/boomerang/to_bump(var/atom/Obstacle)
+ return make_contact(Obstacle)
+
+/obj/effect/tracker/boomerang/proc/make_contact(var/atom/Obstacle)
+ if (boomerang)
+ if (!(Obstacle in hit_atoms))
+ hit_atoms += Obstacle
+ if (Obstacle == boomerang.originator)
+ if (on_expire(FALSE))
+ qdel(src)
+ return TRUE
+ boomerang.throw_impact(Obstacle,boomerang.throw_speed*boomerang.throw_mult,boomerang.originator)
+ if (boomerang.loc != src)//boomerang got grabbed most likely
+ boomerang.originator = null
+ boomerang = null
+ qdel(src)
+ return TRUE
+ else if (iscarbon(Obstacle))
+ boomerang.apply_status_effects(Obstacle)
+ return FALSE
+ Obstacle.Bumped(boomerang)
+ if (!ismob(Obstacle))
+ on_expire(TRUE)
+ qdel(src)
+ return TRUE
+ return FALSE
+ else
+ qdel(src)
+ return FALSE
+/obj/effect/tracker/boomerang/on_expire(var/bumped_atom = FALSE)
+ if (boomerang && boomerang.originator && Adjacent(boomerang.originator))
+ if (boomerang.on_return())
+ playsound(loc,'sound/effects/slap2.ogg', 15, 1)
+ if (boomerang)
+ boomerang.originator = null
+ boomerang = null
+ return TRUE
+ else if (boomerang && bumped_atom)
+ playsound(loc,boomerang.sound_bump, 50, 1)
+ return FALSE
+
+
+
+//////////////////////////////BOOMERANG SUB-TYPES////////////////////////////////
+
+//Toy
/obj/item/weapon/boomerang/toy
name = "toy boomerang"
desc = "A small plastic boomerang for children."
@@ -30,66 +291,128 @@
throwforce = 2
force = 1
+ stun = 0
+ weaken = 0
+
+ sound_bump = 'sound/effects/pop.ogg'
+ throw_impact_sound = 'sound/weapons/tap.ogg'
starting_materials = list(MAT_PLASTIC = 1200)
melt_temperature = MELTPOINT_PLASTIC
w_type = RECYK_PLASTIC
-/obj/item/weapon/boomerang/throw_at(atom/target, range, speed, override = 1)
- if(!usr)
- return ..()
+//Castlevania, deals double damage to supernatural mobs
+/obj/item/weapon/boomerang/cross
+ name = "battle cross"
+ desc = "A holy silver cross that dispels evil and smites unholy creatures."
- spawn()
- animate(src, transform = turn(matrix(), 120), time = 5, loop = -1)
- animate(transform = turn(matrix(), 240), time = 5)
- animate(transform = null, time = 5)
+ icon_state = "cross_modern"
- while(throwing) //Wait until the boomerang is no longer flying. Check on 0.5-second intervals
- sleep(5)
+ starting_materials = list(MAT_SILVER = CC_PER_SHEET_SILVER * 16)
+ melt_temperature = MELTPOINT_SILVER
+ w_type = 0
+ luminosity = 2
- animate(src) //Stop the animation
+ stun = 1
+ weaken = 2
- var/turf/original = get_turf(usr)
- //HOW THIS WORKS
- //An imaginary circle is drawn at the target location. Its radius increases with the distance from center to the thrower
- //Three points are chosen on the circle (at angles 90, 0, -90 - assuming 0 is the direction of the throw)
- //The boomerang is thrown at the first point, then the second point, then the third point. Then it returns to the thrower's original position
+ sound_throw = 'sound/weapons/boomerang_cross_start.ogg'
+ sound_loop = 'sound/weapons/boomerang_cross_loop.ogg'
- var/circle_radius = 1+round(get_dist(usr, target) * 0.5) //Dist = 1, radius = 1. Dist = 2, radius = 2. Dist = 3, radius = 2. Dist = 7, radius = 4
+ var/flickering = 0
+ var/classic = FALSE
- //Get points
- var/list/points = list()
+/obj/item/weapon/boomerang/cross/New()
+ ..()
+ update_moody_light(icon, "[icon_state]-moody")
- var/c_dir = get_dir(usr, target)
- for(var/i = -1 to 1)
- var/m_dir = turn(c_dir, i*90)
- var/T = get_turf(target)
+/obj/item/weapon/boomerang/throw_at(var/atom/targ, var/range, var/speed, var/override = 1, var/fly_speed = 0)
+ plane = ABOVE_LIGHTING_PLANE
+ ..()
- for(var/step_n = 1 to circle_radius)
- if(circle_radius > 50)
- return
- else
- T = get_step(T, m_dir)
+/obj/item/weapon/boomerang/cross/on_step(var/obj/O)
+ ..()
+ dir = turn(dir, 45)
+ var/obj/effect/afterimage/A = new(O.loc, O, fadout = 5, initial_alpha = 100, pla = ABOVE_LIGHTING_PLANE)
+ A.icon_state = icon_state
+ A.dir = dir
+ A.layer = O.layer - 1
+ A.color = "#1E45FF"
+ if (istype(O,/obj/effect/tracker))//only display those particles on the way back
+ A.add_particles(PS_CROSS_DUST)
+ A.add_particles(PS_CROSS_ORB)
- points.Add(T)
+ flickering = (flickering + 1) % 4
+ if (flickering > 1)
+ O.color = "#53A6FF"
+ else
+ O.color = null
- for(var/turf/T in points)
- if(!..(T, range, speed, override, fly_speed = 1))
- return
- if(istype(loc, /turf/space)) //Boomerangs don't work in space
- return
+/obj/item/weapon/boomerang/cross/return_check()
+ if (originator && originator.mind)
+ if (istype(originator.mind.faith, /datum/religion/belmont))
+ return TRUE
+ to_chat(originator, "Only a true vampire hunter may use \the [src] to its full potential.")
+ return FALSE
- ..(original, range, speed, override, fly_speed = 1)
+/obj/item/weapon/boomerang/cross/throw_impact(var/atom/hit_atom, var/speed, var/mob/user, var/list/impact_whitelist)
+ if(istype(hit_atom,/obj/machinery/computer/arcade))
+ playsound(hit_atom,'sound/weapons/boomerang_cross_transform.ogg', 30, 0)
+ classic = !classic
+ icon_state = "[classic ? "cross_classic" : "cross_modern"]"
+ if (istype(loc,/obj))
+ var/obj/O = loc
+ O.icon_state = "[icon_state]-spin"
+ update_moody_light(icon, "[icon_state]-moody")
+ ..()
-/obj/item/weapon/boomerang/throw_impact(atom/hit_atom, var/speed, user)
- if(iscarbon(hit_atom) && !isslime(hit_atom))
- if(user == hit_atom)
- var/mob/living/carbon/L = hit_atom
+//Kamina
+/obj/item/weapon/boomerang/kaminaglasses
+ name = "Kamina's glasses"
+ desc = "I'm going to tell you something important now, so you better dig the wax out of those huge ears of yours and listen! The reputation of Team Gurren echoes far and wide. When they talk about its badass leader - the man of indomitable spirit and masculinity - they're talking about me! The mighty Kamina!"
- if(L.get_active_hand() == null)
- to_chat(hit_atom, "You catch \the [src]!")
- L.put_in_active_hand(src)
- throwing = 0
- return
+ icon_state = "kaminaglasses"
+
+ throwforce = 15
+ force = 10
+ stun = 0
+ weaken = 0
+
+ sound_bump = 'sound/effects/Glasshit.ogg'
+ throw_impact_sound = 'sound/weapons/bladeslice.ogg'
+ w_type = RECYK_GLASS
+ starting_materials = list(MAT_GLASS = CC_PER_SHEET_GLASS/2)
+ melt_temperature = MELTPOINT_GLASS
+
+ var/obj/item/clothing/glasses/kaminaglasses/KG = null
+
+/obj/item/weapon/boomerang/kaminaglasses/Destroy()
+ playsound(get_turf(src),'sound/effects/lagann_eyecatch2.ogg', 30, 0)
+ ..()
+
+/obj/item/weapon/boomerang/kaminaglasses/dropped(var/mob/user)
+ if (!thrown)
+ if (KG)
+ KG.forceMove(get_turf(src))
+ KG = null
+ qdel(src)
+ else
+ ..()
+
+/obj/item/weapon/boomerang/kaminaglasses/on_return()
+ if (istype(originator) && KG)
+ if (KG.mob_can_equip(originator, slot_glasses, TRUE) == CAN_EQUIP)
+ originator.equip_to_slot(KG, slot_glasses)
+ KG = null
+ loc = originator.loc//just to be sure that the sound is centered on them
+ qdel(src)
+ return TRUE
return ..()
+
+//Simon
+/obj/item/weapon/boomerang/kaminaglasses/simonglasses
+ name = "Simon's glasses"
+ desc = "Just who the hell do you think I am?"
+
+ icon_state = "simonglasses"
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index 6b846bb09958..45d04091f060 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -18,6 +18,13 @@
actions_types = list(/datum/action/item_action/convert)
rustle_sound = "pageturn"
+/obj/item/weapon/storage/bible/throw_at(var/atom/targ, var/range, var/speed, var/override = 1, var/fly_speed = 0)
+ var/mob/living/user = usr
+ if (istype(user) && istype(my_rel, /datum/religion/belmont) && user?.mind && istype(user.mind.faith, /datum/religion/belmont))
+ new /obj/effect/bible_spin(get_turf(src),usr,src)
+ return
+ ..()
+
/obj/item/weapon/storage/bible/suicide_act(var/mob/living/user)
user.visible_message("[user] is farting on \the [src]! It looks like \he's trying to commit suicide!")
user.emote("fart")
@@ -274,6 +281,8 @@
owner.mind.faith.convertAct(owner, subject, B) // usr = preacher ; target = subject
return TRUE
+// Cult Deconversion
+
/datum/deconversion_ritual
var/datum/role/cultist/cultist = null
var/cult_chaplain = FALSE
@@ -366,3 +375,70 @@
cultist.deconversion = null
cultist = null
..()
+
+// Belmont Bible Spin
+
+/obj/effect/bible_spin
+ var/mob/living/owner
+ var/obj/item/weapon/storage/bible/source
+ var/image/bible_image
+ var/current_spin = 0
+ var/lifetime = 5 SECONDS
+ var/lifetime_max = 5 SECONDS
+ var/distance = 0
+ var/distance_min = 8
+ var/distance_amplitude = 24
+ var/spin_speed = 30
+
+/obj/effect/bible_spin/New(var/turf/loc, var/_owner, var/_source)
+ ..()
+ if (!_owner || !_source)
+ qdel(src)
+ return
+ playsound(src, 'sound/items/bible_throw.ogg', 70, 0)
+ owner = _owner
+ source = _source
+ source.forceMove(src)
+ owner.lock_atom(src)
+ current_spin = dir2angle_t(owner.dir)
+ bible_image = image(source.icon, source, source.icon_state)
+ bible_image.plane = ABOVE_LIGHTING_PLANE
+ overlays += bible_image
+ spawn()
+ process_spin()
+
+/obj/effect/bible_spin/proc/process_spin()
+ set waitfor = 0
+
+ while(owner && !owner.gcDestroyed && source && !source.gcDestroyed && (source.loc == src) && lifetime > 0)
+ update_spin()
+ var/obj/effect/afterimage/A = new(loc, null, 15)
+ animate(A)
+ A.appearance = appearance
+ A.pixel_x = pixel_x
+ A.pixel_y = pixel_y
+ animate(A,alpha = 0, time = 10)
+ A.layer--
+ A.add_particles(PS_BIBLE_PAGE)
+ A.adjust_particles(PVAR_VELOCITY, list(pixel_x/2, pixel_y/2), PS_BIBLE_PAGE)
+ A.adjust_particles(PVAR_SPAWNING, 2, PS_BIBLE_PAGE)
+ if ((lifetime % 10) == 0)
+ playsound(src, 'sound/items/bible_spin.ogg', 50, 0)
+ for (var/mob/living/L in range(1, src))
+ if (!L.mind || !L.mind.faith || !istype(L.mind.faith, /datum/religion/belmont))
+ source.throw_impact(L,source.throw_speed*2,owner)
+ lifetime--
+ spawn(1)//making sure we're only spawning one page per afterimage
+ A.adjust_particles(PVAR_SPAWNING, 0, PS_BIBLE_PAGE)
+ sleep(1)
+
+ if (source && !source.gcDestroyed)
+ source.forceMove(loc)
+ if (owner)
+ owner.put_in_hands(source)
+ qdel(src)
+
+/obj/effect/bible_spin/proc/update_spin()
+ current_spin += spin_speed
+ distance = distance_min + distance_amplitude*sin(180*(lifetime/lifetime_max))
+ animate(src, pixel_x = distance*cos(current_spin), pixel_y = distance*sin(current_spin), time = 1)
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index b396c48278af..51ad993f07c6 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -574,7 +574,7 @@
icon_state = "frag_shells"
can_add_storageslots = TRUE
items_to_spawn = list(/obj/item/ammo_casing/shotgun/frag = 16)
-
+
/obj/item/weapon/storage/box/rocksaltshells
name = "12-gauge rocksalt shells"
icon_state = "rocksalt_shells"
@@ -1312,3 +1312,16 @@
/obj/item/device/modkit/demolition,
/obj/item/ammo_storage/magazine/lawgiver/demolition = 2,
)
+
+/obj/item/weapon/storage/box/castlevania
+ name = "modern vampire hunter set box"
+ desc = "Apparel for the cooler vampire hunters."
+ icon_state = "castlevania_box"
+
+/obj/item/weapon/storage/box/castlevania/New()
+ ..()
+ new /obj/item/clothing/under/hunter(src)
+ new /obj/item/clothing/suit/hunter(src)
+ new /obj/item/clothing/shoes/hunter(src)
+ new /obj/item/clothing/head/hunter(src)
+ new /obj/item/clothing/gloves/hunter(src)
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 3515c689bf94..cab24ae413cc 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -8,6 +8,8 @@
body_parts_covered = EYES
slot_flags = SLOT_EYES
flammable = FALSE
+ w_type = RECYK_GLASS
+ starting_materials = list(MAT_GLASS = CC_PER_SHEET_GLASS/4)
var/vision_flags = 0
var/darkness_view = 0//Base human is 2
var/invisa_view = 0
@@ -363,17 +365,39 @@ BLIND // can't see anything
desc = "Just who the hell do you think I am?"
icon_state = "simonglasses"
item_state = "simonglasses"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing.dmi')
species_fit = list(GREY_SHAPED)
cover_hair = 1
+/obj/item/clothing/glasses/simonglasses/attack_self(var/mob/living/user)
+ var/obj/item/weapon/boomerang/kaminaglasses/simonglasses/boomerang = new(user.loc)
+ user.drop_item(src, boomerang)
+ boomerang.KG = src
+ boomerang.overlays += overlays
+ user.put_in_active_hand(boomerang)
+ playsound(user.loc,'sound/effects/lagann_eyecatch.ogg', 30, 0)
+ if (!user.in_throw_mode)
+ user.throw_mode_on()
+
/obj/item/clothing/glasses/kaminaglasses
name = "Kamina's glasses"
desc = "I'm going to tell you something important now, so you better dig the wax out of those huge ears of yours and listen! The reputation of Team Gurren echoes far and wide. When they talk about its badass leader - the man of indomitable spirit and masculinity - they're talking about me! The mighty Kamina!"
icon_state = "kaminaglasses"
item_state = "kaminaglasses"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing.dmi')
species_fit = list(GREY_SHAPED)
cover_hair = 1
+/obj/item/clothing/glasses/kaminaglasses/attack_self(var/mob/living/user)
+ var/obj/item/weapon/boomerang/kaminaglasses/boomerang = new(user.loc)
+ user.drop_item(src, boomerang)
+ boomerang.KG = src
+ boomerang.overlays += overlays
+ user.put_in_active_hand(boomerang)
+ playsound(user.loc,'sound/effects/lagann_eyecatch.ogg', 30, 0)
+ if (!user.in_throw_mode)
+ user.throw_mode_on()
+
/obj/item/clothing/glasses/contacts
name = "contact lenses"
desc = "Only nerds wear glasses."
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index 734eb38a47e0..acc1ca06271d 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -454,8 +454,8 @@
return image(icon = 'icons/mob/attackanims.dmi', icon_state = "rockernaut")
/obj/item/clothing/gloves/mittens
- desc = "These mittens are quite comfortable, and will keep you warm!"
name = "mittens"
+ desc = "These mittens are quite comfortable, and will keep you warm!"
icon_state = "mittens"
item_state = "mittens"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/linencrafts.dmi', "right_hand" = 'icons/mob/in-hand/right/linencrafts.dmi')
@@ -464,3 +464,16 @@
color = COLOR_LINEN
clothing_flags = COLORS_OVERLAY
+
+/obj/item/clothing/gloves/hunter
+ name = "leather glove & handwraps"
+ desc = "Cloth handwraps and a tough leather glove for your (hopefully dominant) right hand. Provides a comfortable grip when handling holy weaponry."
+ icon_state = "hunter_gloves"
+ item_state = "hunter_gloves"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing_castlevania.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing_castlevania.dmi')
+
+/obj/item/clothing/gloves/hunter/offenseTackleBonus()
+ return 3
+
+/obj/item/clothing/gloves/hunter/rangeTackleBonus()
+ return 1
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 52d02b618083..89d5b2727a3c 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -832,3 +832,16 @@ var/image/unusual_overlay = image('icons/mob/head.dmi', "unusual_overlay", pixel
flags = FPRINT
icon_state = "trucker"
item_state = "trucker"
+
+/obj/item/clothing/head/hunter
+ name = "white bandana"
+ desc = "An old piece of cloth that keeps hair out of your monster slaying business."
+ icon_state = "hunter"
+ item_state = "hunter_headband"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing_castlevania.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing_castlevania.dmi')
+
+/obj/item/clothing/head/hunter/offenseTackleBonus()
+ return 3
+
+/obj/item/clothing/head/hunter/rangeTackleBonus()
+ return 1
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index f4ab92e88601..87adacf7aeb9 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -614,3 +614,20 @@
item_state = "scubafloppers"
footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/clown
species_fit = list(VOX_SHAPED, GREY_SHAPED, UNDEAD_SHAPED, MUSHROOM_SHAPED, INSECT_SHAPED)
+
+
+/obj/item/clothing/shoes/hunter
+ name = "heavy leather boots"
+ desc = "Tall leather boots, perfect for performing slide kicks."
+ icon_state = "hunter"
+ item_state = "hunter_boots"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing_castlevania.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing_castlevania.dmi')
+ heat_conductivity = INS_SHOE_HEAT_CONDUCTIVITY
+ bonus_kick_damage = 3
+ footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/boots
+
+/obj/item/clothing/shoes/hunter/offenseTackleBonus()
+ return 3
+
+/obj/item/clothing/shoes/hunter/rangeTackleBonus()
+ return 1
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 629b77f206e6..f543b4b786ca 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -426,6 +426,20 @@ var/list/tag_suits_list = list()
body_parts_covered = FULL_TORSO|FEET
species_fit = list(INSECT_SHAPED)
+/obj/item/clothing/suit/hunter
+ name ="modern vampire hunter's overcoat"
+ desc = "An iconic blue overcoat similar to the one worn by a vampire hunter that vanquished Dracula 800 years ago. The sleeves have been ripped off for a better range of motion."
+ icon_state = "hunter_overcoat"
+ item_state = "hunter_overcoat"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing_castlevania.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing_castlevania.dmi')
+ body_parts_covered = FULL_TORSO
+
+/obj/item/clothing/suit/hunter/offenseTackleBonus()
+ return 3
+
+/obj/item/clothing/suit/hunter/rangeTackleBonus()
+ return 1
+
/obj/item/clothing/suit/chickensuit
name = "chicken suit"
desc = "A suit made long ago by the ancient empire KFC."
@@ -1180,7 +1194,6 @@ var/list/tag_suits_list = list()
pressure_resistance = 2 * ONE_ATMOSPHERE
species_fit = list(VOX_SHAPED)
-
/obj/item/clothing/suit/wftr
name ="welding fuel tank refiller shirt"
desc = "A shirt worn by those with a passion for refilling welding fuel tanks."
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index ed3c1946d392..d676d1e67d62 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -1002,6 +1002,20 @@
clothing_flags = ONESIZEFITSALL
species_fit = list(INSECT_SHAPED, VOX_SHAPED, GREY_SHAPED)
+/obj/item/clothing/under/hunter
+ name = "modern vampire hunter's attire"
+ desc = "A tough leather vest with stylish white pants"
+ icon_state = "hunter"
+ item_state = "hunter_uniform"
+ _color = "hunter"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/clothing_castlevania.dmi', "right_hand" = 'icons/mob/in-hand/right/clothing_castlevania.dmi')
+
+/obj/item/clothing/under/hunter/offenseTackleBonus()
+ return 3
+
+/obj/item/clothing/under/hunter/rangeTackleBonus()
+ return 1
+
///////////////////////////////////////////////////////////////////////////
/obj/item/clothing/under/toga
diff --git a/code/modules/mob/living/carbon/combat.dm b/code/modules/mob/living/carbon/combat.dm
index 2e73e1b9171d..259e9cf8ae86 100644
--- a/code/modules/mob/living/carbon/combat.dm
+++ b/code/modules/mob/living/carbon/combat.dm
@@ -1,6 +1,6 @@
/mob/living/carbon/hitby(var/obj/item/I, var/speed, var/dir)
- if(istype(I) && isturf(I.loc) && in_throw_mode) //Only try to catch things while we have throwing mode active (also only items please)
+ if(istype(I) && (isturf(I.loc) || istype(I,/obj/item/weapon/boomerang)) && in_throw_mode) //Only try to catch things while we have throwing mode active (also only items please)
if(can_catch(I, speed) && put_in_hands(I))
visible_message("\The [src] catches \the [I][speed > EMBED_THROWING_SPEED ? ". Wow!" : "!"]")
throw_mode_off()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index d0ba17176029..09e31925f85a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -2228,6 +2228,26 @@ var/datum/record_organ //This is just a dummy proc, not storing any variables he
else
become_zombie = TRUE
+/mob/living/carbon/human/drop_hands(var/atom/Target, force_drop = 0)
+ if (istype(gloves, /obj/item/clothing/gloves/hunter))
+ for(var/obj/item/I in held_items)
+ if (istype(I, /obj/item/weapon/gun/hookshot/whip))
+ to_chat(src, "You hold your grip onto your [I]")
+ else
+ drop_item(I, Target, force_drop = force_drop)
+ else
+ ..()
+
+/mob/living/carbon/human/get_afterimage()
+ if (istype(w_uniform, /obj/item/clothing/under/hunter)\
+ && istype(wear_suit, /obj/item/clothing/suit/hunter)\
+ && istype(shoes, /obj/item/clothing/shoes/hunter)\
+ && istype(head, /obj/item/clothing/head/hunter)\
+ && istype(gloves, /obj/item/clothing/gloves/hunter))
+ playsound(src, 'sound/weapons/authenticrichtertackleslide.ogg', 70, 0)
+ anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "castlevania_tackle_flick", plane = ABOVE_LIGHTING_PLANE)
+ return "richter tackle"
+
/mob/living/carbon/human/throw_item(var/atom/target,var/atom/movable/what=null)
var/atom/movable/item = get_active_hand()
if(what)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 14472604b62e..e4e593c715cf 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1545,7 +1545,7 @@ Thanks.
to_chat(usr, "It's stuck to your hand!")
return FAILED_THROW
- if(I.pre_throw(target))
+ if(I.pre_throw(target,src))
return FAILED_THROW
remove_from_mob(item)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index d7fecbe3e470..f5181d22d70a 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -77,7 +77,7 @@
return PROJECTILE_COLLISION_DEFAULT
//Multiplier for damage when an object has hit.
-/mob/living/proc/thrown_defense(var/obj/O)
+/mob/living/proc/thrown_defense(var/obj/O,var/speed = 5)
return 1
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5,var/dir,var/list/hit_whitelist)//Standardization and logging -Sieve
@@ -112,7 +112,7 @@
zone_normal_name = zone
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone_normal_name].", "Your armor has softened the blow to your [zone_normal_name].", armor_penetration = O.throwforce*(speed/5)*O.sharpness)
if(armor < 100) //Stop the damage if the person is immune
- var/damage = run_armor_absorb(zone, "melee", O.throwforce*(speed/5) * thrown_defense(O))
+ var/damage = run_armor_absorb(zone, "melee", O.throwforce*(speed/5) * thrown_defense(O,speed))
apply_damage(damage, dtype, zone, armor, O.is_sharp(), O)
// Begin BS12 momentum-transfer code.
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 7183596eb2ec..0a2c31bac929 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -250,6 +250,7 @@
M.unarmed_attack_mob(src)
return 1
+/*
/mob/living/simple_animal/construct/attackby(var/obj/item/O as obj, var/mob/user as mob)
user.delayNextAttack(8)
if(O.force)
@@ -258,6 +259,7 @@
damage = 0
if(isholyweapon(O))
playsound(loc, 'sound/weapons/welderattack.ogg', 50, 1)
+ anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "holy",sleeptime = 5, lay = NARSIE_GLOW,plane = ABOVE_LIGHTING_PLANE)
damage *= 2
purge = 3
adjustBruteLoss(damage)
@@ -266,7 +268,7 @@
else
to_chat(usr, "This weapon is ineffective, it does no damage.")
user.visible_message("[user] gently taps [src] with [O]. ")
-
+*/
/mob/living/simple_animal/construct/mode()
set name = "Activate Held Object"
@@ -360,10 +362,12 @@
return PROJECTILE_COLLISION_BLOCKED
return (..(P))
-/mob/living/simple_animal/construct/armoured/thrown_defense(var/obj/O)
- if(juggerblock(O.throwforce,O))
- return FALSE
- return TRUE
+/mob/living/simple_animal/construct/armoured/thrown_defense(var/obj/O,var/speed = 5)
+ . = ..()
+ if (. <= 1)//juggerblock doesn't protect from holy weapons
+ if(juggerblock(O.throwforce*(speed/5),O))
+ return 0
+ return .
/mob/living/simple_animal/construct/armoured/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, sharp, edge, var/used_weapon = null, ignore_events = 0)
if (juggerblock(damage))
diff --git a/code/modules/mob/living/simple_animal/hostile/arcane_golem.dm b/code/modules/mob/living/simple_animal/hostile/arcane_golem.dm
index 18bd1bd48400..6196af977a23 100644
--- a/code/modules/mob/living/simple_animal/hostile/arcane_golem.dm
+++ b/code/modules/mob/living/simple_animal/hostile/arcane_golem.dm
@@ -38,6 +38,7 @@
heat_damage_per_tick = 0
cold_damage_per_tick = 0
stop_automated_movement = 1
+ supernatural = TRUE
blooded = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm
index ded3400e8f5c..bcb85b999004 100644
--- a/code/modules/mob/living/simple_animal/hostile/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bat.dm
@@ -84,7 +84,7 @@
var/shuttletarget = null
var/enroute = 0
- supernatural = 1
+ supernatural = TRUE
/mob/living/simple_animal/hostile/scarybat/cult/Found(var/atom/the_target)
@@ -166,6 +166,7 @@
speed = 5
maxHealth = 15
health = 15
+ supernatural = TRUE
var/book_cover
harm_intent_damage = 8
diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm
index 4d6d60c267db..c321c87a3ce5 100644
--- a/code/modules/mob/living/simple_animal/hostile/creature.dm
+++ b/code/modules/mob/living/simple_animal/hostile/creature.dm
@@ -14,6 +14,7 @@
faction = "creature"
speed = 5
size = SIZE_BIG
+ supernatural = TRUE
/mob/living/simple_animal/hostile/creature/cult
faction = "cult"
@@ -30,7 +31,6 @@
max_n2 = 0
minbodytemp = 0
- supernatural = 1
held_items = list()
/mob/living/simple_animal/hostile/creature/get_butchering_products()
diff --git a/code/modules/mob/living/simple_animal/hostile/deer.dm b/code/modules/mob/living/simple_animal/hostile/deer.dm
index e366f0c0fb4c..3d6de96867f9 100644
--- a/code/modules/mob/living/simple_animal/hostile/deer.dm
+++ b/code/modules/mob/living/simple_animal/hostile/deer.dm
@@ -140,6 +140,7 @@
icon_living = "fleshdeer"
icon_dead = "fleshdeer_dead"
+ supernatural = TRUE
canRegenerate = 1
maxRegenTime = 150
minRegenTime = 60
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index 44a45f94ffb3..f5080ba99174 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -32,7 +32,7 @@
minbodytemp = 0
speed = 5
- supernatural = 1
+ supernatural = TRUE
faction = "faithless"
diff --git a/code/modules/mob/living/simple_animal/hostile/gingerbreadman.dm b/code/modules/mob/living/simple_animal/hostile/gingerbreadman.dm
index bd5d1f8ba401..3a4334a726aa 100644
--- a/code/modules/mob/living/simple_animal/hostile/gingerbreadman.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gingerbreadman.dm
@@ -33,5 +33,6 @@
max_n2 = 0
minbodytemp = 0
speed = 7
+ supernatural = TRUE
blooded = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/gingerbreadmobs.dm b/code/modules/mob/living/simple_animal/hostile/gingerbreadmobs.dm
index d36c33bfea58..0a700dcd8a45 100644
--- a/code/modules/mob/living/simple_animal/hostile/gingerbreadmobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gingerbreadmobs.dm
@@ -36,6 +36,7 @@
max_n2 = 0
minbodytemp = 0
speed = 5
+ supernatural = TRUE
blooded = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/human/greynurse.dm b/code/modules/mob/living/simple_animal/hostile/human/greynurse.dm
index c534767d83b5..60d12a4bffca 100644
--- a/code/modules/mob/living/simple_animal/hostile/human/greynurse.dm
+++ b/code/modules/mob/living/simple_animal/hostile/human/greynurse.dm
@@ -186,6 +186,10 @@
var/dash_dir = null
var/turf/crashing = null
+/mob/living/simple_animal/hostile/humanoid/nurseunit/special_thrown_behaviour()
+ dash_dir = dir
+ throwing = 2//dashing through windows and grilles
+
/mob/living/simple_animal/hostile/humanoid/nurseunit/Aggro()
..()
say(pick("Unauthorized personnel detected, neutralizing.","Unit can no longer interface with disintegrator, proceeding with manual termination.","Source of greyling distress detected. Erasing."), all_languages[LANGUAGE_GREY])
diff --git a/code/modules/mob/living/simple_animal/hostile/mannequin.dm b/code/modules/mob/living/simple_animal/hostile/mannequin.dm
index 9c56568d3b22..9bf28b859aea 100644
--- a/code/modules/mob/living/simple_animal/hostile/mannequin.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mannequin.dm
@@ -49,6 +49,7 @@
var/additional_damage = 0//tracking how much damage we took
+ supernatural = TRUE
blooded = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index f0256d6bcd6c..063303195da7 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -36,6 +36,7 @@
max_n2 = 0
minbodytemp = 0
+ supernatural = TRUE
faction = "forest"
held_items = list()
diff --git a/code/modules/mob/living/simple_animal/hostile/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/wendigo.dm
index 60328e224595..05b3498006cf 100644
--- a/code/modules/mob/living/simple_animal/hostile/wendigo.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wendigo.dm
@@ -38,6 +38,7 @@
speak_chance = 15
speak = list("Help!","Help me!","Somebody help!","Get over here, quickly!")
status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH|UNPACIFIABLE
+ supernatural = TRUE
/mob/living/simple_animal/hostile/wendigo/CanAttack(var/atom/the_target)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 49afb944580e..194487e68c42 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -450,6 +450,10 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
if(!Proj)
return PROJECTILE_COLLISION_DEFAULT
Proj.on_hit(src, 0)
+ if(supernatural && isholyweapon(Proj))
+ playsound(loc, 'sound/weapons/welderattack.ogg', 50, 1)
+ anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "holy",sleeptime = 5, lay = NARSIE_GLOW,plane = ABOVE_LIGHTING_PLANE)
+ purge = 3
adjustBruteLoss(Proj.damage)
return PROJECTILE_COLLISION_DEFAULT
@@ -561,12 +565,20 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
else if (user.is_pacified(VIOLENCE_DEFAULT,src))
return
if(supernatural && isholyweapon(O))
+ playsound(loc, 'sound/weapons/welderattack.ogg', 50, 1)
+ anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "holy",sleeptime = 5, lay = NARSIE_GLOW,plane = ABOVE_LIGHTING_PLANE)
purge = 3
if(O.hitsound)
playsound(loc, O.hitsound, 50, 1, -1)
..()
-
+/mob/living/simple_animal/thrown_defense(var/obj/O,var/speed = 5)
+ if(supernatural && isholyweapon(O))
+ playsound(loc, 'sound/weapons/welderattack.ogg', 50, 1)
+ anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "holy",sleeptime = 5, lay = NARSIE_GLOW,plane = ABOVE_LIGHTING_PLANE)
+ purge = 3
+ return 2
+ return ..()
/mob/living/simple_animal/base_movement_tally()
return speed
@@ -913,3 +925,9 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
// Simplemobs do not have hands.
/mob/living/simple_animal/put_in_hand_check(obj/item/W, index)
return 0
+
+/mob/living/simple_animal/isUnholy()
+ if (supernatural)
+ return TRUE
+ else
+ return ..()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 6649e5f6f2f7..2c83aed171bf 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -541,21 +541,24 @@
// Used in job equipping so shit doesn't pile up at the start loc.
/mob/living/carbon/human/proc/equip_or_collect(var/obj/item/W, var/slot)
if(!equip_to_slot_or_drop(W, slot))
- // Do I have a backpack?
- var/obj/item/weapon/storage/B = back
+ collect_in_backpack(W)
+
+/mob/living/carbon/human/proc/collect_in_backpack(var/obj/item/W)
+ // Do I have a backpack?
+ var/obj/item/weapon/storage/B = back
- // Do I have a plastic bag?
- if(!B)
- var/index = find_held_item_by_type(/obj/item/weapon/storage/bag/plasticbag)
- if(index)
- B = held_items[index]
+ // Do I have a plastic bag?
+ if(!B)
+ var/index = find_held_item_by_type(/obj/item/weapon/storage/bag/plasticbag)
+ if(index)
+ B = held_items[index]
- if(!B)
- // Gimme one.
- B=new /obj/item/weapon/storage/bag/plasticbag(null) // Null in case of failed equip.
- if(!put_in_hands(B,slot_back))
- return // Fuck it
- B.handle_item_insertion(W,1)
+ if(!B)
+ // Gimme one.
+ B=new /obj/item/weapon/storage/bag/plasticbag(null) // Null in case of failed equip.
+ if(!put_in_hands(B,slot_back))
+ return // Fuck it
+ B.handle_item_insertion(W,1)
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
var/static/list/slot_equipment_priority = list( \
@@ -2239,5 +2242,8 @@ Use this proc preferably at the end of an equipment loadout
spawn()
src.update_music()
+/mob/proc/isUnholy()
+ return (isanycultist(src) || isvampire(src))
+
#undef MOB_SPACEDRUGS_HALLUCINATING
#undef MOB_MINDBREAKER_HALLUCINATING
diff --git a/code/modules/projectiles/guns/hookshot.dm b/code/modules/projectiles/guns/hookshot.dm
index 4ecbe41a908c..59b56ce1acaa 100644
--- a/code/modules/projectiles/guns/hookshot.dm
+++ b/code/modules/projectiles/guns/hookshot.dm
@@ -25,6 +25,8 @@
var/mob/living/carbon/firer = null
var/atom/movable/extremity = null
var/panic = 0 //set to 1 by a part of the hookchain that got destroyed.
+ var/rewind_delay = 0 //whips come out faster than hooks, but hang in the air for an instant
+ var/rewind_speed = 1
/obj/item/weapon/gun/hookshot/update_icon()
if(hook || chain_datum)
@@ -80,6 +82,7 @@
if(!hook && !rewinding && !clockwerk && !check_tether())//if there is no projectile already, and we aren't currently rewinding the chain, or reeling in toward a target,
hook = new hooktype(src) //and that the hookshot isn't currently sustaining a tether, then we can fire.
in_chamber = hook
+ rewind_speed = in_chamber.projectile_speed
firer = loc
update_icon()
return 1
@@ -148,6 +151,7 @@
if(rewinding)
return
rewinding = 1
+ sleep(rewind_delay)
for(var/j = 1; j <= maxlength; j++)
rewind_loop()
rewinding = 0
@@ -173,7 +177,7 @@
HC.pixel_x = HC0.pixel_x
HC.pixel_y = HC0.pixel_y
apply_item_overlay()
- sleep(pause)
+ sleep(pause*rewind_speed)
/obj/item/weapon/gun/hookshot/proc/reset_hookchain_overlays(var/obj/effect/overlay/hookchain/HC) //fleshshot only
return
@@ -474,6 +478,7 @@
hooktype = /obj/item/projectile/hookshot/whip
empty_sound = null
slot_flags = SLOT_BELT
+ rewind_delay = 3
/obj/item/weapon/gun/hookshot/whip/update_icon()
return
@@ -499,6 +504,15 @@
hooktype = /obj/item/projectile/hookshot/whip/vampkiller
fire_sound = 'sound/weapons/vampkiller.ogg'
+/obj/item/weapon/gun/hookshot/whip/vampkiller/update_icon()
+ if(hook || chain_datum)
+ item_state = "vampkiller0"
+ else
+ item_state = "vampkiller"
+ if(istype(loc,/mob))
+ var/mob/M = loc
+ M.regenerate_icons()
+
/obj/item/weapon/gun/hookshot/whip/vampkiller/true
desc = "A brutal looking weapon consisting of a morning star head attached to a chain lash. It is blessed to be effective against the undead and radiates an awesome holy aura."
icon_state = "vampkiller_true"
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index fce54773f36b..d75f74fcc23e 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -511,17 +511,23 @@ var/list/impact_master = list()
return 1
+/obj/item/projectile/proc/on_step()
+ return
+
/obj/item/projectile/proc/process_step()
if(src.loc)
+ var/sleeptime = projectile_speed
if(dist_x > dist_y)
- bresenham_step(dist_x,dist_y,dx,dy)
+ sleeptime *= bresenham_step(dist_x,dist_y,dx,dy)
else
- bresenham_step(dist_y,dist_x,dy,dx)
+ sleeptime *= bresenham_step(dist_y,dist_x,dy,dx)
if(linear_movement)
update_pixel()
pixel_x = PixelX
pixel_y = PixelY
-
+ if (sleeptime)//so we don't act twice on the the same frame
+ kill_count--
+ on_step()
bumped = 0
if (tracker_datum && tracker_datum.changed)
@@ -554,7 +560,7 @@ var/list/impact_master = list()
if(rotate)
target_angle = round(Get_Angle(current,target))
- sleep(projectile_speed)
+ sleep(sleeptime)
/obj/item/projectile/proc/bresenham_step(var/distA, var/distB, var/dA, var/dB)
@@ -568,7 +574,6 @@ var/list/impact_master = list()
new decay_type(T)
bullet_die()
return 1
- kill_count--
total_steps++
if(error < 0)
var/atom/step = get_step(src, dB)
diff --git a/code/modules/projectiles/projectile/hookshot.dm b/code/modules/projectiles/projectile/hookshot.dm
index 8bc21741efed..627d0f500dd7 100644
--- a/code/modules/projectiles/projectile/hookshot.dm
+++ b/code/modules/projectiles/projectile/hookshot.dm
@@ -58,7 +58,7 @@
hookshot.rewind_chain()
bullet_die()
- sleep(sleeptime)
+ sleep(sleeptime * projectile_speed)
/obj/item/projectile/hookshot/proc/drop_item() //fleshshot only
return
@@ -180,6 +180,7 @@
sharpness = 1.2
failure_message = "Your hand slips and the whip falls loose..."
can_tether = FALSE
+ projectile_speed = 0.33
var/whipitgood_bonus = 5
/obj/item/projectile/hookshot/whip/on_hit(var/atom/atarget, var/blocked = 0)
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index 3419337c17dd..5bd8629ffec5 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -102,7 +102,7 @@
if (M.mind)
for (var/role in M.mind.antag_roles)
var/datum/role/R = M.mind.antag_roles[role]
- R.handle_splashed_reagent(self.id)
+ R.handle_splashed_reagent(self.id, method, volume)
if(self.tolerance_increase)
M.tolerated_chems[self.id] += self.tolerance_increase
@@ -118,7 +118,7 @@
if (M.mind)
for (var/role in M.mind.antag_roles)
var/datum/role/R = M.mind.antag_roles[role]
- R.handle_splashed_reagent(self.id)
+ R.handle_splashed_reagent(self.id, method, volume)
if(self.tolerance_increase)
M.tolerated_chems[self.id] += self.tolerance_increase
diff --git a/code/modules/reagents/reagent_containers/food/drinks/holy_water.dm b/code/modules/reagents/reagent_containers/food/drinks/holy_water.dm
index cbd47050b8dc..a7eb5bb7eb22 100644
--- a/code/modules/reagents/reagent_containers/food/drinks/holy_water.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks/holy_water.dm
@@ -1,5 +1,5 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater
- name = "Flask of Holy Water"
+ name = "flask of Holy Water"
desc = "A flask of the chaplain's holy water."
icon_state = "holyflask"
bottleheight = 25
@@ -12,3 +12,27 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/New()
..()
reagents.add_reagent(HOLYWATER, 100)
+
+/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/sacredwater
+ name = "flask of Sacred Water"
+ desc = "Spreads a sacred flame when thrown to the floor, burning the unholy."
+ icon_state = "sacredwater"
+ bottleheight = 21
+ molotov = -1
+ isGlass = 1
+ smashtext = ""
+ smashname = "broken flask"
+ controlled_splash = TRUE
+
+/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/sacredwater/New()
+ ..()
+ reagents.clear_reagents()
+ reagents.add_reagent(SACREDWATER, 100)
+
+/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/sacredwater/pre_throw(var/atom/movable/target,var/mob/living/user)
+ icon_state = "sacredwater_thrown"
+ ..()
+
+/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/sacredwater/throw_impact(atom/impacted_atom, speed, mob/user)
+ icon_state = "sacredwater"
+ ..()
diff --git a/code/modules/reagents/reagents/reagents_religious.dm b/code/modules/reagents/reagents/reagents_religious.dm
index abf127968f39..b45100e03b31 100644
--- a/code/modules/reagents/reagents/reagents_religious.dm
+++ b/code/modules/reagents/reagents/reagents_religious.dm
@@ -90,6 +90,72 @@
C.adjustBruteLoss(5)
C.visible_message("The [src] erodes \the [M].")
+
+/datum/reagent/holywater/sacredwater
+ name = "Sacred Water"
+ id = SACREDWATER
+ description = "Water-like liquid that combusts when thrown upon a floor. The flames produced only harm the unholy."
+ color = "#017AFF" //rgb: 1, 122, 255
+
+/datum/reagent/holywater/sacredwater/reaction_turf(var/turf/simulated/T, var/volume)
+ if(..())
+ return 1
+
+ if(volume >= 1)
+ var/obj/effect/overlay/sacred_flames/flames = locate() in T
+ if (flames)
+ flames.lifetime = initial(flames.lifetime)
+ else
+ new /obj/effect/overlay/sacred_flames(T)
+
+/datum/reagent/holywater/sacredwater/special_behaviour()
+ //I sure hope allowing castlevania chaplains to produce infinite sacred flames doesn't turn out to be a bad idea
+ for (var/datum/reagent/R in holder.reagent_list)
+ if (R.id == HOLYWATER)
+ var/added_volume = R.volume
+ holder.del_reagent(R.id)
+ volume += added_volume
+
+////////////////////////////////////////////////////////////////////////////////
+/obj/effect/overlay/sacred_flames
+ mouse_opacity = 0
+ icon = 'icons/effects/fireblue.dmi'
+ icon_state = "1"
+ plane = OBJ_PLANE
+ layer = BELOW_OBJ_LAYER
+ var/lifetime = 3//seconds
+
+/obj/effect/overlay/sacred_flames/New()
+ ..()
+ icon_state = pick("1","2","3")
+ add_particles(PS_CROSS_DUST)
+ adjust_particles(PVAR_VELOCITY, list(0,4), PS_CROSS_DUST)
+ add_particles(PS_SACRED_FLAME)
+ add_particles(PS_SACRED_FLAME2)
+ set_light(3,0.5,"#1414A4")
+ spawn()
+ process_flames()
+
+/obj/effect/overlay/sacred_flames/proc/process_flames()
+ set waitfor = 0
+ while(lifetime > 0)
+ harm_unholy()
+ lifetime--
+ sleep(1 SECONDS)
+ set_light(0)
+ icon = 'icons/effects/32x32.dmi'
+ icon_state = "blank"
+ adjust_particles(PVAR_SPAWNING, 0)
+ sleep(1 SECONDS)
+ qdel(src)
+
+/obj/effect/overlay/sacred_flames/proc/harm_unholy()
+ var/turf/T = get_turf(src)
+ for (var/mob/living/L in T)
+ if (L.isUnholy())
+ L.take_overall_damage(0,15)
+////////////////////////////////////////////////////////////////////////////////
+
/datum/reagent/holysalts
name = "Holy Salts"
id = HOLYSALTS
diff --git a/code/modules/spells/aoe_turf/conjure/bats.dm b/code/modules/spells/aoe_turf/conjure/bats.dm
index 639db97053eb..932c7933eabe 100644
--- a/code/modules/spells/aoe_turf/conjure/bats.dm
+++ b/code/modules/spells/aoe_turf/conjure/bats.dm
@@ -47,6 +47,7 @@
/spell/aoe_turf/conjure/bats/on_creation(atom/movable/AM, mob/user)
var/datum/role/vampire/V = isvampire(user)
var/mob/living/simple_animal/hostile/scarybat/SB = AM
+ SB.supernatural = TRUE
if (V && V.faction)
SB.vamp_fac = V.faction
V.faction.members += SB
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 3bda7933e941..748d52088386 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/effects/effects_particles.dmi b/icons/effects/effects_particles.dmi
index 01303d7fcaa0..71c30a936ef4 100644
Binary files a/icons/effects/effects_particles.dmi and b/icons/effects/effects_particles.dmi differ
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 91ad1fc80711..6e47a4a22d41 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi
index 9be507d29491..fbe1c76fbd36 100644
Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ
diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi
index e35868c951d8..beb67f89f1cc 100644
Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 4ce52aaa2f6a..b2d08c8c05a3 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/in-hand/left/books.dmi b/icons/mob/in-hand/left/books.dmi
index 26cf768ccf08..034893ff282d 100644
Binary files a/icons/mob/in-hand/left/books.dmi and b/icons/mob/in-hand/left/books.dmi differ
diff --git a/icons/mob/in-hand/left/boomerang.dmi b/icons/mob/in-hand/left/boomerang.dmi
new file mode 100644
index 000000000000..08e298f62455
Binary files /dev/null and b/icons/mob/in-hand/left/boomerang.dmi differ
diff --git a/icons/mob/in-hand/left/boxes_and_storage.dmi b/icons/mob/in-hand/left/boxes_and_storage.dmi
index 53573b5e07f8..a62f2611754a 100644
Binary files a/icons/mob/in-hand/left/boxes_and_storage.dmi and b/icons/mob/in-hand/left/boxes_and_storage.dmi differ
diff --git a/icons/mob/in-hand/left/clothing.dmi b/icons/mob/in-hand/left/clothing.dmi
index 49bf87fb8297..d432c63ea5ea 100644
Binary files a/icons/mob/in-hand/left/clothing.dmi and b/icons/mob/in-hand/left/clothing.dmi differ
diff --git a/icons/mob/in-hand/left/clothing_castlevania.dmi b/icons/mob/in-hand/left/clothing_castlevania.dmi
new file mode 100644
index 000000000000..e07cd920ba6b
Binary files /dev/null and b/icons/mob/in-hand/left/clothing_castlevania.dmi differ
diff --git a/icons/mob/in-hand/left/drinkingglass.dmi b/icons/mob/in-hand/left/drinkingglass.dmi
index 16086c448c9d..17688a8e9def 100644
Binary files a/icons/mob/in-hand/left/drinkingglass.dmi and b/icons/mob/in-hand/left/drinkingglass.dmi differ
diff --git a/icons/mob/in-hand/left/swords_axes.dmi b/icons/mob/in-hand/left/swords_axes.dmi
index d0a86f43cb77..cbc90e39647c 100644
Binary files a/icons/mob/in-hand/left/swords_axes.dmi and b/icons/mob/in-hand/left/swords_axes.dmi differ
diff --git a/icons/mob/in-hand/right/books.dmi b/icons/mob/in-hand/right/books.dmi
index 871082964ac4..ada128401017 100644
Binary files a/icons/mob/in-hand/right/books.dmi and b/icons/mob/in-hand/right/books.dmi differ
diff --git a/icons/mob/in-hand/right/boomerang.dmi b/icons/mob/in-hand/right/boomerang.dmi
new file mode 100644
index 000000000000..31ef832c46c5
Binary files /dev/null and b/icons/mob/in-hand/right/boomerang.dmi differ
diff --git a/icons/mob/in-hand/right/boxes_and_storage.dmi b/icons/mob/in-hand/right/boxes_and_storage.dmi
index 1a7808fd7241..da3f0b21bb2d 100644
Binary files a/icons/mob/in-hand/right/boxes_and_storage.dmi and b/icons/mob/in-hand/right/boxes_and_storage.dmi differ
diff --git a/icons/mob/in-hand/right/clothing.dmi b/icons/mob/in-hand/right/clothing.dmi
index 72dc76936710..7c40f5c607c5 100644
Binary files a/icons/mob/in-hand/right/clothing.dmi and b/icons/mob/in-hand/right/clothing.dmi differ
diff --git a/icons/mob/in-hand/right/clothing_castlevania.dmi b/icons/mob/in-hand/right/clothing_castlevania.dmi
new file mode 100644
index 000000000000..cea8100f93e1
Binary files /dev/null and b/icons/mob/in-hand/right/clothing_castlevania.dmi differ
diff --git a/icons/mob/in-hand/right/drinkingglass.dmi b/icons/mob/in-hand/right/drinkingglass.dmi
index 5dd9e97f9af3..a822d5a41840 100644
Binary files a/icons/mob/in-hand/right/drinkingglass.dmi and b/icons/mob/in-hand/right/drinkingglass.dmi differ
diff --git a/icons/mob/in-hand/right/swords_axes.dmi b/icons/mob/in-hand/right/swords_axes.dmi
index 32e8bdb1aecf..408d35372f82 100644
Binary files a/icons/mob/in-hand/right/swords_axes.dmi and b/icons/mob/in-hand/right/swords_axes.dmi differ
diff --git a/icons/mob/monkey_eyes.dmi b/icons/mob/monkey_eyes.dmi
index dec70a527efe..3efb5c640028 100644
Binary files a/icons/mob/monkey_eyes.dmi and b/icons/mob/monkey_eyes.dmi differ
diff --git a/icons/mob/species/grey/eyes.dmi b/icons/mob/species/grey/eyes.dmi
index 88726340516c..ffbd1ae57b37 100644
Binary files a/icons/mob/species/grey/eyes.dmi and b/icons/mob/species/grey/eyes.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index c1841e67af95..242a594cad72 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 495cb79f9031..38b06be93693 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/boomerang.dmi b/icons/obj/boomerang.dmi
new file mode 100644
index 000000000000..c373549a5fe0
Binary files /dev/null and b/icons/obj/boomerang.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index 543f133e4c9e..d63b00384803 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index d25b17bb2b00..5f4a8c4cf2bb 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index b5011453786d..75704ce4cec7 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi
index 29b22f57ac55..3449958c4aeb 100644
Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 1b6fae3352a8..f9fb2d4b6b7b 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 9738a27935b4..1fe82d00f771 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 86be8c2080ad..2054ee107f86 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/storage/smallboxes.dmi b/icons/obj/storage/smallboxes.dmi
index 0d1dc1239370..857e278e5118 100644
Binary files a/icons/obj/storage/smallboxes.dmi and b/icons/obj/storage/smallboxes.dmi differ
diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi
index 38c5009e4822..5c739ab80895 100644
Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ
diff --git a/sound/effects/lagann_eyecatch.ogg b/sound/effects/lagann_eyecatch.ogg
new file mode 100644
index 000000000000..f266c81b05de
Binary files /dev/null and b/sound/effects/lagann_eyecatch.ogg differ
diff --git a/sound/effects/lagann_eyecatch2.ogg b/sound/effects/lagann_eyecatch2.ogg
new file mode 100644
index 000000000000..186f809524b0
Binary files /dev/null and b/sound/effects/lagann_eyecatch2.ogg differ
diff --git a/sound/items/bible_spin.ogg b/sound/items/bible_spin.ogg
new file mode 100644
index 000000000000..ce627f527ae1
Binary files /dev/null and b/sound/items/bible_spin.ogg differ
diff --git a/sound/items/bible_throw.ogg b/sound/items/bible_throw.ogg
new file mode 100644
index 000000000000..77579e2b8458
Binary files /dev/null and b/sound/items/bible_throw.ogg differ
diff --git a/sound/weapons/authenticrichtertackleslide.ogg b/sound/weapons/authenticrichtertackleslide.ogg
new file mode 100644
index 000000000000..7d048698b3ee
Binary files /dev/null and b/sound/weapons/authenticrichtertackleslide.ogg differ
diff --git a/sound/weapons/boomerang_cross_loop.ogg b/sound/weapons/boomerang_cross_loop.ogg
new file mode 100644
index 000000000000..ec7123c1a6bc
Binary files /dev/null and b/sound/weapons/boomerang_cross_loop.ogg differ
diff --git a/sound/weapons/boomerang_cross_start.ogg b/sound/weapons/boomerang_cross_start.ogg
new file mode 100644
index 000000000000..6a9a05ae650e
Binary files /dev/null and b/sound/weapons/boomerang_cross_start.ogg differ
diff --git a/sound/weapons/boomerang_cross_transform.ogg b/sound/weapons/boomerang_cross_transform.ogg
new file mode 100644
index 000000000000..6a65f755602f
Binary files /dev/null and b/sound/weapons/boomerang_cross_transform.ogg differ
diff --git a/sound/weapons/boomerang_loop.ogg b/sound/weapons/boomerang_loop.ogg
new file mode 100644
index 000000000000..b947d10cc3a4
Binary files /dev/null and b/sound/weapons/boomerang_loop.ogg differ
diff --git a/sound/weapons/boomerang_start.ogg b/sound/weapons/boomerang_start.ogg
new file mode 100644
index 000000000000..4b81b866ec5b
Binary files /dev/null and b/sound/weapons/boomerang_start.ogg differ