ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/follow.ext
Revision: 1.23
Committed: Fri May 21 00:42:03 2010 UTC (14 years ago) by root
Branch: MAIN
Changes since 1.22: +4 -1 lines
Log Message:
*** empty log message ***

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 root 1.23 $target->active
46     or next;
47    
48 root 1.22 my ($map, $x, $y) = ($target->map, $target->x, $target->y);
49    
50     # add new position to queue, if any
51     push @$queue, [$map, $x, $y]
52     if $map != $queue->[-1][0]
53     || $x != $queue->[-1][1]
54     || $y != $queue->[-1][2];
55    
56     # try to move to oldest position
57     if (@$queue > $MAX_QUEUE) {
58     $who->message ($target->name . " is too far away - you can't follow anymore!");
59     unfollow $target->name;
60 root 1.23 } elsif (@$queue) {
61 root 1.22 my ($map, $x, $y) = @{ $queue->[0] };
62    
63     $map->load;
64    
65     if (
66     !$map->valid
67     or $map->path !~ /^(\{link\}|\/)/
68     or grep $_->flag (cf::FLAG_IS_FLOOR) && ($_->flag (cf::FLAG_UNIQUE) || $_->type == cf::SHOP_FLOOR),
69     $map->at ($x, $y)
70     ) {
71     $who->message ("You can't follow " . $target->name . " anymore!");
72     unfollow $who->name;
73     } elsif (!$who->blocked ($map, $x, $y)) {
74     shift @$queue;
75     $who->goto ($map, $x, $y);
76     }
77 root 1.13 }
78 root 1.1 }
79 root 1.22
80     Coro::schedule unless keys %FOLLOW;
81 root 1.1 }
82 root 1.22 };
83     }
84 root 1.13
85 root 1.22 start_follow_handler;
86 root 1.1
87     cf::register_command follow => sub {
88     my ($who, $args) = @_;
89    
90     my $name = $who->name;
91    
92     if ($args ne "" && $name ne $args) {
93 root 1.8 if (my $other = cf::player::find_active $args) {
94 root 1.18 $other = $other->ob;
95    
96     if ($other->map == $who->map
97     && abs ($other->x - $who->x) <= 1
98     && abs ($other->y - $who->y) <= 1
99     ) {
100 root 1.1 $who->message ("Following player '$args', to stop, type: 'follow");
101 root 1.18 $other->message ("$name is now following your every step...");
102 root 1.22 $FOLLOW{$name} = [
103 root 1.18 $who,
104     $other,
105     [[$other->map, $other->x, $other->y]],
106 root 1.1 ];
107 root 1.19 $who->contr->attach ("follow_aborter");
108 root 1.22 $FOLLOW_HANDLER->ready;
109 root 1.1 } else {
110     $who->message ("You must stand directly beside '$args' to follow her/him");
111 root 1.22 delete $FOLLOW{$name};
112 root 1.1 }
113     } else {
114     $who->message ("Cannot follow '$args': no such player");
115 root 1.22 delete $FOLLOW{$name};
116 root 1.1 }
117     } else {
118     $who->message ("follow mode off");
119 root 1.22 delete $FOLLOW{$name};
120 root 1.1 }
121     };
122    
123 root 1.18 sub unregister {
124     my ($pl) = @_;
125 root 1.19
126 root 1.18 my $name = $pl->ob->name;
127    
128 root 1.19 unfollow $name;
129 root 1.18
130 root 1.22 while (my ($k, $v) = each %FOLLOW) {
131 root 1.19 unfollow $k
132     if $v->[1]->name eq $name;
133 root 1.18 }
134     }
135    
136 root 1.3 cf::player->attach (
137 root 1.18 on_death => \&unregister,
138     on_logout => \&unregister,
139 root 1.3 );
140 root 1.1