mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-27 15:01:04 +01:00
Mob AI SS & Misc. Mob Cleanup (#3990)
This commit is contained in:
@@ -167,6 +167,7 @@
|
||||
#include "code\controllers\subsystems\lighting.dm"
|
||||
#include "code\controllers\subsystems\machinery.dm"
|
||||
#include "code\controllers\subsystems\mob.dm"
|
||||
#include "code\controllers\subsystems\mob_ai.dm"
|
||||
#include "code\controllers\subsystems\night_lighting.dm"
|
||||
#include "code\controllers\subsystems\openturf.dm"
|
||||
#include "code\controllers\subsystems\orbit.dm"
|
||||
|
||||
@@ -90,3 +90,8 @@
|
||||
|
||||
// -- SSicon_cache --
|
||||
#define LIGHT_FIXTURE_CACHE(icon,state,color) SSicon_cache.light_fixture_cache["[icon]_[state]_[color]"] || (SSicon_cache.light_fixture_cache["[icon]_[state]_[color]"] = SSicon_cache.generate_color_variant(icon,state,color))
|
||||
|
||||
|
||||
// -- SSmob_ai --
|
||||
#define MOB_START_THINKING(mob) if (!mob.thinking_enabled) { SSmob_ai.processing += mob; mob.on_think_enabled(); mob.thinking_enabled = TRUE; }
|
||||
#define MOB_STOP_THINKING(mob) SSmob_ai.processing -= mob; mob.on_think_disabled(); mob.thinking_enabled = FALSE;
|
||||
|
||||
@@ -318,6 +318,12 @@
|
||||
if(typecache_include[A.type] && !typecache_exclude[A.type])
|
||||
. += A
|
||||
|
||||
/proc/range_in_typecache(dist, center, list/typecache)
|
||||
for (var/thing in range(dist, center))
|
||||
var/atom/A = thing
|
||||
if (typecache[A.type])
|
||||
return TRUE
|
||||
|
||||
/proc/typecache_first_match(list/target, list/typecache)
|
||||
for (var/thing in target)
|
||||
var/datum/D = thing
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/var/datum/controller/subsystem/mobs/SSmob
|
||||
|
||||
/datum/controller/subsystem/mobs
|
||||
name = "Mobs"
|
||||
name = "Mobs - Life"
|
||||
flags = SS_NO_INIT
|
||||
priority = SS_PRIORITY_MOB
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/var/datum/controller/subsystem/mob_ai/SSmob_ai
|
||||
|
||||
/datum/controller/subsystem/mob_ai
|
||||
name = "Mobs - AI"
|
||||
flags = SS_NO_INIT
|
||||
priority = SS_PRIORITY_MOB
|
||||
|
||||
var/list/processing = list()
|
||||
var/list/currentrun = list()
|
||||
var/list/slept = list()
|
||||
|
||||
/datum/controller/subsystem/mob_ai/New()
|
||||
NEW_SS_GLOBAL(SSmob_ai)
|
||||
|
||||
/datum/controller/subsystem/mob_ai/stat_entry()
|
||||
..("P:[processing.len]")
|
||||
|
||||
/datum/controller/subsystem/mob_ai/fire(resumed = FALSE)
|
||||
if (!resumed)
|
||||
src.currentrun = processing.Copy()
|
||||
|
||||
var/list/currentrun = src.currentrun
|
||||
while (currentrun.len)
|
||||
var/mob/M = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
|
||||
if (QDELETED(M))
|
||||
processing -= M
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
|
||||
if (M.ckey)
|
||||
// cliented mobs are not allowed to think
|
||||
log_debug("SSmob_ai: Type '[M.type]' was still thinking despite having a client!")
|
||||
MOB_STOP_THINKING(M)
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
|
||||
var/time = world.time
|
||||
|
||||
if (!M.frozen && !M.stat)
|
||||
M.think()
|
||||
|
||||
if (time != world.time && !slept[M.type])
|
||||
slept[M.type] = TRUE
|
||||
var/diff = world.time - time
|
||||
log_debug("SSmob_ai: Type '[M.type]' slept for [diff] ds in think()! Suppressing further warnings.")
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/mob
|
||||
var/tmp/thinking_enabled = FALSE
|
||||
|
||||
/mob/proc/think()
|
||||
return
|
||||
|
||||
/mob/proc/on_think_disabled()
|
||||
walk_to(src, 0)
|
||||
|
||||
/mob/proc/on_think_enabled()
|
||||
return
|
||||
@@ -25,13 +25,12 @@
|
||||
|
||||
var/list/datum/feedback_variable/feedback = list()
|
||||
|
||||
var/status_needs_update = FALSE
|
||||
|
||||
/datum/controller/subsystem/statistics/New()
|
||||
NEW_SS_GLOBAL(SSfeedback)
|
||||
|
||||
/datum/controller/subsystem/statistics/Initialize(timeofday)
|
||||
if (!config.kick_inactive && !(config.sql_enabled && config.sql_stats))
|
||||
can_fire = FALSE
|
||||
|
||||
for (var/type in subtypesof(/datum/statistic) - list(/datum/statistic/numeric, /datum/statistic/grouped))
|
||||
var/datum/statistic/S = new type
|
||||
if (!S.name)
|
||||
@@ -70,6 +69,14 @@
|
||||
var/err = query.ErrorMsg()
|
||||
log_game("SQL ERROR during population polling. Error : \[[err]\]\n")
|
||||
|
||||
if (status_needs_update)
|
||||
// Update world status.
|
||||
world.update_status()
|
||||
status_needs_update = FALSE
|
||||
|
||||
/datum/controller/subsystem/statistics/proc/update_status()
|
||||
status_needs_update = TRUE
|
||||
|
||||
/datum/controller/subsystem/statistics/Recover()
|
||||
src.messages = SSfeedback.messages
|
||||
src.messages_admin = SSfeedback.messages_admin
|
||||
|
||||
@@ -38,6 +38,8 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
var/obj/item/device/multitool/ghost_multitool
|
||||
incorporeal_move = 1
|
||||
|
||||
mob_thinks = FALSE
|
||||
|
||||
/mob/dead/observer/New(mob/body)
|
||||
if (istype(body, /mob/dead/observer))
|
||||
return//A ghost can't become a ghost.
|
||||
|
||||
@@ -11,6 +11,7 @@ var/mob/dview/dview_mob = new
|
||||
simulated = 0
|
||||
|
||||
see_in_dark = 1e6
|
||||
mob_thinks = FALSE
|
||||
|
||||
/mob/dview/New()
|
||||
..()
|
||||
|
||||
@@ -90,9 +90,11 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
|
||||
return 1
|
||||
return
|
||||
|
||||
/mob/living/bot/cleanbot/proc/remove_from_ignore(path)
|
||||
ignorelist -= path
|
||||
|
||||
/mob/living/bot/cleanbot/Life()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
ignorelist = list()
|
||||
return
|
||||
@@ -117,16 +119,21 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
|
||||
visible_message("Something flies out of [src]. He seems to be acting oddly.")
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc)
|
||||
ignorelist += gib
|
||||
spawn(600)
|
||||
ignorelist -= gib
|
||||
addtimer(CALLBACK(src, .proc/remove_from_ignore, gib), 600)
|
||||
|
||||
/mob/living/bot/cleanbot/think()
|
||||
..()
|
||||
if (!on)
|
||||
return
|
||||
|
||||
if(pulledby) // Don't wiggle if someone pulls you
|
||||
patrol_path = list()
|
||||
patrol_path.Cut()
|
||||
return
|
||||
|
||||
var/found_spot
|
||||
if(!should_patrol) return
|
||||
if(!should_patrol)
|
||||
return
|
||||
|
||||
// This loop will progressively search outwards for /cleanables in view(), gradually to prevent excessively large view() calls when none are needed.
|
||||
search_for: // We use the label so we can break out of this loop from within the next loop.
|
||||
// Not breaking out of these loops properly is where the infinite loop was coming from before.
|
||||
@@ -154,7 +161,6 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
|
||||
D.clean_marked = null
|
||||
|
||||
|
||||
|
||||
if(!found_spot && !target) // No targets in range
|
||||
if(!patrol_path || !patrol_path.len)
|
||||
if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
|
||||
@@ -188,8 +194,6 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
|
||||
if(moved)
|
||||
patrol_path -= patrol_path[1]
|
||||
|
||||
|
||||
|
||||
/mob/living/bot/cleanbot/UnarmedAttack(var/obj/effect/decal/cleanable/D, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
@@ -125,11 +125,12 @@
|
||||
|
||||
/mob/living/bot/farmbot/Life()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
if(emagged && prob(1))
|
||||
flick("farmbot_broke", src)
|
||||
if(client)
|
||||
|
||||
/mob/living/bot/farmbot/think()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(target)
|
||||
|
||||
@@ -106,7 +106,6 @@
|
||||
|
||||
/mob/living/bot/floorbot/Life()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
return
|
||||
|
||||
@@ -115,17 +114,13 @@
|
||||
tilemake = 0
|
||||
addTiles(1)
|
||||
|
||||
if(client)
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
custom_emote(2, "makes an excited booping beeping sound!")
|
||||
|
||||
if(ignorelist.len) // Don't stick forever
|
||||
for(var/T in ignorelist)
|
||||
if(prob(1))
|
||||
ignorelist -= T
|
||||
|
||||
/mob/living/bot/floorbot/think()
|
||||
..()
|
||||
if (!on)
|
||||
return
|
||||
if(amount && !emagged)
|
||||
if(!target && targetdirection) // Building a bridge
|
||||
var/turf/T = get_step(src, targetdirection)
|
||||
@@ -137,7 +132,7 @@
|
||||
|
||||
if(!target) // Fixing floors
|
||||
for(var/turf/T in view(src))
|
||||
if(T.loc.name == "Space")
|
||||
if (istype(T.loc, /area/space))
|
||||
continue
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
@@ -151,7 +146,7 @@
|
||||
|
||||
if(emagged) // Time to griff
|
||||
for(var/turf/simulated/floor/D in view(src))
|
||||
if(D.loc.name == "Space")
|
||||
if (istype(D.loc, /area/space))
|
||||
continue
|
||||
if(D in ignorelist)
|
||||
continue
|
||||
@@ -187,6 +182,17 @@
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
|
||||
if(ignorelist.len) // Don't stick forever
|
||||
for(var/T in ignorelist)
|
||||
if(prob(1))
|
||||
ignorelist -= T
|
||||
|
||||
/mob/living/bot/floorbot/on_think_disabled()
|
||||
..()
|
||||
ignorelist.Cut()
|
||||
path.Cut()
|
||||
target = null
|
||||
|
||||
/mob/living/bot/floorbot/UnarmedAttack(var/atom/A, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
@@ -34,47 +34,44 @@
|
||||
QDEL_NULL(reagent_glass)
|
||||
return ..()
|
||||
|
||||
/mob/living/bot/medbot/Life()
|
||||
/mob/living/bot/medbot/think()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(!client)
|
||||
if(vocal && prob(1))
|
||||
var/message = pick("Radar, put a mask on!", "There's always a catch, and it's the best there is.", "I knew it, I should've been a plastic surgeon.", "What kind of medbay is this? Everyone's dropping like dead flies.", "Delicious!")
|
||||
say(message)
|
||||
|
||||
if(vocal && prob(1))
|
||||
var/message = pick("Radar, put a mask on!", "There's always a catch, and it's the best there is.", "I knew it, I should've been a plastic surgeon.", "What kind of medbay is this? Everyone's dropping like dead flies.", "Delicious!")
|
||||
say(message)
|
||||
|
||||
if(patient)
|
||||
if(Adjacent(patient))
|
||||
if(!currently_healing)
|
||||
INVOKE_ASYNC(src, .proc/UnarmedAttack, patient)
|
||||
else
|
||||
if(path.len && (get_dist(patient, path[path.len]) > 2)) // We have a path, but it's off
|
||||
path = list()
|
||||
if(!path.len && (get_dist(src, patient) > 1))
|
||||
spawn(0)
|
||||
path = AStar(loc, get_turf(patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
++frustration
|
||||
if(get_dist(src, patient) > 7 || frustration > 8)
|
||||
patient = null
|
||||
if(patient)
|
||||
if(Adjacent(patient))
|
||||
if(!currently_healing)
|
||||
INVOKE_ASYNC(src, .proc/UnarmedAttack, patient)
|
||||
else
|
||||
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
|
||||
if(valid_healing_target(H))
|
||||
patient = H
|
||||
frustration = 0
|
||||
if(last_newpatient_speak + 300 < world.time)
|
||||
var/message = pick("Hey, [H.name]! Hold on, I'm coming.", "Wait [H.name]! I want to help!", "[H.name], you appear to be injured!")
|
||||
say(message)
|
||||
custom_emote(1, "points at [H.name].")
|
||||
last_newpatient_speak = world.time
|
||||
break
|
||||
if(path.len && (get_dist(patient, path[path.len]) > 2)) // We have a path, but it's off
|
||||
path = list()
|
||||
if(!path.len && (get_dist(src, patient) > 1))
|
||||
spawn(0)
|
||||
path = AStar(loc, get_turf(patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
++frustration
|
||||
if(get_dist(src, patient) > 7 || frustration > 8)
|
||||
patient = null
|
||||
else
|
||||
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
|
||||
if(valid_healing_target(H))
|
||||
patient = H
|
||||
frustration = 0
|
||||
if(last_newpatient_speak + 300 < world.time)
|
||||
var/message = pick("Hey, [H.name]! Hold on, I'm coming.", "Wait [H.name]! I want to help!", "[H.name], you appear to be injured!")
|
||||
say(message)
|
||||
custom_emote(1, "points at [H.name].")
|
||||
last_newpatient_speak = world.time
|
||||
break
|
||||
|
||||
/mob/living/bot/medbot/UnarmedAttack(var/mob/living/carbon/human/H, var/proximity)
|
||||
if(!..())
|
||||
|
||||
@@ -40,8 +40,21 @@
|
||||
var/nearest_beacon // Tag of the beakon that we assume to be the closest one
|
||||
|
||||
var/bot_version = 1.4
|
||||
var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
|
||||
var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
|
||||
var/list/threat_found_sounds = list(
|
||||
'sound/voice/bcriminal.ogg',
|
||||
'sound/voice/bjustice.ogg',
|
||||
'sound/voice/bfreeze.ogg'
|
||||
)
|
||||
var/list/preparing_arrest_sounds = list(
|
||||
'sound/voice/bgod.ogg',
|
||||
'sound/voice/biamthelaw.ogg',
|
||||
'sound/voice/bsecureday.ogg',
|
||||
'sound/voice/bradio.ogg',
|
||||
'sound/voice/binsult.ogg',
|
||||
'sound/voice/bcreep.ogg'
|
||||
)
|
||||
|
||||
var/datum/callback/patrol_callback // this is here so we don't constantly recreate this datum, it being identical each time.
|
||||
|
||||
/mob/living/bot/secbot/beepsky
|
||||
name = "Officer Beepsky"
|
||||
@@ -56,6 +69,9 @@
|
||||
if(SSradio)
|
||||
SSradio.add_object(listener, control_freq, filter = RADIO_SECBOT)
|
||||
SSradio.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
|
||||
if (!patrol_callback)
|
||||
patrol_callback = CALLBACK(src, .proc/patrol_step)
|
||||
|
||||
/mob/living/bot/secbot/Destroy()
|
||||
QDEL_NULL(listener)
|
||||
@@ -145,14 +161,12 @@
|
||||
awaiting_surrender = 5
|
||||
mode = SECBOT_HUNT
|
||||
|
||||
/mob/living/bot/secbot/Life()
|
||||
/mob/living/bot/secbot/think()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
if(client)
|
||||
return
|
||||
|
||||
if(!target)
|
||||
if(QDELETED(target))
|
||||
scan_view()
|
||||
|
||||
if(!locked && (mode == SECBOT_START_PATROL || mode == SECBOT_PATROL)) // Stop running away when we set you up
|
||||
@@ -189,12 +203,10 @@
|
||||
RangedAttack(target)
|
||||
else
|
||||
step_towards(src, target) // Melee bots chase a bit faster
|
||||
spawn(8)
|
||||
if(!Adjacent(target))
|
||||
step_towards(src, target)
|
||||
spawn(16)
|
||||
if(!Adjacent(target))
|
||||
step_towards(src, target)
|
||||
|
||||
var/cb = CALLBACK(src, .proc/step_nonadjacent, target)
|
||||
addtimer(cb, 8)
|
||||
addtimer(cb, 16)
|
||||
|
||||
if(SECBOT_ARREST) // Target is next to us - attack it
|
||||
if(!target)
|
||||
@@ -253,18 +265,19 @@
|
||||
|
||||
if(SECBOT_PATROL)
|
||||
patrol_step()
|
||||
spawn(10)
|
||||
patrol_step()
|
||||
addtimer(patrol_callback, 10)
|
||||
return
|
||||
|
||||
if(SECBOT_SUMMON)
|
||||
patrol_step()
|
||||
spawn(8)
|
||||
patrol_step()
|
||||
spawn(16)
|
||||
patrol_step()
|
||||
addtimer(patrol_callback, 8)
|
||||
addtimer(patrol_callback, 16)
|
||||
return
|
||||
|
||||
/mob/living/bot/secbot/proc/step_nonadjacent(target)
|
||||
if (!Adjacent(target))
|
||||
step_towards(src, target)
|
||||
|
||||
/mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
@@ -287,9 +300,7 @@
|
||||
do_attack_animation(C)
|
||||
is_attacking = 1
|
||||
update_icons()
|
||||
spawn(2)
|
||||
is_attacking = 0
|
||||
update_icons()
|
||||
addtimer(CALLBACK(src, .proc/stop_attacking_cb), 2)
|
||||
visible_message("<span class='warning'>[C] was prodded by [src] with a stun baton!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
|
||||
@@ -308,11 +319,13 @@
|
||||
playsound(loc, "swing_hit", 50, 1, -1)
|
||||
is_attacking = 1
|
||||
update_icons()
|
||||
spawn(2)
|
||||
is_attacking = 0
|
||||
update_icons()
|
||||
addtimer(CALLBACK(src, .proc/stop_attacking_cb), 2)
|
||||
visible_message("<span class='warning'>[M] was beaten by [src] with a stun baton!</span>")
|
||||
|
||||
/mob/living/bot/secbot/proc/stop_attacking_cb()
|
||||
is_attacking = FALSE
|
||||
update_icons()
|
||||
|
||||
/mob/living/bot/secbot/explode()
|
||||
visible_message("<span class='warning'>[src] blows apart!</span>")
|
||||
var/turf/Tsec = get_turf(src)
|
||||
@@ -332,6 +345,7 @@
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/secbot/proc/scan_view()
|
||||
target = null
|
||||
for(var/mob/living/M in view(7, src))
|
||||
if(M.invisibility >= INVISIBILITY_LEVEL_ONE)
|
||||
continue
|
||||
|
||||
@@ -33,12 +33,13 @@
|
||||
updatehealth()
|
||||
check_status_as_organ()
|
||||
|
||||
if (!gestalt)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/alien/diona/think()
|
||||
..()
|
||||
if (!gestalt)
|
||||
if(master_nymph && !client && master_nymph != src)
|
||||
walk_to(src,master_nymph,1,movement_delay())
|
||||
else
|
||||
walk_to(src,0)
|
||||
..()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
real_name = "Test Dummy"
|
||||
status_flags = GODMODE|CANPUSH
|
||||
|
||||
/mob/living/carbon/human/dummy/mannequin
|
||||
mob_thinks = FALSE
|
||||
|
||||
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy/mannequin)
|
||||
|
||||
/mob/living/carbon/human/dummy/mannequin/Initialize()
|
||||
|
||||
@@ -85,9 +85,6 @@
|
||||
if (is_diona())
|
||||
diona_handle_light(DS)
|
||||
|
||||
if(!client)
|
||||
species.handle_npc(src)
|
||||
|
||||
handle_stasis_bag()
|
||||
|
||||
if(!handle_some_updates())
|
||||
@@ -101,6 +98,10 @@
|
||||
if(mind && mind.vampire)
|
||||
handle_vampire()
|
||||
|
||||
/mob/living/carbon/human/think()
|
||||
..()
|
||||
species.handle_npc(src)
|
||||
|
||||
/mob/living/carbon/human/proc/handle_some_updates()
|
||||
if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle
|
||||
return 0
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
if(is_ventcrawling == 0) // Stops sight returning to normal if inside a vent
|
||||
sight = initial(sight)
|
||||
|
||||
if (!client)
|
||||
handle_targets()
|
||||
if (!AIproc)
|
||||
spawn()
|
||||
handle_AI()
|
||||
handle_speech_and_mood()
|
||||
/mob/living/carbon/slime/think()
|
||||
..()
|
||||
handle_targets()
|
||||
if (!AIproc)
|
||||
handle_AI()
|
||||
handle_speech_and_mood()
|
||||
|
||||
/mob/living/carbon/slime/handle_environment(datum/gas_mixture/environment)
|
||||
if(!environment)
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
var/obj/item/weapon/card/id/idcard
|
||||
var/idcard_type = /obj/item/weapon/card/id/synthetic
|
||||
|
||||
mob_thinks = FALSE
|
||||
|
||||
#define SEC_HUD 1 //Security HUD mode
|
||||
#define MED_HUD 2 //Medical HUD mode
|
||||
|
||||
@@ -384,4 +386,4 @@
|
||||
|
||||
if (!underdoor)
|
||||
spawn(3)//A slight delay to let us finish walking out from under the door
|
||||
layer = initial(layer)
|
||||
layer = initial(layer)
|
||||
|
||||
@@ -67,163 +67,155 @@
|
||||
|
||||
..()
|
||||
|
||||
if(stat == CONSCIOUS)
|
||||
//if we're strong enough, sting some people
|
||||
var/mob/living/carbon/human/M = target_mob
|
||||
var/sting_prob = 40 // Bees will always try to sting.
|
||||
var/prob_mult = 1
|
||||
if(M && M in view(src,1)) // Can I see my target?
|
||||
var/obj/item/clothing/worn_suit = M.wear_suit
|
||||
var/obj/item/clothing/worn_helmet = M.head
|
||||
if(worn_suit) // Are you wearing clothes?
|
||||
if ((worn_suit.flags & THICKMATERIAL))
|
||||
prob_mult -= 0.7
|
||||
else
|
||||
prob_mult -= 0.01 * (min(LAZYACCESS(worn_suit.armor, "bio"), 70)) // Is it sealed? I can't get to 70% of your body.
|
||||
if(worn_helmet)
|
||||
if ((worn_helmet.flags & THICKMATERIAL))
|
||||
prob_mult -= 0.3
|
||||
else
|
||||
prob_mult -= 0.01 *(min(LAZYACCESS(worn_helmet.armor, "bio"), 30))// Is your helmet sealed? I can't get to 30% of your body.
|
||||
if( prob(sting_prob*prob_mult) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25*prob_mult))) ) // Try to sting! If you're not moving, think about stinging.
|
||||
M.apply_damage(min(strength*0.85,2)+mut, BURN, sharp=1) // Stinging. The more mutated I am, the harder I sting.
|
||||
M.apply_damage(max(strength*0.2,(round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic), TOX) // Bee venom based on how angry I am and how many there are of me!
|
||||
M << "<span class='warning'>You have been stung!</span>"
|
||||
M.flash_pain()
|
||||
|
||||
/mob/living/simple_animal/bee/think()
|
||||
..()
|
||||
if (stat != CONSCIOUS)
|
||||
return
|
||||
|
||||
//if we're strong enough, sting some people
|
||||
var/mob/living/carbon/human/M = target_mob
|
||||
var/sting_prob = 40 // Bees will always try to sting.
|
||||
var/prob_mult = 1
|
||||
if(M && M in view(src,1)) // Can I see my target?
|
||||
var/obj/item/clothing/worn_suit = M.wear_suit
|
||||
var/obj/item/clothing/worn_helmet = M.head
|
||||
if(worn_suit) // Are you wearing clothes?
|
||||
if ((worn_suit.flags & THICKMATERIAL))
|
||||
prob_mult -= 0.7
|
||||
else
|
||||
prob_mult -= 0.01 * (min(LAZYACCESS(worn_suit.armor, "bio"), 70)) // Is it sealed? I can't get to 70% of your body.
|
||||
if(worn_helmet)
|
||||
if ((worn_helmet.flags & THICKMATERIAL))
|
||||
prob_mult -= 0.3
|
||||
else
|
||||
prob_mult -= 0.01 *(min(LAZYACCESS(worn_helmet.armor, "bio"), 30))// Is your helmet sealed? I can't get to 30% of your body.
|
||||
if( prob(sting_prob*prob_mult) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25*prob_mult))) ) // Try to sting! If you're not moving, think about stinging.
|
||||
M.apply_damage(min(strength*0.85,2)+mut, BURN, sharp=1) // Stinging. The more mutated I am, the harder I sting.
|
||||
M.apply_damage(max(strength*0.2,(round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic), TOX) // Bee venom based on how angry I am and how many there are of me!
|
||||
M << "<span class='warning'>You have been stung!</span>"
|
||||
M.flash_pain()
|
||||
|
||||
|
||||
|
||||
//calm down a little bit
|
||||
if(feral > 0 && !target_mob)
|
||||
if(prob(feral * 20))
|
||||
feral -= 1
|
||||
else
|
||||
//if feral is less than 0, we're becalmed by smoke or steam
|
||||
if(feral < 0)
|
||||
feral += 1
|
||||
//calm down a little bit
|
||||
if(feral > 0 && !target_mob)
|
||||
if(prob(feral * 20))
|
||||
feral -= 1
|
||||
else
|
||||
//if feral is less than 0, we're becalmed by smoke or steam
|
||||
if(feral < 0)
|
||||
feral += 1
|
||||
|
||||
if(target_mob)
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
if(strength > 5)
|
||||
//calm down and spread out a little
|
||||
var/mob/living/simple_animal/bee/B = new(get_turf(src))
|
||||
B.strength = rand(1,5)
|
||||
src.strength -= B.strength
|
||||
update_icons()
|
||||
B.update_icons()
|
||||
if(src.parent)
|
||||
B.parent = src.parent
|
||||
src.parent.owned_bee_swarms.Add(B)
|
||||
|
||||
//make some noise
|
||||
if(prob(3))
|
||||
src.visible_message("<span class='notice'>[pick("Buzzzz.","Hmmmmm.","Bzzz.")]</span>")
|
||||
playsound(src.loc, pick('sound/effects/Buzz1.ogg','sound/effects/Buzz2.ogg'), 15, 1,-4)
|
||||
|
||||
if (feral && isturf(loc))
|
||||
//smoke, water and steam calms us down
|
||||
var/static/list/calmers = typecacheof(list(
|
||||
/obj/effect/effect/smoke,
|
||||
/obj/effect/effect/water,
|
||||
/obj/effect/effect/foam,
|
||||
/obj/effect/effect/steam,
|
||||
/obj/effect/mist
|
||||
))
|
||||
|
||||
if(range_in_typecache(src, 2, calmers))
|
||||
if(feral > 0)
|
||||
src.visible_message("<span class='notice'>The bees calm down!</span>")
|
||||
feral = -15
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
wander = 1
|
||||
|
||||
for(var/mob/living/simple_animal/bee/B in src.loc)
|
||||
if(B == src)
|
||||
continue
|
||||
|
||||
if(feral > 0)
|
||||
src.strength += B.strength
|
||||
B.strength = 0
|
||||
B.update_icons()
|
||||
update_icons()
|
||||
|
||||
else if(prob(10))
|
||||
//make the other swarm of bees stronger, then move away
|
||||
var/total_bees = B.strength + src.strength
|
||||
if(total_bees < 10)
|
||||
B.strength = min(5, total_bees)
|
||||
src.strength = total_bees - B.strength
|
||||
|
||||
if(target_mob)
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
if(strength > 5)
|
||||
//calm down and spread out a little
|
||||
var/mob/living/simple_animal/bee/B = new(get_turf(src))
|
||||
B.strength = rand(1,5)
|
||||
src.strength -= B.strength
|
||||
update_icons()
|
||||
B.update_icons()
|
||||
if(src.parent)
|
||||
B.parent = src.parent
|
||||
src.parent.owned_bee_swarms.Add(B)
|
||||
|
||||
//make some noise
|
||||
if(prob(3))
|
||||
src.visible_message("<span class='notice'>[pick("Buzzzz.","Hmmmmm.","Bzzz.")]</span>")
|
||||
playsound(src.loc, pick('sound/effects/Buzz1.ogg','sound/effects/Buzz2.ogg'), 15, 1,-4)
|
||||
|
||||
var/calming = 0
|
||||
if (feral && istype(loc, /turf))
|
||||
//smoke, water and steam calms us down
|
||||
|
||||
var/list/calmers = list(/obj/effect/effect/smoke, \
|
||||
/obj/effect/effect/water, \
|
||||
/obj/effect/effect/foam, \
|
||||
/obj/effect/effect/steam, \
|
||||
/obj/effect/mist)
|
||||
|
||||
for(var/obj/effect/E in range(src, 2))//Check in 1-tile range because these effects often have 3x3 sprites
|
||||
for (var/e in calmers)
|
||||
if(istype(E, e))
|
||||
calming = 1
|
||||
break
|
||||
if (calming)
|
||||
break
|
||||
|
||||
if(calming)
|
||||
if(feral > 0)
|
||||
src.visible_message("<span class='notice'>The bees calm down!</span>")
|
||||
feral = -15
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
wander = 1
|
||||
|
||||
for(var/mob/living/simple_animal/bee/B in src.loc)
|
||||
if(B == src)
|
||||
continue
|
||||
|
||||
if(feral > 0)
|
||||
|
||||
src.strength += B.strength
|
||||
B.strength = 0
|
||||
B.update_icons()
|
||||
update_icons()
|
||||
|
||||
else if(prob(10))
|
||||
//make the other swarm of bees stronger, then move away
|
||||
var/total_bees = B.strength + src.strength
|
||||
if(total_bees < 10)
|
||||
B.strength = min(5, total_bees)
|
||||
src.strength = total_bees - B.strength
|
||||
|
||||
update_icons()
|
||||
B.update_icons()
|
||||
if(src.strength <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
|
||||
density = 1
|
||||
if(T.Enter(src, get_turf(src)))
|
||||
src.loc = T
|
||||
density = 0
|
||||
break
|
||||
if(src.strength <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
var/turf/simulated/floor/T = get_step(src, pick(1,2,4,8))
|
||||
density = 1
|
||||
Move(T)
|
||||
density = 0
|
||||
break
|
||||
|
||||
|
||||
if(target_mob)//If we have a target
|
||||
if(target_mob in view(src,7))//Check that we can still see them
|
||||
target_turf = get_turf(target_mob)//If so, update the location
|
||||
wander = 0
|
||||
else//Otherwise, if our target is out of view, we clear them so we can pick a new one in the next step
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
wander = 1
|
||||
if(target_mob)//If we have a target
|
||||
if(target_mob in view(src,7))//Check that we can still see them
|
||||
target_turf = get_turf(target_mob)//If so, update the location
|
||||
wander = 0
|
||||
else//Otherwise, if our target is out of view, we clear them so we can pick a new one in the next step
|
||||
target_mob = null
|
||||
target_turf = null
|
||||
wander = 1
|
||||
|
||||
//If we're angry but have no target, lets search for one
|
||||
if (!target_mob && feral)
|
||||
for(var/mob/living/carbon/G in view(src,7))
|
||||
target_mob = G
|
||||
break
|
||||
//If we're angry but have no target, lets search for one
|
||||
if (!target_mob && feral)
|
||||
for(var/mob/living/carbon/G in view(src,7))
|
||||
target_mob = G
|
||||
break
|
||||
|
||||
//if we're chasing someone, get a little bit angry
|
||||
if(target_mob && prob(5))
|
||||
feral++
|
||||
|
||||
if(target_turf)
|
||||
if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors!
|
||||
Move(get_step(src, get_dir(src,target_turf)))
|
||||
if (prob(10))
|
||||
src.visible_message("<span class='notice'>The bees swarm after [target_mob]!</span>")
|
||||
if(src.loc == target_turf)
|
||||
target_turf = null
|
||||
wander = 1
|
||||
else
|
||||
//find some flowers, harvest
|
||||
//angry bee swarms don't hang around
|
||||
if(feral > 0)
|
||||
turns_per_move = rand(1,3)
|
||||
else if(feral < 0)
|
||||
turns_since_move = 0
|
||||
else if(!my_hydrotray || my_hydrotray.loc != src.loc || my_hydrotray.dead || !my_hydrotray.seed)
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray = locate() in src.loc
|
||||
if(my_hydrotray)
|
||||
if(!my_hydrotray.dead && my_hydrotray.seed)
|
||||
turns_per_move = rand(20,50)
|
||||
else
|
||||
my_hydrotray = null
|
||||
|
||||
pixel_x = rand(-12,12)
|
||||
pixel_y = rand(-12,12)
|
||||
//if we're chasing someone, get a little bit angry
|
||||
if(target_mob && prob(5))
|
||||
feral++
|
||||
|
||||
if(target_turf)
|
||||
if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors!
|
||||
Move(get_step(src, get_dir(src,target_turf)))
|
||||
if (prob(10))
|
||||
src.visible_message("<span class='notice'>The bees swarm after [target_mob]!</span>")
|
||||
if(src.loc == target_turf)
|
||||
target_turf = null
|
||||
wander = 1
|
||||
else
|
||||
//find some flowers, harvest
|
||||
//angry bee swarms don't hang around
|
||||
if(feral > 0)
|
||||
turns_per_move = rand(1,3)
|
||||
else if(feral < 0)
|
||||
turns_since_move = 0
|
||||
else if(!my_hydrotray || my_hydrotray.loc != src.loc || my_hydrotray.dead || !my_hydrotray.seed)
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray = locate() in src.loc
|
||||
if(my_hydrotray)
|
||||
if(!my_hydrotray.dead && my_hydrotray.seed)
|
||||
turns_per_move = rand(20,50)
|
||||
else
|
||||
my_hydrotray = null
|
||||
|
||||
animate(src, pixel_x = rand(-12, 12), pixel_y = rand(-12, 12), time = 0.5)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bee/update_icons()
|
||||
@@ -234,8 +226,7 @@
|
||||
|
||||
//Kill it with fire!
|
||||
/mob/living/simple_animal/bee/adjustFireLoss(damage)
|
||||
damage *= 2
|
||||
..()
|
||||
..(damage * 2)
|
||||
|
||||
|
||||
//No more grabbing bee swarms
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
var/list/construct_spells = list()
|
||||
var/can_repair = 0
|
||||
|
||||
var/health_prefix = ""
|
||||
|
||||
|
||||
/mob/living/simple_animal/construct/cultify()
|
||||
return
|
||||
@@ -114,6 +116,7 @@
|
||||
icon_living = "behemoth"
|
||||
maxHealth = 400
|
||||
health = 400
|
||||
health_prefix = "juggernaut"
|
||||
response_harm = "harmlessly punches"
|
||||
harm_intent_damage = 0
|
||||
melee_damage_lower = 30
|
||||
@@ -165,6 +168,7 @@
|
||||
icon_living = "floating"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
health_prefix = "wraith"
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
attacktext = "slashed"
|
||||
@@ -196,6 +200,7 @@
|
||||
icon_living = "artificer"
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
health_prefix = "artificer"
|
||||
response_harm = "viciously beaten"
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 5
|
||||
@@ -225,6 +230,7 @@
|
||||
icon_living = "behemoth"
|
||||
maxHealth = 750
|
||||
health = 750
|
||||
health_prefix = "juggernaut"
|
||||
speak_emote = list("rumbles")
|
||||
response_harm = "harmlessly punched"
|
||||
harm_intent_damage = 0
|
||||
@@ -252,6 +258,7 @@
|
||||
icon_living = "harvester"
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
health_prefix = "harvester"
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
attacktext = "violently stabbed"
|
||||
@@ -297,84 +304,44 @@
|
||||
/mob/living/simple_animal/construct/Life()
|
||||
. = ..()
|
||||
if(.)
|
||||
var/newstate
|
||||
if(fire)
|
||||
if(fire_alert) fire.icon_state = "fire1"
|
||||
else fire.icon_state = "fire0"
|
||||
newstate = fire_alert ? "fire1" : "fire0"
|
||||
if (fire.icon_state != newstate)
|
||||
fire.icon_state = newstate
|
||||
|
||||
if(pullin)
|
||||
if(pulling) pullin.icon_state = "pull1"
|
||||
else pullin.icon_state = "pull0"
|
||||
newstate = pulling ? "pull1" : "pull0"
|
||||
if (pullin.icon_state != newstate)
|
||||
pullin.icon_state = newstate
|
||||
|
||||
if(purged)
|
||||
if(purge > 0) purged.icon_state = "purge1"
|
||||
else purged.icon_state = "purge0"
|
||||
newstate = purge > 0 ? "purge1" : "purge0"
|
||||
if (purged.icon_state != newstate)
|
||||
purged.icon_state = newstate
|
||||
|
||||
silence_spells(purge)
|
||||
|
||||
/mob/living/simple_animal/construct/armoured/Life()
|
||||
..()
|
||||
if(healths)
|
||||
switch(health)
|
||||
if(250 to INFINITY) healths.icon_state = "juggernaut_health0"
|
||||
if(208 to 249) healths.icon_state = "juggernaut_health1"
|
||||
if(167 to 207) healths.icon_state = "juggernaut_health2"
|
||||
if(125 to 166) healths.icon_state = "juggernaut_health3"
|
||||
if(84 to 124) healths.icon_state = "juggernaut_health4"
|
||||
if(42 to 83) healths.icon_state = "juggernaut_health5"
|
||||
if(1 to 41) healths.icon_state = "juggernaut_health6"
|
||||
else healths.icon_state = "juggernaut_health7"
|
||||
|
||||
|
||||
/mob/living/simple_animal/construct/behemoth/Life()
|
||||
..()
|
||||
if(healths)
|
||||
switch(health)
|
||||
if(750 to INFINITY) healths.icon_state = "juggernaut_health0"
|
||||
if(625 to 749) healths.icon_state = "juggernaut_health1"
|
||||
if(500 to 624) healths.icon_state = "juggernaut_health2"
|
||||
if(375 to 499) healths.icon_state = "juggernaut_health3"
|
||||
if(250 to 374) healths.icon_state = "juggernaut_health4"
|
||||
if(125 to 249) healths.icon_state = "juggernaut_health5"
|
||||
if(1 to 124) healths.icon_state = "juggernaut_health6"
|
||||
else healths.icon_state = "juggernaut_health7"
|
||||
|
||||
/mob/living/simple_animal/construct/builder/Life()
|
||||
..()
|
||||
if(healths)
|
||||
switch(health)
|
||||
if(50 to INFINITY) healths.icon_state = "artificer_health0"
|
||||
if(42 to 49) healths.icon_state = "artificer_health1"
|
||||
if(34 to 41) healths.icon_state = "artificer_health2"
|
||||
if(26 to 33) healths.icon_state = "artificer_health3"
|
||||
if(18 to 25) healths.icon_state = "artificer_health4"
|
||||
if(10 to 17) healths.icon_state = "artificer_health5"
|
||||
if(1 to 9) healths.icon_state = "artificer_health6"
|
||||
else healths.icon_state = "artificer_health7"
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/construct/wraith/Life()
|
||||
..()
|
||||
if(healths)
|
||||
switch(health)
|
||||
if(75 to INFINITY) healths.icon_state = "wraith_health0"
|
||||
if(62 to 74) healths.icon_state = "wraith_health1"
|
||||
if(50 to 61) healths.icon_state = "wraith_health2"
|
||||
if(37 to 49) healths.icon_state = "wraith_health3"
|
||||
if(25 to 36) healths.icon_state = "wraith_health4"
|
||||
if(12 to 24) healths.icon_state = "wraith_health5"
|
||||
if(1 to 11) healths.icon_state = "wraith_health6"
|
||||
else healths.icon_state = "wraith_health7"
|
||||
|
||||
|
||||
/mob/living/simple_animal/construct/harvester/Life()
|
||||
..()
|
||||
if(healths)
|
||||
switch(health)
|
||||
if(150 to INFINITY) healths.icon_state = "harvester_health0"
|
||||
if(125 to 149) healths.icon_state = "harvester_health1"
|
||||
if(100 to 124) healths.icon_state = "harvester_health2"
|
||||
if(75 to 99) healths.icon_state = "harvester_health3"
|
||||
if(50 to 74) healths.icon_state = "harvester_health4"
|
||||
if(25 to 49) healths.icon_state = "harvester_health5"
|
||||
if(1 to 24) healths.icon_state = "harvester_health6"
|
||||
else healths.icon_state = "harvester_health7"
|
||||
if (healths)
|
||||
var/health_percent = (health/maxHealth)*100
|
||||
var/newstate = 0
|
||||
switch (health_percent)
|
||||
if (84 to INFINITY)
|
||||
newstate = 0
|
||||
if (70 to 84)
|
||||
newstate = 1
|
||||
if (56 to 70)
|
||||
newstate = 2
|
||||
if (42 to 56)
|
||||
newstate = 3
|
||||
if (28 to 42)
|
||||
newstate = 4
|
||||
if (14 to 28)
|
||||
newstate = 5
|
||||
if (1 to 14)
|
||||
newstate = 6
|
||||
else
|
||||
newstate = 7
|
||||
newstate = "[health_prefix][newstate]"
|
||||
if (healths.icon_state != newstate)
|
||||
healths.icon_state = newstate
|
||||
|
||||
@@ -34,22 +34,22 @@
|
||||
pass_flags = PASSTABLE
|
||||
possession_candidate = 1
|
||||
|
||||
/mob/living/simple_animal/cat/Life()
|
||||
/mob/living/simple_animal/cat/think()
|
||||
//MICE!
|
||||
|
||||
|
||||
..()
|
||||
|
||||
if (!stat)
|
||||
for(var/mob/living/simple_animal/mouse/snack in oview(src,7))
|
||||
if(snack.stat != DEAD && prob(65))//The probability allows her to not get stuck target the first mouse, reducing exploits
|
||||
mousetarget = snack
|
||||
movement_target = snack
|
||||
foodtarget = 0//chasing mice takes precedence over eating food
|
||||
foodtarget = 0 //chasing mice takes precedence over eating food
|
||||
if(prob(15))
|
||||
audible_emote(pick("hisses and spits!","mrowls fiercely!","eyes [snack] hungrily."))
|
||||
|
||||
addtimer(CALLBACK(src, .proc/attack_mice), 2)
|
||||
break
|
||||
|
||||
|
||||
if(!buckled)
|
||||
if (turns_since_move > 5 || (flee_target || mousetarget))
|
||||
walk_to(src,0)
|
||||
@@ -63,8 +63,6 @@
|
||||
if (!movement_target)
|
||||
walk_to(src,0)
|
||||
|
||||
addtimer(CALLBACK(src, .proc/attack_mice), 2)
|
||||
|
||||
if(prob(2)) //spooky
|
||||
var/mob/dead/observer/spook = locate() in range(src,5)
|
||||
if(spook)
|
||||
@@ -89,7 +87,7 @@
|
||||
|
||||
if(movement_target)
|
||||
stop_automated_movement = 1
|
||||
walk_to(src,movement_target,0,seek_move_delay)
|
||||
walk_to(src, movement_target, 0, DS2TICKS(seek_move_delay))
|
||||
|
||||
/mob/living/simple_animal/cat/proc/attack_mice()
|
||||
if((src.loc) && isturf(src.loc))
|
||||
@@ -183,7 +181,7 @@
|
||||
//walk to friend
|
||||
stop_automated_movement = 1
|
||||
movement_target = friend
|
||||
walk_to(src, movement_target, near_dist, seek_move_delay)
|
||||
walk_to(src, movement_target, near_dist, DS2TICKS(seek_move_delay))
|
||||
|
||||
//already following and close enough, stop
|
||||
else if (current_dist <= near_dist)
|
||||
@@ -196,7 +194,7 @@
|
||||
if (!friend || movement_target != friend)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/cat/fluff/Life()
|
||||
/mob/living/simple_animal/cat/fluff/think()
|
||||
..()
|
||||
if (stat || QDELETED(friend))
|
||||
return
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
response_disarm = "bops"
|
||||
response_harm = "kicks"
|
||||
|
||||
/mob/living/simple_animal/corgi/Ian/Life()
|
||||
/mob/living/simple_animal/corgi/Ian/think()
|
||||
..()
|
||||
|
||||
if(!stat && !resting && !buckled)
|
||||
@@ -68,14 +68,16 @@
|
||||
/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
|
||||
if(istype(O, /obj/item/weapon/newspaper))
|
||||
if(!stat)
|
||||
for(var/mob/M in viewers(user, null))
|
||||
if ((M.client && !( M.blinded )))
|
||||
M.show_message("<span class='notice'>[user] baps [name] on the nose with the rolled up [O]</span>")
|
||||
scan_interval = max_scan_interval//discipline your dog to make it stop stealing food for a while
|
||||
movement_target = null
|
||||
foodtarget = 0
|
||||
stop_automated_movement = 0
|
||||
turns_since_scan = 0
|
||||
visible_message(
|
||||
"<span class='notice'>[user] baps [src] on the nose with the rolled up [O.name].</span>",
|
||||
"<span class='alert'>[user] baps you on the nose with the rolled up [O.name]!</span>"
|
||||
)
|
||||
scan_interval = max_scan_interval
|
||||
movement_target = null
|
||||
foodtarget = 0
|
||||
stop_automated_movement = 0
|
||||
turns_since_scan = 0
|
||||
|
||||
INVOKE_ASYNC(src, .proc/do_dance, list(1,2,4,8,4,2,1,2))
|
||||
else
|
||||
..()
|
||||
@@ -138,9 +140,8 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/corgi/Lisa/Life()
|
||||
/mob/living/simple_animal/corgi/Lisa/think()
|
||||
..()
|
||||
|
||||
if(!stat && !resting && !buckled)
|
||||
turns_since_scan++
|
||||
if(turns_since_scan > 15)
|
||||
@@ -161,8 +162,8 @@
|
||||
if(near_camera(src) || near_camera(ian))
|
||||
return
|
||||
new /mob/living/simple_animal/corgi/puppy(loc)
|
||||
puppies++
|
||||
|
||||
|
||||
if(prob(1))
|
||||
visible_emote(pick("dances around","chases her tail"),0)
|
||||
INVOKE_ASYNC(src, .proc/do_dance, list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
|
||||
if (!stat && !resting && !buckled && prob(1))
|
||||
visible_emote(pick("dances around","chases her tail"),0)
|
||||
INVOKE_ASYNC(src, .proc/do_dance, list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var/obj/item/inventory_mask
|
||||
possession_candidate = 1
|
||||
|
||||
/mob/living/simple_animal/crab/Life()
|
||||
/mob/living/simple_animal/crab/think()
|
||||
..()
|
||||
//CRAB movement
|
||||
if(!ckey && !stat)
|
||||
|
||||
@@ -36,15 +36,6 @@
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Life()
|
||||
. = ..()
|
||||
if(.)
|
||||
//chance to go crazy and start wacking stuff
|
||||
if(!enemies.len && prob(1))
|
||||
Retaliate()
|
||||
|
||||
if(enemies.len && prob(10))
|
||||
enemies = list()
|
||||
LoseTarget()
|
||||
src.visible_message("<span class='notice'>[src] calms down.</span>")
|
||||
|
||||
if(stat == CONSCIOUS)
|
||||
if(udder && prob(5))
|
||||
udder.add_reagent("milk", rand(5, 10))
|
||||
@@ -57,12 +48,22 @@
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/SP = locate() in loc
|
||||
qdel(SP)
|
||||
|
||||
if(!pulledby)
|
||||
var/obj/effect/plant/food
|
||||
food = locate(/obj/effect/plant) in oview(5,loc)
|
||||
if(food)
|
||||
var/step = get_step_to(src, food, 0)
|
||||
Move(step)
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/think()
|
||||
..()
|
||||
//chance to go crazy and start wacking stuff
|
||||
if(!enemies.len && prob(1))
|
||||
Retaliate()
|
||||
|
||||
if(enemies.len && prob(10))
|
||||
enemies = list()
|
||||
LoseTarget()
|
||||
src.visible_message("<span class='notice'>[src] calms down.</span>")
|
||||
|
||||
if(!pulledby)
|
||||
var/obj/effect/plant/food = locate(/obj/effect/plant) in oview(5,loc)
|
||||
if(food)
|
||||
var/step = get_step_to(src, food, 0)
|
||||
Move(step)
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
|
||||
..()
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/lizard/death()
|
||||
.=..()
|
||||
. = ..()
|
||||
desc = "It doesn't hiss anymore."
|
||||
|
||||
/mob/living/simple_animal/lizard/dust()
|
||||
|
||||
@@ -89,11 +89,15 @@
|
||||
/mob/living/simple_animal/mouse/Move()
|
||||
if(..())
|
||||
if (prob(50))
|
||||
pixel_x += rand(-2,2)
|
||||
pixel_x = Clamp(pixel_x, -10, 10)
|
||||
var/new_pixelx = pixel_x
|
||||
new_pixelx += rand(-2,2)
|
||||
new_pixelx = Clamp(new_pixelx, -10, 10)
|
||||
animate(src, pixel_x = new_pixelx, time = 0.5)
|
||||
else
|
||||
pixel_y += rand(-2,2)
|
||||
pixel_y = Clamp(pixel_y, -4, 14)
|
||||
var/new_pixely = pixel_y
|
||||
new_pixely += rand(-2,2)
|
||||
new_pixely = Clamp(new_pixely, -4, 14)
|
||||
animate(src, pixel_y = new_pixely, time = 0.5)
|
||||
|
||||
/mob/living/simple_animal/mouse/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
if (stance != previous)
|
||||
stance_step = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/Life()
|
||||
/mob/living/simple_animal/hostile/bear/think()
|
||||
. =..()
|
||||
safety = 0
|
||||
if (stat != CONSCIOUS)
|
||||
@@ -100,7 +100,6 @@
|
||||
if (life_tick % 5 == 0)
|
||||
update_bearmode()
|
||||
|
||||
|
||||
//This covers cases where the bear is damaged by things it can't detect.
|
||||
//Most notably, security bots, beepsky kept murdering them without resistance
|
||||
if (health < health_last_tick && stance != HOSTILE_STANCE_TIRED)
|
||||
@@ -111,7 +110,6 @@
|
||||
anger = max(0, anger-1)
|
||||
|
||||
switch(stance)
|
||||
|
||||
if(HOSTILE_STANCE_TIRED)
|
||||
stop_automated_movement = 1
|
||||
stance_step++
|
||||
@@ -145,9 +143,6 @@
|
||||
else
|
||||
stance_step--
|
||||
|
||||
|
||||
|
||||
|
||||
if (anger && found_mob)
|
||||
instant_aggro()//If we're angry and someone is nearby, skip waiting and charge them
|
||||
|
||||
@@ -166,7 +161,6 @@
|
||||
tire_out()
|
||||
return
|
||||
|
||||
|
||||
//If we're having no luck attacking our current target
|
||||
if (target_mob && !Adjacent(target_mob) && turns_since_hit > 3)
|
||||
LoseTarget()
|
||||
@@ -175,7 +169,6 @@
|
||||
|
||||
health_last_tick = health
|
||||
|
||||
|
||||
//Causes the bear to find and start attacking the nearest target.
|
||||
//This will overwrite any existing target if a different one is closer
|
||||
//If there are no other suitable targets, targeting will not be changed
|
||||
@@ -461,7 +454,7 @@
|
||||
else if (forcechange)
|
||||
MoveToTarget()
|
||||
|
||||
/mob/living/simple_animal/hostile/bear/spatial/Life()
|
||||
/mob/living/simple_animal/hostile/bear/spatial/think()
|
||||
..()
|
||||
if (stat != CONSCIOUS)
|
||||
return
|
||||
@@ -482,7 +475,6 @@
|
||||
if (focus_time % tactical_delay == 0)
|
||||
teleport_tactical(target_mob)
|
||||
|
||||
|
||||
//Teleport away from other bears
|
||||
for (var/mob/living/simple_animal/hostile/bear/bear in view(world.view, get_turf(src)))
|
||||
if (bear != src && bear.stat != DEAD)
|
||||
|
||||
@@ -11,18 +11,18 @@
|
||||
var/retribution = 1 //whether or not they will attack us if we attack them like some kinda dick.
|
||||
|
||||
/mob/living/simple_animal/hostile/commanded/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
if((speaker in friends) || speaker == master)
|
||||
if(thinking_enabled && !stat && ((speaker in friends) || speaker == master))
|
||||
command_buffer.Add(speaker)
|
||||
command_buffer.Add(lowertext(html_decode(message)))
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/hostile/commanded/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0)
|
||||
if((speaker in friends) || speaker == master)
|
||||
if(thinking_enabled && !stat && ((speaker in friends) || speaker == master))
|
||||
command_buffer.Add(speaker)
|
||||
command_buffer.Add(lowertext(html_decode(message)))
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/hostile/commanded/Life()
|
||||
/mob/living/simple_animal/hostile/commanded/think()
|
||||
while(command_buffer.len > 0)
|
||||
var/mob/speaker = command_buffer[1]
|
||||
var/text = command_buffer[2]
|
||||
@@ -31,15 +31,16 @@
|
||||
var/substring = copytext(text,length(filtered_name)+1) //get rid of the name.
|
||||
listen(speaker,substring)
|
||||
command_buffer.Remove(command_buffer[1],command_buffer[2])
|
||||
. = ..()
|
||||
if(.)
|
||||
switch(stance)
|
||||
if(COMMANDED_FOLLOW)
|
||||
follow_target()
|
||||
if(COMMANDED_STOP)
|
||||
commanded_stop()
|
||||
|
||||
..()
|
||||
switch(stance)
|
||||
if(COMMANDED_FOLLOW)
|
||||
follow_target()
|
||||
if(COMMANDED_STOP)
|
||||
commanded_stop()
|
||||
|
||||
/mob/living/simple_animal/hostile/commanded/on_think_disabled()
|
||||
..()
|
||||
command_buffer.Cut()
|
||||
|
||||
/mob/living/simple_animal/hostile/commanded/FindTarget(var/new_stance = HOSTILE_STANCE_ATTACK)
|
||||
if(!allowed_targets.len)
|
||||
@@ -197,4 +198,4 @@
|
||||
allowed_targets += M
|
||||
stance = HOSTILE_STANCE_ATTACK
|
||||
if(M in friends)
|
||||
friends -= M
|
||||
friends -= M
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
O.implants += eggs
|
||||
H << "<span class='warning'>The [src] injects something into your [O.name]!</span>"
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/Life()
|
||||
/mob/living/simple_animal/hostile/giant_spider/think()
|
||||
..()
|
||||
if(!stat)
|
||||
if(stance == HOSTILE_STANCE_IDLE)
|
||||
@@ -106,15 +106,14 @@
|
||||
stop_automated_movement = 0
|
||||
walk(src, 0)
|
||||
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/Life()
|
||||
/mob/living/simple_animal/hostile/giant_spider/nurse/think()
|
||||
..()
|
||||
if(!stat)
|
||||
if(stance == HOSTILE_STANCE_IDLE)
|
||||
var/list/can_see = view(src, 10)
|
||||
//30% chance to stop wandering and do something
|
||||
if(!busy && prob(30))
|
||||
//first, check for potential food nearby to cocoon
|
||||
for(var/mob/living/C in can_see)
|
||||
for(var/mob/living/C in view(src, world.view))
|
||||
if(C.stat)
|
||||
cocoon_target = C
|
||||
busy = MOVING_TO_TARGET
|
||||
@@ -140,8 +139,7 @@
|
||||
addtimer(CALLBACK(src, .proc/finalize_eggs), 50, TIMER_UNIQUE)
|
||||
else
|
||||
//fourthly, cocoon any nearby items so those pesky pinkskins can't use them
|
||||
for(var/obj/O in can_see)
|
||||
|
||||
for(var/obj/O in view(src, world.view))
|
||||
if(O.anchored)
|
||||
continue
|
||||
|
||||
|
||||
@@ -149,28 +149,20 @@
|
||||
..()
|
||||
walk(src, 0)
|
||||
|
||||
/mob/living/simple_animal/hostile/Life()
|
||||
/mob/living/simple_animal/hostile/think()
|
||||
..()
|
||||
switch(stance)
|
||||
if(HOSTILE_STANCE_IDLE)
|
||||
target_mob = FindTarget()
|
||||
|
||||
. = ..()
|
||||
if(!.)
|
||||
walk(src, 0)
|
||||
return 0
|
||||
if(client)
|
||||
return 0
|
||||
if(HOSTILE_STANCE_ATTACK)
|
||||
if(destroy_surroundings)
|
||||
DestroySurroundings()
|
||||
MoveToTarget()
|
||||
|
||||
if(!stat)
|
||||
switch(stance)
|
||||
if(HOSTILE_STANCE_IDLE)
|
||||
target_mob = FindTarget()
|
||||
|
||||
if(HOSTILE_STANCE_ATTACK)
|
||||
if(destroy_surroundings)
|
||||
DestroySurroundings()
|
||||
MoveToTarget()
|
||||
|
||||
if(HOSTILE_STANCE_ATTACKING)
|
||||
if(!AttackTarget() && destroy_surroundings)//hit a window OR a mob, not both at once
|
||||
DestroySurroundings()
|
||||
if(HOSTILE_STANCE_ATTACKING)
|
||||
if(!AttackTarget() && destroy_surroundings) //hit a window OR a mob, not both at once
|
||||
DestroySurroundings()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/OpenFire(target_mob)
|
||||
@@ -186,7 +178,7 @@
|
||||
else
|
||||
Shoot(target, src.loc, src)
|
||||
if(casingtype)
|
||||
new casingtype
|
||||
new casingtype(loc)
|
||||
|
||||
stance = HOSTILE_STANCE_IDLE
|
||||
target_mob = null
|
||||
|
||||
@@ -266,9 +266,8 @@
|
||||
/*
|
||||
* AI - Not really intelligent, but I'm calling it AI anyway.
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/Life()
|
||||
/mob/living/simple_animal/parrot/think()
|
||||
..()
|
||||
|
||||
//Sprite and AI update for when a parrot gets pulled
|
||||
if(pulledby && stat == CONSCIOUS)
|
||||
icon_state = "parrot_fly"
|
||||
|
||||
@@ -32,9 +32,10 @@
|
||||
/mob/living/simple_animal/shade/cultify()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/shade/Life()
|
||||
..()
|
||||
OnDeathInLife()
|
||||
/mob/living/simple_animal/shade/death()
|
||||
visible_message("<span class='warning'>[src] lets out a contented sigh as their form unwinds.</span>")
|
||||
new /obj/item/weapon/ectoplasm(loc)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
|
||||
if(istype(O, /obj/item/device/soulstone))
|
||||
@@ -42,16 +43,6 @@
|
||||
S.transfer_soul("SHADE", src, user)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/shade/proc/OnDeathInLife()
|
||||
if(stat == 2)
|
||||
new /obj/item/weapon/ectoplasm (src.loc)
|
||||
for(var/mob/M in viewers(src, null))
|
||||
if((M.client && !( M.blinded )))
|
||||
M.show_message("<span class='warning'>[src] lets out a contented sigh as their form unwinds.</span>")
|
||||
ghostize()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/shade/can_fall()
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
/mob/living/simple_animal/Initialize()
|
||||
. = ..()
|
||||
seek_move_delay = (1 / seek_speed) / (world.tick_lag / 10)//number of ticks between moves
|
||||
seek_move_delay = (1 / seek_speed) * 10 //number of ds between moves
|
||||
turns_since_scan = rand(min_scan_interval, max_scan_interval)//Randomise this at the start so animals don't sync up
|
||||
health = maxHealth
|
||||
verbs -= /mob/verb/observe
|
||||
@@ -177,102 +177,37 @@
|
||||
handle_supernatural()
|
||||
process_food()
|
||||
|
||||
handle_foodscanning()
|
||||
//Movement
|
||||
turns_since_move++
|
||||
if (!client)
|
||||
if(!stop_automated_movement && wander && !anchored)
|
||||
if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
|
||||
|
||||
if(turns_since_move >= turns_per_move)
|
||||
if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled
|
||||
var/moving_to = 0 // otherwise it always picks 4, fuck if I know. Did I mention fuck BYOND
|
||||
moving_to = pick(cardinal)
|
||||
dir = moving_to //How about we turn them the direction they are moving, yay.
|
||||
Move(get_step(src,moving_to))
|
||||
turns_since_move = 0
|
||||
|
||||
//Speaking
|
||||
if(speak_chance)
|
||||
if(rand(0,200) < speak_chance)
|
||||
if(speak && speak.len)
|
||||
if((emote_hear && emote_hear.len) || (emote_see && emote_see.len))
|
||||
var/length = speak.len
|
||||
if(emote_hear && emote_hear.len)
|
||||
length += emote_hear.len
|
||||
if(emote_see && emote_see.len)
|
||||
length += emote_see.len
|
||||
var/randomValue = rand(1,length)
|
||||
if(randomValue <= speak.len)
|
||||
say(pick(speak))
|
||||
else
|
||||
randomValue -= speak.len
|
||||
if(emote_see && randomValue <= emote_see.len)
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
else
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
else
|
||||
say(pick(speak))
|
||||
else
|
||||
if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len))
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len))
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
if((emote_hear && emote_hear.len) && (emote_see && emote_see.len))
|
||||
var/length = emote_hear.len + emote_see.len
|
||||
var/pick = rand(1,length)
|
||||
if(pick <= emote_see.len)
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
else
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
speak_audio()
|
||||
|
||||
if (can_nap)
|
||||
if (!resting && prob(1))
|
||||
fall_asleep()
|
||||
else if (resting && (prob(0.5) || !stat))
|
||||
wake_up()
|
||||
|
||||
|
||||
//Atmos
|
||||
var/atmos_suitable = 1
|
||||
|
||||
var/atom/A = src.loc
|
||||
|
||||
if(istype(A,/turf))
|
||||
var/turf/T = A
|
||||
if(isturf(loc))
|
||||
var/turf/T = loc
|
||||
|
||||
var/datum/gas_mixture/Environment = T.return_air()
|
||||
|
||||
if(Environment)
|
||||
|
||||
if( abs(Environment.temperature - bodytemperature) > 40 )
|
||||
if (abs(Environment.temperature - bodytemperature) > 40)
|
||||
bodytemperature += ((Environment.temperature - bodytemperature) / 5)
|
||||
|
||||
if(min_oxy)
|
||||
if(Environment.gas["oxygen"] < min_oxy)
|
||||
atmos_suitable = 0
|
||||
if(max_oxy)
|
||||
if(Environment.gas["oxygen"] > max_oxy)
|
||||
atmos_suitable = 0
|
||||
if(min_tox)
|
||||
if(Environment.gas["phoron"] < min_tox)
|
||||
atmos_suitable = 0
|
||||
if(max_tox)
|
||||
if(Environment.gas["phoron"] > max_tox)
|
||||
atmos_suitable = 0
|
||||
if(min_n2)
|
||||
if(Environment.gas["nitrogen"] < min_n2)
|
||||
atmos_suitable = 0
|
||||
if(max_n2)
|
||||
if(Environment.gas["nitrogen"] > max_n2)
|
||||
atmos_suitable = 0
|
||||
if(min_co2)
|
||||
if(Environment.gas["carbon_dioxide"] < min_co2)
|
||||
atmos_suitable = 0
|
||||
if(max_co2)
|
||||
if(Environment.gas["carbon_dioxide"] > max_co2)
|
||||
atmos_suitable = 0
|
||||
if(min_oxy && Environment.gas["oxygen"] < min_oxy)
|
||||
atmos_suitable = 0
|
||||
else if(max_oxy && Environment.gas["oxygen"] > max_oxy)
|
||||
atmos_suitable = 0
|
||||
else if(min_tox && Environment.gas["phoron"] < min_tox)
|
||||
atmos_suitable = 0
|
||||
else if(max_tox && Environment.gas["phoron"] > max_tox)
|
||||
atmos_suitable = 0
|
||||
else if(min_n2 && Environment.gas["nitrogen"] < min_n2)
|
||||
atmos_suitable = 0
|
||||
else if(max_n2 && Environment.gas["nitrogen"] > max_n2)
|
||||
atmos_suitable = 0
|
||||
else if(min_co2 && Environment.gas["carbon_dioxide"] < min_co2)
|
||||
atmos_suitable = 0
|
||||
else if(max_co2 && Environment.gas["carbon_dioxide"] > max_co2)
|
||||
atmos_suitable = 0
|
||||
|
||||
//Atmos effect
|
||||
if(bodytemperature < minbodytemp)
|
||||
@@ -288,12 +223,64 @@
|
||||
apply_damage(unsuitable_atoms_damage, OXY, used_weapon = "Atmosphere")
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/think()
|
||||
..()
|
||||
handle_foodscanning()
|
||||
if(!stop_automated_movement && wander && !anchored)
|
||||
if(isturf(loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
|
||||
if(turns_since_move >= turns_per_move && !(stop_automated_movement_when_pulled && pulledby)) //Some animals don't move when pulled
|
||||
var/moving_to = 0 // otherwise it always picks 4, fuck if I know. Did I mention fuck BYOND
|
||||
moving_to = pick(cardinal)
|
||||
set_dir(moving_to) //How about we turn them the direction they are moving, yay.
|
||||
Move(get_step(src,moving_to))
|
||||
turns_since_move = 0
|
||||
|
||||
//Speaking
|
||||
if(speak_chance && rand(0,200) < speak_chance)
|
||||
if(LAZYLEN(speak))
|
||||
if(LAZYLEN(emote_hear) || LAZYLEN(emote_see))
|
||||
var/length = speak.len
|
||||
if(emote_hear && emote_hear.len)
|
||||
length += emote_hear.len
|
||||
if(emote_see && emote_see.len)
|
||||
length += emote_see.len
|
||||
var/randomValue = rand(1,length)
|
||||
if(randomValue <= speak.len)
|
||||
say(pick(speak))
|
||||
else
|
||||
randomValue -= speak.len
|
||||
if(emote_see && randomValue <= emote_see.len)
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
else
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
else
|
||||
say(pick(speak))
|
||||
else
|
||||
if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len))
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len))
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
if((emote_hear && emote_hear.len) && (emote_see && emote_see.len))
|
||||
var/length = emote_hear.len + emote_see.len
|
||||
var/pick = rand(1,length)
|
||||
if(pick <= emote_see.len)
|
||||
visible_emote("[pick(emote_see)].",0)
|
||||
else
|
||||
audible_emote("[pick(emote_hear)].",0)
|
||||
speak_audio()
|
||||
|
||||
if (can_nap)
|
||||
if (resting)
|
||||
if (prob(1))
|
||||
fall_asleep()
|
||||
else
|
||||
if (!stat || prob(0.5))
|
||||
wake_up()
|
||||
|
||||
/mob/living/simple_animal/proc/handle_supernatural()
|
||||
if(purge)
|
||||
purge -= 1
|
||||
|
||||
|
||||
|
||||
//Simple reagent processing for simple animals
|
||||
//This allows animals to digest food, and only food
|
||||
//Most drugs, poisons etc, are designed to work on carbons and affect many values a simple animal doesnt have
|
||||
@@ -337,7 +324,7 @@
|
||||
else return 2//hungry
|
||||
|
||||
/mob/living/simple_animal/gib()
|
||||
..(icon_gib,1)
|
||||
..(icon_gib, 1)
|
||||
|
||||
/mob/living/simple_animal/emote(var/act, var/type, var/desc)
|
||||
if(act)
|
||||
@@ -589,29 +576,18 @@ mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
|
||||
scan_interval = min_scan_interval
|
||||
stop_automated_movement = 1
|
||||
|
||||
if (istype(movement_target.loc, /turf))
|
||||
walk_to(src,movement_target,0, seek_move_delay)//Stand ontop of food
|
||||
if (isturf(movement_target.loc))
|
||||
walk_to(src, movement_target, 0, DS2TICKS(seek_move_delay)) //Stand ontop of food
|
||||
else
|
||||
walk_to(src,movement_target.loc,1, seek_move_delay)//Don't stand ontop of people
|
||||
walk_to(src, get_turf(movement_target), 1, DS2TICKS(seek_move_delay)) //Don't stand ontop of people
|
||||
|
||||
|
||||
|
||||
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 (movement_target)
|
||||
set_dir(get_dir(src, movement_target))
|
||||
|
||||
if(isturf(movement_target.loc) && Adjacent(get_turf(movement_target), src))
|
||||
UnarmedAttack(movement_target)
|
||||
if (get_turf(movement_target) == src.loc)
|
||||
set_dir(pick(1,2,4,8,1,1))//Face a random direction when eating, but mostly upwards
|
||||
if (get_turf(movement_target) == loc)
|
||||
set_dir(pick(NORTH, SOUTH, EAST, WEST, NORTH, NORTH))//Face a random direction when eating, but mostly upwards
|
||||
else if(ishuman(movement_target.loc) && Adjacent(src, get_turf(movement_target)) && prob(10))
|
||||
beg(movement_target, movement_target.loc)
|
||||
else
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).",ckey=key_name(src))
|
||||
|
||||
/mob/Login()
|
||||
|
||||
player_list |= src
|
||||
update_Login_details()
|
||||
world.update_status()
|
||||
SSfeedback.update_status()
|
||||
|
||||
client.images = null //remove the images such as AIs being unable to see runes
|
||||
client.screen = null //remove hud items just in case
|
||||
if(hud_used) qdel(hud_used) //remove the hud objects
|
||||
client.images.Cut() //remove the images such as AIs being unable to see runes
|
||||
client.screen.Cut() //remove hud items just in case
|
||||
if(hud_used)
|
||||
qdel(hud_used) //remove the hud objects
|
||||
hud_used = new /datum/hud(src)
|
||||
|
||||
disconnect_time = null
|
||||
@@ -48,3 +48,4 @@
|
||||
|
||||
//set macro to normal incase it was overriden (like cyborg currently does)
|
||||
winset(src, null, "mainwindow.macro=macro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5")
|
||||
MOB_STOP_THINKING(src)
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
player_list -= src
|
||||
disconnect_time = world.realtime
|
||||
log_access("Logout: [key_name(src)]",ckey=key_name(src))
|
||||
SSfeedback.update_status()
|
||||
|
||||
if(admin_datums[src.ckey])
|
||||
if (SSticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
|
||||
var/admins_number = 0
|
||||
var/admins_number_afk = 0
|
||||
for (var/client/C)
|
||||
for (var/client/C in clients)
|
||||
if (C.holder && (C.holder.rights & (R_MOD|R_ADMIN)))
|
||||
admins_number++
|
||||
if (C.is_afk())
|
||||
@@ -21,5 +23,8 @@
|
||||
else if ((admins_number - admins_number_afk) <= 0)
|
||||
post_webhook_event(WEBHOOK_ADMIN, list("title"="Admin has logged out", "message"="**[key_name(src)]** logged out - only AFK admins _([admins_number_afk])_ are online."))
|
||||
discord_bot.send_to_admins("[key_name(src)] logged out - only AFK admins ([admins_number_afk]) are online.")
|
||||
|
||||
if (mob_thinks)
|
||||
MOB_START_THINKING(src)
|
||||
..()
|
||||
return 1
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
var/atom/movable/AM = src.loc
|
||||
LAZYREMOVE(AM.contained_mobs, src)
|
||||
|
||||
MOB_STOP_THINKING(src)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -61,13 +63,16 @@
|
||||
spell_masters = null
|
||||
zone_sel = null
|
||||
|
||||
/mob/New()
|
||||
/mob/Initialize()
|
||||
. = ..()
|
||||
mob_list += src
|
||||
if(stat == DEAD)
|
||||
dead_mob_list += src
|
||||
else
|
||||
living_mob_list += src
|
||||
..()
|
||||
|
||||
if (!ckey && mob_thinks)
|
||||
MOB_START_THINKING(src)
|
||||
|
||||
/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
|
||||
|
||||
|
||||
@@ -222,3 +222,5 @@
|
||||
|
||||
gfi_layer_rotation = GFI_ROTATION_DEFDIR
|
||||
var/disconnect_time = null//Time of client loss, set by Logout(), for timekeeping
|
||||
|
||||
var/mob_thinks = TRUE
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/mob/Life()
|
||||
..()
|
||||
if(spell_masters && spell_masters.len)
|
||||
if(LAZYLEN(spell_masters))
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
spell_master.update_spells(0, src)
|
||||
|
||||
|
||||
+3
-2
@@ -321,7 +321,7 @@ var/list/world_api_rate_limit = list()
|
||||
D.associate(directory[ckey])
|
||||
|
||||
/world/proc/update_status()
|
||||
var/s = ""
|
||||
var/list/s = list()
|
||||
|
||||
if (config && config.server_name)
|
||||
s += "<b>[config.server_name]</b> — "
|
||||
@@ -363,13 +363,14 @@ var/list/world_api_rate_limit = list()
|
||||
else if (n > 0)
|
||||
features += "~[n] player"
|
||||
|
||||
|
||||
if (config && config.hostedby)
|
||||
features += "hosted by <b>[config.hostedby]</b>"
|
||||
|
||||
if (features)
|
||||
s += ": [list2text(features, ", ")]"
|
||||
|
||||
s = s.Join()
|
||||
|
||||
/* does this help? I do not know */
|
||||
if (src.status != s)
|
||||
src.status = s
|
||||
|
||||
Reference in New Issue
Block a user