-
Notifications
You must be signed in to change notification settings - Fork 3
/
iff.pl
155 lines (129 loc) · 3.32 KB
/
iff.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
##
# IFF (Identify Friend or Foe) Plugin
#
# This plugin is meant as a helper for GVG AIs to determine which players are
# enemies. It currently cannot handle monsters.
#
# A foe is anyone who is not a friend.
# A friend is anyone who is:
# * a member of your party
# * a member of your guild
# * a member of an allied guild
# * a member of a guild in $config{iff_friendlyGuilds}
# * a player listed in $config{iff_friendlyPlayers}
#
# This plugin provides:
# * an 'iff' command to list friendliness of all players on screen
# * an 'iff <name>' command to list the friendliness of a specific player
# * the function IFF::foe($player) which returns 1 iff $player is a foe
package IFF;
use strict;
use Globals;
use Match;
use Plugins;
use Utils;
use Log qw(message error);
use Network::Send;
Plugins::register('iff', 'Identify Friend or Foe', \&Unload, \&Reload);
my $hooks = Plugins::addHooks(
["packet/map_loaded", \&map_loaded],
["Command_post", \&Command_post]
);
sub Reload { Unload(); }
sub Unload { Plugins::delHooks($hooks); }
our $reason;
sub map_loaded {
message "IFF: Requesting guild ally information...\n";
sendGuildRequest(\$remote_socket, 0);
}
##
# IFF::foe($player)
#
# Returns 1 if $player is a foe, 0 otherwise.
# Sets $IFF::reason to indicate why.
sub foe {
my ($player) = @_;
if (existsInList($config{iff_hostilePlayers}, $player->{name})) {
$reason = 'manual hostile player';
return 1;
}
if ($config{iff_hostilePlayers}) {
# Only players in that list are hostile
$reason = 'not hostile';
return 0;
}
if ($char->{party} && $char->{party}{users}{$player->{ID}}) {
$reason = 'party member';
return 0;
}
if ($pvp == 2 && $char->{guildID} && $char->{guildID} eq $player->{guildID}) {
$reason = 'guild member';
return 0;
}
if ($pvp == 2 && $player->{guildID} && $guild{ally}{$player->{guildID}}) {
$reason = 'allied guild member';
return 0;
}
# Since names are not immediately available, IFF may identify a manual
# friendly as a foe at first...?
if (existsInList($config{iff_friendlyGuilds}, $player->{guild}{name})) {
$reason = 'manual friendly guild member';
return 0;
}
if (existsInList($config{iff_friendlyAID}, unpack("L1", $player->{ID}))) {
$reason = 'manual friendly AID';
return 0;
}
if (existsInList($config{iff_friendlyPlayers}, $player->{name})) {
$reason = 'manual friendly player';
return 0;
}
$reason = 'not friendly';
return 1;
}
sub Command_post {
my (undef, $data) = @_;
return unless $data->{switch} eq 'iff';
$data->{return} = 1;
my (undef, $args) = split(' ', $data->{input}, 2);
if (defined $args) {
iff_player($args);
} else {
iff();
}
}
##
# iff()
#
# Lists all players and their IFF status.
sub iff {
for my $ID (@playersID) {
next unless $ID;
my $player = $players{$ID};
_iff_player($player);
}
message "End of IFF list.\n", "list";
}
##
# iff_player($name)
#
# Matches $name to a player and prints whether it is friendly and why.
sub iff_player {
my ($name) = @_;
my $player = Match::player($name, 1);
if (!$player) {
error "Player $name does not exist.\n";
return;
}
_iff_player($player);
}
##
# _iff_player($player)
#
# Prints whether $player is friendly and why.
sub _iff_player {
my ($player) = @_;
my $status = foe($player) ? 'foe' : 'friend';
message "Player $player->{name} ($player->{binID}) is $status ($reason).\n", "list";
}
1;