diff --git a/code/datums/beam.dm b/code/datums/beam.dm index 7a8c802b42d..bb1cef167d6 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -15,12 +15,13 @@ var/static_beam = 0 var/beam_type = /obj/effect/ebeam //must be subtype -/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam) +/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3) endtime = world.time+time origin = beam_origin origin_oldloc = get_turf(origin) target = beam_target target_oldloc = get_turf(target) + sleep_time = beam_sleep_time if(origin_oldloc == origin && target_oldloc == target) static_beam = 1 max_distance = maxdistance @@ -117,13 +118,13 @@ /obj/effect/ebeam/Destroy() owner = null return ..() - + /obj/effect/ebeam/deadly/Crossed(atom/A) ..() A.ex_act(1) -/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam) - var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type) +/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3) + var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time) spawn(0) newbeam.Start() return newbeam \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index c7d393b77a7..57f086b46ed 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -17,18 +17,21 @@ dna_cost = -1 genetic_damage = 1000 + var/silent = FALSE var/weapon_type var/weapon_name_simple /obj/effect/proc_holder/changeling/weapon/try_to_sting(var/mob/user, var/mob/target) if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh qdel(user.l_hand) - user.visible_message("With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "[user] forces the airlock to open with \his [src]!", "We force the airlock to open.", "You hear a metal screeching sound.") A.open(2) +/***************************************\ +|***********COMBAT TENTACLES*************| +\***************************************/ + +/obj/effect/proc_holder/changeling/weapon/tentacle + name = "Tentacle" + desc = "We ready a tentacle to grab items or victims with." + helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \ + Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \ + and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form." + chemical_cost = 10 + dna_cost = 2 + genetic_damage = 5 + req_human = 1 + max_genetic_damage = 10 + weapon_type = /obj/item/weapon/gun/magic/tentacle + weapon_name_simple = "tentacle" + silent = TRUE + +/obj/item/weapon/gun/magic/tentacle + name = "tentacle" + desc = "A fleshy tentacle that can stretch out and grab things or people." + icon = 'icons/obj/weapons.dmi' + icon_state = "tentacle" + item_state = "tentacle" + flags = ABSTRACT | NODROP | NOBLUDGEON + w_class = WEIGHT_CLASS_HUGE + ammo_type = /obj/item/ammo_casing/magic/tentacle + fire_sound = 'sound/effects/splat.ogg' + force = 0 + max_charges = 1 + throwforce = 0 //Just to be on the safe side + throw_range = 0 + throw_speed = 0 + +/obj/item/weapon/gun/magic/tentacle/New(location,silent) + ..() + if(ismob(loc)) + if(!silent) + loc.visible_message("[loc.name]\'s arm starts stretching inhumanly!", "Our arm twists and mutates, transforming it into a tentacle.", "You hear organic matter ripping and tearing!") + else + to_chat(loc, "You prepare to extend a tentacle.") + +/obj/item/weapon/gun/magic/tentacle/dropped() + . = ..() + qdel(src) + +/obj/item/weapon/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj) + to_chat(user, "The [name] is not ready yet.") + +/obj/item/weapon/gun/magic/tentacle/suicide_act(mob/user) + user.visible_message("[user] coils [src] tightly around \his neck! It looks like \he's trying to commit suicide.") + return (OXYLOSS) + +/obj/item/ammo_casing/magic/tentacle + name = "tentacle" + desc = "a tentacle." + projectile_type = /obj/item/projectile/tentacle + caliber = "tentacle" + icon_state = "tentacle_end" + var/obj/item/weapon/gun/magic/tentacle/gun //the item that shot it + +/obj/item/ammo_casing/magic/tentacle/New(obj/item/weapon/gun/magic/tentacle/tentacle_gun) + gun = tentacle_gun + ..() + +/obj/item/ammo_casing/magic/tentacle/Destroy() + gun = null + return ..() + +/obj/item/projectile/tentacle + name = "tentacle" + icon_state = "tentacle_end" + pass_flags = PASSTABLE + damage = 0 + damage_type = BRUTE + range = 8 + hitsound = 'sound/weapons/thudswoosh.ogg' + var/chain + var/obj/item/ammo_casing/magic/tentacle/source //the item that shot it + +/obj/item/projectile/tentacle/New(obj/item/ammo_casing/magic/tentacle/tentacle_casing) + source = tentacle_casing + ..() + +/obj/item/projectile/tentacle/fire(setAngle) + if(firer) + chain = firer.Beam(src, icon_state = "tentacle", time = INFINITY, maxdistance = INFINITY, beam_sleep_time = 1) + ..() + +/obj/item/projectile/tentacle/proc/reset_throw(mob/living/carbon/human/H) + if(H.in_throw_mode) + H.throw_mode_off() //Don't annoy the changeling if he doesn't catch the item + +/mob/proc/tentacle_grab(mob/living/carbon/C) + if(Adjacent(C)) + var/obj/item/weapon/grab/G = C.grabbedby(src,1) + if(istype(G)) + G.state = GRAB_AGGRESSIVE //Instant aggressive grab + +/mob/proc/tentacle_stab(mob/living/carbon/C) + if(Adjacent(C)) + var/obj/item/I = r_hand + if(!is_sharp(I)) + I = l_hand + if(!is_sharp(I)) + return + + C.visible_message("[src] impales [C] with [I]!", "[src] impales you with [I]!") + C.apply_damage(I.force, BRUTE, "chest") + do_attack_animation(C) + add_blood(C) + playsound(get_turf(src), I.hitsound, 75, 1) + + +/obj/item/projectile/tentacle/on_hit(atom/target, blocked = 0) + qdel(source.gun) //one tentacle only unless you miss + if(blocked >= 100) + return 0 + var/mob/living/carbon/human/H = firer + if(istype(target, /obj/item)) + var/obj/item/I = target + if(!I.anchored) + to_chat(firer, "You pull [I] towards yourself.") + H.throw_mode_on() + I.throw_at(H, 10, 2) + . = 1 + + else if(isliving(target)) + var/mob/living/L = target + if(!L.anchored && !L.throwing)//avoid double hits + if(iscarbon(L)) + var/mob/living/carbon/C = L + switch(firer.a_intent) + if(INTENT_HELP) + C.visible_message("[L] is pulled by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") + C.throw_at(get_step_towards(H,C), 8, 2) + return 1 + + if(INTENT_DISARM) + var/obj/item/I = C.get_active_hand() + if(I) + if(C.drop_item()) + C.visible_message("[I] is yanked out of [C]'s hand by [src]!","A tentacle pulls [I] away from you!") + on_hit(I) //grab the item as if you had hit it directly with the tentacle + return 1 + else + to_chat(firer, "You can't seem to pry [I] out of [C]'s hands!") + return 0 + else + to_chat(firer, "[C] has nothing in hand to disarm!") + return 0 + + if(INTENT_GRAB) + C.visible_message("[L] is grabbed by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") + C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_grab, C)) + return 1 + + if(INTENT_HARM) + C.visible_message("[L] is thrown towards [H] by a tentacle!","A tentacle grabs you and throws you towards [H]!") + C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_stab, C)) + return 1 + else + L.visible_message("[L] is pulled by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") + L.throw_at(get_step_towards(H,L), 8, 2) + . = 1 + +/obj/item/projectile/tentacle/Destroy() + qdel(chain) + source = null + return ..() + /***************************************\ |****************SHIELD*****************| diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 548f1fb357b..c54060cca7e 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -266,6 +266,8 @@ if(!supress_message) visible_message("[user] has grabbed [src] passively!") + return G + /mob/living/incapacitated() if(stat || paralysis || stunned || weakened || restrained()) return 1 diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index ec06922a07d..b45657fff51 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 08050649225..1461df9bbbe 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 90a218c7166..c66e67820a3 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 316790998c5..8c3d0f2c81f 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 83276e5ec57..e4569806d57 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