mirror of
https://github.com/CorsixTH/CorsixTH.git
synced 2025-07-23 12:23:05 +02:00
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:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user