General Diagnosis. Crash fixes on doctor change (#2844)

* General Diagnosis crash fixes #1328

Co-authored-by: Alberth289346 <alberth289346@gmail.com>
This commit is contained in:
Artem Argus
2025-05-10 20:05:55 +03:00
committed by GitHub
parent ac54375594
commit 51881eaf90
4 changed files with 123 additions and 68 deletions

View File

@@ -540,7 +540,9 @@ function Humanoid:startAction()
-- Call the action start handler
TheApp.humanoid_actions[action.name](action, self)
if action == self.action_queue[1] and action.todo_interrupt then
-- If action has been marked as to be interrupted
if action == self.action_queue[1] and action.todo_interrupt and not action.uninterruptible then
-- Interrupt this action
local high_priority = action.todo_interrupt == "high"
action.todo_interrupt = nil
local on_interrupt = action.on_interrupt

View File

@@ -509,6 +509,20 @@ function Staff:adviseWrongPersonForThisRoom()
end
end
--! Check whether staff are meandering
--"meander" action always insert "move" or "idle" action before itself.
--so when humanoid "meandering" his action queue usually looks like:
--[1 idle, 2 meander] or [1 walk, 2 meander].
--!return true if staff currently has a meander action
function Staff:isMeandering()
if ((self.action_queue[1].name == "idle") or
(self.action_queue[1].name == "walk")) and
(self.action_queue[2].name == "meander") then
return true
end
return false
end
-- Function to decide if staff currently has nothing to do and can be called to a room where they're needed
function Staff:isIdle()
-- Make sure we're not in an undesired state

View File

@@ -356,42 +356,46 @@ function Room:onHumanoidEnter(humanoid)
if class.is(humanoid, Staff) then
-- If the room is already full of staff, or the staff member isn't relevant
-- to the room, then make them leave. Otherwise, take control of them.
if not self:staffFitsInRoom(humanoid) then
if self:getStaffMember() and self:staffMeetsRoomRequirements(humanoid) then
local staff_member = self:getStaffMember()
self.humanoids[humanoid] = true
if staff_member.profile.is_researcher and self.room_info.id == "research" then
self.hospital:giveAdvice(researcher_desks)
end
if staff_member.humanoid_class == "Nurse" and self.room_info.id == "ward" then
self.hospital:giveAdvice(nurse_desks)
end
if not staff_member.dealing_with_patient then
staff_member:setNextAction(self:createLeaveAction())
staff_member:queueAction(MeanderAction())
self.staff_member = humanoid
humanoid:setCallCompleted()
self:commandEnteringStaff(humanoid)
local staff_entered = humanoid
if not self:staffFitsInRoom(staff_entered) then
if self:getStaffMember() and self:staffMeetsRoomRequirements(staff_entered) then
local staff_in_room = self:getStaffMember()
self.humanoids[staff_entered] = true
if staff_in_room.profile.is_researcher and self.room_info.id == "research" then
self.hospital:giveAdvice(researcher_desks)
end
if staff_in_room.humanoid_class == "Nurse" and self.room_info.id == "ward" then
self.hospital:giveAdvice(nurse_desks)
end
if not staff_in_room.dealing_with_patient or staff_in_room:isMeandering() then
-- Previous staff in the room not currently occupied by serving patient in room.
-- Send out the previous staff and appoint new one.
staff_in_room:setNextAction(self:createLeaveAction())
staff_in_room:queueAction(MeanderAction())
self.staff_member = staff_entered
staff_entered:setCallCompleted()
self:commandEnteringStaff(staff_entered)
else
if self.waiting_staff_member then
self.waiting_staff_member.waiting_on_other_staff = nil
self.waiting_staff_member:setNextAction(self:createLeaveAction())
self.waiting_staff_member:queueAction(MeanderAction())
end
self:createDealtWithPatientCallback(humanoid)
humanoid.waiting_on_other_staff = true
humanoid:setNextAction(MeanderAction())
self:createDealtWithPatientCallback(staff_entered)
staff_entered.waiting_on_other_staff = true
staff_entered:setNextAction(MeanderAction())
end
else
self.humanoids[humanoid] = true
humanoid:setNextAction(self:createLeaveAction())
humanoid:queueAction(MeanderAction())
humanoid:adviseWrongPersonForThisRoom()
-- Inappropriate staff for this room
self.humanoids[staff_entered] = true
staff_entered:setNextAction(self:createLeaveAction())
staff_entered:queueAction(MeanderAction())
staff_entered:adviseWrongPersonForThisRoom()
end
else
self.humanoids[humanoid] = true
humanoid:setCallCompleted()
self:commandEnteringStaff(humanoid)
self.humanoids[staff_entered] = true
staff_entered:setCallCompleted()
self:commandEnteringStaff(staff_entered)
end
self:tryAdvanceQueue()
return
@@ -402,22 +406,23 @@ function Room:onHumanoidEnter(humanoid)
-- An infect patient's disease may have changed so they might have
-- been sent to an incorrect diagnosis room, they should leave and go
-- back to the gp for redirection
if (humanoid.infected) and not humanoid.diagnosed and
not self:isDiagnosisRoomForPatient(humanoid) then
humanoid:queueAction(self:createLeaveAction())
humanoid.needs_redirecting = true
humanoid:queueAction(SeekRoomAction("gp"))
local patient_entered = humanoid
if patient_entered.infected and not patient_entered.diagnosed and
not self:isDiagnosisRoomForPatient(patient_entered) then
patient_entered:queueAction(self:createLeaveAction())
patient_entered.needs_redirecting = true
patient_entered:queueAction(SeekRoomAction("gp"))
return
end
-- Check if the staff requirements are still fulfilled (the staff might have left / been picked up meanwhile)
if self:testStaffCriteria(self:getRequiredStaffCriteria()) then
if self.staff_member then
if self.staff_member then
self:setStaffMembersAttribute("dealing_with_patient", true)
end
self:commandEnteringPatient(humanoid)
self:commandEnteringPatient(patient_entered)
else
humanoid:setNextAction(self:createLeaveAction())
humanoid:queueAction(self:createEnterAction(humanoid))
patient_entered:setNextAction(self:createLeaveAction())
patient_entered:queueAction(self:createEnterAction(patient_entered))
end
end
end
@@ -492,16 +497,16 @@ end
--! When a valid member of staff enters the room this function is called.
-- Can be extended in derived classes.
--!param humanoid The staff in question
--!param already_initialized If true, this means that the staff has already got order
--!param staff (object) The staff in question
--!param already_initialized (bool) If true, this means that the staff has already got order
-- what to do.
function Room:commandEnteringStaff(humanoid, already_initialized)
function Room:commandEnteringStaff(staff, already_initialized)
if not already_initialized then
self.staff_member = humanoid
humanoid:setNextAction(MeanderAction())
self.staff_member = staff
staff:setNextAction(MeanderAction())
end
self:tryToFindNearbyPatients()
humanoid:setDynamicInfoText("")
staff:setDynamicInfoText("")
-- This variable is used to avoid multiple calls for staff (sound played only)
self.sound_played = nil
if self:testStaffCriteria(self:getRequiredStaffCriteria()) then

View File

@@ -52,49 +52,83 @@ end
function GeneralDiagRoom:commandEnteringPatient(patient)
local screen, sx, sy = self.world:findObjectNear(patient, "screen")
-- Patient walks to screen
patient:walkTo(sx, sy)
local after_use_screen1 = --[[persistable:general_diag_screen_after_use1]] function()
local staff = self.staff_member
local trolley, cx, cy = self.world:findObjectNear(patient, "crash_trolley")
staff:walkTo(trolley:getSecondaryUsageTile())
local staff_idle = IdleAction()
staff:queueAction(staff_idle)
patient:walkTo(cx, cy, true)
local after_use_screen2 = function() end
local staff = self:getStaffMember()
if staff then
local trolley, cx, cy = self.world:findObjectNear(patient, "crash_trolley")
local after_use_trolley = --[[persistable:general_diag_trolley_after_use]] function()
if #staff.action_queue == 1 then
-- Doctor walks to trolley
local ox, oy = trolley:getSecondaryUsageTile()
local staff_prepare = WalkAction(ox, oy)
:setMustHappen(true)
:disableTruncate()
:setUninterruptable(true)
staff:setNextAction(staff_prepare)
-- Doctor waits for patient near trolley
local staff_idle = IdleAction()
:setMustHappen(true)
:disableTruncate()
:setUninterruptable(true)
staff:queueAction(staff_idle)
-- Patient walks to trolley
local go_to_trolley = WalkAction(cx, cy)
:setMustHappen(true)
:disableTruncate()
patient:queueAction(go_to_trolley)
local after_use_trolley = --[[persistable:general_diag_trolley_after_use]] function()
-- Release doctor after procedure and finish his IdleAction() near trolley
staff:setNextAction(MeanderAction())
else
staff:finishAction(staff_idle)
end
end
patient:queueAction(MultiUseObjectAction(trolley, staff):setMustHappen(false)
:setProlongedUsage(false):setAfterUse(after_use_trolley))
patient:queueAction(WalkAction(sx, sy):setIsLeaving(true):setMustHappen(false):disableTruncate())
-- Patient uses trolley (trolly animation with patient and doctor)
local use_trolley = MultiUseObjectAction(trolley, staff)
:disableTruncate()
:setMustHappen(true)
:setProlongedUsage(false)
:setAfterUse(after_use_trolley)
patient:queueAction(use_trolley)
local after_use_screen2 = --[[persistable:general_diag_screen_after_use2]] function()
if #patient.action_queue == 1 then
self:dealtWithPatient(patient)
-- Patient walks back to screen
local go_to_screen2 = WalkAction(sx, sy)
:setIsLeaving(true)
:setMustHappen(true)
:disableTruncate()
patient:queueAction(go_to_screen2)
after_use_screen2 = --[[persistable:general_diag_screen_after_use2]] function()
if #patient.action_queue == 1 then
self:dealtWithPatient(patient)
end
end
else
-- Patient didn't get served
self:makeHumanoidLeave(patient)
patient:queueAction(SeekRoomAction(self.room_info.id))
end
patient:queueAction(UseScreenAction(screen):setIsLeaving(true):setMustHappen(true)
:setAfterUse(after_use_screen2))
-- Patient dresses back to their clothes
local dress_back = UseScreenAction(screen)
:setIsLeaving(true)
:setMustHappen(true)
:setAfterUse(after_use_screen2)
patient:queueAction(dress_back)
end
patient:queueAction(UseScreenAction(screen):setAfterUse(after_use_screen1))
-- Patient undresses for procedure
local undress = UseScreenAction(screen):setAfterUse(after_use_screen1)
patient:queueAction(undress)
return Room.commandEnteringPatient(self, patient)
end
function GeneralDiagRoom:onHumanoidLeave(humanoid)
if self.staff_member == humanoid then
self.staff_member = nil
end
Room.onHumanoidLeave(self, humanoid)
end
function GeneralDiagRoom:makeHumanoidLeave(humanoid)
self:makeHumanoidDressIfNecessaryAndThenLeave(humanoid)
end