ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/follow.ext
Revision: 1.18
Committed: Sun May 2 19:04:01 2010 UTC (14 years, 1 month ago) by root
Branch: MAIN
Changes since 1.17: +55 -49 lines
Log Message:
hopefully better follow implementation

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     our %follow; # $followername => [$follower, $target, [$queue]]
11 root 1.1
12 root 1.13 our $CORO = cf::async {
13     $Coro::current->{desc} = "follow handler";
14 root 1.12
15 root 1.13 while () {
16     cf::wait_for_tick;
17 root 1.12
18 root 1.18 for (values %follow) {
19     my ($who, $target, $queue) = @$_;
20 root 1.13
21 root 1.18 my ($map, $x, $y) = ($target->map, $target->x, $target->y);
22    
23     # add new position to queue, if any
24     push @$queue, [$map, $x, $y]
25     if $map != $queue->[-1][0]
26     || $x != $queue->[-1][1]
27     || $y != $queue->[-1][2];
28    
29     # try to move to oldest position
30     if (@$queue > $MAX_QUEUE) {
31     delete $follow{$who->name};
32     $who->message ($target->name . " is too far away - you can't follow anymore!");
33     } else {
34     my ($map, $x, $y) = @{ $queue->[0] };
35    
36     $map->load;
37 root 1.13
38     if (
39 root 1.18 $map->path !~ /^(\{link\}|\/)/
40     or grep $_->flag (cf::FLAG_IS_FLOOR) && ($_->flag (cf::FLAG_UNIQUE) || $_->type == cf::SHOP_FLOOR),
41     $map->at ($x, $y)
42 root 1.13 ) {
43 root 1.18 delete $follow{$who->name};
44     $who->ob->message ("You can't follow " . $target->name . " anymore!");
45     } elsif (!$who->blocked ($map, $x, $y)) {
46     shift @$queue;
47     $who->goto ($map, $x, $y);
48 root 1.13 }
49 root 1.1 }
50     }
51 root 1.13
52     Coro::schedule unless keys %follow;
53 root 1.12 }
54 root 1.13 };
55 root 1.1
56     cf::register_command follow => sub {
57     my ($who, $args) = @_;
58    
59     my $name = $who->name;
60    
61     if ($args ne "" && $name ne $args) {
62 root 1.8 if (my $other = cf::player::find_active $args) {
63 root 1.18 $other = $other->ob;
64    
65     if ($other->map == $who->map
66     && abs ($other->x - $who->x) <= 1
67     && abs ($other->y - $who->y) <= 1
68     ) {
69 root 1.1 $who->message ("Following player '$args', to stop, type: 'follow");
70 root 1.18 $other->message ("$name is now following your every step...");
71 root 1.1 $follow{$name} = [
72 root 1.18 $who,
73     $other,
74     [[$other->map, $other->x, $other->y]],
75 root 1.1 ];
76 root 1.13 $CORO->ready;
77 root 1.1 } else {
78     $who->message ("You must stand directly beside '$args' to follow her/him");
79     delete $follow{$name};
80     }
81     } else {
82     $who->message ("Cannot follow '$args': no such player");
83     delete $follow{$name};
84     }
85     } else {
86     $who->message ("follow mode off");
87     delete $follow{$name};
88     }
89     };
90    
91 root 1.18 sub unregister {
92     my ($pl) = @_;
93     my $name = $pl->ob->name;
94     delete $follow{$name};
95    
96     warn "unfollow $name\n";#d#
97    
98     while (my ($k, $v) = each %follow) {
99     if ($v->[1]->name eq $name) {
100     warn "unfollow $k\n";#d#
101     delete $follow{$k};
102     }
103     }
104     }
105    
106 root 1.3 cf::player->attach (
107 root 1.18 on_death => \&unregister,
108     on_logout => \&unregister,
109 root 1.3 );
110 root 1.1
111    
112    
113