Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/__DEFINES/qdel.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

// Defines for the time an item has to get its reference cleaned before it fails the queue and moves to the next.
#define GC_FILTER_QUEUE 1 SECONDS
#define GC_CHECK_QUEUE 5 MINUTES
#define GC_CHECK_QUEUE 30 SECONDS // Reduced from 5 MINUTES for long-running rounds
#define GC_DEL_QUEUE 10 SECONDS


Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
#define FIRE_PRIORITY_VIS 10
#define FIRE_PRIORITY_AMBIENCE 10
#define FIRE_PRIORITY_MISSIONS 10
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_GARBAGE 10 // Increased from 15 for better performance in long rounds
#define FIRE_PRIORITY_WET_FLOORS 20
#define FIRE_PRIORITY_AIR 20
#define FIRE_PRIORITY_NPC 20
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/subsystem/garbage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ By using these methods of finding references, you can make your life far, far ea
SUBSYSTEM_DEF(garbage)
name = "Garbage"
priority = FIRE_PRIORITY_GARBAGE
wait = 2 SECONDS
wait = 1 SECONDS // Increased frequency from 2 SECONDS for better throughput
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_order = INIT_ORDER_GARBAGE
Expand Down
21 changes: 15 additions & 6 deletions code/controllers/subsystem/idlenpcpool.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ SUBSYSTEM_DEF(idlenpcpool)
name = "Idling NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
priority = FIRE_PRIORITY_IDLE_NPC
wait = 60
wait = 30 // Reduced from 60 to check more frequently for player presence
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

var/list/currentrun = list()
Expand All @@ -23,7 +23,9 @@ SUBSYSTEM_DEF(idlenpcpool)

if (!resumed)
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
src.currentrun = idlelist.Copy()
var/list/zlist = GLOB.simple_animals[AI_Z_OFF]
// Process both idle and z-off mobs
src.currentrun = idlelist.Copy() + zlist.Copy()

//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
Expand All @@ -33,12 +35,19 @@ SUBSYSTEM_DEF(idlenpcpool)
--currentrun.len
if (!SA)
GLOB.simple_animals[AI_IDLE] -= SA
GLOB.simple_animals[AI_Z_OFF] -= SA
continue

if(!SA.ckey)
if(SA.stat != DEAD)
SA.handle_automated_movement()
if(SA.stat != DEAD)
SA.check_should_sleep()
// For AI_Z_OFF mobs, only check if they should wake up, don't move them
if(SA.AIStatus == AI_Z_OFF)
if(SA.stat != DEAD)
SA.check_should_sleep()
else
// For AI_IDLE mobs, do normal processing
if(SA.stat != DEAD)
SA.handle_automated_movement()
if(SA.stat != DEAD)
SA.check_should_sleep()
if (MC_TICK_CHECK)
return
34 changes: 32 additions & 2 deletions code/controllers/subsystem/machines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ SUBSYSTEM_DEF(machines)
var/list/processing = list()
var/list/currentrun = list()
var/list/powernets = list()
/// Track how many machines we skipped due to empty virtual z-levels
var/skipped_machines = 0

/datum/controller/subsystem/machines/Initialize()
makepowernets()
Expand All @@ -31,7 +33,7 @@ SUBSYSTEM_DEF(machines)
propagate_network(PC,PC.powernet)

/datum/controller/subsystem/machines/stat_entry(msg)
msg = "M:[length(processing)]|PN:[length(powernets)]"
msg = "M:[length(processing)]|PN:[length(powernets)]|S:[skipped_machines]"
return ..()


Expand All @@ -40,17 +42,45 @@ SUBSYSTEM_DEF(machines)
for(var/datum/powernet/Powernet in powernets)
Powernet.reset() //reset the power state.
src.currentrun = processing.Copy()
skipped_machines = 0

//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun

while(currentrun.len)
var/obj/machinery/thing = currentrun[currentrun.len]
currentrun.len--
if(QDELETED(thing) || thing.process(wait * 0.1) == PROCESS_KILL)

