ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/follow.ext
Revision: 1.22
Committed: Tue May 18 21:45:37 2010 UTC (14 years ago) by root
Branch: MAIN
Changes since 1.21: +53 -48 lines
Log Message:
make it better

File Contents

# User Rev Content
1 root 1.1 #! perl
2    
3     # TODO: skip arena
4     # TODO: check for player leaving
5    
6     # implement a 'follow' command
7     # don't follow on damned ground
8    
9 root 1.18 our $MAX_QUEUE = 5; # the # of positions somebody else can lead
10 root 1.22 our %FOLLOW; # $followername => [$follower, $target, [$queue]]
11     our $FOLLOW_HANDLER;
12 root 1.1
13 root 1.19 sub unfollow($) {
14     my $name = shift;
15    
16 root 1.22 if (my $f = delete $FOLLOW{$name}) {
17 root 1.19 my ($who, $target, undef) = @$f;
18     $who->contr->detach ("follow_aborter");
19     $target->message ("$name no longer follows you.");
20     $who->message ("You no longer follow " . $target->name . ".");
21     }
22     }
23    
24     cf::player::attachment follow_aborter =>
25     on_move => sub {
26     my ($pl, $dir) = @_;
27     unfollow $pl->ob->name;
28     },
29     on_login => sub {
30     my ($pl, $dir) = @_;
31     $pl->detach ("follow_aborter");
32     },
33     ;
34    
35 root 1.22 sub start_follow_handler {
36     $FOLLOW_HANDLER = cf::async_ext {
37     $Coro::current->{desc} = "follow handler";
38    
39     while () {
40     cf::wait_for_tick;
41    
42     for (values %FOLLOW) {
43     my ($who, $target, $queue) = @$_;
44    
45     my ($map, $x, $y) = ($target->map, $target->x, $target->y);
46    
47     # add new position to queue, if any
48     push @$queue, [$map, $x, $y]
49     if $map != $queue->[-1][0]
50     || $x != $queue->[-1][1]
51     || $y != $queue->[-1][2];
52    
53     # try to move to oldest position
54     if (@$queue > $MAX_QUEUE) {
55     $who->message ($target->name . " is too far away - you can't follow anymore!");
56     unfollow $target->name;
57     } else {
58     my ($map, $x, $y) = @{ $queue->[0] };
59    
60     $map->load;
61    
62     if (
63     !$map->valid
64     or $map->path !~ /^(\{link\}|\/)/
65     or grep $_->flag (cf::FLAG_IS_FLOOR) && ($_->flag (cf::FLAG_UNIQUE) || $_->type == cf::SHOP_FLOOR),
66     $map->at ($x, $y)
67     ) {
68     $who->message ("You can't follow " . $target->name . " anymore!");
69     unfollow $who->name;
70     } elsif (!$who->blocked ($map, $x, $y)) {
71     shift @$queue;
72     $who->goto ($map, $x, $y);
73     }
74 root 1.13 }
75 root 1.1 }
76 root 1.22
77     Coro::schedule unless keys %FOLLOW;
78 root 1.1 }
79 root 1.22 };
80     }
81 root 1.13
82 root 1.22 start_follow_handler;
83 root 1.1
84     cf::register_command follow => sub {
85     my ($who, $args) = @_;
86    
87     my $name = $who->name;
88    
89     if ($args ne "" && $name ne $args) {
90 root 1.8 if (my $other = cf::player::find_active $args) {
91 root 1.18 $other = $other->ob;
92    
93     if ($other->map == $who->map
94     && abs ($other->x - $who->x) <= 1
95     && abs ($other->y - $who->y) <= 1
96     ) {
97 root 1.1 $who->message ("Following player '$args', to stop, type: 'follow");
98 root 1.18 $other->message ("$name is now following your every step...");
99 root 1.22 $FOLLOW{$name} = [
100 root 1.18 $who,
101     $other,
102     [[$other->map, $other->x, $other->y]],
103 root 1.1 ];
104 root 1.19 $who->contr->attach ("follow_aborter");
105 root 1.22 $FOLLOW_HANDLER->ready;
106 root 1.1 } else {
107     $who->message ("You must stand directly beside '$args' to follow her/him");
108 root 1.22 delete $FOLLOW{$name};
109 root 1.1 }
110     } else {
111     $who->message ("Cannot follow '$args': no such player");
112 root 1.22 delete $FOLLOW{$name};
113 root 1.1 }
114     } else {
115     $who->message ("follow mode off");
116 root 1.22 delete $FOLLOW{$name};
117 root 1.1 }
118     };
119    
120 root 1.18 sub unregister {
121     my ($pl) = @_;
122 root 1.19
123 root 1.18 my $name = $pl->ob->name;
124    
125 root 1.19 unfollow $name;
126 root 1.18
127 root 1.22 while (my ($k, $v) = each %FOLLOW) {
128 root 1.19 unfollow $k
129     if $v->[1]->name eq $name;
130 root 1.18 }
131     }
132    
133 root 1.3 cf::player->attach (
134 root 1.18 on_death => \&unregister,
135     on_logout => \&unregister,
136 root 1.3 );
137 root 1.1