#! perl
#
# This file is part of Deliantra, the Roguelike Realtime MMORPG.
#
# Copyright (©) 2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
#
# Deliantra is free software: you can redistribute it and/or modify it under
# the terms of the Affero GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the Affero GNU General Public License
# and the GNU General Public License along with this program. If not, see
# .
#
# The authors can be reached via e-mail to
#
=head1 NAME
cf::mapscript
=head1 DESCRIPTION
This module implements the mapscript object.
Map scripts are perl snippets that get executed whenever any connected
element is triggered (e.g. a check inv, a lever etc.)
=head1 ENVIRONMENT
The map scripts are compiled and executed into a namespace with the
following symbols available:
=over 4
=cut
package cf::mapscript::eval;
use common::sense;
=item $self
The mapscript object itself.
=item $state
The state value (0 means release, <>0 means push/trigger/enable) that
triggered the map script.
=item $activator
The object that was triggered (the lever, check inv element, npc etc.).
=item $originator
The object that triggered the activator, usually (but not always) the
player who stepped on a check inv, pulled a lever etc. Can be C.
=cut
use vars qw($self $state $activator $originator);
=item @obs = find $id_or_object
Finds all objects with the given I C<$id>. If an object
reference is passed, it will be returned unchanged.
=cut
sub find($) {
ref $_[0] ? $_[0]
: $self->map->find_link ($_[0])
}
=item trigger $id_or_object[, $state]
Triggers the linked chain with the given I id, or the connected
chain associated with the given object (if an objetc reference is passed),
and passes the given state (or C<1>, if missing) to it.
=cut
sub trigger($;$) {
$self->map->trigger ($_[0], $#_ ? $_[1] : 1, $self);
}
=item timer $id_or_object, $seconds
Starts the timer on the given mapscript object (usually, $id_or_object is
C<$self>). When the timer expires on the mapscript object, it will trigger
the script with C<$activator == $self> and C<$originator == undef>.
=cut
sub timer($$) {
my $ob = (&find)[0];
$ob->speed_left (-$_[1] / cf::TICK);
$ob->set_speed (1);
}
package cf::mapscript;
use common::sense;
*{"main::safe::cf::mapscript::eval::"} = \%{"main::cf::mapscript::eval::"};
our %CACHE;
sub activate($$$) {
package cf::mapscript::eval;
($self, $state, $activator, $originator) = @_;
(
$CACHE{$self->msg} ||= cf::safe_eval
"package cf::mapscript::eval; sub {\n"
. "#line 1 '" . ($self->debug_desc) . "'\n"
. $self->msg
. "\n}"
or sub { }
)->();
}
=back
=head1 EXAMPLE
Have a look at F for a nontrivial example.
=cut
1;