if(QDELETED(thing))
processing -= thing
if (MC_TICK_CHECK)
return
continue

// Skip machines on virtual z-levels with no players present
// Exceptions:
// 1. Critical machines (SM, PA, telecomms) always process
// 2. Machines in outpost areas always process (player hubs)
// 3. Machines in ship areas always process (player-owned vessels)
if(!thing.critical_machine)
var/area/machine_area = get_area(thing)
// Check if it's an outpost or ship area - these always process
if(!istype(machine_area, /area/outpost) && !istype(machine_area, /area/ship))
var/thing_vz = thing.virtual_z()
if(thing_vz)
var/players_on_vz = LAZYACCESS(SSmobs.players_by_virtual_z, "[thing_vz]")
if(!length(players_on_vz))
skipped_machines++
if (MC_TICK_CHECK)
return
continue

// Process the machine
if(thing.process(wait * 0.1) == PROCESS_KILL)
processing -= thing
if (!QDELETED(thing))
thing.datum_flags &= ~DF_ISPROCESSING

if (MC_TICK_CHECK)
return

Expand Down
4 changes: 4 additions & 0 deletions code/controllers/subsystem/npcpool.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ SUBSYSTEM_DEF(npcpool)
if(QDELETED(SA))
continue

// Skip AI_Z_OFF mobs - they're on virtual z-levels with no players
if(SA.AIStatus == AI_Z_OFF)
continue

if(!SA.ckey && !SA.notransform)
if(SA.stat != DEAD)
SA.handle_automated_movement()
Expand Down
5 changes: 5 additions & 0 deletions code/modules/mob/living/living_movement.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
return TRUE
if(ismob(mover) && (mover in buckled_mobs))
return TRUE
//Allow squeezing by on grab intent
if(iscarbon(mover))
var/mob/living/carbon/C = mover
if(C.a_intent == INTENT_GRAB)
return TRUE
return !mover.density || body_position == LYING_DOWN

/mob/living/toggle_move_intent()
Expand Down
34 changes: 30 additions & 4 deletions code/modules/mob/living/simple_animal/simple_animal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@

/mob/living/simple_animal/proc/handle_automated_action()
set waitfor = FALSE
// Periodically check if we should sleep (for non-hostile mobs)
// Hostile mobs override this and do their own checks
if(prob(10)) // 10% chance per action to check sleep state
check_should_sleep()
return

/mob/living/simple_animal/proc/handle_automated_movement()
Expand Down Expand Up @@ -658,17 +662,39 @@
LAZYREMOVEASSOC(SSidlenpcpool.idle_mobs_by_virtual_level, "[virt_z]", src)

/mob/living/simple_animal/proc/check_should_sleep()
// Don't sleep if being pulled or explicitly flagged to stay awake
if (pulledby || shouldwakeup)
toggle_ai(AI_ON)
return

// Don't sleep if we're player-controlled
if(ckey)
return

var/virt_z = virtual_z()
if(!virt_z)
return

var/players_on_virtual_z = 0
if(virt_z)
players_on_virtual_z = LAZYACCESS(SSmobs.players_by_virtual_z, "[virt_z]")
if(!length(players_on_virtual_z))
players_on_virtual_z = LAZYACCESS(SSmobs.players_by_virtual_z, "[virt_z]")

// If no players on this virtual z-level, sleep
if(!length(players_on_virtual_z))
if(AIStatus != AI_Z_OFF)
toggle_ai(AI_Z_OFF)
else if(AIStatus == AI_Z_OFF)
// If there are players and we're asleep, wake up
else if(AIStatus == AI_Z_OFF)
// Check if any players are actually close enough to matter
var/should_wake = FALSE
var/turf/our_turf = get_turf(src)
if(our_turf)
for(var/mob/living/player_mob in players_on_virtual_z)
// Wake up if a player is within reasonable distance
if(get_dist(our_turf, get_turf(player_mob)) <= MAX_SIMPLEMOB_WAKEUP_RANGE * 3)
should_wake = TRUE
break

if(should_wake)
toggle_ai(AI_ON)

/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
Expand Down
Loading