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