# NOTE1 - to make this thing work you will need triggers to set the state of your variables.
# i used my previously written routines, which captured the state from prompt and are not included here.
# the easiest way would be to set equilibrium to 0 after the spell is cast in 'cast_now'
# and set it to 1 when the according trigger fires. this is far from foolproof, but the fastest way to get
# you started.
#
# NOTE2 - if you have no idea what happens here with the variables and their types, refer to perldoc.
# i used alot of references and complex data structures just to compress the code and make the whole thing
# faster and easier
#
# NOTE3 - the whole solution is based on as much flexibility as i could think of at this point. you can use it for healing,
# herbs, attacks, whatever you want. all you have to do is rewrite 'cast_spell' so it checks the propper requirements,
# the variables to check and a new @waiting_queue
#
# NOTE4 - a few things can be removed here. the creation of new triggers is back from my idea/attempt to delete them after
# fireing, which is unnecessary and even time consuming. a better way is to deactivate them as it actually happens,
# or even keep them up and use them for loss/regain control too. there are many possibilities
#
# NOTE5 - as you see, the readiness triggers are set up as temporary and with moderate sequence number. to make the checks
# work properly your -real- regain triggers will need lower seq and 'keep evaluating'
#
#
#####
my @waiting_queue = (); # this line has to be either in global script scope or in some routine that is run at the start of the world
#####
sub cast_now { # this one just sends the supplied string to the world. you can rename it and use it as the main output sub
$world->Send(shift);
} # see NOTE 1
sub cast_spell { # this is what all your spell aliases should call
my ($spell,$supersede) = @_; # we get the full spell string as it will be sent to the world and optional 'supersede' flag
my $failed = &check_readiness('eq','bal'); # first we check if variables for all required states give us a 'go' - NOTE2 & 3
if ($failed) { # nope, some of them was not ready, we have to queue
@waiting_queue = () if ($supersede == 1); # we empty the queue if this is a high priority spell
push @waiting_queue, {$spell => ['eq','bal']}; # we queue the spell with its requirements - NOTE3
&set_readiness_triggers(@$failed); # and set the according triggers for those states that failed the test
} else { # ah! looks like we can cast!
@waiting_queue = (); # empty the queue 'just in case'. it should be emty, but you never know
&cast_now($spell); # and we cast the spell
}
}
sub check_readiness { # this sub checks the variables and returns those that are not '1'
my $failed = undef;
foreach my $name (@_) {
push @$failed, $name if ($world->GetVariable("$name")) ne '1'; # if the variable is not '1', we add it to the 'failed' array
} # see also NOTE 1, 2 & 3
return $failed; # return the failed
}
sub set_readiness_triggers { # this is used to set the triggers that will be watching for changes - NOTE4
foreach my $name (@_) {
if ($world->GetTriggerInfo("waitfor_$name", 1) eq '') { # sets a trigger if its not set already - NOTE5
$world->AddTriggerEx("waitfor_$name", ($world->GetTriggerInfo($name."_regain", 1)), "%1", 16384+32+8+1, -1, 0, "", "readiness_trigger", 12, 50)
} else { # there is a trigger already, lets activate it
$world->EnableTrigger("waitfor_$name", 1);
}
}
}
sub readiness_trigger { # this one will be used by our created triggers
my $name = shift;
if ($#waiting_queue >= 0) { # if there is at least 1 item in queue we can go ahead
my ($spell,$requirements) = each %{$waiting_queue[0]}; # get the first spell and its requirements from the queue - NOTE 2
my $failed = &check_readiness(@$requirements); # check if we meet the requirements
if ($failed) { # nope, we dont
&set_readiness_triggers(@$failed) #set new triggers for what we are missing
} else { # yup, we do
shift @waiting_queue; # remove the first spell from the queue
&cast_now($spell); # and cast it
}
} else { # the queue is empty
$world->EnableTrigger($name, 0); # disable the trigger that fired
}
}
|