--- deliantra/server/ext/cfplus.ext 2006/12/15 19:29:18 1.1 +++ deliantra/server/ext/cfplus.ext 2007/11/14 08:10:12 1.11 @@ -21,35 +21,23 @@ =cut cf::register_extcmd cfplus_support => sub { - my ($pl, $msg) = @_; + my ($pl, %msg) = @_; - # $msg->{version} + $pl->ns->{cfplus_ext} = $msg{version}; - (version => 2) + (version => $msg{version} >= 2 ? 2 : 0) }; -my %dialog; # currently active dialogs - -my $timer = Event->timer (interval => 0.2, parked => 1, data => cf::WF_AUTOCANCEL, cb => sub { - while (my ($id, $dialog) = each %dialog) { - my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc}); - next if (abs $dx) <= 2 && (abs $dy) <= 2; - - $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "out of range"); - delete $dialog{$id}; - } - - $_[0]->w->stop unless keys %dialog; -}); - sub dialog_tell { my ($id, $dialog, $msg) = @_; - my $pl = $dialog->{ob}->contr; + my $pl = $dialog->{pl}; my ($reply, @kw) = $dialog->tell ($msg); - $reply = "..." unless $reply; - $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw); + $reply = "..." unless defined $reply; + + $pl->ext_msg ($id, update => msg => $pl->expand_cfpod ($reply), add_topics => \@kw) + if $reply ne ""; # NPC might not want to say, or wants to say something later } =item ... = extcmd lookat { dx => $dx, dy => $dy } @@ -65,8 +53,9 @@ =cut cf::register_extcmd lookat => sub { - my ($pl, $msg) = @_; - my ($dx, $dy) = @$msg{qw(dx dy)}; + my ($pl, $dx, $dy) = @_; + + return unless $pl->ob && $pl->ob->map; my $near = (abs $dx) <= 2 && (abs $dy) <= 2; @@ -74,8 +63,8 @@ if ($pl->cell_visible ($dx, $dy)) { for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { - $res{npc_dialog} = $ob->name - if $near && NPC_Dialogue::has_dialogue $ob; + $res{npc_dialog} = [$ob->name, $dx, $dy] + if $near && NPC_Dialogue::has_dialogue $ob && !$pl->{npc_dialog}; } } @@ -89,28 +78,35 @@ messages related to this dialog interaction. It either replies with an error reply or starts a dialog by telling -the npc "hi" and returning a reply strcuture as with C. =cut cf::register_extcmd npc_dialog_begin => sub { - my ($pl, $msg) = @_; - my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)}; + my ($pl, $id, $token) = @_; + + #TODO: + # this is not a request, so returnign does no good: make it a request and die on error + + return unless $pl->ob && $pl->ob->map; - return unless (abs $dx) <= 2 && (abs $dy) <= 2; - return unless $pl->cell_visible ($dx, $dy); + my ($name, $dx, $dy) = @$token; + + return (error => "too far away") unless (abs $dx) <= 2 && (abs $dy) <= 2; + return (error => "nothing to talk there") unless $pl->cell_visible ($dx, $dy); + return (error => "only one dialog can be open at a time") if $pl->{npc_dialog}; # only one dialog at a time for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { if (NPC_Dialogue::has_dialogue $npc) { - $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc; - dialog_tell $id, $dialog{$id}, "hi"; - $timer->start; + $pl->attach ("npc_dialog_active"); + $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id; + dialog_tell $id, $pl->{npc_dialog}, "hi"; return; } } - (msgtype => "error", msg => "nothing to talk to found") + (error => "nothing to talk to to found") }; =item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text } @@ -118,7 +114,6 @@ Tells the NPC the given $text message and returns a reply structure which can have the following keys: - msgtype => "reply" msg => $reply_text, add_topics => [additional topic strings] del_topics => [invalidated topic strings] @@ -126,12 +121,11 @@ =cut cf::register_extcmd npc_dialog_tell => sub { - my ($pl, $msg) = @_; - - dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg} - if $dialog{$msg->{msgid}}; + my ($pl, $id, $msg) = @_; - () + if (my $dialog = $pl->{npc_dialog}) { + dialog_tell $id, $dialog, $msg; + } }; =item extcmd npc_dialog_end { msgid => $id } @@ -141,21 +135,13 @@ =cut cf::register_extcmd npc_dialog_end => sub { - my ($pl, $msg) = @_; - - delete $dialog{$msg->{msgid}}; + my ($pl, $id) = @_; - () + if (my $dialog = delete $pl->{npc_dialog}) { + $pl->detach ("ncp_dialog_active"); + } }; -cf::attach_to_players - on_logout => sub { - my ($pl) = @_; - - delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog; - }, -; - =item ... = extcmd editor_support Returns the value required by clients that have an editor to download and @@ -185,19 +171,56 @@ =cut cf::register_extcmd editor_support => sub { - my ($pl, $msg) = @_; + my ($pl, %msg) = @_; map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui) }; sub unload { - while (my ($id, $dialog) = each %dialog) { - $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "npc dialogue module was reloaded"); + for my $pl (cf::player::list) { + if (my $dialog = delete $pl->{npc_dialog}) { + $pl->detach ("npc_dialog_active"); + $pl->ext_msg ($dialog->{id} => error => "npc dialogue module was reloaded"); + } } - - %dialog = (); } +cf::player::attachment npc_dialog_active => + on_logout => sub { + my ($pl) = @_; + + delete $pl->{npc_dialog}; + $pl->detach ("npc_dialog_active"); + }, + on_move => sub { + my ($pl, $dir) = @_; + + # must delay a bit :/ + my $delay; $delay = EV::timer 0, 0, sub { + undef $delay; + + if (my $dialog = $pl->{npc_dialog}) { + my (undef, $dx, $dy) = $pl->ob->rangevector ($dialog->{npc}); + + return if (abs $dx) <= 2 && (abs $dy) <= 2; + + $pl->ext_msg ($dialog->{id} => error => "out of range"); + } + + delete $pl->{npc_dialog}; + $pl->detach ("npc_dialog_active"); + }; + }, +; + +cf::player->attach ( + on_login => sub { + my ($pl) = @_; + + delete $pl->{npc_dialog}; + }, +); + =back =cut