diff --git a/code/modules/emotes/definitions/audible.dm b/code/modules/emotes/definitions/audible.dm index 29031da5c3..1a5a4e3084 100644 --- a/code/modules/emotes/definitions/audible.dm +++ b/code/modules/emotes/definitions/audible.dm @@ -228,13 +228,10 @@ emote_message_3p_target = "trills at TARGET." emote_sound = 'sound/voice/teshtrill.ogg' // Copyright CC BY-NC 3.0 Arnaud Coutancier (freesound.org) for the source audio. -//CHOMPEdit Add Start /decl/emote/audible/prbt key = "prbt" emote_message_1p = "You prbt." emote_message_3p = "prbts." emote_message_1p_target = "You prbt at TARGET." emote_message_3p_target = "prbts at TARGET." - emote_sound = 'sound/voice/prbt.ogg' - -//CHOMPEdit Add End \ No newline at end of file + emote_sound = 'sound/voice/prbt.ogg' \ No newline at end of file diff --git a/modular_chomp/code/modules/emotes/definitions/audiable.dm b/modular_chomp/code/modules/emotes/definitions/audiable.dm new file mode 100644 index 0000000000..c845d1ae39 --- /dev/null +++ b/modular_chomp/code/modules/emotes/definitions/audiable.dm @@ -0,0 +1,4 @@ +/decl/emote/audible/wheeze + ..() + emote_sound = 'modular_chomp/sound/voice/wheeze.ogg' + diff --git a/modular_chomp/code/modules/mob/living/emote.dm b/modular_chomp/code/modules/mob/living/emote.dm new file mode 100644 index 0000000000..c5f36f01c8 --- /dev/null +++ b/modular_chomp/code/modules/mob/living/emote.dm @@ -0,0 +1,9 @@ +world/New() + . = ..() + //add stuff to default emote vars specifically for chomp. + + //human default emotes + _human_default_emotes += /decl/emote/audible/wheeze + + //simple_mob default emotes + _simple_mob_default_emotes += /decl/emote/audible/wheeze \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/simple_mob_ch.dm b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm similarity index 73% rename from code/modules/mob/living/simple_mob/simple_mob_ch.dm rename to modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm index cf89e7c625..75bbf9ab2a 100644 --- a/code/modules/mob/living/simple_mob/simple_mob_ch.dm +++ b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm @@ -1,7 +1,19 @@ /mob/living/simple_mob + //speech sounds + var/list/speech_sounds = list() + var/speech_chance = 75 //mobs can be a bit more emotive than carbon/humans + //vars for vore_icons toggle control - var/vore_icons_toggle = 1 // on by default, as is legacy - var/vore_icons_cache = 0 // 0 by default. Going from ON to OFF should store vore_icons val here. + var/vore_icons_cache = null // null by default. Going from ON to OFF should store vore_icons val here, OFF to ON reset as null + + //spitting projectiles + var/spitting = 0 + var/spit_projectile = null // what our spit projectile is. Can be anything + +/mob/living/simple_mob/RangedAttack(var/atom/A) + if(!isnull(spit_projectile) && spitting) + Spit(A) + . = ..() mob/living/simple_mob/verb/toggle_vore_icons() @@ -11,18 +23,24 @@ mob/living/simple_mob/verb/toggle_vore_icons() if(!vore_icons && !vore_icons_cache) to_chat(src,"This simplemob has no vore sprite.") - else if(vore_icons_toggle) + else if(isnull(vore_icons_cache)) vore_icons_cache = vore_icons vore_icons = 0 - vore_icons_toggle = 0 to_chat(src,"Vore sprite disabled.") else vore_icons = vore_icons_cache - vore_icons_toggle = 1 + vore_icons_cache = null to_chat(src,"Vore sprite enabled.") update_icon() +mob/living/simple_mob/handle_speech_sound() + if(speech_sounds && speech_sounds.len && prob(speech_chance)) + var/list/returns[2] + returns[1] = sound(pick(speech_sounds)) + returns[2] = 50 + return returns + . = ..() // a unique named update_transforms override to allow simplemobs going horizontal on lay/stun. // This will not make the mob horizontal if the mob has a icon_rest != null @@ -65,3 +83,5 @@ mob/living/simple_mob/verb/toggle_vore_icons() // This from original living.dm update_transforms too handle_status_indicators() + + diff --git a/modular_chomp/code/modules/mob/living/simple_mob/simple_mob_abilities.dm b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob_abilities.dm new file mode 100644 index 0000000000..97e8fc607f --- /dev/null +++ b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob_abilities.dm @@ -0,0 +1,349 @@ +//Place for abilities that any /mob/living/simple_mob can use. Chomp-modular located file. +/mob/living/simple_mob + // pounce proc specific + var/pouncing = 0 // if the user has toggled 'pounce mode' on + var/pounce_last = 0 // time of previous pounce + var/pounce_delay = 0 // pounce delay in game ticks + var/pounce_speed = 1 // pounce speed in idk?? 2 kinda fast tho + + // icon handling for pounce. Has to handle a possible file change + var/icon_state_prepounce = null //icon state for 'preparing to pounce'. Null to not use any icon. + + var/icon_pounce_cache = null // cache. If pounce icons are in different files, the procs will cache the original icon filepath here for resetting + var/icon_pounce = null // icon filepath for pouncing (Flying through air). Null if same as original icon path. + var/icon_state_pounce = null // icon state for pouncing (Flying through air). Null to not use any icon. + var/icon_pounce_x = 0 // icon pixelshift x + var/icon_pounce_y = 0 // icon pixelshift y + var/icon_pounce_x_old = null // icon pixelshift x cache to preserve original value + var/icon_pounce_y_old = null // icon pixelshift y cache to preserve original value + + //spitting + var/spit_delay = 20 // maximum spit fire rate + var/spit_last = 0 + var/icon_overlay_spit = null // spit iconstate + var/icon_overlay_spit_pounce = null // spit while pouncing + + //speen + var/speen_last = 0 + var/speen_delay = 80 // maximum spin spam + + + +/mob/living/simple_mob/update_icon() + . = ..() + //use prepounce or pounce sprites, if any + if(pouncing && (status_flags & LEAPING)) //pouncing, flying through the air + if(!isnull(icon_state_pounce)) // if state is set + icon_state = icon_state_pounce + if(!isnull(icon_pounce)) // if icon filepath is set and not equal to pounce cache + if(icon != icon_pounce) // prevent accidently writing the pounce icon into the icon cache + icon_pounce_cache = icon + icon = icon_pounce + + else if(pouncing) //pre-pouncing + if(!isnull(icon_state_prepounce)) // if state is set + icon_state = icon_state_prepounce + if(!isnull(icon_pounce_cache)) // if cache is set + icon = icon_pounce_cache + icon_pounce_cache = null + else if(!isnull(icon_pounce_cache)) // not pouncing at all but cache is still set + icon = icon_pounce_cache + icon_pounce_cache = null + + //handle pounce variant pixelshifting + // X first + if(icon_pounce_x) // if an offset is even assigned + if(pouncing) + if(status_flags & LEAPING) //Flying through air - set + if(isnull(icon_pounce_x_old)) // only set once + icon_pounce_x_old = pixel_x + pixel_x = icon_pounce_x + else //Prepouncing - reset + if(!isnull(icon_pounce_x_old)) //only act if not already cleared + pixel_x = icon_pounce_x_old + icon_pounce_x_old = null + + else //Not pouncing or prepouncing - reset + if(!isnull(icon_pounce_x_old)) //only act if not already cleared + pixel_x = icon_pounce_x_old + icon_pounce_x_old = null + // Then Y + if(icon_pounce_y) // if an offset is even assigned + if(pouncing) + if(status_flags & LEAPING) //Flying through air - set + if(isnull(icon_pounce_y_old)) // only set once + icon_pounce_y_old = pixel_y + pixel_y = icon_pounce_y + else //Prepouncing - reset + if(!isnull(icon_pounce_y_old)) //only act if not already cleared + pixel_y = icon_pounce_y_old + icon_pounce_y_old = null + + else //Not pouncing or prepouncing - reset + if(!isnull(icon_pounce_y_old)) //only act if not already cleared + pixel_y = icon_pounce_y_old + icon_pounce_y_old = null + + // show spitting warning overlay, if any + if(spitting) + var/spiticon = null + if(!isnull(icon_overlay_spit) && (icon_state == icon_living)) + spiticon = icon_overlay_spit + else if(!isnull(icon_overlay_spit_pounce) && (icon_state == icon_state_prepounce)) + spiticon = icon_overlay_spit_pounce + + if(spiticon) + var/image/I = image(icon, spiticon) + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + I.plane = MOB_PLANE + I.layer = MOB_LAYER + add_overlay(I) + +// Pouncing procs. +// Pouncing consists of a series of functions: +// > A user-toggleable enable or disable to 'pounce' or not pounce; "pouncing" toggled by a verb +// > When enabled, just click somewhere not adjacent to pounce there. +// > If you bump a person, stop on them and knock them over. +// > If you bump a solid object, stun yourself and fall over +/mob/living/simple_mob/proc/pounce_toggle() + set name = "Toggle Pouncing" + set desc = "Toggle pouncing. Doubleclick to pounce." + set category = "Abilities" + + if(pouncing) + to_chat(src, "Pouncing toggled off.") + pouncing = 0 + else + to_chat(src, "Pouncing toggled on! DoubleClick somewhere to pounce there.") + pouncing = 1 + update_icon() + +// This is the on-double-click action. +// We should alter them for the space of this specific proc, and then return them to what they were. +/mob/living/simple_mob/DblClickOn(atom/A, P) + //trying/permitted to pounce + if(pouncing) + //able to pounce (not dead or stunned or on CD) + if(isliving(src) && !src.weakened && (world.time > pounce_last) && !(status_flags & LEAPING)) + //can see pounce target + if((A in view(src, world.view))) + //make sure we're targetting a turf! + var/turf/T = get_turf(A) + //handle delay spam + pounce_last = world.time + pounce_delay + status_flags |= LEAPING + + //deal with passflag - give flags if don't have, mark for removal. Prevent removal if already has flags. + var/foundpt = 0 + var/foundpm = 0 + if(pass_flags & PASSTABLE) + foundpt = 1 + else + pass_flags |= PASSTABLE + if(pass_flags & PASSMOB) + foundpm = 1 + else + pass_flags |= PASSMOB + + // Do the pounce action + + //flying = 1 //So we can thunk into things + hovering = 1 // So we don't hurt ourselves running off cliffs + playsound(src, "sound/weapons/punchmiss.ogg", 50, 1) + + // throw_at returns FALSE if it will not call it's callback - useful to prevent state jamming + if(!throw_at(T, 10, pounce_speed, callback = CALLBACK(src, .proc/pouncefinish, foundpt, foundpm, T))) + if(status_flags & LEAPING) + status_flags &= ~LEAPING + flying = 0 + hovering = 0 + if(!foundpt) + pass_flags &= ~PASSTABLE + if(!foundpm) + pass_flags &= ~PASSMOB + else + to_chat(src, "Pouncing blind isn't wise!") + else + to_chat(src, "You can't do that right now!") + // some sanity incase the callback didn't fire for some reason + if(status_flags & LEAPING) + status_flags &= ~LEAPING + flying = 0 + hovering = 0 + pouncing = 0 + update_icon() + else + . = ..() + +// callback to terminate leap mode. Reset passflag if passflag = 0 (Mob doesn't already have it) +/mob/living/simple_mob/proc/pouncefinish(var/pt, var/pm, var/atom/T) + if(status_flags & LEAPING) + status_flags &= ~LEAPING + flying = 0 + hovering = 0 + + if(!pt) + pass_flags &= ~PASSTABLE + if(!pm) + pass_flags &= ~PASSMOB + + //PASSMOB is broken so we have to perform jank + //if we're adjacent to our target turf (but not ontop of it) and we are not blocked from moving there + if(Adjacent(T) && get_dist(src, T) && !LinkBlocked(src, T)) + //if a mob is on our target (This should be the only reason we didn't arrive) + for(var/mob/living/M in T) + if(isliving(M) && M != src) + var/mob/living/LM = M + + if(M.buckled) // make sure they fall when weakened + M.buckled.unbuckle_mob() + + LM.Weaken(5) + playsound(src, get_sfx("punch"), 50, 1) + pouncing = 0 + src.Move(T) + + //did we fail to arrive at our destination? + if(get_dist(src, T)) + pouncing = 0 + update_icon() + src.Weaken(5) + playsound(src, get_sfx("punch"), 50, 1) + else + //if we arrived, and weren't blocked, and are STILL pouncing, see if we landed on any living things that didn't block us that ISN't ourselves lmfao. + if(pouncing) + for(var/mob/living/M in T) + if(isliving(M) && M != src) + var/mob/living/LM = M + LM.Weaken(5) + playsound(src, get_sfx("punch"), 50, 1) + pouncing = 0 + update_icon() + + +// ported from mob/living/carbon/human/species/xenomorph/alien_powers +/mob/living/simple_mob/proc/Spit(var/atom/A) + if(isnull(spit_projectile)) + return + + if((spit_last + spit_delay) > world.time) //To prevent YATATATATATAT spitting. + to_chat(src, "You have not yet prepared your chemical glands. You must wait before spitting again.") + return + else + spit_last = world.time + + if(spitting && incapacitated(INCAPACITATION_DISABLED)) + to_chat(src, "You cannot spit in your current state.") + spitting = 0 + update_icon() + return + else if(spitting) + //visible_message("[src] spits [spit_name] at \the [A]!", "You spit [spit_name] at \the [A].") + var/obj/item/projectile/P = new spit_projectile(get_turf(src)) + P.firer = src + P.old_style_target(A) + P.fire() + playsound(src, 'sound/weapons/alien_spitacid.ogg', 25, 0) + +/mob/living/simple_mob/proc/neurotoxin() + set name = "Toggle Neurotoxic Spit" + set desc = "Readies a neurotoxic spit, which paralyzes the target for a short time if they are not wearing protective gear." + set category = "Abilities" + + if(spitting) + to_chat(src, "You stop preparing to spit.") + spitting = 0 + else + spitting = 1 + spit_projectile = /obj/item/projectile/energy/neurotoxin + to_chat(src, "You prepare to spit neurotoxin.") + update_icon() + +/mob/living/simple_mob/proc/acidspit() + set name = "Toggle Acid Spit" + set desc = "Readies an acidic spit, which burns the target if they are not wearing protective gear." + set category = "Abilities" + + if(spitting) + to_chat(src, "You stop preparing to spit.") + spitting = 0 + else + spitting = 1 + spit_projectile = /obj/item/projectile/energy/acid + to_chat(src, "You prepare to spit acid.") + update_icon() + +/mob/living/simple_mob/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N + set name = "Corrosive Acid" + set desc = "Drench an object in acid, destroying it over time." + set category = "Abilities" + + if(!(O in oview(1))) + to_chat(src, "[O] is too far away.") + return + + // OBJ CHECK + var/cannot_melt + if(isobj(O)) + var/obj/I = O //Gurgs : Melts pretty much any object that isn't considered unacidable = TRUE + if(I.unacidable) + cannot_melt = 1 + else + if(istype(O, /turf/simulated/wall)) + var/turf/simulated/wall/W = O //Gurgs : Walls are deconstructed into girders. + if(W.material.flags & MATERIAL_UNMELTABLE) + cannot_melt = 1 + else if(istype(O, /turf/simulated/floor)) + var/turf/simulated/floor/F = O //Gurgs : Floors are destroyed with ex_act(1), turning them into whatever tile it would be if empty. Z-Level Friendly, does not destroy pipes. + if(F.flooring && (F.flooring.flags & TURF_ACID_IMMUNE)) + cannot_melt = 1 + else + cannot_melt = 1 //Gurgs : Everything that isn't a object, simulated wall, or simulated floor is assumed to be acid immune. Includes weird things like unsimulated floors and space. + + if(cannot_melt) + to_chat(src, "You cannot dissolve this object.") + return + + new /obj/effect/alien/acid(get_turf(O), O) + visible_message("[src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") + + return + +// spin blatantly stolen from BlackMajor's bigdragon +/mob/living/simple_mob/proc/speen(var/range = 2) + set name = "Spin Attack" + set desc = "Spins to strike enemies away from you." + set category = "Abilities" + + if(world.time < speen_last) + to_chat(src, "You cannot spin again so soon.") + return + + speen_last = world.time + speen_delay + var/list/thrownatoms = list() + for(var/mob/living/victim in oview(range, src)) + thrownatoms += victim + src.spin(12,1) + for(var/am in thrownatoms) + var/atom/movable/AM = am + if(AM == src || AM.anchored) + continue + addtimer(CALLBACK(src, .proc/speen_throw, am), 1) + playsound(src, "sound/weapons/punchmiss.ogg", 50, 1) + +/mob/living/simple_mob/proc/speen_throw(var/atom/movable/AM, var/gentle = 0, var/damage = 10) + var/maxthrow = 7 + var/atom/throwtarget + throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(AM, src))) + + if (!throwtarget) // default case is north if unset + throwtarget = locate(src.x, world.maxy, src.z) + + if(isliving(AM)) + var/mob/living/M = AM + M.Weaken(1.5) + if(!gentle) + M.adjustBruteLoss(damage) + to_chat(M, "You're thrown back by [src]!") + playsound(src, get_sfx("punch"), 50, 1) + AM.throw_at(throwtarget, maxthrow, 3, src) \ No newline at end of file diff --git a/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph.dm b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph.dm new file mode 100644 index 0000000000..c3e8b129c1 --- /dev/null +++ b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph.dm @@ -0,0 +1,203 @@ +// Chomp version of a xeno. Uses the thicc sprites for the queen - has a couple little custom abilities too. +// Thanks to BlackMajor for much guidance / stealing stuff from his bigdragon mob + +// Base type (Mostly initialises as an ability-less xeno hunter +/mob/living/simple_mob/xeno_ch + name = "badly spawned xenomorph" + desc = "A chitin-covered bipedal creature with an eerie skittery nature. this one was spawned in wrong." + + icon = 'modular_chomp/icons/mob/xenos_32.dmi' + vis_height = 32 + + faction = "xeno" + maxHealth = 200 + health = 200 + see_in_dark = 10 + + + 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 + + melee_damage_lower = 8 + melee_damage_upper = 16 + grab_resist = 50 + + vore_active = 1 + vore_capacity = 2 + vore_pounce_chance = 50 + vore_icons = null + + response_help = "pats" + response_disarm = "tries to shove" + response_harm = "hits" + attacktext = list("slashed") + friendly = list("nuzzles", "caresses", "headbumps against", "leans against", "nibbles affectionately on") + speech_sounds = list( 'sound/voice/hiss1.ogg', + 'sound/voice/hiss2.ogg', + 'sound/voice/hiss3.ogg', + 'sound/voice/hiss4.ogg', + 'sound/voice/hiss5.ogg') + has_hands = TRUE + + can_enter_vent_with = list( /obj/item/weapon/implant, + /obj/item/device/radio/borg, + /obj/item/weapon/holder, + /obj/machinery/camera, + /obj/belly, + /obj/screen, + /atom/movable/emissive_blocker, + /obj/item/weapon/material, + /obj/item/weapon/melee, + /obj/item/stack/, + /obj/item/weapon/tool, + /obj/item/weapon/reagent_containers/food, + /obj/item/weapon/coin, + /obj/item/weapon/aliencoin, + /obj/item/weapon/ore, + /obj/item/weapon/disk/nuclear, + /obj/item/toy, + /obj/item/weapon/card, + /obj/item/device/radio, + /obj/item/device/perfect_tele_beacon, + /obj/item/weapon/clipboard, + /obj/item/weapon/paper, + /obj/item/weapon/pen, + /obj/item/canvas, + /obj/item/paint_palette, + /obj/item/paint_brush, + /obj/item/device/camera, + /obj/item/weapon/photo, + /obj/item/device/camera_film, + /obj/item/device/taperecorder, + /obj/item/device/tape) + + var/xeno_build_time = 5 //time to build a structure + + //HUD + var/datum/action/innate/xeno_ch/xeno_build/build_action = new + var/datum/action/innate/xeno_ch/xeno_neuro/neurotox_action = new + var/datum/action/innate/xeno_ch/xeno_acidspit/acidspit_action = new + var/datum/action/innate/xeno_ch/xeno_corrode/corrode_action = new + var/datum/action/innate/xeno_ch/xeno_pounce/pounce_action = new + var/datum/action/innate/xeno_ch/xeno_spin/spin_action = new + +/mob/living/simple_mob/xeno_ch/Initialize() + ..() + src.adjust_nutrition(src.max_nutrition) + sight |= SEE_MOBS + +/mob/living/simple_mob/xeno_ch/Login() + . = ..() + faction = "neutral" + verbs |= /mob/living/simple_mob/xeno_ch/proc/xeno_build + build_action.Grant(src) + + +// Xenomorph hunter subtype +/mob/living/simple_mob/xeno_ch/hunter + name = "xenomorph hunter" + desc = "A chitin-covered bipedal creature with an eerie skittery nature." + + movement_cooldown = 1 + + icon_dead = "alienh_dead" + icon_living = "alienh" + icon_rest = "alienh_sleep" + icon_state = "alienh" + + icon_state_prepounce = "alienh_pounce" + icon_pounce = 'modular_chomp/icons/mob/xenoleap_96.dmi' + icon_state_pounce = "alienh_leap" + icon_overlay_spit = "alienspit" + icon_overlay_spit_pounce = "alienspit_leap" + icon_pounce_x = -32 + icon_pounce_y = -32 + +/mob/living/simple_mob/xeno_ch/hunter/Login() + . = ..() + verbs |= /mob/living/simple_mob/proc/pounce_toggle + verbs |= /mob/living/proc/ventcrawl + verbs |= /mob/living/proc/hide + pounce_action.Grant(src) + +//Xenomorph Sentinel subtype +/mob/living/simple_mob/xeno_ch/sentinel + name = "xenomorph sentinel" + desc = "A chitin-covered bipedal creature with an acrid scent about it." + + movement_cooldown = 1.5 + + icon_dead = "aliens_dead" + icon_living = "aliens" + icon_rest = "aliens_sleep" + icon_state = "aliens" + + icon_state_prepounce = "aliens_pounce" + icon_pounce = 'modular_chomp/icons/mob/xenoleap_96.dmi' + icon_state_pounce = "aliens_leap" + icon_overlay_spit = "alienspit" + icon_overlay_spit_pounce = "alienspit_leap" + icon_pounce_x = -32 + icon_pounce_y = -32 + + +/mob/living/simple_mob/xeno_ch/sentinel/Login() + . = ..() + verbs |= /mob/living/simple_mob/proc/pounce_toggle + verbs |= /mob/living/proc/hide + verbs |= /mob/living/simple_mob/proc/neurotoxin + verbs |= /mob/living/simple_mob/proc/acidspit + verbs |= /mob/living/simple_mob/proc/corrosive_acid + pounce_action.Grant(src) + neurotox_action.Grant(src) + acidspit_action.Grant(src) + corrode_action.Grant(src) + + +//Xenomorph queen subtype +/mob/living/simple_mob/xeno_ch/queen + name = "xenomorph queen" + desc = "A towering chitin-covered bipedal creature with a rather intimidating aura about them." + + icon_dead = "alienq_dead" + icon_living = "alienq" + icon_rest = "alienq_sleep" + icon_state = "alienq" + icon = 'modular_chomp/icons/mob/xenoqueen_64.dmi' + vis_height = 64 + pixel_x = -16 + default_pixel_x = -16 + pixel_y = 0 + default_pixel_y = 0 + + maxHealth = 600 + health = 600 + + movement_cooldown = 2 + +/mob/living/simple_mob/xeno_ch/queen/Login() + . = ..() + verbs |= /mob/living/simple_mob/proc/neurotoxin + verbs |= /mob/living/simple_mob/proc/acidspit + verbs |= /mob/living/simple_mob/proc/corrosive_acid + verbs |= /mob/living/simple_mob/proc/speen + neurotox_action.Grant(src) + acidspit_action.Grant(src) + corrode_action.Grant(src) + spin_action.Grant(src) + +/mob/living/simple_mob/xeno_ch/queen/maid + name = "xenomorph maid queen" + desc = "A towering chitin-covered bipedal creature with a rather intimidating aura about them... though, they seem to be wearing an interesting outfit." + + icon_dead = "alienqmaid_dead" + icon_living = "alienqmaid" + icon_rest = "alienqmaid_sleep" + icon_state = "alienqmaid" diff --git a/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph_abilities.dm b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph_abilities.dm new file mode 100644 index 0000000000..f7153d2eee --- /dev/null +++ b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/xenomorph_abilities.dm @@ -0,0 +1,117 @@ +/mob/living/simple_mob/xeno_ch/proc/xeno_build() + set name = "Build Resin Structure" + set desc = "Build a xenomorph resin structure." + set category = "Abilities" + + var/list/options = list("Resin Door","Resin Membrane","Nest","Resin Wall","Weed Node") + for(var/option in options) + LAZYSET(options, option, image('modular_chomp/icons/mob/xeno_screen.dmi', option)) + var/choice = show_radial_menu(src, src, options, radius = 60) + if(!choice || QDELETED(src) || src.incapacitated()) + return FALSE + . = TRUE + + var/targetLoc = get_step(src, dir) + + if(iswall(targetLoc)) + targetLoc = get_turf(src) + + var/obj/O + + if(do_after(src, xeno_build_time)) + switch(choice) + if("Resin Door") + O = new /obj/structure/simple_door/resin(targetLoc) + + if("Resin Membrane") + O = new /obj/structure/alien/membrane(targetLoc) + + if("Nest") + O = new /obj/structure/bed/nest(targetLoc) + + if("Resin Wall") + O = new /obj/structure/alien/wall(targetLoc) + + if("Weed Node") + O = new /obj/effect/alien/weeds/node(targetLoc) + + if(O) + visible_message("[src] vomits up a thick purple substance and begins to shape it!", "You shape a [choice].") + O.color = "#321D37" + playsound(src, 'sound/effects/blobattack.ogg', 40, 1) + + + +///// +///// +// DATUM actions for xeno buttons +///// +///// + + + +/datum/action/innate/xeno_ch + check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_ALIVE + button_icon = 'modular_chomp/icons/mob/xeno_screen.dmi' + var/mob/living/simple_mob/xeno_ch/parent_xeno + + +/datum/action/innate/xeno_ch/Grant(mob/living/L) + if(L) + parent_xeno = L + ..() + +/datum/action/innate/xeno_ch/xeno_build + name = "Build resin structures" + button_icon_state = "Nest" + +/datum/action/innate/xeno_ch/xeno_build/Activate() + parent_xeno.xeno_build() + + +/datum/action/innate/xeno_ch/xeno_neuro + name = "Spit neurotoxin" + button_icon_state = "Neuro Spit" + +/datum/action/innate/xeno_ch/xeno_neuro/Activate() + parent_xeno.neurotoxin() + + +/datum/action/innate/xeno_ch/xeno_acidspit + name = "Spit acid" + button_icon_state = "Acid Spit" + +/datum/action/innate/xeno_ch/xeno_acidspit/Activate() + parent_xeno.acidspit() + + +/datum/action/innate/xeno_ch/xeno_corrode + name = "Corrode Object" + button_icon_state = "Acid" + +/datum/action/innate/xeno_ch/xeno_corrode/Activate() + parent_xeno.corrosive_acid() + + +/datum/action/innate/xeno_ch/xeno_pounce + name = "Pounce" + button_icon_state = "Pounce" + +/datum/action/innate/xeno_ch/xeno_pounce/Activate() + parent_xeno.pounce_toggle() + +/datum/action/innate/xeno_ch/xeno_spin + name = "Spin" + button_icon_state = "Spin" + +/datum/action/innate/xeno_ch/xeno_spin/Activate() + parent_xeno.speen() + + +/mob/living/simple_mob/xeno_ch/proc/grantallactions() + build_action.Grant(src) + neurotox_action.Grant(src) + acidspit_action.Grant(src) + corrode_action.Grant(src) + pounce_action.Grant(src) + spin_action.Grant(src) \ No newline at end of file diff --git a/modular_chomp/icons/mob/xeno_screen.dmi b/modular_chomp/icons/mob/xeno_screen.dmi new file mode 100644 index 0000000000..6d8aa9e997 Binary files /dev/null and b/modular_chomp/icons/mob/xeno_screen.dmi differ diff --git a/modular_chomp/icons/mob/xenoleap_96.dmi b/modular_chomp/icons/mob/xenoleap_96.dmi new file mode 100644 index 0000000000..7e10b8a5c5 Binary files /dev/null and b/modular_chomp/icons/mob/xenoleap_96.dmi differ diff --git a/modular_chomp/icons/mob/xenoqueen_64.dmi b/modular_chomp/icons/mob/xenoqueen_64.dmi new file mode 100644 index 0000000000..863aeb84ad Binary files /dev/null and b/modular_chomp/icons/mob/xenoqueen_64.dmi differ diff --git a/modular_chomp/icons/mob/xenos_32.dmi b/modular_chomp/icons/mob/xenos_32.dmi new file mode 100644 index 0000000000..b4397da603 Binary files /dev/null and b/modular_chomp/icons/mob/xenos_32.dmi differ diff --git a/modular_chomp/sound/voice/wheeze.ogg b/modular_chomp/sound/voice/wheeze.ogg new file mode 100644 index 0000000000..873bbbd2c7 Binary files /dev/null and b/modular_chomp/sound/voice/wheeze.ogg differ diff --git a/vorestation.dme b/vorestation.dme index 1e5d7944e5..14791bba3a 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3158,7 +3158,6 @@ #include "code\modules\mob\living\simple_mob\sd_pets.dm" #include "code\modules\mob\living\simple_mob\simple_hud.dm" #include "code\modules\mob\living\simple_mob\simple_mob.dm" -#include "code\modules\mob\living\simple_mob\simple_mob_ch.dm" #include "code\modules\mob\living\simple_mob\simple_mob_vr.dm" #include "code\modules\mob\living\simple_mob\taming.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\animal.dm" @@ -4481,7 +4480,9 @@ #include "maps\~map_system\maps.dm" #include "modular_chomp\code\modules\admin\functions\modify_traits.dm" #include "modular_chomp\code\modules\clothing\spacesuits\rig\rig.dm" +#include "modular_chomp\code\modules\emotes\definitions\audiable.dm" #include "modular_chomp\code\modules\mob\holder.dm" +#include "modular_chomp\code\modules\mob\living\emote.dm" #include "modular_chomp\code\modules\mob\living\carbon\human\species\species.dm" #include "modular_chomp\code\modules\mob\living\carbon\human\species\station\protean\_protean_defines.dm" #include "modular_chomp\code\modules\mob\living\carbon\human\species\station\protean\protean_blob.dm" @@ -4489,5 +4490,9 @@ #include "modular_chomp\code\modules\mob\living\carbon\human\species\station\protean\protean_powers.dm" #include "modular_chomp\code\modules\mob\living\carbon\human\species\station\protean\protean_rig.dm" #include "modular_chomp\code\modules\mob\living\carbon\human\species\station\protean\protean_species.dm" +#include "modular_chomp\code\modules\mob\living\simple_mob\simple_mob.dm" +#include "modular_chomp\code\modules\mob\living\simple_mob\simple_mob_abilities.dm" +#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\xenomorph.dm" +#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\xenomorph_abilities.dm" #include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\vore\bigdragon.dm" // END_INCLUDE