diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm new file mode 100644 index 000000000000..5ecbef8b41b4 --- /dev/null +++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm @@ -0,0 +1,848 @@ +/mob/living/simple_animal/hostile/werewolf/funwolf + name = "Fun Werewolf" + desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one seems to have a strange look in its eyes.." + var/change_target_hole_cooldown = 0 + var/chosen_hole + var/voremode = FALSE // Fixes runtime when grabbing victim + gold_core_spawnable = NO_SPAWN // Admin only + werewolf_mode = "rape" + +/mob/living/simple_animal/hostile/werewolf/funwolf/gentle + name = "Gentle Werewolf" + desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one has the bedroom eyes.." + werewolf_mode = "gentle" + +/mob/living/simple_animal/hostile/werewolf/funwolf/abomination + name = "Exiled Werewolf" + desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one has a strange smell for some reason.." + werewolf_mode = "abomination" + +/mob/living/simple_animal/hostile/werewolf/funwolf/AttackingTarget() + var/mob/living/M = target + + var/onLewdCooldown = FALSE + var/wantsNoncon = FALSE + + if(get_refraction_dif() > 0) + onLewdCooldown = TRUE + + if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes") + wantsNoncon = TRUE + + switch(werewolf_mode) + if("gentle") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("abomination") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("rape") + if(onLewdCooldown || !wantsNoncon || M.health > 60) + ..() // Attack target + return + + if(!M.pulledby) + if(!M.buckled && !M.density) + M.forceMove(src.loc) + + start_pulling(M, supress_message = TRUE) + log_combat(src, M, "grabbed") + M.visible_message(span_warning("[src] violently grabs [M]!"), \ + span_userdanger("[src] violently grabs you!")) + setGrabState(GRAB_NECK) //Instant neck grab + + return + + if(get_refraction_dif() > 0) + ..() + return + + if(change_target_hole_cooldown < world.time) + chosen_hole = null + while (chosen_hole == null) + pickNewHole(M) + change_target_hole_cooldown = world.time + 100 + + + do_lewd_action(M) + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12)) + + // Regular sex has an extra action per tick to seem less slow and robotic + if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes") + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16)) + + +/mob/living/simple_animal/hostile/werewolf/funwolf/proc/pickNewHole(mob/living/M) + switch(rand(2)) + if(0) + chosen_hole = CUM_TARGET_ANUS + if(1) + if(M.has_vagina()) + chosen_hole = CUM_TARGET_VAGINA + else + chosen_hole = CUM_TARGET_ANUS + if(2) + chosen_hole = CUM_TARGET_THROAT + +/mob/living/simple_animal/hostile/werewolf/funwolf/proc/do_lewd_action(mob/living/M) + if(get_refraction_dif() > 0) + return + + if(rand(1,7) == 7) + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1) + + var/datum/interaction/I + switch(chosen_hole) + if(CUM_TARGET_ANUS) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"] + else + I = SSinteractions.interactions["/datum/interaction/lewd/grindface"] + handle_post_sex(25, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"] + I.display_interaction(src, M) + + if(CUM_TARGET_VAGINA) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"] + handle_post_sex(10, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck"] + I.display_interaction(src, M) + + if(CUM_TARGET_THROAT) + if(tearSlot(M, ITEM_SLOT_HEAD)) + return + if(tearSlot(M, ITEM_SLOT_MASK)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + do_faceshit(M) + else + do_facefart(M) + handle_post_sex(25, null, M) + shake_camera(M, 6, 1) + else + I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"] + I.display_interaction(src, M) + +/mob/living/simple_animal/hostile/werewolf/funwolf/cum(mob/living/M) + + if(get_refraction_dif() > 0) + return + + var/message + + if(!istype(M)) + chosen_hole = null + + switch(chosen_hole) + if(CUM_TARGET_THROAT) + if(M.has_mouth() && M.mouth_is_free()) + message = "shoves their fat canine cock deep down \the [M]'s throat and cums." + else + message = "cums on \the [M]'s face." + if(CUM_TARGET_VAGINA) + if(M.is_bottomless() && M.has_vagina()) + message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm." + M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type) + else + message = "cums on \the [M]'s belly." + if(CUM_TARGET_ANUS) + if(M.is_bottomless() && M.has_anus()) + message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz." + else + message = "cums on \the [M]'s backside." + else + message = "cums on the floor!" + + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + message = "cums all over [M]'s body" + + if(istype(M, /mob/living/carbon)) + M.reagents.add_reagent(/datum/reagent/consumable/semen, 30) + new /obj/effect/decal/cleanable/semen(loc) + + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1) + visible_message("\The [src] [message]") + shake_camera(M, 6, 1) + set_is_fucking(null ,null) + + refractory_period = world.time + rand(100, 150) // Sex cooldown + set_lust(0) // Nuts at 400 + + addtimer(CALLBACK(src, .proc/slap, M), 15) + + +/mob/living/simple_animal/hostile/werewolf/funwolf/proc/slap(mob/living/M) + playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \ + span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE) + +/mob/living/simple_animal/hostile/werewolf/funwolf/proc/tearSlot(mob/living/M, slot) + var/obj/item/W = M.get_item_by_slot(slot) + if(W) + M.dropItemToGround(W) + playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \ + span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE) + return TRUE + return FALSE + +//////////////// +// // +// Ice Wolf // +// // +//////////////// + +/mob/living/simple_animal/hostile/ice_wolf/funwolf + name = "Fun Ice Wolf" + desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one seems to have a strange look in its eyes.." + var/change_target_hole_cooldown = 0 + var/chosen_hole + var/voremode = FALSE // Fixes runtime when grabbing victim + gold_core_spawnable = NO_SPAWN // Admin only + werewolf_mode = "rape" + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/gentle + name = "Gentle Ice Wolf" + desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one has the bedroom eyes.." + werewolf_mode = "gentle" + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/abomination + name = "Exiled Ice Wolf" + desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one has a strange smell for some reason.." + werewolf_mode = "abomination" + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/AttackingTarget() + var/mob/living/M = target + + var/onLewdCooldown = FALSE + var/wantsNoncon = FALSE + + if(get_refraction_dif() > 0) + onLewdCooldown = TRUE + + if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes") + wantsNoncon = TRUE + + switch(werewolf_mode) + if("gentle") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("abomination") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("rape") + if(onLewdCooldown || !wantsNoncon || M.health > 60) + ..() // Attack target + return + + if(!M.pulledby) + if(!M.buckled && !M.density) + M.forceMove(src.loc) + + start_pulling(M, supress_message = TRUE) + log_combat(src, M, "grabbed") + M.visible_message(span_warning("[src] violently grabs [M]!"), \ + span_userdanger("[src] violently grabs you!")) + setGrabState(GRAB_NECK) //Instant neck grab + + return + + if(get_refraction_dif() > 0) + ..() + return + + if(change_target_hole_cooldown < world.time) + chosen_hole = null + while (chosen_hole == null) + pickNewHole(M) + change_target_hole_cooldown = world.time + 100 + + + do_lewd_action(M) + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12)) + + // Regular sex has an extra action per tick to seem less slow and robotic + if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes") + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16)) + + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/pickNewHole(mob/living/M) + switch(rand(2)) + if(0) + chosen_hole = CUM_TARGET_ANUS + if(1) + if(M.has_vagina()) + chosen_hole = CUM_TARGET_VAGINA + else + chosen_hole = CUM_TARGET_ANUS + if(2) + chosen_hole = CUM_TARGET_THROAT + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/do_lewd_action(mob/living/M) + if(get_refraction_dif() > 0) + return + + if(rand(1,7) == 7) + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1) + + var/datum/interaction/I + switch(chosen_hole) + if(CUM_TARGET_ANUS) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"] + else + I = SSinteractions.interactions["/datum/interaction/lewd/grindface"] + handle_post_sex(25, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"] + I.display_interaction(src, M) + + if(CUM_TARGET_VAGINA) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"] + handle_post_sex(10, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck"] + I.display_interaction(src, M) + + if(CUM_TARGET_THROAT) + if(tearSlot(M, ITEM_SLOT_HEAD)) + return + if(tearSlot(M, ITEM_SLOT_MASK)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + do_faceshit(M) + else + do_facefart(M) + handle_post_sex(25, null, M) + shake_camera(M, 6, 1) + else + I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"] + I.display_interaction(src, M) + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/cum(mob/living/M) + + if(get_refraction_dif() > 0) + return + + var/message + + if(!istype(M)) + chosen_hole = null + + switch(chosen_hole) + if(CUM_TARGET_THROAT) + if(M.has_mouth() && M.mouth_is_free()) + message = "shoves their fat canine cock deep down \the [M]'s throat and cums." + else + message = "cums on \the [M]'s face." + if(CUM_TARGET_VAGINA) + if(M.is_bottomless() && M.has_vagina()) + message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm." + M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type) + else + message = "cums on \the [M]'s belly." + if(CUM_TARGET_ANUS) + if(M.is_bottomless() && M.has_anus()) + message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz." + else + message = "cums on \the [M]'s backside." + else + message = "cums on the floor!" + + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + message = "cums all over [M]'s body" + + if(istype(M, /mob/living/carbon)) + M.reagents.add_reagent(/datum/reagent/consumable/semen, 30) + new /obj/effect/decal/cleanable/semen(loc) + + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1) + visible_message("\The [src] [message]") + shake_camera(M, 6, 1) + set_is_fucking(null ,null) + + refractory_period = world.time + rand(100, 150) // Sex cooldown + set_lust(0) // Nuts at 400 + + addtimer(CALLBACK(src, .proc/slap, M), 15) + + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/slap(mob/living/M) + playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \ + span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE) + +/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/tearSlot(mob/living/M, slot) + var/obj/item/W = M.get_item_by_slot(slot) + if(W) + M.dropItemToGround(W) + playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \ + span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE) + return TRUE + return FALSE + + +//////////////// +// // +// Hell Hound // +// // +//////////////// + +/mob/living/simple_animal/hostile/hellhound/funwolf + name = "Fun Hell Hound" + desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one seems to have a strange look in its eyes.." + var/change_target_hole_cooldown = 0 + var/chosen_hole + var/voremode = FALSE // Fixes runtime when grabbing victim + gold_core_spawnable = NO_SPAWN // Admin only + werewolf_mode = "rape" + +/mob/living/simple_animal/hostile/hellhound/funwolf/gentle + name = "Gentle Hell Hound" + desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one has the bedroom eyes.." + werewolf_mode = "gentle" + +/mob/living/simple_animal/hostile/hellhound/funwolf/abomination + name = "Exiled Hell Hound" + desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one has a strange smell for some reason.." + werewolf_mode = "abomination" + +/mob/living/simple_animal/hostile/hellhound/funwolf/AttackingTarget() + var/mob/living/M = target + + var/onLewdCooldown = FALSE + var/wantsNoncon = FALSE + + if(get_refraction_dif() > 0) + onLewdCooldown = TRUE + + if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes") + wantsNoncon = TRUE + + switch(werewolf_mode) + if("gentle") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("abomination") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("rape") + if(onLewdCooldown || !wantsNoncon || M.health > 60) + ..() // Attack target + return + + if(!M.pulledby) + if(!M.buckled && !M.density) + M.forceMove(src.loc) + + start_pulling(M, supress_message = TRUE) + log_combat(src, M, "grabbed") + M.visible_message(span_warning("[src] violently grabs [M]!"), \ + span_userdanger("[src] violently grabs you!")) + setGrabState(GRAB_NECK) //Instant neck grab + + return + + if(get_refraction_dif() > 0) + ..() + return + + if(change_target_hole_cooldown < world.time) + chosen_hole = null + while (chosen_hole == null) + pickNewHole(M) + change_target_hole_cooldown = world.time + 100 + + + do_lewd_action(M) + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12)) + + // Regular sex has an extra action per tick to seem less slow and robotic + if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes") + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16)) + + +/mob/living/simple_animal/hostile/hellhound/funwolf/proc/pickNewHole(mob/living/M) + switch(rand(2)) + if(0) + chosen_hole = CUM_TARGET_ANUS + if(1) + if(M.has_vagina()) + chosen_hole = CUM_TARGET_VAGINA + else + chosen_hole = CUM_TARGET_ANUS + if(2) + chosen_hole = CUM_TARGET_THROAT + +/mob/living/simple_animal/hostile/hellhound/funwolf/proc/do_lewd_action(mob/living/M) + if(get_refraction_dif() > 0) + return + + if(rand(1,7) == 7) + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1) + + var/datum/interaction/I + switch(chosen_hole) + if(CUM_TARGET_ANUS) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"] + else + I = SSinteractions.interactions["/datum/interaction/lewd/grindface"] + handle_post_sex(25, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"] + I.display_interaction(src, M) + + if(CUM_TARGET_VAGINA) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"] + handle_post_sex(10, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck"] + I.display_interaction(src, M) + + if(CUM_TARGET_THROAT) + if(tearSlot(M, ITEM_SLOT_HEAD)) + return + if(tearSlot(M, ITEM_SLOT_MASK)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + do_faceshit(M) + else + do_facefart(M) + handle_post_sex(25, null, M) + shake_camera(M, 6, 1) + else + I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"] + I.display_interaction(src, M) + +/mob/living/simple_animal/hostile/hellhound/funwolf/cum(mob/living/M) + + if(get_refraction_dif() > 0) + return + + var/message + + if(!istype(M)) + chosen_hole = null + + switch(chosen_hole) + if(CUM_TARGET_THROAT) + if(M.has_mouth() && M.mouth_is_free()) + message = "shoves their fat canine cock deep down \the [M]'s throat and cums." + else + message = "cums on \the [M]'s face." + if(CUM_TARGET_VAGINA) + if(M.is_bottomless() && M.has_vagina()) + message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm." + M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type) + else + message = "cums on \the [M]'s belly." + if(CUM_TARGET_ANUS) + if(M.is_bottomless() && M.has_anus()) + message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz." + else + message = "cums on \the [M]'s backside." + else + message = "cums on the floor!" + + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + message = "cums all over [M]'s body" + + if(istype(M, /mob/living/carbon)) + M.reagents.add_reagent(/datum/reagent/consumable/semen, 30) + new /obj/effect/decal/cleanable/semen(loc) + + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1) + visible_message("\The [src] [message]") + shake_camera(M, 6, 1) + set_is_fucking(null ,null) + + refractory_period = world.time + rand(100, 150) // Sex cooldown + set_lust(0) // Nuts at 400 + + addtimer(CALLBACK(src, .proc/slap, M), 15) + + +/mob/living/simple_animal/hostile/hellhound/funwolf/proc/slap(mob/living/M) + playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \ + span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE) + +/mob/living/simple_animal/hostile/hellhound/funwolf/proc/tearSlot(mob/living/M, slot) + var/obj/item/W = M.get_item_by_slot(slot) + if(W) + M.dropItemToGround(W) + playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \ + span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE) + return TRUE + return FALSE + + +////////////////// +// // +// The Mosley // +// // +////////////////// + +/mob/living/simple_animal/hostile/the_mosley/funwolf + name = "Fun Mosley" + desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one seems to have a strange look in its eyes.." + var/change_target_hole_cooldown = 0 + var/chosen_hole + var/voremode = FALSE // Fixes runtime when grabbing victim + gold_core_spawnable = NO_SPAWN // Admin only + werewolf_mode = "rape" + +/mob/living/simple_animal/hostile/the_mosley/funwolf/gentle + name = "Gentle Mosley" + desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one has the bedroom eyes.." + werewolf_mode = "gentle" + +/mob/living/simple_animal/hostile/the_mosley/funwolf/abomination + name = "Exiled Mosley" + desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one has a strange smell for some reason.." + werewolf_mode = "abomination" + +/mob/living/simple_animal/hostile/the_mosley/funwolf/AttackingTarget() + var/mob/living/M = target + + var/onLewdCooldown = FALSE + var/wantsNoncon = FALSE + + if(get_refraction_dif() > 0) + onLewdCooldown = TRUE + + if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes") + wantsNoncon = TRUE + + switch(werewolf_mode) + if("gentle") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("abomination") + if(onLewdCooldown || !wantsNoncon) + return // Do nothing + if("rape") + if(onLewdCooldown || !wantsNoncon || M.health > 60) + ..() // Attack target + return + + if(!M.pulledby) + if(!M.buckled && !M.density) + M.forceMove(src.loc) + + start_pulling(M, supress_message = TRUE) + log_combat(src, M, "grabbed") + M.visible_message(span_warning("[src] violently grabs [M]!"), \ + span_userdanger("[src] violently grabs you!")) + setGrabState(GRAB_NECK) //Instant neck grab + + return + + if(get_refraction_dif() > 0) + ..() + return + + if(change_target_hole_cooldown < world.time) + chosen_hole = null + while (chosen_hole == null) + pickNewHole(M) + change_target_hole_cooldown = world.time + 100 + + + do_lewd_action(M) + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12)) + + // Regular sex has an extra action per tick to seem less slow and robotic + if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes") + addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16)) + + +/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/pickNewHole(mob/living/M) + switch(rand(2)) + if(0) + chosen_hole = CUM_TARGET_ANUS + if(1) + if(M.has_vagina()) + chosen_hole = CUM_TARGET_VAGINA + else + chosen_hole = CUM_TARGET_ANUS + if(2) + chosen_hole = CUM_TARGET_THROAT + +/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/do_lewd_action(mob/living/M) + if(get_refraction_dif() > 0) + return + + if(rand(1,7) == 7) + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1) + + var/datum/interaction/I + switch(chosen_hole) + if(CUM_TARGET_ANUS) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"] + else + I = SSinteractions.interactions["/datum/interaction/lewd/grindface"] + handle_post_sex(25, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"] + I.display_interaction(src, M) + + if(CUM_TARGET_VAGINA) + if(tearSlot(M, ITEM_SLOT_OCLOTHING)) + return + if(tearSlot(M, ITEM_SLOT_ICLOTHING)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"] + handle_post_sex(10, null, M) + else + I = SSinteractions.interactions["/datum/interaction/lewd/fuck"] + I.display_interaction(src, M) + + if(CUM_TARGET_THROAT) + if(tearSlot(M, ITEM_SLOT_HEAD)) + return + if(tearSlot(M, ITEM_SLOT_MASK)) + return + + // Abomination deathclaws do other stuff instead + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + if(prob(1)) + do_faceshit(M) + else + do_facefart(M) + handle_post_sex(25, null, M) + shake_camera(M, 6, 1) + else + I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"] + I.display_interaction(src, M) + +/mob/living/simple_animal/hostile/the_mosley/funwolf/cum(mob/living/M) + + if(get_refraction_dif() > 0) + return + + var/message + + if(!istype(M)) + chosen_hole = null + + switch(chosen_hole) + if(CUM_TARGET_THROAT) + if(M.has_mouth() && M.mouth_is_free()) + message = "shoves their fat canine cock deep down \the [M]'s throat and cums." + else + message = "cums on \the [M]'s face." + if(CUM_TARGET_VAGINA) + if(M.is_bottomless() && M.has_vagina()) + message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm." + M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type) + else + message = "cums on \the [M]'s belly." + if(CUM_TARGET_ANUS) + if(M.is_bottomless() && M.has_anus()) + message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz." + else + message = "cums on \the [M]'s backside." + else + message = "cums on the floor!" + + if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes") + message = "cums all over [M]'s body" + + if(istype(M, /mob/living/carbon)) + M.reagents.add_reagent(/datum/reagent/consumable/semen, 30) + new /obj/effect/decal/cleanable/semen(loc) + + playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1) + visible_message("\The [src] [message]") + shake_camera(M, 6, 1) + set_is_fucking(null ,null) + + refractory_period = world.time + rand(100, 150) // Sex cooldown + set_lust(0) // Nuts at 400 + + addtimer(CALLBACK(src, .proc/slap, M), 15) + + +/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/slap(mob/living/M) + playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \ + span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE) + +/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/tearSlot(mob/living/M, slot) + var/obj/item/W = M.get_item_by_slot(slot) + if(W) + M.dropItemToGround(W) + playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1) + visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \ + span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE) + return TRUE + return FALSE + diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm new file mode 100644 index 000000000000..68a3ee3edd8b --- /dev/null +++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm @@ -0,0 +1,134 @@ +/mob/living/simple_animal/hostile/hellhound + name = "Hell Hound" + desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match." + icon = 'modular_splurt/icons/mobs/werewolf.dmi' + icon_state = "Hell_Hound_idle" + icon_living = "Hell_Hound_idle" + icon_dead = "Hell_Hound__dead" + icon_gib = "syndicate_gib" + pixel_x = -16 + gender = MALE + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + stat_attack = UNCONSCIOUS + speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!") + speak_emote = list("growls", "snarls") + emote_hear = list("grumbles.","snarls.") + emote_taunt = list("bares its teeth", "stomps") + speak_chance = 10 + taunt_chance = 25 + speed = 0 + see_in_dark = 8 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4, + /obj/item/stack/sheet/animalhide = 2, + /obj/item/stack/sheet/bone = 4) + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + maxHealth = 500 + health = 500 + obj_damage = 60 + armour_penetration = 30 + melee_damage_lower = 56 + melee_damage_upper = 56 + attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg' + faction = list("werewolf") + atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) + unsuitable_atmos_damage = 5 + gold_core_spawnable = HOSTILE_SPAWN + var/charging = FALSE + has_penis = TRUE + has_butt = TRUE + + footstep_type = FOOTSTEP_MOB_HEAVY + + //**werewolf_mode** + // Hostile: Normal deathclaw murder machine + // Friendly: Does not attack + // Rape: Hurts and lewds people + // Gentle: lewds people + // Abomination: Hurts and does unspeakable lewd things to people + var/werewolf_mode = "hostile" + +/mob/living/simple_animal/hostile/hellhound/pacifist + name = "Friendly Hell Hound" + desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match." + werewolf_mode = "friendly" + friendly_verb_continuous = "howls at" + friendly_verb_simple = "howl at" + +/mob/living/simple_animal/hostile/hellhound/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + if(prob(10)) + visible_message(span_danger("\The [src] growls, enraged!")) + sleep(3) + Charge() + if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be + return ..() + else + visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!")) + return 0 + +/mob/living/simple_animal/hostile/hellhound/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/hellhound/AttackingTarget() + if (werewolf_mode == "friendly") + return // Do not attack + + if(!charging) + return ..() + +/mob/living/simple_animal/hostile/hellhound/Goto(target, delay, minimum_distance) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/hellhound/Move() + if(charging) + new /obj/effect/temp_visual/decoy/fading(loc,src) + DestroySurroundings() + . = ..() + if(charging) + DestroySurroundings() + +/mob/living/simple_animal/hostile/hellhound/proc/Charge() + var/turf/T = get_turf(target) + if(!T || T == loc) + return + charging = TRUE + visible_message(span_danger("[src] charges!")) + DestroySurroundings() + walk(src, 0) + setDir(get_dir(src, T)) + var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src) + animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1) + sleep(3) + throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end)) + +/mob/living/simple_animal/hostile/hellhound/charge_end(list/effects_to_destroy) + charging = FALSE + if(target) + Goto(target, move_to_delay, minimum_distance) + +/mob/living/simple_animal/hostile/hellhound/Bump(atom/A) + if(charging) + if(isturf(A) || isobj(A) && A.density) + A.ex_act(EXPLODE_HEAVY) + DestroySurroundings() + ..() + +/mob/living/simple_animal/hostile/hellhound/throw_impact(atom/A) + if(!charging) + return ..() + + else if(isliving(A)) + var/mob/living/L = A + L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!")) + L.apply_damage(melee_damage_lower/2, BRUTE) + playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) + shake_camera(L, 4, 3) + shake_camera(src, 2, 3) + var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) + L.throw_at(throwtarget, 3) + + charging = FALSE diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm new file mode 100644 index 000000000000..8f785c2b2b8b --- /dev/null +++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm @@ -0,0 +1,134 @@ +/mob/living/simple_animal/hostile/ice_wolf + name = "Ice Werewolf" + desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match." + icon = 'modular_splurt/icons/mobs/werewolf.dmi' + icon_state = "Ice_Wolf_idle" + icon_living = "Ice_Wolf_idle" + icon_dead = "Ice_Wolf_dead" + icon_gib = "syndicate_gib" + pixel_x = -16 + gender = MALE + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + stat_attack = UNCONSCIOUS + speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!") + speak_emote = list("growls", "snarls") + emote_hear = list("grumbles.","snarls.") + emote_taunt = list("bares its teeth", "stomps") + speak_chance = 10 + taunt_chance = 25 + speed = 0 + see_in_dark = 8 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4, + /obj/item/stack/sheet/animalhide = 2, + /obj/item/stack/sheet/bone = 4) + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + maxHealth = 500 + health = 500 + obj_damage = 60 + armour_penetration = 30 + melee_damage_lower = 56 + melee_damage_upper = 56 + attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg' + faction = list("werewolf") + atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) + unsuitable_atmos_damage = 5 + gold_core_spawnable = HOSTILE_SPAWN + var/charging = FALSE + has_penis = TRUE + has_butt = TRUE + + footstep_type = FOOTSTEP_MOB_HEAVY + + //**werewolf_mode** + // Hostile: Normal deathclaw murder machine + // Friendly: Does not attack + // Rape: Hurts and lewds people + // Gentle: lewds people + // Abomination: Hurts and does unspeakable lewd things to people + var/werewolf_mode = "hostile" + +/mob/living/simple_animal/hostile/ice_wolf/pacifist + name = "Friendly Ice Werewolf" + desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match." + werewolf_mode = "friendly" + friendly_verb_continuous = "howls at" + friendly_verb_simple = "howl at" + +/mob/living/simple_animal/hostile/ice_wolf/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + if(prob(10)) + visible_message(span_danger("\The [src] growls, enraged!")) + sleep(3) + Charge() + if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be + return ..() + else + visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!")) + return 0 + +/mob/living/simple_animal/hostile/ice_wolf/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/ice_wolf/AttackingTarget() + if (werewolf_mode == "friendly") + return // Do not attack + + if(!charging) + return ..() + +/mob/living/simple_animal/hostile/ice_wolf/Goto(target, delay, minimum_distance) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/ice_wolf/Move() + if(charging) + new /obj/effect/temp_visual/decoy/fading(loc,src) + DestroySurroundings() + . = ..() + if(charging) + DestroySurroundings() + +/mob/living/simple_animal/hostile/ice_wolf/proc/Charge() + var/turf/T = get_turf(target) + if(!T || T == loc) + return + charging = TRUE + visible_message(span_danger("[src] charges!")) + DestroySurroundings() + walk(src, 0) + setDir(get_dir(src, T)) + var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src) + animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1) + sleep(3) + throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end)) + +/mob/living/simple_animal/hostile/ice_wolf/charge_end(list/effects_to_destroy) + charging = FALSE + if(target) + Goto(target, move_to_delay, minimum_distance) + +/mob/living/simple_animal/hostile/ice_wolf/Bump(atom/A) + if(charging) + if(isturf(A) || isobj(A) && A.density) + A.ex_act(EXPLODE_HEAVY) + DestroySurroundings() + ..() + +/mob/living/simple_animal/hostile/ice_wolf/throw_impact(atom/A) + if(!charging) + return ..() + + else if(isliving(A)) + var/mob/living/L = A + L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!")) + L.apply_damage(melee_damage_lower/2, BRUTE) + playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) + shake_camera(L, 4, 3) + shake_camera(src, 2, 3) + var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) + L.throw_at(throwtarget, 3) + + charging = FALSE diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm new file mode 100644 index 000000000000..ba74e5bce45b --- /dev/null +++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm @@ -0,0 +1,134 @@ +/mob/living/simple_animal/hostile/the_mosley + name = "The Mosley" + desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match." + icon = 'modular_splurt/icons/mobs/werewolf.dmi' + icon_state = "The_Mosley_idle" + icon_living = "The_Mosley_idle" + icon_dead = "The_Mosley_dead" + icon_gib = "syndicate_gib" + pixel_x = -16 + gender = MALE + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + stat_attack = UNCONSCIOUS + speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!") + speak_emote = list("growls", "snarls") + emote_hear = list("grumbles.","snarls.") + emote_taunt = list("bares its teeth", "stomps") + speak_chance = 10 + taunt_chance = 25 + speed = 0 + see_in_dark = 8 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4, + /obj/item/stack/sheet/animalhide = 2, + /obj/item/stack/sheet/bone = 4) + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + maxHealth = 500 + health = 500 + obj_damage = 60 + armour_penetration = 30 + melee_damage_lower = 56 + melee_damage_upper = 56 + attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg' + faction = list("werewolf") + atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) + unsuitable_atmos_damage = 5 + gold_core_spawnable = FALSE + var/charging = FALSE + has_penis = TRUE + has_butt = TRUE + + footstep_type = FOOTSTEP_MOB_HEAVY + + //**werewolf_mode** + // Hostile: Normal deathclaw murder machine + // Friendly: Does not attack + // Rape: Hurts and lewds people + // Gentle: lewds people + // Abomination: Hurts and does unspeakable lewd things to people + var/werewolf_mode = "hostile" + +/mob/living/simple_animal/hostile/the_mosley/pacifist + name = "Friendly Mosley" + desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match." + werewolf_mode = "friendly" + friendly_verb_continuous = "howls at" + friendly_verb_simple = "howl at" + +/mob/living/simple_animal/hostile/the_mosley/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + if(prob(10)) + visible_message(span_danger("\The [src] growls, enraged!")) + sleep(3) + Charge() + if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be + return ..() + else + visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!")) + return 0 + +/mob/living/simple_animal/hostile/the_mosley/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/the_mosley/AttackingTarget() + if (werewolf_mode == "friendly") + return // Do not attack + + if(!charging) + return ..() + +/mob/living/simple_animal/hostile/the_mosley/Goto(target, delay, minimum_distance) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/the_mosley/Move() + if(charging) + new /obj/effect/temp_visual/decoy/fading(loc,src) + DestroySurroundings() + . = ..() + if(charging) + DestroySurroundings() + +/mob/living/simple_animal/hostile/the_mosley/proc/Charge() + var/turf/T = get_turf(target) + if(!T || T == loc) + return + charging = TRUE + visible_message(span_danger("[src] charges!")) + DestroySurroundings() + walk(src, 0) + setDir(get_dir(src, T)) + var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src) + animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1) + sleep(3) + throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end)) + +/mob/living/simple_animal/hostile/the_mosley/charge_end(list/effects_to_destroy) + charging = FALSE + if(target) + Goto(target, move_to_delay, minimum_distance) + +/mob/living/simple_animal/hostile/the_mosley/Bump(atom/A) + if(charging) + if(isturf(A) || isobj(A) && A.density) + A.ex_act(EXPLODE_HEAVY) + DestroySurroundings() + ..() + +/mob/living/simple_animal/hostile/the_mosley/throw_impact(atom/A) + if(!charging) + return ..() + + else if(isliving(A)) + var/mob/living/L = A + L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!")) + L.apply_damage(melee_damage_lower/2, BRUTE) + playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) + shake_camera(L, 4, 3) + shake_camera(src, 2, 3) + var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) + L.throw_at(throwtarget, 3) + + charging = FALSE diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm new file mode 100644 index 000000000000..46df07d37f6f --- /dev/null +++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm @@ -0,0 +1,134 @@ +/mob/living/simple_animal/hostile/werewolf + name = "Werewolf" + desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match." + icon = 'modular_splurt/icons/mobs/werewolf.dmi' + icon_state = "Werewolf_idle" + icon_living = "Werewolf_idle" + icon_dead = "Werewolf_dead" + icon_gib = "syndicate_gib" + pixel_x = -16 + gender = MALE + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + stat_attack = UNCONSCIOUS + speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!") + speak_emote = list("growls", "snarls") + emote_hear = list("grumbles.","snarls.") + emote_taunt = list("bares its teeth", "stomps") + speak_chance = 10 + taunt_chance = 25 + speed = 0 + see_in_dark = 8 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4, + /obj/item/stack/sheet/animalhide = 2, + /obj/item/stack/sheet/bone = 4) + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + maxHealth = 500 + health = 500 + obj_damage = 60 + armour_penetration = 30 + melee_damage_lower = 56 + melee_damage_upper = 56 + attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg' + faction = list("werewolf") + atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) + unsuitable_atmos_damage = 5 + gold_core_spawnable = HOSTILE_SPAWN + var/charging = FALSE + has_penis = TRUE + has_butt = TRUE + + footstep_type = FOOTSTEP_MOB_HEAVY + + //**werewolf_mode** + // Hostile: Normal deathclaw murder machine + // Friendly: Does not attack + // Rape: Hurts and lewds people + // Gentle: lewds people + // Abomination: Hurts and does unspeakable lewd things to people + var/werewolf_mode = "hostile" + +/mob/living/simple_animal/hostile/werewolf/pacifist + name = "Friendly Werewolf" + desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match." + werewolf_mode = "friendly" + friendly_verb_continuous = "howls at" + friendly_verb_simple = "howl at" + +/mob/living/simple_animal/hostile/werewolf/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return + if(prob(10)) + visible_message(span_danger("\The [src] growls, enraged!")) + sleep(3) + Charge() + if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be + return ..() + else + visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!")) + return 0 + +/mob/living/simple_animal/hostile/werewolf/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/werewolf/AttackingTarget() + if (werewolf_mode == "friendly") + return // Do not attack + + if(!charging) + return ..() + +/mob/living/simple_animal/hostile/werewolf/Goto(target, delay, minimum_distance) + if(!charging) + ..() + +/mob/living/simple_animal/hostile/werewolf/Move() + if(charging) + new /obj/effect/temp_visual/decoy/fading(loc,src) + DestroySurroundings() + . = ..() + if(charging) + DestroySurroundings() + +/mob/living/simple_animal/hostile/werewolf/proc/Charge() + var/turf/T = get_turf(target) + if(!T || T == loc) + return + charging = TRUE + visible_message(span_danger("[src] charges!")) + DestroySurroundings() + walk(src, 0) + setDir(get_dir(src, T)) + var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src) + animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1) + sleep(3) + throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end)) + +/mob/living/simple_animal/hostile/werewolf/charge_end(list/effects_to_destroy) + charging = FALSE + if(target) + Goto(target, move_to_delay, minimum_distance) + +/mob/living/simple_animal/hostile/werewolf/Bump(atom/A) + if(charging) + if(isturf(A) || isobj(A) && A.density) + A.ex_act(EXPLODE_HEAVY) + DestroySurroundings() + ..() + +/mob/living/simple_animal/hostile/werewolf/throw_impact(atom/A) + if(!charging) + return ..() + + else if(isliving(A)) + var/mob/living/L = A + L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!")) + L.apply_damage(melee_damage_lower/2, BRUTE) + playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) + shake_camera(L, 4, 3) + shake_camera(src, 2, 3) + var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) + L.throw_at(throwtarget, 3) + + charging = FALSE diff --git a/modular_splurt/icons/mobs/werewolf.dmi b/modular_splurt/icons/mobs/werewolf.dmi index fb89c833ed1a..b7051253a8e7 100644 Binary files a/modular_splurt/icons/mobs/werewolf.dmi and b/modular_splurt/icons/mobs/werewolf.dmi differ diff --git a/modular_splurt/sound/misc/claw_rend.ogg b/modular_splurt/sound/misc/claw_rend.ogg new file mode 100644 index 000000000000..a0acaa2a06d0 Binary files /dev/null and b/modular_splurt/sound/misc/claw_rend.ogg differ diff --git a/tgstation.dme b/tgstation.dme index b422ff6f19c0..efffd9522384 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4877,6 +4877,11 @@ #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\king_of_goats.dm" #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\penguinhiero.dm" #include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\sand.dm" +#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\funwolf.dm" +#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\hellhound.dm" +#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\icewolf.dm" +#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\themosley.dm" +#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\werewolf.dm" #include "modular_splurt\code\modules\paperwork\pen.dm" #include "modular_splurt\code\modules\power\cell.dm" #include "modular_splurt\code\modules\power\reactor\fluffed.dm"