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