Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13
This commit is contained in:
@@ -93,6 +93,7 @@
|
||||
//Mob AI Status
|
||||
|
||||
//Hostile simple animals
|
||||
//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm
|
||||
#define AI_ON 1
|
||||
#define AI_IDLE 2
|
||||
#define AI_OFF 3
|
||||
|
||||
@@ -18,13 +18,16 @@ Ask ninjanomnom if they're around
|
||||
#define RAD_TOX_COEFFICIENT 0.05 // Toxin damage per tick coefficient
|
||||
|
||||
#define RAD_MOB_SAFE 300 // How much stored radiation in a mob with no ill effects
|
||||
#define RAD_MOB_KNOCKDOWN 1500 // How much stored radiation to start stunning
|
||||
// If (mutate*2<knockdown) then monkeys will sometimes turn into gorillas before being knocked down
|
||||
// otherwise they only turn into gorillas *after* being knocked down
|
||||
#define RAD_MOB_MUTATE 800 // How much stored radiation to check for mutation
|
||||
#define RAD_MOB_HAIRLOSS 500 // How much stored radiation to check for hair loss
|
||||
|
||||
#define RAD_KNOCKDOWN_TIME 200 // How much knockdown to apply
|
||||
#define RAD_MOB_KNOCKDOWN 2000 // How much stored radiation to check for stunning
|
||||
#define RAD_MOB_KNOCKDOWN_PROB 1 // Chance of knockdown per tick when over threshold
|
||||
#define RAD_MOB_KNOCKDOWN_AMOUNT 3 // Amount of knockdown when it occurs
|
||||
|
||||
#define RAD_MOB_VOMIT 1500 // The amount of radiation to check for vomitting
|
||||
#define RAD_MOB_VOMIT_PROB 1 // Chance per tick of vomitting
|
||||
|
||||
#define RAD_MOB_MUTATE 1000 // How much stored radiation to check for mutation
|
||||
#define RAD_MOB_HAIRLOSS 500 // How much stored radiation to check for hair loss
|
||||
|
||||
#define RAD_NO_INSULATION 1.0 // For things that shouldn't become irradiated for whatever reason
|
||||
#define RAD_VERY_LIGHT_INSULATION 0.9 // What girders have
|
||||
|
||||
@@ -19,7 +19,7 @@ GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
|
||||
GLOBAL_LIST_EMPTY(ai_list)
|
||||
GLOBAL_LIST_EMPTY(pai_list)
|
||||
GLOBAL_LIST_EMPTY(available_ai_shells)
|
||||
GLOBAL_LIST_EMPTY(simple_animals)
|
||||
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define
|
||||
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
|
||||
|
||||
GLOBAL_LIST_EMPTY(language_datum_instances)
|
||||
|
||||
+11
-16
@@ -22,7 +22,6 @@
|
||||
else
|
||||
A.move_camera_by_click()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
|
||||
if(world.time <= next_click)
|
||||
return
|
||||
@@ -36,20 +35,16 @@
|
||||
return
|
||||
|
||||
var/turf/pixel_turf = get_turf_pixel(A)
|
||||
var/turf_visible
|
||||
if(pixel_turf)
|
||||
turf_visible = GLOB.cameranet.checkTurfVis(pixel_turf)
|
||||
if(!turf_visible)
|
||||
if(istype(loc, /obj/item/device/aicard) && (pixel_turf in view(client.view, loc)))
|
||||
turf_visible = TRUE
|
||||
else
|
||||
if (pixel_turf.obscured)
|
||||
log_admin("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)])")
|
||||
message_admins("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
|
||||
if(REALTIMEOFDAY >= chnotify + 9000)
|
||||
chnotify = REALTIMEOFDAY
|
||||
send2irc_adminless_only("NOCHEAT", "[key_name(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)]))")
|
||||
return
|
||||
if(isnull(pixel_turf))
|
||||
return
|
||||
if(!can_see(A))
|
||||
message_admins("[key_name_admin(src)] might be running a modified client! (failed can_see on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
|
||||
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A]([COORD(pixel_turf)]))"
|
||||
log_admin(message)
|
||||
if(REALTIMEOFDAY >= chnotify + 9000)
|
||||
chnotify = REALTIMEOFDAY
|
||||
send2irc_adminless_only("NOCHEAT", message)
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
@@ -74,7 +69,7 @@
|
||||
if(world.time <= next_move)
|
||||
return
|
||||
|
||||
if(aicamera.in_camera_mode && pixel_turf && turf_visible)
|
||||
if(aicamera.in_camera_mode)
|
||||
aicamera.camera_mode_off()
|
||||
aicamera.captureimage(pixel_turf, usr)
|
||||
return
|
||||
|
||||
@@ -243,7 +243,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/obj/screen/alert/fire/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.canmove)
|
||||
@@ -559,7 +559,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
|
||||
/obj/screen/alert/restrained/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if((L.canmove) && (L.last_special <= world.time))
|
||||
@@ -567,7 +567,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
|
||||
/obj/screen/alert/restrained/buckled/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.last_special <= world.time)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
SUBSYSTEM_DEF(idlenpcpool)
|
||||
name = "Idling NPC Pool"
|
||||
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
|
||||
priority = 10
|
||||
wait = 60
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
|
||||
var/list/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/idlenpcpool/stat_entry()
|
||||
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
|
||||
..("IdleNPCS:[idlelist.len]")
|
||||
|
||||
/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE)
|
||||
|
||||
if (!resumed)
|
||||
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
|
||||
src.currentrun = idlelist.Copy()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
|
||||
while(currentrun.len)
|
||||
var/mob/living/simple_animal/SA = currentrun[currentrun.len]
|
||||
--currentrun.len
|
||||
|
||||
if(!SA.ckey)
|
||||
if(SA.stat != DEAD)
|
||||
SA.handle_automated_movement()
|
||||
if(SA.stat != DEAD)
|
||||
SA.consider_wakeup()
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
@@ -37,7 +37,8 @@ SUBSYSTEM_DEF(npcpool)
|
||||
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
|
||||
|
||||
if (!resumed)
|
||||
src.currentrun = GLOB.simple_animals.Copy()
|
||||
var/list/activelist = GLOB.simple_animals[AI_ON]
|
||||
src.currentrun = activelist.Copy()
|
||||
stage = PROCESSING_SIMPLES
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
list/atom/output_atoms
|
||||
|
||||
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
mid_length (num) The length to wait between playing mid_sounds
|
||||
|
||||
start_sound (soundfile) Played before starting the mid_sounds loop
|
||||
start_length (num) How long to wait before starting the main loop after playing start_sound
|
||||
|
||||
end_sound (soundfile) The sound played after the main loop has concluded
|
||||
|
||||
chance (num) Chance per loop to play a mid_sound
|
||||
volume (num) Sound output volume
|
||||
muted (bool) Private. Used to stop the sound loop.
|
||||
max_loops (num) The max amount of loops to run for.
|
||||
*/
|
||||
/datum/looping_sound
|
||||
var/list/atom/output_atoms
|
||||
var/mid_sounds
|
||||
var/mid_length
|
||||
var/start_sound
|
||||
var/start_length
|
||||
var/end_sound
|
||||
var/chance
|
||||
var/volume
|
||||
var/muted = TRUE
|
||||
var/max_loops
|
||||
|
||||
/datum/looping_sound/New(list/_output_atoms, start_immediately=FALSE)
|
||||
if(!mid_sounds)
|
||||
WARNING("A looping sound datum was created without sounds to play.")
|
||||
return
|
||||
|
||||
if(_output_atoms)
|
||||
output_atoms = _output_atoms
|
||||
else
|
||||
output_atoms = list()
|
||||
|
||||
if(start_immediately)
|
||||
start()
|
||||
|
||||
/datum/looping_sound/Destroy()
|
||||
stop()
|
||||
output_atoms = null
|
||||
return ..()
|
||||
|
||||
/datum/looping_sound/proc/start()
|
||||
if(!muted)
|
||||
return
|
||||
muted = FALSE
|
||||
on_start()
|
||||
|
||||
/datum/looping_sound/proc/stop()
|
||||
if(muted)
|
||||
return
|
||||
muted = TRUE
|
||||
|
||||
/datum/looping_sound/proc/sound_loop(looped=0)
|
||||
if(muted || (max_loops && looped > max_loops))
|
||||
on_stop(looped)
|
||||
return
|
||||
if(!chance || prob(chance))
|
||||
play(get_sound(looped))
|
||||
addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length)
|
||||
|
||||
/datum/looping_sound/proc/play(soundfile)
|
||||
var/list/atoms_cache = output_atoms
|
||||
for(var/i in 1 to atoms_cache.len)
|
||||
var/atom/thing = atoms_cache[i]
|
||||
playsound(thing, soundfile, volume)
|
||||
|
||||
/datum/looping_sound/proc/get_sound(looped, _mid_sounds)
|
||||
if(!_mid_sounds)
|
||||
. = mid_sounds
|
||||
else
|
||||
. = _mid_sounds
|
||||
while(!isfile(.) && !isnull(.))
|
||||
. = pickweight(.)
|
||||
|
||||
/datum/looping_sound/proc/on_start()
|
||||
var/start_wait = 0
|
||||
if(start_sound)
|
||||
play(start_sound)
|
||||
start_wait = start_length
|
||||
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
|
||||
|
||||
/datum/looping_sound/proc/on_stop(looped)
|
||||
if(end_sound)
|
||||
play(end_sound)
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/looping_sound/showering
|
||||
start_sound = 'sound/machines/shower/shower_start.ogg'
|
||||
start_length = 2
|
||||
mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1)
|
||||
mid_length = 10
|
||||
end_sound = 'sound/machines/shower/shower_end.ogg'
|
||||
volume = 25
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -89,7 +89,7 @@
|
||||
continue
|
||||
thing.rad_act(strength)
|
||||
|
||||
var/static/list/blacklisted = typecacheof(list(/turf, /obj/structure/cable, /obj/machinery/atmospherics))
|
||||
var/static/list/blacklisted = typecacheof(list(/turf, /mob, /obj/structure/cable, /obj/machinery/atmospherics))
|
||||
if(!can_contaminate || blacklisted[thing.type])
|
||||
continue
|
||||
if(prob((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1/(steps*range_modifier), 1))) // Only stronk rads get to have little baby rads
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
beckon(AM)
|
||||
|
||||
/obj/effect/clockwork/city_of_cogs_rift/proc/beckon(atom/movable/AM)
|
||||
AM.visible_message("<span class='danger'>[AM] passes through [src]!</span>", ignore_mob = AM)
|
||||
AM.visible_message("<span class='danger'>[AM] passes through [src]!</span>", ignored_mob = AM)
|
||||
AM.forceMove(pick(!is_servant_of_ratvar(AM) ? GLOB.city_of_cogs_spawns : GLOB.servant_spawns))
|
||||
AM.visible_message("<span class='danger'>[AM] materializes from the air!</span>", \
|
||||
"<span class='boldannounce'>You pass through [src] and appear [is_servant_of_ratvar(AM) ? "back at the City of Cogs" : "somewhere unfamiliar. Looks like it was a one-way trip.."].</span>")
|
||||
|
||||
@@ -45,7 +45,11 @@
|
||||
/datum/game_mode/wizard/check_finished()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
|
||||
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
|
||||
return FALSE
|
||||
|
||||
if(SSevents.wizardmode) //If summon events was active, turn it off
|
||||
SSevents.toggleWizardmode()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define RADIATION_DURATION_MAX 30
|
||||
#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
|
||||
|
||||
#define RADIATION_IRRADIATION_MULTIPLIER 10 //multiplier for how much radiation a test subject recieves
|
||||
#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject recieves
|
||||
|
||||
#define SCANNER_ACTION_SE 1
|
||||
#define SCANNER_ACTION_UI 2
|
||||
|
||||
@@ -798,7 +798,7 @@
|
||||
// Otherwise it will runtime with this kind of error: null.Topic()
|
||||
if(!nowindow)
|
||||
..()
|
||||
if(usr.incapacitated() && !IsAdminGhost(usr))
|
||||
if(!usr.canUseTopic(src) && !IsAdminGhost(usr))
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
if(href_list["close"])
|
||||
|
||||
@@ -617,7 +617,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
P.show_recieved_message(msg,src)
|
||||
if(!multiple)
|
||||
show_to_ghosts(user,msg)
|
||||
log_talk(user,"[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [key_name(P,null,TRUE)]",LOGPDA)
|
||||
log_talk(user,"[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [P.name]",LOGPDA)
|
||||
else
|
||||
if(!multiple)
|
||||
to_chat(user, "<span class='notice'>ERROR: Server isn't responding.</span>")
|
||||
|
||||
@@ -124,6 +124,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
a = copytext(sanitize(a), 1, 20)
|
||||
gpstag = a
|
||||
. = TRUE
|
||||
name = "global positioning system ([gpstag])"
|
||||
|
||||
if("power")
|
||||
toggletracking(usr)
|
||||
. = TRUE
|
||||
@@ -134,15 +136,6 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
global_mode = !global_mode
|
||||
. = TRUE
|
||||
|
||||
/obj/item/device/gps/Topic(href, href_list)
|
||||
..()
|
||||
if(href_list["tag"] )
|
||||
var/a = input("Please enter desired tag.", name, gpstag) as text
|
||||
a = uppertext(copytext(sanitize(a), 1, 5))
|
||||
if(in_range(src, usr))
|
||||
gpstag = a
|
||||
name = "global positioning system ([gpstag])"
|
||||
attack_self(usr)
|
||||
|
||||
/obj/item/device/gps/science
|
||||
icon_state = "gps-s"
|
||||
|
||||
@@ -109,7 +109,6 @@
|
||||
new /obj/item/clothing/gloves/krav_maga/sec(src)
|
||||
new /obj/item/door_remote/head_of_security(src)
|
||||
new /obj/item/gun/ballistic/shotgun/automatic/combat/compact(src)
|
||||
new /obj/item/pinpointer/crew(src)
|
||||
|
||||
/obj/structure/closet/secure_closet/security
|
||||
name = "security officer's locker"
|
||||
|
||||
@@ -68,14 +68,15 @@
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/machinery/manned_turret/process()
|
||||
if(!LAZYLEN(buckled_mobs))
|
||||
if (!update_positioning())
|
||||
return PROCESS_KILL
|
||||
update_positioning()
|
||||
|
||||
/obj/machinery/manned_turret/proc/update_positioning()
|
||||
if (!LAZYLEN(buckled_mobs))
|
||||
return FALSE
|
||||
var/mob/living/controller = buckled_mobs[1]
|
||||
if(!istype(controller))
|
||||
return
|
||||
return FALSE
|
||||
var/client/C = controller.client
|
||||
if(C)
|
||||
var/atom/A = C.mouseObject
|
||||
@@ -143,7 +144,7 @@
|
||||
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
|
||||
|
||||
/obj/machinery/manned_turret/proc/fire_helper(mob/user)
|
||||
if(user.incapacitated())
|
||||
if(user.incapacitated() || !(user in buckled_mobs))
|
||||
return
|
||||
update_positioning() //REFRESH MOUSE TRACKING!!
|
||||
var/turf/targets_from = get_turf(src)
|
||||
|
||||
@@ -199,7 +199,15 @@
|
||||
var/obj/effect/mist/mymist = null
|
||||
var/ismist = 0 //needs a var so we can make it linger~
|
||||
var/watertemp = "normal" //freezing, normal, or boiling
|
||||
var/datum/looping_sound/showering/soundloop
|
||||
|
||||
/obj/machinery/shower/Initialize()
|
||||
. = ..()
|
||||
soundloop = new(list(src), FALSE)
|
||||
|
||||
/obj/machinery/shower/Destroy()
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/effect/mist
|
||||
name = "mist"
|
||||
@@ -215,6 +223,7 @@
|
||||
update_icon()
|
||||
add_fingerprint(M)
|
||||
if(on)
|
||||
soundloop.start()
|
||||
wash_turf()
|
||||
for(var/atom/movable/G in loc)
|
||||
if(isliving(G))
|
||||
@@ -223,6 +232,7 @@
|
||||
else if(isobj(G)) // Skip the light objects
|
||||
wash_obj(G)
|
||||
else
|
||||
soundloop.stop()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/tile = loc
|
||||
tile.MakeSlippery(min_wet_time = 5, wet_time_to_add = 1)
|
||||
@@ -368,6 +378,15 @@
|
||||
else
|
||||
L.clean_blood()
|
||||
|
||||
/obj/machinery/shower/proc/contamination_cleanse(atom/movable/thing)
|
||||
var/datum/component/radioactive/healthy_green_glow = thing.GetComponent(/datum/component/radioactive)
|
||||
if(!healthy_green_glow || QDELETED(healthy_green_glow))
|
||||
return
|
||||
var/strength = healthy_green_glow.strength
|
||||
if(strength <= RAD_BACKGROUND_RADIATION)
|
||||
qdel(healthy_green_glow)
|
||||
return
|
||||
healthy_green_glow.strength = max(strength-1, 0)
|
||||
|
||||
/obj/machinery/shower/process()
|
||||
if(on)
|
||||
@@ -377,6 +396,7 @@
|
||||
wash_mob(AM)
|
||||
else if(isobj(AM))
|
||||
wash_obj(AM)
|
||||
contamination_cleanse(AM)
|
||||
|
||||
/obj/machinery/shower/deconstruct(disassembled = TRUE)
|
||||
new /obj/item/stack/sheet/metal (loc, 3)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
var/datum/excited_group/excited_group
|
||||
var/excited = 0
|
||||
var/recently_active = 0
|
||||
var/datum/gas_mixture/air
|
||||
var/datum/gas_mixture/turf/air
|
||||
|
||||
var/obj/effect/hotspot/active_hotspot
|
||||
var/atmos_cooldown = 0
|
||||
|
||||
@@ -65,22 +65,17 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
|
||||
//PV = nRT
|
||||
|
||||
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
|
||||
/datum/gas_mixture/proc/heat_capacity(data = MOLES) //joules per kelvin
|
||||
var/list/cached_gases = gases
|
||||
. = 0
|
||||
for(var/id in cached_gases)
|
||||
var/gas_data = cached_gases[id]
|
||||
. += gas_data[MOLES] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
|
||||
if(!. && temperature) //if temp isn't defined, this mixture isn't a vacuum like space is. it hasn't been filled with *anything* so we want it to take on the properties of whatever gas enters it
|
||||
. += HEAT_CAPACITY_VACUUM //however, if temp is defined but HC is still 0, then we want the mixture to behave like space does, as a heat sink
|
||||
. += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
|
||||
|
||||
|
||||
/datum/gas_mixture/proc/heat_capacity_archived() //joules per kelvin
|
||||
var/list/cached_gases = gases
|
||||
. = 0
|
||||
for(var/id in cached_gases)
|
||||
var/gas_data = cached_gases[id]
|
||||
. += gas_data[ARCHIVE] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
|
||||
/datum/gas_mixture/turf/heat_capacity()
|
||||
. = ..()
|
||||
if(!.)
|
||||
. += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
|
||||
|
||||
//prefer this in performance critical areas
|
||||
#define TOTAL_MOLES(cached_gases, out_var)\
|
||||
@@ -195,7 +190,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
amount = min(amount, sum) //Can not take more air than tile has!
|
||||
if(amount <= 0)
|
||||
return null
|
||||
var/datum/gas_mixture/removed = new
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
@@ -213,7 +208,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
ratio = min(ratio, 1)
|
||||
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/removed = new
|
||||
var/datum/gas_mixture/removed = new type
|
||||
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
|
||||
|
||||
removed.temperature = temperature
|
||||
@@ -228,7 +223,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
|
||||
/datum/gas_mixture/copy()
|
||||
var/list/cached_gases = gases
|
||||
var/datum/gas_mixture/copy = new
|
||||
var/datum/gas_mixture/copy = new type
|
||||
var/list/copy_gases = copy.gases
|
||||
|
||||
copy.temperature = temperature
|
||||
@@ -364,8 +359,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
sharer_temperature = sharer.temperature_archived
|
||||
var/temperature_delta = temperature_archived - sharer_temperature
|
||||
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = heat_capacity_archived()
|
||||
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archived()
|
||||
var/self_heat_capacity = heat_capacity(ARCHIVE)
|
||||
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE)
|
||||
|
||||
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
|
||||
var/heat = conduction_coefficient*temperature_delta* \
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
/datum/gas_mixture/immutable/merge()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/heat_capacity_archived()
|
||||
return heat_capacity()
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
garbage_collect()
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
if(!isnull(new_piping_layer))
|
||||
target_layer = new_piping_layer
|
||||
SSair.atmos_machinery += src
|
||||
if(mapload && !target)
|
||||
if(!target)
|
||||
reattach_to_layer()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
//Make sure are close enough for a valid connection
|
||||
if(new_port.loc != get_turf(src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//Perform the connection
|
||||
connected_port = new_port
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
//Engineering Mesons
|
||||
|
||||
#define MODE_NONE ""
|
||||
#define MODE_MESON "meson"
|
||||
#define MODE_TRAY "t-ray"
|
||||
#define MODE_RAD "radiation"
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine
|
||||
name = "engineering scanner goggles"
|
||||
desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, regardless of lighting condition. The T-ray Scanner mode lets you see underfloor objects such as cables and pipes."
|
||||
icon_state = "trayson-meson"
|
||||
desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, the T-ray Scanner mode lets you see underfloor objects such as cables and pipes, and the Radiation Scanner mode let's you see objects contaminated by radiation."
|
||||
icon_state = "trayson"
|
||||
actions_types = list(/datum/action/item_action/toggle_mode)
|
||||
origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3"
|
||||
|
||||
var/mesons_on = TRUE //if set to FALSE, these goggles work as t-ray scanners.
|
||||
vision_flags = NONE
|
||||
darkness_view = 2
|
||||
invis_view = SEE_INVISIBLE_LIVING
|
||||
|
||||
var/list/modes = list(MODE_NONE = MODE_MESON, MODE_MESON = MODE_TRAY, MODE_TRAY = MODE_RAD, MODE_RAD = MODE_NONE)
|
||||
var/mode = MODE_NONE
|
||||
var/range = 1
|
||||
|
||||
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/toggle_mode(mob/user, voluntary)
|
||||
mesons_on = !mesons_on
|
||||
mode = modes[mode]
|
||||
to_chat(user, "<span class='[voluntary ? "notice":"warning"]'>[voluntary ? "You turn the goggles":"The goggles turn"] [mode ? "to [mode] mode":"off"][voluntary ? ".":"!"]</span>")
|
||||
|
||||
if(!mesons_on)
|
||||
vision_flags = 0
|
||||
darkness_view = 2
|
||||
invis_view = SEE_INVISIBLE_LIVING
|
||||
lighting_alpha = null
|
||||
if(voluntary)
|
||||
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[T-Ray].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The goggles abruptly toggle to \[T-Ray] mode!</span>")
|
||||
else
|
||||
vision_flags = SEE_TURFS
|
||||
darkness_view = 1
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
if(voluntary)
|
||||
to_chat(user, "<span class='notice'>You toggle the goggles' scanning mode to \[Meson].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The goggles abruptly toggle to \[Meson] mode!</span>")
|
||||
switch(mode)
|
||||
if(MODE_MESON)
|
||||
vision_flags = SEE_TURFS
|
||||
darkness_view = 1
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
|
||||
if(MODE_TRAY) //undoes the last mode, meson
|
||||
vision_flags = NONE
|
||||
darkness_view = 2
|
||||
lighting_alpha = null
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -55,7 +58,7 @@
|
||||
toggle_mode(user, TRUE)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/process()
|
||||
if(mesons_on)
|
||||
if(mode == MODE_MESON)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && T.z == ZLEVEL_MINING)
|
||||
toggle_mode(loc)
|
||||
@@ -63,11 +66,13 @@
|
||||
|
||||
if(!ishuman(loc))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/user = loc
|
||||
if(user.glasses != src)
|
||||
if(user.glasses != src || !user.client)
|
||||
return
|
||||
scan()
|
||||
if(mode == MODE_TRAY)
|
||||
scan()
|
||||
else if(mode == MODE_RAD)
|
||||
show_rads()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/scan()
|
||||
for(var/turf/T in range(range, loc))
|
||||
@@ -79,17 +84,40 @@
|
||||
flick_sonar(O)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/flick_sonar(obj/pipe)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
var/image/I = new(loc = get_turf(pipe))
|
||||
var/mutable_appearance/MA = new(pipe)
|
||||
var/mob/M = loc
|
||||
var/image/I = new(loc = get_turf(pipe))
|
||||
var/mutable_appearance/MA = new(pipe)
|
||||
MA.alpha = 128
|
||||
I.appearance = MA
|
||||
flick_overlay(I, list(M.client), 8)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/show_rads()
|
||||
var/mob/living/carbon/human/user = loc
|
||||
var/list/rad_places = list()
|
||||
for(var/datum/component/radioactive/thing in SSradiation.processing)
|
||||
var/atom/owner = thing.parent
|
||||
var/turf/place = get_turf(owner)
|
||||
if(rad_places[place])
|
||||
rad_places[place] += thing.strength
|
||||
else
|
||||
rad_places[place] = thing.strength
|
||||
|
||||
for(var/i in rad_places)
|
||||
var/turf/place = i
|
||||
if(get_dist(user, place) >= range*2) //Rads are easier to see than wires under the floor
|
||||
continue
|
||||
var/strength = round(rad_places[i] / 1000, 0.1)
|
||||
var/image/pic = new(loc = place)
|
||||
var/mutable_appearance/MA = new()
|
||||
MA.alpha = 128
|
||||
I.appearance = MA
|
||||
if(M.client)
|
||||
flick_overlay(I, list(M.client), 8)
|
||||
MA.maptext = "[strength]k"
|
||||
MA.color = "#64C864"
|
||||
MA.layer = AREA_LAYER
|
||||
pic.appearance = MA
|
||||
flick_overlay(pic, list(user.client), 8)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/update_icon()
|
||||
icon_state = mesons_on ? "trayson-meson" : "trayson-tray"
|
||||
icon_state = "[initial(icon_state)]-[mode]"
|
||||
if(istype(loc, /mob/living/carbon/human/))
|
||||
var/mob/living/carbon/human/user = loc
|
||||
if(user.glasses == src)
|
||||
@@ -98,35 +126,13 @@
|
||||
/obj/item/clothing/glasses/meson/engine/tray //atmos techs have lived far too long without tray goggles while those damned engineers get their dual-purpose gogles all to themselves
|
||||
name = "optical t-ray scanner"
|
||||
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
|
||||
icon_state = "trayson-tray_off"
|
||||
origin_tech = "materials=3;magnets=2;engineering=2"
|
||||
|
||||
mesons_on = FALSE
|
||||
var/on = FALSE
|
||||
vision_flags = 0
|
||||
darkness_view = 2
|
||||
invis_view = SEE_INVISIBLE_LIVING
|
||||
range = 2
|
||||
|
||||
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray/process()
|
||||
if(!on)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray/update_icon()
|
||||
icon_state = "trayson-tray[on ? "" : "_off"]"
|
||||
if(istype(loc, /mob/living/carbon/human/))
|
||||
var/mob/living/carbon/human/user = loc
|
||||
if(user.glasses == src)
|
||||
user.update_inv_glasses()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray/toggle_mode(mob/user, voluntary)
|
||||
on = !on
|
||||
|
||||
to_chat(user, "<span class='[voluntary ? "notice":"warning"]'>[voluntary ? "You turn the goggles":"The goggles turn"] [on ? "on":"off"][voluntary ? ".":"!"]</span>")
|
||||
|
||||
update_icon()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
#undef MODE_NONE
|
||||
#undef MODE_MESON
|
||||
#undef MODE_TRAY
|
||||
#undef MODE_RAD
|
||||
@@ -119,7 +119,7 @@
|
||||
L.anchored = TRUE
|
||||
if(ishostile(L))
|
||||
var/mob/living/simple_animal/hostile/H = L
|
||||
H.AIStatus = AI_OFF
|
||||
H.toggle_ai(AI_OFF)
|
||||
H.LoseTarget()
|
||||
|
||||
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L)
|
||||
@@ -128,4 +128,4 @@
|
||||
frozen_mobs -= L
|
||||
if(ishostile(L))
|
||||
var/mob/living/simple_animal/hostile/H = L
|
||||
H.AIStatus = initial(H.AIStatus)
|
||||
H.toggle_ai(initial(H.AIStatus))
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
SetCollectBehavior()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/sentience_act()
|
||||
AIStatus = AI_OFF
|
||||
..()
|
||||
check_friendly_fire = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
@@ -1144,11 +1144,14 @@
|
||||
radiation = 0
|
||||
return TRUE
|
||||
|
||||
if(radiation > RAD_MOB_KNOCKDOWN)
|
||||
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
|
||||
if(!H.IsKnockdown())
|
||||
H.emote("collapse")
|
||||
H.Knockdown(RAD_KNOCKDOWN_TIME)
|
||||
H.Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
|
||||
to_chat(H, "<span class='danger'>You feel weak.</span>")
|
||||
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
H.vomit(10, TRUE)
|
||||
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
@@ -1158,10 +1161,9 @@
|
||||
H.domutcheck()
|
||||
|
||||
if(radiation > RAD_MOB_HAIRLOSS)
|
||||
if(prob(15))
|
||||
if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || (HAIR in species_traits))
|
||||
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
|
||||
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
|
||||
if(prob(15) && !(H.hair_style == "Bald") && (HAIR in species_traits))
|
||||
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
|
||||
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
|
||||
|
||||
/datum/species/proc/go_bald(mob/living/carbon/human/H)
|
||||
if(QDELETED(H)) //may be called from a timer
|
||||
|
||||
@@ -63,7 +63,7 @@ There are several things that need to be remembered:
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/update_fire()
|
||||
..("Standing")
|
||||
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
|
||||
|
||||
|
||||
/* --------------------------------------- */
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
/mob/living/carbon/monkey/handle_mutations_and_radiation()
|
||||
if(radiation)
|
||||
if(radiation > RAD_MOB_KNOCKDOWN)
|
||||
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
|
||||
if(!IsKnockdown())
|
||||
emote("collapse")
|
||||
Knockdown(200)
|
||||
Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
@@ -39,6 +39,8 @@
|
||||
if(radiation > RAD_MOB_MUTATE * 2 && prob(50))
|
||||
gorillize()
|
||||
return
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
vomit(10, TRUE)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
|
||||
|
||||
@@ -41,39 +41,28 @@
|
||||
clear_fullscreen("eye_damage")
|
||||
|
||||
/mob/living/carbon/adjust_drugginess(amount)
|
||||
var/old_druggy = druggy
|
||||
if(amount>0)
|
||||
druggy += amount
|
||||
if(!old_druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else if(old_druggy)
|
||||
druggy = max(druggy+amount, 0)
|
||||
if(!druggy)
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
druggy = max(druggy+amount, 0)
|
||||
if(druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
|
||||
/mob/living/carbon/set_drugginess(amount)
|
||||
var/old_druggy = druggy
|
||||
druggy = amount
|
||||
if(amount>0)
|
||||
if(!old_druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else if(old_druggy)
|
||||
druggy = max(amount, 0)
|
||||
if(druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
|
||||
/mob/living/carbon/adjust_disgust(amount)
|
||||
var/old_disgust = disgust
|
||||
if(amount>0)
|
||||
disgust = min(disgust+amount, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
else if(old_disgust)
|
||||
disgust = max(disgust+amount, 0)
|
||||
disgust = Clamp(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
/mob/living/carbon/set_disgust(amount)
|
||||
if(amount >= 0)
|
||||
disgust = amount
|
||||
disgust = Clamp(amount, 0, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
/mob/living/carbon/cure_blind()
|
||||
if(disabilities & BLIND)
|
||||
|
||||
@@ -586,7 +586,7 @@
|
||||
if(!force_moving)
|
||||
..(pressure_difference, direction, pressure_resistance_prob_delta)
|
||||
|
||||
/mob/living/proc/can_resist()
|
||||
/mob/living/can_resist()
|
||||
return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE))
|
||||
|
||||
/mob/living/verb/resist()
|
||||
|
||||
@@ -813,12 +813,16 @@
|
||||
return FALSE
|
||||
if(be_close && !in_range(M, src))
|
||||
return FALSE
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
//apc_override is needed here because AIs use their own APC when powerless
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
return FALSE
|
||||
return TRUE
|
||||
return can_see(M) //stop AIs from leaving windows open and using then after they lose vision
|
||||
|
||||
/mob/living/silicon/ai/proc/can_see(atom/A)
|
||||
if(isturf(loc)) //AI in core, check if on cameras
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
//apc_override is needed here because AIs use their own APC when depowered
|
||||
return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override
|
||||
//AI is carded/shunted
|
||||
//view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist
|
||||
return get_dist(src, A) <= client.view
|
||||
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
|
||||
|
||||
@@ -305,6 +305,7 @@
|
||||
/obj/item/device/multitool/cyborg,
|
||||
/obj/item/device/t_scanner,
|
||||
/obj/item/device/analyzer,
|
||||
/obj/item/device/geiger_counter,
|
||||
/obj/item/device/assembly/signaler/cyborg,
|
||||
/obj/item/areaeditor/blueprints/cyborg,
|
||||
/obj/item/device/electroadaptive_pseudocircuit,
|
||||
|
||||
@@ -348,7 +348,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM)
|
||||
if(ismob(AM))
|
||||
if(ismob(AM) && (on)) //only if its online
|
||||
if(prob(30)) //you're far more likely to trip on a honkbot
|
||||
var/mob/living/carbon/C = AM
|
||||
if(!istype(C) || !C || in_range(src, target))
|
||||
@@ -362,7 +362,8 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
"[C] leaps out of [src]'s way!")]</span>")
|
||||
C.Knockdown(10)
|
||||
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1, -1)
|
||||
speak("Honk!")
|
||||
if(!client)
|
||||
speak("Honk!")
|
||||
sensor_blink()
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
var/idle = 0
|
||||
var/isqueen = FALSE
|
||||
var/icon_base = "bee"
|
||||
var/static/beehometypecache = typecacheof(/obj/structure/beebox)
|
||||
var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
|
||||
@@ -118,7 +120,7 @@
|
||||
if(istype(A, /obj/machinery/hydroponics))
|
||||
var/obj/machinery/hydroponics/Hydro = A
|
||||
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
|
||||
wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
|
||||
wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -132,8 +134,9 @@
|
||||
if(target == beehome)
|
||||
var/obj/structure/beebox/BB = target
|
||||
forceMove(BB)
|
||||
toggle_ai(AI_IDLE)
|
||||
target = null
|
||||
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
|
||||
wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
|
||||
return //no don't attack the goddamm box
|
||||
else
|
||||
. = ..()
|
||||
@@ -157,7 +160,7 @@
|
||||
return
|
||||
|
||||
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
|
||||
wanted_objects -= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
|
||||
wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
|
||||
Hydro.recent_bee_visit = TRUE
|
||||
spawn(BEE_TRAY_RECENT_VISIT)
|
||||
if(Hydro)
|
||||
@@ -187,12 +190,13 @@
|
||||
if(loc == beehome)
|
||||
idle = min(100, ++idle)
|
||||
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
|
||||
toggle_ai(AI_ON)
|
||||
forceMove(beehome.drop_location())
|
||||
else
|
||||
idle = max(0, --idle)
|
||||
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
|
||||
if(!FindTarget())
|
||||
wanted_objects |= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
|
||||
wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home
|
||||
target = beehome
|
||||
if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
|
||||
for(var/obj/structure/beebox/BB in view(vision_range, src))
|
||||
@@ -285,3 +289,11 @@
|
||||
QDEL_NULL(queen)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/bees/consider_wakeup()
|
||||
if (beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets
|
||||
idle = min(100, ++idle)
|
||||
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
|
||||
toggle_ai(AI_ON)
|
||||
forceMove(beehome.drop_location())
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
|
||||
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
|
||||
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
|
||||
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
|
||||
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
|
||||
var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
|
||||
|
||||
@@ -88,7 +87,7 @@
|
||||
DestroySurroundings()
|
||||
if(!MoveToTarget(possible_targets)) //if we lose our target
|
||||
if(AIShouldSleep(possible_targets)) // we try to acquire a new one
|
||||
AIStatus = AI_IDLE // otherwise we go idle
|
||||
toggle_ai(AI_IDLE) // otherwise we go idle
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user)
|
||||
@@ -289,7 +288,7 @@
|
||||
target = null
|
||||
LoseSearchObjects()
|
||||
if(AIStatus == AI_IDLE)
|
||||
AIStatus = AI_ON
|
||||
toggle_ai(AI_ON)
|
||||
FindTarget()
|
||||
else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
|
||||
FindTarget()
|
||||
@@ -424,7 +423,7 @@
|
||||
if(AI_IDLE)
|
||||
if(FindTarget(possible_targets, 1))
|
||||
. = 1
|
||||
AIStatus = AI_ON //Wake up for more than one Life() cycle.
|
||||
toggle_ai(AI_ON) //Wake up for more than one Life() cycle.
|
||||
else
|
||||
. = 0
|
||||
|
||||
@@ -455,3 +454,9 @@
|
||||
if(!value)
|
||||
value = initial(search_objects)
|
||||
search_objects = value
|
||||
|
||||
/mob/living/simple_animal/hostile/consider_wakeup()
|
||||
..()
|
||||
if(AIStatus == AI_IDLE && FindTarget(ListTargets(), 1))
|
||||
toggle_ai(AI_ON)
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@
|
||||
var/dextrous_hud_type = /datum/hud/dextrous
|
||||
var/datum/personal_crafting/handcrafting
|
||||
|
||||
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
|
||||
|
||||
var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check.
|
||||
|
||||
//domestication
|
||||
var/tame = 0
|
||||
|
||||
@@ -89,7 +93,7 @@
|
||||
|
||||
/mob/living/simple_animal/Initialize()
|
||||
. = ..()
|
||||
GLOB.simple_animals += src
|
||||
GLOB.simple_animals[AIStatus] += src
|
||||
handcrafting = new()
|
||||
if(gender == PLURAL)
|
||||
gender = pick(MALE,FEMALE)
|
||||
@@ -102,7 +106,7 @@
|
||||
verbs |= /mob/living/proc/animal_nom
|
||||
|
||||
/mob/living/simple_animal/Destroy()
|
||||
GLOB.simple_animals -= src
|
||||
GLOB.simple_animals[AIStatus] -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/updatehealth()
|
||||
@@ -422,7 +426,7 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
|
||||
return
|
||||
toggle_ai(AI_OFF) // To prevent any weirdness.
|
||||
|
||||
/mob/living/simple_animal/update_sight()
|
||||
if(!client)
|
||||
@@ -545,3 +549,23 @@
|
||||
/mob/living/simple_animal/buckle_mob(mob/living/buckled_mob, force = 0, check_loc = 1)
|
||||
. = ..()
|
||||
riding_datum = new/datum/riding/animal
|
||||
|
||||
|
||||
/mob/living/simple_animal/proc/toggle_ai(togglestatus)
|
||||
if (AIStatus != togglestatus)
|
||||
if (togglestatus > 0 && togglestatus < 4)
|
||||
GLOB.simple_animals[AIStatus] -= src
|
||||
GLOB.simple_animals[togglestatus] += src
|
||||
AIStatus = togglestatus
|
||||
else
|
||||
stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]")
|
||||
|
||||
/mob/living/simple_animal/proc/consider_wakeup()
|
||||
if (pulledby || shouldwakeup)
|
||||
toggle_ai(AI_ON)
|
||||
|
||||
/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(!ckey && !stat)//Not unconscious
|
||||
if(AIStatus == AI_IDLE)
|
||||
toggle_ai(AI_ON)
|
||||
@@ -30,7 +30,7 @@
|
||||
spawned_mobs = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/handle_automated_action()
|
||||
/mob/living/simple_animal/hostile/spawner/Life()
|
||||
. = ..()
|
||||
spawn_mob()
|
||||
|
||||
|
||||
@@ -356,6 +356,9 @@
|
||||
else
|
||||
M.LAssailant = usr
|
||||
|
||||
/mob/proc/can_resist()
|
||||
return FALSE //overridden in living.dm
|
||||
|
||||
/mob/proc/spin(spintime, speed)
|
||||
set waitfor = 0
|
||||
var/D = dir
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
//dist_check - set to only shock mobs within 1 of source (vendors, airlocks, etc.)
|
||||
//No animations will be performed by this proc.
|
||||
/proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE)
|
||||
if(ismecha(M.loc))
|
||||
if(!M || ismecha(M.loc))
|
||||
return 0 //feckin mechs are dumb
|
||||
if(dist_check)
|
||||
if(!in_range(source,M))
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
var/move_self = 1 //Do we move on our own?
|
||||
var/grav_pull = 4 //How many tiles out do we pull?
|
||||
var/consume_range = 0 //How many tiles out do we eat
|
||||
var/event_chance = 15 //Prob for event each tick
|
||||
var/event_chance = 10 //Prob for event each tick
|
||||
var/target = null //its target. moves towards the target if it has one
|
||||
var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing
|
||||
var/last_warning
|
||||
@@ -114,7 +114,7 @@
|
||||
/obj/singularity/process()
|
||||
if(current_size >= STAGE_TWO)
|
||||
move()
|
||||
radiation_pulse(src, energy, 0.5)
|
||||
radiation_pulse(src, min(5000, (energy*3)+1000), RAD_DISTANCE_COEFFICIENT*0.5)
|
||||
if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit
|
||||
event()
|
||||
eat()
|
||||
@@ -367,15 +367,13 @@
|
||||
|
||||
|
||||
/obj/singularity/proc/event()
|
||||
var/numb = pick(1,2,3,4,5,6)
|
||||
var/numb = rand(1,4)
|
||||
switch(numb)
|
||||
if(1)//EMP
|
||||
emp_area()
|
||||
if(2,3)//tox damage all carbon mobs in area
|
||||
toxmob()
|
||||
if(4)//Stun mobs who lack optic scanners
|
||||
if(2)//Stun mobs who lack optic scanners
|
||||
mezzer()
|
||||
if(5,6) //Sets all nearby mobs on fire
|
||||
if(3,4) //Sets all nearby mobs on fire
|
||||
if(current_size < STAGE_SIX)
|
||||
return 0
|
||||
combust_mobs()
|
||||
@@ -384,13 +382,6 @@
|
||||
return 1
|
||||
|
||||
|
||||
/obj/singularity/proc/toxmob()
|
||||
var/radiation = 15
|
||||
if (energy>200)
|
||||
radiation += round((energy-150)/10,1)
|
||||
radiation_pulse(src, radiation)
|
||||
|
||||
|
||||
/obj/singularity/proc/combust_mobs()
|
||||
for(var/mob/living/carbon/C in urange(20, src, 1))
|
||||
C.visible_message("<span class='warning'>[C]'s skin bursts into flame!</span>", \
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
/datum/reagent/blob/networked_fibers
|
||||
name = "Networked Fibers"
|
||||
id = "networked_fibers"
|
||||
description = "will do high brute and burn damage but non-manual expansion will only generate resources."
|
||||
description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually."
|
||||
shortdesc = "will do high brute and burn damage."
|
||||
effectdesc = "will move your core when manually expanding near it."
|
||||
analyzerdescdamage = "Does high brute and burn damage."
|
||||
|
||||
@@ -466,7 +466,7 @@
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
|
||||
/datum/reagent/medicine/pen_acid/on_mob_life(mob/living/M)
|
||||
M.radiation -= min(M.radiation, log(M.radiation)*10)
|
||||
M.radiation -= min(M.radiation-RAD_MOB_SAFE, 0)/100
|
||||
M.adjustToxLoss(-2*REM, 0)
|
||||
for(var/datum/reagent/R in M.reagents.reagent_list)
|
||||
if(R != src)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
new /obj/item/device/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs)))
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/handle_automated_action()
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/Life()
|
||||
consume()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
|
||||
if(. < UI_INTERACTIVE)
|
||||
return
|
||||
|
||||
// The AI can interact with anything it can see nearby, or with cameras.
|
||||
if((get_dist(src, src_object) <= client.view) || GLOB.cameranet.checkTurfVis(get_turf_pixel(src_object)))
|
||||
// The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled.
|
||||
if(!control_disabled && can_see(src_object))
|
||||
return UI_INTERACTIVE
|
||||
return UI_CLOSE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user