Files
Paradise/code/game/gamemodes/changeling/powers/mutations.dm
Fox McCloud 592eeb97b7 Merge pull request #13515 from trololiver112/changeling-tentacle-fix
Fixes the Changeling tentacle grab logging
2020-06-24 04:19:40 -04:00

490 lines
19 KiB
Plaintext

/*
Changeling Mutations! ~By Miauw (ALL OF IT :V)
Contains:
Arm Blade
Space Suit
Shield
Armor
*/
//Parent to shields and blades because muh copypasted code.
/datum/action/changeling/weapon
name = "Organic Weapon"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
chemical_cost = 1000
dna_cost = -1
genetic_damage = 1000
var/silent = FALSE
var/weapon_type
var/weapon_name_simple
/datum/action/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)
if(!silent)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='warning'>You hear organic matter ripping and tearing!</span>")
user.update_inv_l_hand()
return
if(istype(user.r_hand, weapon_type))
qdel(user.r_hand)
if(!silent)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='warning'>You hear organic matter ripping and tearing!</span>")
user.update_inv_r_hand()
return
..(user, target)
/datum/action/changeling/weapon/sting_action(var/mob/user)
if(!user.drop_item())
to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
return
var/obj/item/W = new weapon_type(user, silent)
user.put_in_hands(W)
return W
//Parent to space suits and armor.
/datum/action/changeling/suit
name = "Organic Suit"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
chemical_cost = 1000
dna_cost = -1
genetic_damage = 1000
var/helmet_type = /obj/item
var/suit_type = /obj/item
var/suit_name_simple = " "
var/helmet_name_simple = " "
var/recharge_slowdown = 0
var/blood_on_castoff = 0
/datum/action/changeling/suit/try_to_sting(var/mob/user, var/mob/target)
var/datum/changeling/changeling = user.mind.changeling
if(!ishuman(user) || !changeling)
return
var/mob/living/carbon/human/H = user
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
H.visible_message("<span class='warning'>[H] casts off [H.p_their()] [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]</span>", "<span class='warning'>You hear the organic matter ripping and tearing!</span>")
qdel(H.wear_suit)
qdel(H.head)
H.update_inv_wear_suit()
H.update_inv_head()
H.update_hair()
H.update_fhair()
if(blood_on_castoff)
H.add_splatter_floor()
playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
changeling.chem_recharge_slowdown -= recharge_slowdown
return
..(H, target)
/datum/action/changeling/suit/sting_action(var/mob/living/carbon/human/user)
if(!user.unEquip(user.wear_suit))
to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!")
return
if(!user.unEquip(user.head))
to_chat(user, "\the [user.head] is stuck on your head, you cannot grow a [helmet_name_simple] over it!")
return
user.unEquip(user.head)
user.unEquip(user.wear_suit)
user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, TRUE, TRUE)
user.equip_to_slot_if_possible(new helmet_type(user), slot_head, TRUE, TRUE)
var/datum/changeling/changeling = user.mind.changeling
changeling.chem_recharge_slowdown += recharge_slowdown
return 1
//fancy headers yo
/***************************************\
|***************ARM BLADE***************|
\***************************************/
/datum/action/changeling/weapon/arm_blade
name = "Arm Blade"
desc = "We reform one of our arms into a deadly blade. Costs 25 chemicals."
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
button_icon_state = "armblade"
chemical_cost = 25
dna_cost = 2
genetic_damage = 10
req_human = 1
max_genetic_damage = 20
weapon_type = /obj/item/melee/arm_blade
weapon_name_simple = "blade"
/obj/item/melee/arm_blade
name = "arm blade"
desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter"
icon_state = "arm_blade"
item_state = "arm_blade"
flags = ABSTRACT | NODROP | DROPDEL
w_class = WEIGHT_CLASS_HUGE
sharp = 1
force = 25
throwforce = 0 //Just to be on the safe side
throw_range = 0
throw_speed = 0
/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
if(istype(target, /obj/structure/table))
var/obj/structure/table/T = target
T.deconstruct(FALSE)
else if(istype(target, /obj/machinery/computer))
var/obj/machinery/computer/C = target
C.attack_alien(user) //muh copypasta
else if(istype(target, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/A = target
if(!A.requiresID() || A.allowed(user)) //This is to prevent stupid shit like hitting a door with an arm blade, the door opening because you have acces and still getting a "the airlocks motors resist our efforts to force it" message.
return
if(A.locked)
to_chat(user, "<span class='notice'>The airlock's bolts prevent it from being forced.</span>")
return
if(A.arePowerSystemsOn())
user.visible_message("<span class='warning'>[user] jams [src] into the airlock and starts prying it open!</span>", "<span class='warning'>We start forcing the airlock open.</span>", \
"<span class='italics'>You hear a metal screeching sound.</span>")
playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1)
if(!do_after(user, 100, target = A))
return
//user.say("Heeeeeeeeeerrre's Johnny!")
user.visible_message("<span class='warning'>[user] forces the airlock to open with [user.p_their()] [name]!</span>", "<span class='warning'>We force the airlock to open.</span>", "<span class='warning'>You hear a metal screeching sound.</span>")
A.open(2)
/***************************************\
|***********COMBAT TENTACLES*************|
\***************************************/
/datum/action/changeling/weapon/tentacle
name = "Tentacle"
desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals."
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."
button_icon_state = "tentacle"
chemical_cost = 10
dna_cost = 2
genetic_damage = 5
req_human = 1
max_genetic_damage = 10
weapon_type = /obj/item/gun/magic/tentacle
weapon_name_simple = "tentacle"
silent = TRUE
/obj/item/gun/magic/tentacle
name = "tentacle"
desc = "A fleshy tentacle that can stretch out and grab things or people."
icon_state = "tentacle"
item_state = "tentacle"
flags = ABSTRACT | NODROP | NOBLUDGEON | DROPDEL
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/gun/magic/tentacle/New(location,silent)
..()
if(ismob(loc))
if(!silent)
loc.visible_message("<span class='warning'>[loc.name]\'s arm starts stretching inhumanly!</span>", "<span class='warning'>Our arm twists and mutates, transforming it into a tentacle.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
else
to_chat(loc, "<span class='notice'>You prepare to extend a tentacle.</span>")
/obj/item/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj)
to_chat(user, "<span class='warning'>The [name] is not ready yet.</span>")
/obj/item/gun/magic/tentacle/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] coils [src] tightly around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide.</span>")
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/gun/magic/tentacle/gun //the item that shot it
/obj/item/ammo_casing/magic/tentacle/New(obj/item/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/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("<span class='danger'>[src] impales [C] with [I]!</span>", "<span class='userdanger'>[src] impales you with [I]!</span>")
add_attack_logs(src, C, "[src] pulled [C] with a tentacle, attacking them with [I]") //Attack log is here so we can fetch the item they're stabbing with.
C.apply_damage(I.force, BRUTE, "chest")
do_item_attack_animation(C, used_item = I)
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, "<span class='notice'>You pull [I] towards yourself.</span>")
add_attack_logs(src, I, "[src] pulled [I] towards them with a tentacle")
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("<span class='danger'>[L] is pulled by [H]'s tentacle!</span>","<span class='userdanger'>A tentacle grabs you and pulls you towards [H]!</span>")
add_attack_logs(H, L, "[H] pulled [L] towards them with a tentacle")
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("<span class='danger'>[I] is yanked out of [C]'s hand by [src]!</span>","<span class='userdanger'>A tentacle pulls [I] away from you!</span>")
add_attack_logs(src, C, "[src] has grabbed [I] out of [C]'s hand with a tentacle")
on_hit(I) //grab the item as if you had hit it directly with the tentacle
return 1
else
to_chat(firer, "<span class='danger'>You can't seem to pry [I] out of [C]'s hands!</span>")
add_attack_logs(src, C, "[src] tried to grab [I] out of [C]'s hand with a tentacle, but failed")
return 0
else
to_chat(firer, "<span class='danger'>[C] has nothing in hand to disarm!</span>")
return 0
if(INTENT_GRAB)
C.visible_message("<span class='danger'>[L] is grabbed by [H]'s tentacle!</span>","<span class='userdanger'>A tentacle grabs you and pulls you towards [H]!</span>")
add_attack_logs(H, C, "[H] grabbed [C] with a changeling tentacle")
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("<span class='danger'>[L] is thrown towards [H] by a tentacle!</span>","<span class='userdanger'>A tentacle grabs you and throws you towards [H]!</span>")
C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_stab, C))
return 1
else
L.visible_message("<span class='danger'>[L] is pulled by [H]'s tentacle!</span>","<span class='userdanger'>A tentacle grabs you and pulls you towards [H]!</span>")
L.throw_at(get_step_towards(H,L), 8, 2)
. = 1
/obj/item/projectile/tentacle/Destroy()
qdel(chain)
source = null
return ..()
/***************************************\
|****************SHIELD*****************|
\***************************************/
/datum/action/changeling/weapon/shield
name = "Organic Shield"
desc = "We reform one of our arms into a hard shield. Costs 20 chemicals."
helptext = "Organic tissue cannot resist damage forever. The shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
button_icon_state = "organic_shield"
chemical_cost = 20
dna_cost = 1
genetic_damage = 12
req_human = 1
max_genetic_damage = 20
weapon_type = /obj/item/shield/changeling
weapon_name_simple = "shield"
/datum/action/changeling/weapon/shield/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount.
if(!changeling)
return
var/obj/item/shield/changeling/S = ..(user)
if(!S)
return
S.remaining_uses = round(changeling.absorbedcount * 3)
return 1
/obj/item/shield/changeling
name = "shield-like mass"
desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield."
flags = NODROP | DROPDEL
icon_state = "ling_shield"
block_chance = 50
var/remaining_uses //Set by the changeling ability.
/obj/item/shield/changeling/New()
..()
if(ismob(loc))
loc.visible_message("<span class='warning'>The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!</span>", "<span class='warning'>We inflate our hand into a strong shield.</span>", "<span class='warning'>You hear organic matter ripping and tearing!</span>")
/obj/item/shield/changeling/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(remaining_uses < 1)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.visible_message("<span class='warning'>With a sickening crunch, [H] reforms [H.p_their()] shield into an arm!</span>", "<span class='notice'>We assimilate our shield into our body</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
H.unEquip(src, 1)
qdel(src)
return 0
else
remaining_uses--
return ..()
/***************************************\
|*********SPACE SUIT + HELMET***********|
\***************************************/
/datum/action/changeling/suit/organic_space_suit
name = "Organic Space Suit"
desc = "We grow an organic suit to protect ourselves from space exposure. Costs 20 chemicals."
helptext = "We must constantly repair our form to make it space proof, reducing chemical production while we are protected. Cannot be used in lesser form."
button_icon_state = "organic_suit"
chemical_cost = 20
dna_cost = 2
genetic_damage = 8
req_human = 1
max_genetic_damage = 20
suit_type = /obj/item/clothing/suit/space/changeling
helmet_type = /obj/item/clothing/head/helmet/space/changeling
suit_name_simple = "flesh shell"
helmet_name_simple = "space helmet"
recharge_slowdown = 0.5
blood_on_castoff = 1
/obj/item/clothing/suit/space/changeling
name = "flesh mass"
icon_state = "lingspacesuit"
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
flags = STOPSPRESSUREDMAGE | NODROP | DROPDEL
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/tank/oxygen)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) //No armor at all
/obj/item/clothing/suit/space/changeling/New()
..()
if(ismob(loc))
loc.visible_message("<span class='warning'>[loc.name]\'s flesh rapidly inflates, forming a bloated mass around [loc.p_their()] body!</span>", "<span class='warning'>We inflate our flesh, creating a spaceproof suit!</span>", "<span class='warning'>You hear organic matter ripping and tearing!</span>")
START_PROCESSING(SSobj, src)
/obj/item/clothing/suit/space/changeling/process()
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.reagents.add_reagent("perfluorodecalin", REAGENTS_METABOLISM)
/obj/item/clothing/head/helmet/space/changeling
name = "flesh mass"
icon_state = "lingspacehelmet"
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
flags = BLOCKHAIR | STOPSPRESSUREDMAGE | NODROP | DROPDEL
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/***************************************\
|*****************ARMOR*****************|
\***************************************/
/datum/action/changeling/suit/armor
name = "Chitinous Armor"
desc = "We turn our skin into tough chitin to protect us from damage. Costs 25 chemicals."
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
button_icon_state = "chitinous_armor"
chemical_cost = 25
dna_cost = 2
genetic_damage = 11
req_human = 1
max_genetic_damage = 20
suit_type = /obj/item/clothing/suit/armor/changeling
helmet_type = /obj/item/clothing/head/helmet/changeling
suit_name_simple = "armor"
helmet_name_simple = "helmet"
recharge_slowdown = 0.25
/obj/item/clothing/suit/armor/changeling
name = "chitinous mass"
desc = "A tough, hard covering of black chitin."
icon_state = "lingarmor"
flags = NODROP | DROPDEL
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
flags_inv = HIDEJUMPSUIT
cold_protection = 0
heat_protection = 0
sprite_sheets = null
/obj/item/clothing/suit/armor/changeling/New()
..()
if(ismob(loc))
loc.visible_message("<span class='warning'>[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!</span>", "<span class='warning'>We harden our flesh, creating a suit of armor!</span>", "<span class='warning'>You hear organic matter ripping and tearing!</span>")
/obj/item/clothing/head/helmet/changeling
name = "chitinous mass"
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
flags = BLOCKHAIR | NODROP | DROPDEL
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
flags_inv = HIDEEARS