diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm new file mode 100644 index 00000000000..3b2fedce807 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/gaslamp_vr.dm @@ -0,0 +1,81 @@ +/* +LORE: +Gaslamps are a phoron-based life form endemic to the world of Virgo-3B. They are +a sort of fungal organism with physical ties to Diona and Vox, deriving energy +for movement from a gentle combustion-like reaction in their bodies using +atmospheric phoron, carefully filtered trace oxygen, and captured meat products. +Over-exposure to oxygen causes their insides to burn too hot and eventually +kills them. + +TODO: Make them light up and heat the air when exposed to oxygen. +*/ + +/mob/living/simple_mob/animal/space/gaslamp + name = "gaslamp" + desc = "Some sort of floaty alien with a warm glow. This creature is endemic to Virgo-3B." + tt_desc = "Semaeostomeae virginus" + + icon_state = "gaslamp" + icon_living = "gaslamp" + icon_dead = "gaslamp-dead" + icon = 'icons/mob/vore32x64.dmi' + + faction = "virgo3b" + maxHealth = 100 + health = 100 + movement_cooldown = 12 + + say_list_type = /datum/say_list/gaslamp + ai_holder_type = /datum/ai_holder/simple_mob/gaslamp + + //speed = 2 not sure what this is, guessing animation, but it conflicts with new system. + + melee_damage_lower = 30 // Because fuck anyone who hurts this sweet, innocent creature. + melee_damage_upper = 30 + attacktext = list("thrashed") + friendly = "caressed" + + response_help = "brushes" // If clicked on help intent + response_disarm = "pushes" // If clicked on disarm intent + response_harm = "swats" // If clicked on harm intent + + minbodytemp = 0 + maxbodytemp = 350 + + min_oxy = 0 + max_oxy = 5 // Does not like oxygen very much. + min_tox = 1 // Needs phoron to survive. + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + +/datum/say_list/gaslamp + emote_see = list("looms", "sways gently") + +/datum/ai_holder/simple_mob/gaslamp + hostile = FALSE // The majority of simplemobs are hostile, gaslamps are nice. + cooperative = FALSE + retaliate = TRUE //so the monster can attack back + returns_home = FALSE + can_flee = FALSE + speak_chance = 1 + wander = TRUE + base_wander_delay = 9 + +// Activate Noms! +/mob/living/simple_mob/animal/space/gaslamp + vore_active = 1 + vore_capacity = 2 + vore_bump_chance = 90 //they're frickin' jellyfish anenome filterfeeders, get tentacled + vore_bump_emote = "lazily wraps its tentacles around" + vore_standing_too = 1 // Defaults to trying to give you that big tentacle hug. + vore_ignores_undigestable = 0 // they absorb rather than digest, you're going in either way + vore_default_mode = DM_HOLD + vore_digest_chance = 0 // Chance to switch to digest mode if resisted + vore_absorb_chance = 20 // BECOME A PART OF ME. + vore_pounce_chance = 5 // Small chance to punish people who abuse their nomming behaviour to try and kite them forever with repeated melee attacks. + vore_stomach_name = "internal chamber" + vore_stomach_flavor = "You are squeezed into the tight embrace of the alien creature's warm and cozy insides." + vore_icons = SA_ICON_LIVING diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/mimic_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/mimic_vr.dm new file mode 100644 index 00000000000..3cd2f744a00 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/mimic_vr.dm @@ -0,0 +1,244 @@ +// +// Abstract Class +// + +/mob/living/simple_mob/animal/space/mimic + name = "crate" + desc = "A rectangular steel crate." + + icon_state = "crate" + icon_living = "crate" + icon = 'icons/obj/storage.dmi' + + faction = "mimic" + + maxHealth = 250 + health = 250 + //speed = 4 no idea what this is, conflicts with new AI update. + movement_cooldown = 10 //slow crate. + + response_help = "touches" + response_disarm = "pushes" + response_harm = "hits" + + harm_intent_damage = 5 + melee_damage_lower = 8 + melee_damage_upper = 12 + attacktext = list("attacked") + attack_sound = 'sound/weapons/bite.ogg' + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat + + say_list_type = /datum/say_list/mimic + ai_holder_type = /datum/ai_holder/mimic + + var/knockdown_chance = 15 //Stubbing your toe on furniture hurts. + + showvoreprefs = 0 //VOREStation Edit - Hides mechanical vore prefs for mimics. You can't see their gaping maws when they're just sitting idle. + +/datum/say_list/mimic + say_got_target = list("growls") + +/datum/ai_holder/mimic + wander = FALSE + hostile = TRUE + threaten = TRUE + threaten_timeout = 5 SECONDS + threaten_delay = 1 SECONDS //not a threat, more of a delay. + +/mob/living/simple_mob/animal/space/carp/apply_melee_effects(var/atom/A) + if(isliving(A)) + var/mob/living/L = A + if(prob(knockdown_chance)) + L.Weaken(3) + L.visible_message(span("danger", "\The [src] knocks down \the [L]!")) + +/* should be covered by my "growls" say thing, but keeping it just in case. +/mob/living/simple_mob/animal/space/mimic/set_target() + . = ..() + if(.) + audible_emote("growls at [.]") +*/ +/mob/living/simple_mob/animal/space/mimic/death() + ..() + qdel(src) + +/mob/living/simple_mob/animal/space/mimic/will_show_tooltip() + return FALSE + +/mob/living/simple_mob/animal/space/mimic/death() + var/obj/structure/closet/crate/C = new(get_turf(src)) + // Put loot in crate + for(var/obj/O in src) + if(isbelly(O)) //VOREStation edit + continue + O.forceMove(C) + ..() + +/mob/living/simple_mob/animal/space/mimic/initialize() + . = ..() + for(var/obj/item/I in loc) + I.forceMove(src) +/* I honestly have no idea what's happening down there so I'm just taking the essentials and yeeting. +// +// Crate Mimic +// + +// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. +/mob/living/simple_mob/animal/space/mimic/crate + + attacktext = list("bitten") + +// stop_automated_movement = 1 we don't need these +// wander = 0 + var/attempt_open = 0 + +// Pickup loot +/mob/living/simple_mob/animal/space/mimic/crate/initialize() + . = ..() + for(var/obj/item/I in loc) + I.forceMove(src) +/* I can't find an equivilant to this, don't know why we really have it even so... +/mob/living/simple_mob/animal/space/mimic/crate/DestroySurroundings() + ..() + if(prob(90)) + icon_state = "[initial(icon_state)]open" + else + icon_state = initial(icon_state) +*/ +/mob/living/simple_mob/animal/space/mimic/crate/ListTargets() + if(attempt_open) + return ..() + else + return ..(1) + +/mob/living/simple_mob/animal/space/mimic/crate/set_target() + . = ..() + if(.) + trigger() + +/mob/living/simple_mob/animal/space/mimic/crate/PunchTarget() + . = ..() + if(.) + icon_state = initial(icon_state) + +/mob/living/simple_mob/animal/space/mimic/crate/proc/trigger() + if(!attempt_open) + visible_message("[src] starts to move!") + attempt_open = 1 + +/mob/living/simple_mob/animal/space/mimic/crate/adjustBruteLoss(var/damage) + trigger() + ..(damage) + +/mob/living/simple_mob/animal/space/mimic/crate/LoseTarget() + ..() + icon_state = initial(icon_state) + +/mob/living/simple_mob/animal/space/mimic/crate/LostTarget() + ..() + icon_state = initial(icon_state) + +/mob/living/simple_mob/animal/space/mimic/crate/death() + var/obj/structure/closet/crate/C = new(get_turf(src)) + // Put loot in crate + for(var/obj/O in src) + if(isbelly(O)) //VOREStation edit + continue + O.forceMove(C) + ..() + +/mob/living/simple_mob/animal/space/mimic/crate/PunchTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(2) + L.visible_message("\the [src] knocks down \the [L]!") + +// +// Copy Mimic +// + +var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window, /obj/item/projectile/animate) + +/mob/living/simple_mob/animal/space/mimic/copy + + health = 100 + maxHealth = 100 + var/mob/living/creator = null // the creator + var/destroy_objects = 0 + var/knockdown_people = 0 + +/mob/living/simple_mob/animal/space/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator) + ..(loc) + CopyObject(copy, creator) + +/mob/living/simple_mob/animal/space/mimic/copy/death() + + for(var/atom/movable/M in src) + if(isbelly(M)) //VOREStation edit + continue + M.forceMove(get_turf(src)) + ..() + +/mob/living/simple_mob/animal/space/mimic/copy/ListTargets() + // Return a list of targets that isn't the creator + . = ..() + return . - creator + +/mob/living/simple_mob/animal/space/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator) + + if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects)) + + O.forceMove(src) + name = O.name + desc = O.desc + icon = O.icon + icon_state = O.icon_state + icon_living = icon_state + + if(istype(O, /obj/structure)) + health = (anchored * 50) + 50 + destroy_objects = 1 + if(O.density && O.anchored) + knockdown_people = 1 + melee_damage_lower *= 2 + melee_damage_upper *= 2 + else if(istype(O, /obj/item)) + var/obj/item/I = O + health = 15 * I.w_class + melee_damage_lower = 2 + I.force + melee_damage_upper = 2 + I.force + move_to_delay = 2 * I.w_class + + maxHealth = health + if(creator) + src.creator = creator + faction = "\ref[creator]" // very unique + return 1 + return + +/mob/living/simple_mob/animal/space/mimic/copy/DestroySurroundings() + if(destroy_objects) + ..() + +/mob/living/simple_mob/animal/space/mimic/copy/PunchTarget() + . =..() + if(knockdown_people) + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(1) + L.visible_message("\the [src] knocks down \the [L]!") +*/ \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm new file mode 100644 index 00000000000..a0b03f8e730 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/snake_vr.dm @@ -0,0 +1,173 @@ +/mob/living/simple_mob/animal/space/snake + name = "snake" + desc = "A big thick snake." + + icon_state = "snake" + icon_living = "snake" + icon_dead = "snake_dead" + icon = 'icons/mob/snake_vr.dmi' + + maxHealth = 20 + health = 20 + + movement_cooldown = 8 // SLOW-ASS MUTHAFUCKA, I hope. + + response_help = "pets" + response_disarm = "shoos" + response_harm = "kicks" + + melee_damage_lower = 3 + melee_damage_upper = 5 + attacktext = list("bitten") + + say_list_type = /datum/say_list/snake + ai_holder_type = /datum/ai_holder/simple_mob/melee + +/datum/say_list/snake + emote_hear = list("hisses") + +//NOODLE IS HERE! SQUEEEEEEEE~ +/mob/living/simple_mob/animal/space/snake/noodle + name = "Noodle" + desc = "This snake is particularly chubby and demands nothing but the finest of treats." + + ai_holder_type = /datum/ai_holder/simple_mob/passive + + var/turns_since_scan = 0 + var/obj/movement_target + +/datum/ai_holder/simple_mob/passive + base_wander_delay = 11 //Them pets better be slow to not push us around + +/datum/ai_holder/simple_mob/passive + hostile = FALSE + can_flee = TRUE + violent_breakthrough = FALSE + +/mob/living/simple_mob/animal/space/snake/noodle/Life() + ..() + + //Not replacing with SA FollowTarget mechanics because Ian behaves... very... specifically. + + //Feeding, chasing food, FOOOOODDDD + if(!stat && !resting && !buckled) + turns_since_scan++ + if(turns_since_scan > 5) + turns_since_scan = 0 + if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) + movement_target = null + if( !movement_target || !(movement_target.loc in oview(src, 3)) ) + movement_target = null + for(var/obj/item/weapon/reagent_containers/food/snacks/snakesnack/S in oview(src,3)) + if(isturf(S.loc) || ishuman(S.loc)) + movement_target = S + visible_emote("turns towards \the [movement_target] and slithers towards it.") + break + if(movement_target) + step_to(src,movement_target,1) + sleep(3) + step_to(src,movement_target,1) + sleep(3) + step_to(src,movement_target,1) + + if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds + if (movement_target.loc.x < src.x) + set_dir(WEST) + else if (movement_target.loc.x > src.x) + set_dir(EAST) + else if (movement_target.loc.y < src.y) + set_dir(SOUTH) + else if (movement_target.loc.y > src.y) + set_dir(NORTH) + else + set_dir(SOUTH) + + if(isturf(movement_target.loc) ) + UnarmedAttack(movement_target) + else if(ishuman(movement_target.loc) && prob(20)) + visible_emote("stares at the [movement_target] that [movement_target.loc] has with an unknowable reptilian gaze.") + +/* old eating code, couldn't figure out how to make the "swallows food" thing so I'm keeping this here incase someone wants legacy" +/mob/living/simple_mob/animal/space/snake/noodle/Life() //stolen from Ian in corgi.dm + if(!..()) + return 0 + + if(!stat && !resting && !buckled && !ai_inactive) + turns_since_scan++ + if(turns_since_scan > 5) + turns_since_scan = 0 + if(movement_target && !(isturf(movement_target.loc) || ishuman(movement_target.loc))) + movement_target = null + stop_automated_movement = 0 + if(!movement_target || !(movement_target.loc in oview(src, 5)) ) + movement_target = null + stop_automated_movement = 0 + walk(src,0) + for(var/obj/item/weapon/reagent_containers/food/snacks/snakesnack/S in oview(src,3)) + if(isturf(S.loc)) + movement_target = S + visible_emote("turns towards \the [movement_target] and slithers towards it.") + break + + if(movement_target) + stop_automated_movement = 1 + walk_to(src, movement_target, 0, 5) + spawn(10) + if(Adjacent(movement_target)) + visible_message("[src] swallows the [movement_target] whole!") + qdel(movement_target) + walk(src,0) + else if(ishuman(movement_target.loc) && prob(20)) + visible_emote("stares at the [movement_target] that [movement_target.loc] has with an unknowable reptilian gaze.") +*/ + +/mob/living/simple_mob/animal/space/snake/noodle/apply_melee_effects(var/atom/A) + if(ismouse(A)) + var/mob/living/simple_mob/animal/passive/mouse/mouse = A + if(mouse.getMaxHealth() < 20) // In case a badmin makes giant mice or something. + mouse.splat() + visible_emote(pick("swallows \the [mouse] whole!")) + else + ..() + +/mob/living/simple_mob/animal/space/snake/noodle/attackby(var/obj/item/O, var/mob/user) + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/snakesnack)) + visible_message("[user] feeds \the [O] to [src].") + qdel(O) + else + return ..() + +//Special snek-snax for Noodle! +/obj/item/weapon/reagent_containers/food/snacks/snakesnack + name = "sugar mouse" + desc = "A little mouse treat made of coloured sugar. Noodle loves these!" + var/snack_colour + icon = 'icons/mob/snake_vr.dmi' + icon_state = "snack_yellow" + nutriment_amt = 1 + nutriment_desc = list("sugar" = 1) + +/obj/item/weapon/reagent_containers/food/snacks/snakesnack/New() + ..() + if(!snack_colour) + snack_colour = pick( list("yellow","green","pink","blue") ) + icon_state = "snack_[snack_colour]" + desc = "A little mouse treat made of coloured sugar. Noodle loves these! This one is [snack_colour]." + reagents.add_reagent("sugar", 2) + +/obj/item/weapon/storage/box/snakesnackbox + name = "box of Snake Snax" + desc = "A box containing Noodle's special sugermouse treats." + icon = 'icons/mob/snake_vr.dmi' + icon_state = "sneksnakbox" + storage_slots = 7 + +/obj/item/weapon/storage/box/snakesnackbox/New() + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + new /obj/item/weapon/reagent_containers/food/snacks/snakesnack(src) + ..()