more work
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
//mob based off the game Carrion.
|
||||
//replica sprite made by quotefox
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion
|
||||
name = "mass of red tentacles"
|
||||
desc = "A creature composed of tentacles and teeth, you aren't sure where it starts and where it ends."
|
||||
icon = 'hyperstation/icons/mobs/carrion.dmi'
|
||||
icon_state = "c_idle"
|
||||
icon_living = "c_idle"
|
||||
icon_dead = "idle"
|
||||
gender = NEUTER
|
||||
speak_chance = 0
|
||||
turns_per_move = 2
|
||||
turns_per_move = 3
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
see_in_dark = 7
|
||||
response_help = "pets"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "attacks"
|
||||
melee_damage_lower = 12
|
||||
melee_damage_upper = 20
|
||||
attacktext = "attacks"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
faction = list("hostile")
|
||||
ranged = 1
|
||||
harm_intent_damage = 5
|
||||
obj_damage = 60
|
||||
a_intent = INTENT_HARM
|
||||
ventcrawler = 1
|
||||
death_sound = 'sound/voice/ed209_20sec.ogg'
|
||||
deathmessage = "lets out scream and its tentacles shrivel away..."
|
||||
move_to_delay = 4
|
||||
loot = list(/obj/effect/gibspawner/human)
|
||||
|
||||
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 150
|
||||
maxbodytemp = 500
|
||||
do_footstep = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion/OpenFire(atom/the_target)
|
||||
var/dist = get_dist(src,the_target)
|
||||
Beam(the_target, "tentacle", time=dist*2, maxdistance=dist, beam_sleep_time = 5)
|
||||
the_target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion/Initialize(mapload)
|
||||
//Move the sprite into position, cant use Pixel_X and Y, causes issues with the tenticle sprite!
|
||||
..()
|
||||
var/matrix/M = src.transform
|
||||
src.transform = M.Translate(-32,-32)
|
||||
@@ -0,0 +1,56 @@
|
||||
/mob/living/dancercaptain
|
||||
name = "Captain Beats"
|
||||
desc = "A captain cursed to dance for all eternity!"
|
||||
icon = 'hyperstation/icons/mobs/dancer/captain.dmi'
|
||||
icon_state = "idle"
|
||||
var/danceaction = 1
|
||||
var/lastaction = 0 //when the last action was!
|
||||
var/actiontime = 4
|
||||
var/list/dancefloor_turfs
|
||||
var/list/dancefloor_turfs_types
|
||||
var/dancefloor_exists = FALSE
|
||||
|
||||
/mob/living/dancercaptain/Move(atom/newloc, direct)
|
||||
|
||||
if(!danceaction)
|
||||
if(!(world.time > lastaction))
|
||||
return // no move for you!
|
||||
|
||||
animate(src, pixel_x, pixel_y = pixel_y + 10, time = 0.7, 0)
|
||||
. = ..()
|
||||
danceaction = 0 //you did your move
|
||||
lastaction = world.time+actiontime //next action time
|
||||
sleep(1)
|
||||
animate(src, pixel_x, pixel_y = pixel_y - 10, time = 0.7, 0)
|
||||
sleep(1)
|
||||
|
||||
LAZYINITLIST(dancefloor_turfs)
|
||||
LAZYINITLIST(dancefloor_turfs_types)
|
||||
|
||||
if(dancefloor_exists) //remove the old one!
|
||||
dancefloor_exists = FALSE
|
||||
for(var/i in 1 to dancefloor_turfs.len)
|
||||
var/turf/T = dancefloor_turfs[i]
|
||||
T.ChangeTurf(dancefloor_turfs_types[i])
|
||||
var/list/funky_turfs = RANGE_TURFS(2, src)
|
||||
|
||||
|
||||
dancefloor_exists = TRUE
|
||||
var/i = 1
|
||||
dancefloor_turfs.len = funky_turfs.len
|
||||
dancefloor_turfs_types.len = funky_turfs.len
|
||||
for(var/t in funky_turfs)
|
||||
if(!(istype(t, /turf/closed))) //dont change walls
|
||||
var/turf/T = t
|
||||
dancefloor_turfs[i] = T
|
||||
dancefloor_turfs_types[i] = T.type
|
||||
T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b)
|
||||
i++
|
||||
|
||||
|
||||
/mob/living/dancercaptain/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
lastaction = round(world.time) //round to the nearest second! to keep in beat!
|
||||
|
||||
/mob/living/dancercaptain/proc/mtimer()
|
||||
@@ -0,0 +1,33 @@
|
||||
/datum/emote/living/chirp
|
||||
key = "chirp"
|
||||
key_third_person = "chirps!"
|
||||
message = "chirps!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
muzzle_ignore = FALSE
|
||||
restraint_check = FALSE
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai)
|
||||
|
||||
/datum/emote/living/chirp/run_emote(mob/living/user, params)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(user.nextsoundemote >= world.time)
|
||||
return
|
||||
user.nextsoundemote = world.time + 7
|
||||
playsound(user, 'sound/voice/chirp.ogg', 50, 1, -1)
|
||||
|
||||
/datum/emote/living/caw
|
||||
key = "caw"
|
||||
key_third_person = "caws!"
|
||||
message = "caws!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
muzzle_ignore = FALSE
|
||||
restraint_check = FALSE
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai)
|
||||
|
||||
/datum/emote/living/caw/run_emote(mob/living/user, params)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(user.nextsoundemote >= world.time)
|
||||
return
|
||||
user.nextsoundemote = world.time + 7
|
||||
playsound(user, 'sound/voice/caw.ogg', 50, 1, -1)
|
||||
@@ -0,0 +1,311 @@
|
||||
//HUGBOT
|
||||
//HUGBOT PATHFINDING
|
||||
//HUGBOT ASSEMBLY
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot
|
||||
name = "\improper Hugbot"
|
||||
desc = "A little cudly robot. He looks excited."
|
||||
icon = 'hyperstation/icons/mobs/aibots.dmi'
|
||||
icon_state = "hugbot0"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 20
|
||||
maxHealth = 20
|
||||
pass_flags = PASSMOB
|
||||
|
||||
status_flags = (CANPUSH | CANSTUN)
|
||||
|
||||
bot_type = HUG_BOT
|
||||
model = "Hugbot"
|
||||
bot_core_type = /obj/machinery/bot_core/hugbot
|
||||
window_id = "autohug"
|
||||
window_name = "Automatic Hugging Unit v1.0 Alpha"
|
||||
path_image_color = "#FFDDDD"
|
||||
|
||||
base_speed = 4
|
||||
|
||||
var/stationary_mode = 0 //If enabled, the Hugbot will not move automatically.
|
||||
var/mob/living/carbon/patient = null
|
||||
var/mob/living/carbon/oldpatient = null
|
||||
var/last_found = 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/update_icon()
|
||||
cut_overlays()
|
||||
if(!on)
|
||||
icon_state = "hugbot0"
|
||||
return
|
||||
if(IsStun())
|
||||
icon_state = "hugbota"
|
||||
return
|
||||
if(mode == BOT_HEALING)
|
||||
icon_state = "hugbots[stationary_mode]"
|
||||
return
|
||||
else if(stationary_mode) //Bot has yellow light to indicate stationary mode.
|
||||
icon_state = "hugbot2"
|
||||
else
|
||||
icon_state = "hugbot1"
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/Initialize(mapload, new_skin)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/update_canmove()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/bot_reset()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/soft_reset() //Allows the medibot to still actively perform its medical duties without being completely halted as a hard reset does.
|
||||
path = list()
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/set_custom_texts()
|
||||
|
||||
text_hack = "You bypass [name]'s manipulator pressure sensors."
|
||||
text_dehack = "You rewire [name]'s manipulator pressure sensors."
|
||||
text_dehack_fail = "[name] seems damaged and does not respond to reprogramming!"
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/get_controls(mob/user)
|
||||
var/dat
|
||||
dat += hack(user)
|
||||
dat += showpai(user)
|
||||
dat += "<TT><B>Hugging Unit Controls v1.0 Alpha</B></TT><BR><BR>"
|
||||
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
dat += "Patrol Station: <a href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</a><br>"
|
||||
dat += "Stationary Mode: <a href='?src=[REF(src)];stationary=1'>[stationary_mode ? "Yes" : "No"]</a><br>"
|
||||
|
||||
return dat
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
update_controls()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
var/current_health = health
|
||||
..()
|
||||
if(health < current_health) //if medbot took some damage
|
||||
step_to(src, (get_step_away(src,user)))
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/emag_act(mob/user)
|
||||
..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You short out [src]'s manipulator pressure sensors.</span>")
|
||||
audible_message("<span class='danger'>[src]'s arm twitches violently!</span>")
|
||||
flick("medibot_spark", src)
|
||||
playsound(src, "sparks", 75, 1)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/assess_patient(mob/living/carbon/C)
|
||||
//Time to see if they need medical help!
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
return FALSE //welp too late for them!
|
||||
|
||||
if(!(loc == C.loc) && !(isturf(C.loc) && isturf(loc)))
|
||||
return FALSE
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
|
||||
if(emagged != 2) // EVERYONE GETS HUGS!
|
||||
for(var/datum/mood_event/i in mood.mood_events)
|
||||
if (i.description == "<span class='nicegreen'>Hugs are nice.</span>\n" )
|
||||
return FALSE
|
||||
else if (C.IsKnockdown())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/process_scan(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD)
|
||||
return
|
||||
|
||||
if((H == oldpatient) && (world.time < last_found + 200))
|
||||
return
|
||||
|
||||
if(assess_patient(H))
|
||||
last_found = world.time
|
||||
return H
|
||||
else
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/handle_automated_action()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(mode == BOT_HEALING)
|
||||
medicate_patient(patient)
|
||||
return
|
||||
|
||||
if(IsStun())
|
||||
oldpatient = patient
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(frustration > 8)
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
|
||||
if(QDELETED(patient))
|
||||
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
|
||||
if(patient && (get_dist(src,patient) <= 1)) //Patient is next to us, begin treatment!
|
||||
if(mode != BOT_HEALING)
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
frustration = 0
|
||||
medicate_patient(patient)
|
||||
return
|
||||
|
||||
//Patient has moved away from us!
|
||||
else if(patient && path.len && (get_dist(patient,path[path.len]) > 2))
|
||||
path = list()
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
|
||||
else if(stationary_mode && patient) //Since we cannot move in this mode, ignore the patient and wait for another.
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(patient && path.len == 0 && (get_dist(src,patient) > 1))
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,id=access_card)
|
||||
mode = BOT_MOVING
|
||||
if(!path.len) //try to get closer if you can't reach the patient directly
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,1,id=access_card)
|
||||
if(!path.len) //Do not chase a patient we cannot reach.
|
||||
soft_reset()
|
||||
|
||||
if(path.len > 0 && patient)
|
||||
if(!bot_move(path[path.len]))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(path.len > 8 && patient)
|
||||
frustration++
|
||||
|
||||
if(auto_patrol && !stationary_mode && !patient)
|
||||
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
|
||||
start_patrol()
|
||||
|
||||
if(mode == BOT_PATROL)
|
||||
bot_patrol()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/UnarmedAttack(atom/A)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
patient = C
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
medicate_patient(C)
|
||||
update_icon()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/medicate_patient(mob/living/carbon/C)
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(!istype(C))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>[src] hugs [C] to make [C.p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You hug [C] to make [C.p_them()] feel better!</span>")
|
||||
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
|
||||
|
||||
if (emagged != 2)
|
||||
C.AdjustStun(-60)
|
||||
C.AdjustKnockdown(-60)
|
||||
C.AdjustUnconscious(-60)
|
||||
C.AdjustSleeping(-100)
|
||||
if(recoveringstam)
|
||||
C.adjustStaminaLoss(-15)
|
||||
else if(resting)
|
||||
C.resting = 0
|
||||
C.update_canmove()
|
||||
else
|
||||
C.Knockdown(100)
|
||||
C.Stun(100)
|
||||
C.update_canmove()
|
||||
|
||||
playsound(C.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
oldpatient = patient
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/explode()
|
||||
on = FALSE
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
do_sparks(3, TRUE, src)
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/hugbot
|
||||
req_one_access = list(ACCESS_ROBOTICS)
|
||||
|
||||
/obj/item/bot_assembly/hugbot
|
||||
desc = "It's a box of hugs with an arm attached."
|
||||
name = "incomplete hugbot assembly"
|
||||
icon = 'hyperstation/icons/mobs/aibots.dmi'
|
||||
icon_state = "hugbot_arm"
|
||||
created_name = "Hugbot"
|
||||
|
||||
/obj/item/bot_assembly/hugbot/attackby(obj/item/W, mob/user, params)
|
||||
..()
|
||||
if(istype(W, /obj/item/assembly/prox_sensor))
|
||||
if(!can_finish_build(W, user))
|
||||
return
|
||||
var/mob/living/simple_animal/bot/hugbot/A = new(drop_location())
|
||||
A.name = created_name
|
||||
A.robot_arm = W.type
|
||||
to_chat(user, "<span class='notice'>You add [W] to [src]. Beep boop!</span>")
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/storage/box/hug/attackby(obj/item/I, mob/user, params)
|
||||
if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
|
||||
if(contents.len) //prevent accidently deleting contents
|
||||
to_chat(user, "<span class='warning'>You need to empty [src] out first!</span>")
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
return
|
||||
qdel(I)
|
||||
to_chat(user, "<span class='notice'>You add [I] to the [src]! You've got a hugbot assembly now!</span>")
|
||||
var/obj/item/bot_assembly/hugbot/A = new
|
||||
qdel(src)
|
||||
user.put_in_hands(A)
|
||||
else
|
||||
return ..()
|
||||
@@ -0,0 +1,414 @@
|
||||
/mob/living/simple_animal/hostile/hs13mimic
|
||||
name = "Mimic"
|
||||
icon = 'hyperstation/icons/mobs/mimic.dmi'
|
||||
desc = "A writhing mass of black flesh, unlikely to be happy to see you."
|
||||
icon_state = "mimic"
|
||||
icon_living = "mimic"
|
||||
icon_dead = "mimic_dead"
|
||||
gender = NEUTER
|
||||
speak_chance = 0
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
turns_per_move = 5
|
||||
move_to_delay = 1
|
||||
speed = 0
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
pass_flags = PASSTABLE
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 2)
|
||||
response_help = "prods"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "smacks"
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 12
|
||||
attacktext = "stings"
|
||||
attack_sound = 'hyperstation/sound/creatures/mimic/mimic_attack.ogg'
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
blood_volume = 0
|
||||
faction = list("mimic")
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
vision_range = 1
|
||||
aggro_vision_range = 9
|
||||
wander = TRUE
|
||||
minbodytemp = 250 //weak to cold
|
||||
maxbodytemp = 1500
|
||||
pressure_resistance = 1200
|
||||
sight = SEE_MOBS
|
||||
var/stealthed = TRUE
|
||||
var/knockdown_people = 1
|
||||
var/playerTransformCD = 50
|
||||
var/playerTfTime
|
||||
var/static/mimic_blacklisted_transform_items = typecacheof(list(
|
||||
/obj/item/projectile,
|
||||
/obj/item/radio/intercom,
|
||||
/mob/living/simple_animal/bot))
|
||||
var/transformsound = 'hyperstation/sound/creatures/mimic/mimic_transform.ogg'
|
||||
var/playstyle_string = "<span class='boldannounce'>You are a mimic</span></b>, a tricky creature that can take the form of \
|
||||
almost any item nearby by shift-clicking it. While morphed, you move slowly and do less damage. \
|
||||
Finally, you can restore yourself to your original form while morphed by shift-clicking yourself. \
|
||||
Attacking carbon lifeforms will heal you at the cost of destructuring their DNA. \
|
||||
You can also change your form to that of simple animals, but be wary that anyone examining you can \
|
||||
find out.</b>"
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/Initialize(mapload)
|
||||
. = ..()
|
||||
trytftorandomobject() // When initialized, make sure they take the form of something.
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/Login()
|
||||
. = ..()
|
||||
SEND_SOUND(src, sound('sound/ambience/antag/ling_aler.ogg'))
|
||||
to_chat(src, src.playstyle_string)
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
if(stealthed && stat == CONSCIOUS)
|
||||
if(M.a_intent == INTENT_HELP)//They're trying to pick us up! We tricked them boys! *plays runescape sea shanty*
|
||||
target = M
|
||||
guaranteedknockdown(M)
|
||||
trigger() // Bring our friends if any!
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/AttackingTarget()
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(.)
|
||||
if(stealthed && knockdown_people) //Guaranteed knockdown if we get the first hit while disguised. Typically, only players can do this since NPC mimics transform first before attacking.
|
||||
restore()
|
||||
C.Knockdown(40)
|
||||
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
else if(knockdown_people && prob(15))
|
||||
C.Knockdown(40)
|
||||
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
if(C.nutrition >= 15)
|
||||
C.nutrition -= (rand(7,15)) //They lose 7-15 nutrition
|
||||
adjustBruteLoss(-3) //We heal 3 damage
|
||||
C.adjustCloneLoss(rand(2,4)) //They also take a bit of cellular damage.
|
||||
if(isanimal(target))
|
||||
var/mob/living/simple_animal/A = target
|
||||
if(.)
|
||||
if(stealthed)
|
||||
restore()
|
||||
if(A.stat == CONSCIOUS)
|
||||
adjustBruteLoss(-3) //We heal 3 damage
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
trigger()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/FindTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
trigger() //We have a target! Trigger!
|
||||
else if(!target && !stealthed) //Has no target, isn't stealthed, let's search for an object to transform
|
||||
trytftorandomobject()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/death(gibbed)
|
||||
restore() //We died. Restore form.
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_health()
|
||||
if(stealthed)
|
||||
var/image/holder = hud_list[HEALTH_HUD]
|
||||
holder.icon_state = null
|
||||
return //we hide medical hud while morphed
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_status()
|
||||
if(stealthed)
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
holder.icon_state = null
|
||||
return //we hide medical hud while morphed
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/mimicTransformList() //The list of default things to transform needs to be bigger, consider this in the future.
|
||||
var/transformitem = rand(1,100)
|
||||
medhudupdate()
|
||||
wander = FALSE
|
||||
vision_range = initial(vision_range)
|
||||
switch(transformitem)
|
||||
if(1 to 10)
|
||||
name = "drinking glass"
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "glass_empty"
|
||||
desc = "Your standard drinking glass."
|
||||
if(11 to 20)
|
||||
name = "insulated gloves"
|
||||
icon = 'icons/obj/clothing/gloves.dmi'
|
||||
icon_state = "yellow"
|
||||
desc = "These gloves will protect the wearer from electric shock."
|
||||
if(21 to 30)
|
||||
name = "stunbaton"
|
||||
desc = "A stun baton for incapacitating people with."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "stunbaton"
|
||||
if(31 to 40)
|
||||
name = "pen"
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "pen"
|
||||
desc = "It's a black ink pen, modified for use with both paper and Nanotransen-brand Digital-Readpads™!"
|
||||
if(41 to 50)
|
||||
name = "newspaper"
|
||||
desc = "An issue of The Catpaw, the newspaper circulating aboard GATO stations."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "newspaper"
|
||||
if(51 to 60)
|
||||
name = "stechkin pistol" //greytider bait
|
||||
desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors."
|
||||
icon = 'icons/obj/guns/projectile.dmi'
|
||||
icon_state = "pistol"
|
||||
if(61 to 70)
|
||||
name = "emergency oxygen tank"
|
||||
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
icon_state = "emergency"
|
||||
if(71 to 80)
|
||||
name = "drinking glass"
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "glass_empty"
|
||||
desc = "Your standard drinking glass."
|
||||
if(81 to 90)
|
||||
name = "fleshlight"
|
||||
icon = 'hyperstation/icons/obj/fleshlight.dmi'
|
||||
icon_state = "fleshlight_totallynotamimic"
|
||||
desc = "A sex toy disguised as a flashlight, used to stimulate someones penis, complete with colour changing sleeve."
|
||||
if(91 to 100)
|
||||
icon = 'modular_citadel/icons/obj/genitals/dildo.dmi'
|
||||
switch(rand(1,3)) //switch within a switch hmmmmmmmmmm
|
||||
if(1)
|
||||
icon_state = "dildo_knotted_2"
|
||||
name = "small knotted dildo"
|
||||
if(2)
|
||||
icon_state = "dildo_flared_4"
|
||||
name = "huge flared dildo"
|
||||
if(3)
|
||||
icon_state = "dildo_knotted_3"
|
||||
name = "big knotted dildo"
|
||||
desc = "Floppy!"
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/guaranteedknockdown(mob/living/carbon/human/M)
|
||||
M.Knockdown(40)
|
||||
M.visible_message("<span class='danger'>\The [src] knocks down \the [M]!</span>", \
|
||||
"<span class='userdanger'>\The [src] tricks you, knocking you down!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/medhudupdate()
|
||||
med_hud_set_health()
|
||||
med_hud_set_status()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/restore()
|
||||
//back to normal mimic sprite
|
||||
stealthed = FALSE
|
||||
medhudupdate()
|
||||
name = initial(name)
|
||||
icon = 'hyperstation/icons/mobs/mimic.dmi'
|
||||
icon_state = "mimic"
|
||||
desc = initial(desc)
|
||||
speed = initial(speed)
|
||||
wander = TRUE
|
||||
vision_range = 9
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/trigger()
|
||||
if(stealthed && stat == CONSCIOUS)
|
||||
visible_message("<span class='danger'>The [src] Reveals itself to be a Mimic!</span>")
|
||||
restore()
|
||||
playsound(loc, transformsound, 75, TRUE)
|
||||
triggerOthers(target) // Friends too!
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/triggerOthers(passtarget) //
|
||||
for(var/mob/living/simple_animal/hostile/hs13mimic/C in oview(5, src.loc))
|
||||
if(passtarget && C.target == null && !(isdead(target)))
|
||||
C.target = passtarget
|
||||
C.trigger()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/trytftorandomobject()
|
||||
stealthed = TRUE
|
||||
medhudupdate()
|
||||
var/list/obj/item/listItems = list()
|
||||
for(var/obj/item/I in oview(9,src.loc))
|
||||
if(allowed(I))
|
||||
listItems += I
|
||||
if(LAZYLEN(listItems))
|
||||
var/obj/item/changedReference = pick(listItems)
|
||||
wander = FALSE
|
||||
vision_range = initial(vision_range)
|
||||
name = changedReference.name
|
||||
icon = changedReference.icon
|
||||
icon_state = changedReference.icon_state
|
||||
desc = changedReference.desc
|
||||
else
|
||||
mimicTransformList() //Couldn't find any valid items, let's go for the default list then.
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/allowed(atom/movable/A)
|
||||
return !is_type_in_typecache(A, mimic_blacklisted_transform_items) && (isitem(A) || isanimal(A))
|
||||
|
||||
//One leader mimic spawns per mimic event spawn, they are able to consume and transform themselves into the station's dead pets. Buckle up.
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader
|
||||
var/mob/living/consumptionTarget = null
|
||||
var/consuming = FALSE
|
||||
health = 38 //They have a teeeny tiny more health.
|
||||
maxHealth = 38
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader/Life()
|
||||
. = ..()
|
||||
if(!consuming)
|
||||
if(!consumptionTarget)
|
||||
for(var/mob/living/simple_animal/pet/A in oview(5, src))
|
||||
if(A.stat == DEAD)
|
||||
consumptionTarget = A
|
||||
break
|
||||
if(!target && consumptionTarget) //Don't try to consume anything if we're currently attacking something.
|
||||
var/target_distance = get_dist(targets_from, consumptionTarget)
|
||||
if(target_distance > minimum_distance)
|
||||
Goto(consumptionTarget,move_to_delay,minimum_distance)
|
||||
else
|
||||
tryConsume(consumptionTarget)
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader/proc/tryConsume(var/mob/living/simple_animal/pet/A)
|
||||
src.visible_message("<span class='warning'>[A] is being consumed...</span>",
|
||||
"<span class='notice'>You start to consume the dead [A]...</span>", "You hear strange fleshy sounds.")
|
||||
consuming = TRUE
|
||||
if(do_after(src, 100, target = A))
|
||||
stealthed = TRUE
|
||||
speed = 5
|
||||
wander = TRUE
|
||||
name = A.name
|
||||
desc = A.desc
|
||||
icon = A.icon
|
||||
icon_state = A.icon_living
|
||||
desc += "<span class='warning'> But something about it seems wrong...</span>"
|
||||
qdel(A)
|
||||
consuming = FALSE
|
||||
consumptionTarget = FALSE
|
||||
return TRUE
|
||||
consuming = FALSE
|
||||
return FALSE
|
||||
|
||||
//Player control code
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/ShiftClickOn(atom/movable/A)
|
||||
if(playerTfTime <= world.time && stat == CONSCIOUS)
|
||||
if(A == src)
|
||||
restore()
|
||||
playerTfTime = world.time + playerTransformCD
|
||||
return
|
||||
if(istype(A) && allowed(A))
|
||||
stealthed = TRUE
|
||||
SEND_SOUND(src, sound(transformsound,volume=50))
|
||||
name = A.name
|
||||
icon = A.icon
|
||||
icon_state = A.icon_state
|
||||
desc = A.desc
|
||||
speed = 5
|
||||
playerTfTime = world.time + playerTransformCD
|
||||
if(isanimal(A))
|
||||
var/mob/living/simple_animal/animal = A
|
||||
icon_state = animal.icon_living
|
||||
desc += "<span class='warning'> But something about it seems wrong...</span>"
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You need to wait a little longer before you can shift into something else!</span>")
|
||||
..()
|
||||
|
||||
//Event control
|
||||
|
||||
/datum/round_event_control/mimic_infestation
|
||||
name = "Mimic Infestation"
|
||||
typepath = /datum/round_event/mimic_infestation
|
||||
weight = 5
|
||||
max_occurrences = 1
|
||||
min_players = 15
|
||||
|
||||
/datum/round_event/mimic_infestation
|
||||
announceWhen = 200
|
||||
var/static/list/mimic_station_areas_blacklist = typecacheof(/area/space,
|
||||
/area/shuttle,
|
||||
/area/mine,
|
||||
/area/holodeck,
|
||||
/area/ruin,
|
||||
/area/hallway,
|
||||
/area/hallway/primary,
|
||||
/area/hallway/secondary,
|
||||
/area/hallway/secondary/entry,
|
||||
/area/engine/supermatter,
|
||||
/area/engine/atmospherics_engine,
|
||||
/area/engine/engineering/reactor_core,
|
||||
/area/engine/engineering/reactor_control,
|
||||
/area/ai_monitored/turret_protected,
|
||||
/area/layenia/cloudlayer,
|
||||
/area/asteroid/nearstation,
|
||||
/area/science/server,
|
||||
/area/science/explab,
|
||||
/area/science/xenobiology,
|
||||
/area/security/processing)
|
||||
var/spawncount = 1
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/mimic_infestation/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
spawncount = rand(4, 7)
|
||||
|
||||
/datum/round_event/mimic_infestation/announce(fake)
|
||||
priority_announce("Unidentified lifesigns detected aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
|
||||
|
||||
/datum/round_event/mimic_infestation/start()
|
||||
var/list/area/stationAreas = list()
|
||||
var/list/area/eligible_areas = list()
|
||||
for(var/area/A in world) // Get the areas in the Z level
|
||||
if(A.z == SSmapping.station_start)
|
||||
stationAreas += A
|
||||
for(var/area/place in stationAreas) // first we check if it's a valid area
|
||||
if(place.outdoors)
|
||||
continue
|
||||
if(place.areasize < 16)
|
||||
continue
|
||||
if(is_type_in_typecache(place, mimic_station_areas_blacklist))
|
||||
continue
|
||||
eligible_areas += place
|
||||
for(var/area/place in eligible_areas) // now we check if there are people in that area
|
||||
var/numOfPeople
|
||||
for(var/mob/living/carbon/H in place)
|
||||
numOfPeople++
|
||||
break
|
||||
if(numOfPeople > 0)
|
||||
eligible_areas -= place
|
||||
|
||||
var/validFound = FALSE
|
||||
var/list/turf/validTurfs = list()
|
||||
var/area/pickedArea
|
||||
while(!validFound || !eligible_areas.len)
|
||||
pickedArea = pick_n_take(eligible_areas)
|
||||
var/list/turf/t = get_area_turfs(pickedArea, SSmapping.station_start)
|
||||
for(var/turf/thisTurf in t) // now we check if it's a closed turf, cold turf or occupied turf and yeet it
|
||||
if(isopenturf(thisTurf))
|
||||
var/turf/open/tempGet = thisTurf
|
||||
if(tempGet.air.temperature <= T0C)
|
||||
t -= thisTurf
|
||||
continue
|
||||
if(isclosedturf(thisTurf))
|
||||
t -= thisTurf
|
||||
else
|
||||
for(var/obj/O in thisTurf)
|
||||
if(O.density && !(istype(O, /obj/structure/table)))
|
||||
t -= thisTurf
|
||||
break
|
||||
if(t.len >= spawncount) //Is the number of available turfs equal or bigger than spawncount?
|
||||
validFound = TRUE
|
||||
validTurfs = t
|
||||
|
||||
if(!eligible_areas.len)
|
||||
message_admins("No eligible areas for spawning mimics.")
|
||||
return WAITING_FOR_SOMETHING
|
||||
|
||||
notify_ghosts("A group of mimics has spawned in [pickedArea]!", source=pickedArea, action=NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
while(spawncount > 0 && validTurfs.len)
|
||||
spawncount--
|
||||
var/turf/pickedTurf = pick_n_take(validTurfs)
|
||||
if(spawncount != 0)
|
||||
var/spawn_type = /mob/living/simple_animal/hostile/hs13mimic
|
||||
spawn_atom_to_turf(spawn_type, pickedTurf, 1, FALSE)
|
||||
else
|
||||
var/spawn_type = /mob/living/simple_animal/hostile/hs13mimic/leader
|
||||
spawn_atom_to_turf(spawn_type, pickedTurf, 1, FALSE)
|
||||
return SUCCESSFUL_SPAWN
|
||||
Reference in New Issue
Block a user