sensor 4 sec delay then turn on relays

OP almost has it. Well, not really.

First is to change all those ints that will never be outside 0 to 255 to byte instead of int. RAM is limited.

Second is to get rid of the code-blocking delays, NOTHING happens during a delay.

Can you tell what is wrong with this?

     lastDebounceTime = millis();
  if ((millis() - lastDebounceTime) > debounceDelay) {

Are you throwing other people's code that you don't understand up for fixing? Or did you write that?
Because if that's so then nothing below will make any sense to you. Learn BlinkWithoutDelay.

But if you're not a noob who treats code like incantations...
When you write code to handle events, tasks break down to pieces that run in loop() when triggered.

One kind of trigger is TIME through millis() or micros(), both return unsigned long values.

tNow = millis();
if ( tNow - tStart >= tWait ) { code for when timed event is triggered }

Another kind of trigger is STATE which is simply a value in a variable that reflects the current stage that events have reached. The total code for the task is split into pieces wherever there is a delay and the new piece triggers on time set by the part split from. That way when loop() comes to the part that is waiting, the next piece of code gets a chance to trigger, and so on.
A simple state machine can handle serial input on a per-char basis, match keywords, evaluate numbers, things like that even while it blinks led 13 on time as a status light and still be able to add tasks without making spaghetti code.

Other triggers are interrupts and pin reads.
My last priority, bottom of the list trigger is serial available, but I always run a fast loop by never running long code in one piece. Break tasks to sub-tasks and let other tasks run a slice in between. 1 ms is 16000 CPU cycles. If a task in loop() is cycle-heavy, do a return at the end of that task to make loop() run again and check the critical triggers first, etc. Small, very fast code steps in loop() let your code be immensely responsive in Real Time.
Hey, microcontrollers were invented to handle Real Time. That's what setup() and loop() are geared to support.