]> ruin.nu Git - NDIRC.git/blob - PA.pm
Converted the .g command
[NDIRC.git] / PA.pm
1 #**************************************************************************
2 #   Copyright (C) 2006 by Michael Andreen <harvATruinDOTnu>               *
3 #                                                                         *
4 #   This program is free software; you can redistribute it and/or modify  *
5 #   it under the terms of the GNU General Public License as published by  *
6 #   the Free Software Foundation; either version 2 of the License, or     *
7 #   (at your option) any later version.                                   *
8 #                                                                         *
9 #   This program is distributed in the hope that it will be useful,       *
10 #   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12 #   GNU General Public License for more details.                          *
13 #                                                                         *
14 #   You should have received a copy of the GNU General Public License     *
15 #   along with this program; if not, write to the                         *
16 #   Free Software Foundation, Inc.,                                       *
17 #   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
18 #**************************************************************************/
19 package NDIRC::PA;
20 use strict;
21 use warnings;
22 use ND::DB;
23 use ND::Include;
24 use NDIRC::Access;
25 use NDIRC::Misc;
26 use POSIX;
27 require Exporter;
28
29 our @ISA = qw/Exporter/;
30
31 our @EXPORT = qw/shipEff shipStop parseValue prettyValue calcXp findCovOpper tick_time/;
32
33 sub shipEff {
34         my ($msg,$command) = @_;
35         my ($amount,$ship,$value,$target);
36         my $eff = 1;
37         $eff = 0 if $command =~ /stop/;
38         if(defined $msg && $msg =~ /^(-?\d+(?:\.\d+)?[hkMG]?) (\w+)(?: (\w+))?/){
39                 $ship = "\%$2\%";
40                 $target = ($3 || '%');
41                 my $am = $1;
42                 if ($command =~ /^v.+$/){
43                         $value = parseValue($am);
44                         $value *= -1.5 if $value < 0;
45                         my $feud = '';
46                 }else{
47                         $amount = parseValue($am);
48                 }
49         }else{
50                 $ND::server->command("notice $ND::nick syntax: $command amount ship [race|class] | Amount can use SI prefixes like k and M. Race or class is an optional argument, using the short form (i.e. cath or Fi)");
51                 return;
52         }
53         my $feud = '';
54
55         my $s= $ND::DBH->selectrow_hashref(q{
56                 SELECT name,t1,t2,t3,"type",damage
57                         ,metal+crystal+eonium AS cost
58                         ,init,"class",guns,race,eres,armor
59                 FROM ship_stats WHERE name ILIKE ?
60                 }, undef, $ship);
61         if ($s){
62                 if (defined $value){
63                         $amount = int(($value*100/$s->{cost}));
64                         $feud = '(FEUD: '.prettyValue(int($amount/0.86)).') ';
65                 }
66                 $value = prettyValue(($amount*$s->{cost}/100));
67                 my $name = shipColor($s->{name},$s->{type});
68                 my $text = prettyValue($amount)." $name ($s->{init}:$value) :";
69                 for my $tn ('t1','t2','t3'){
70                         next if ($eff && not defined $s->{$tn});
71                         $text .= " $ND::B${ND::C}03" . ($eff ? $s->{$tn} : $tn) . "$ND::O: ";
72                         my $st = q{
73                                 SELECT name,"class","type",armor
74                                         ,metal+crystal+eonium AS cost
75                                         ,init,t1,t2,t3,eres,race
76                                         ,damage,guns
77                                 FROM ship_stats 
78                                 };
79                         if ($eff){
80                                 $st = $ND::DBH->prepare($st . q{
81                                 WHERE "class" = $1
82                                         AND ("class" ILIKE $2 OR race ILIKE $2)
83                                 });
84                                 $st->execute($s->{$tn},$target);
85                         }else{
86                                 $st = $ND::DBH->prepare($st . qq{
87                                 WHERE $tn = \$1
88                                         AND ("class" ILIKE \$2 OR race ILIKE \$2)
89                                 });
90                                 $st->execute($s->{class},$target);
91                         }
92                         while (my $t = $st->fetchrow_hashref()){
93                                 my $number = calcEff($s,$t,$amount,$eff);
94                                 if ($eff){
95                                         $number *= 0.60 if $tn eq 't2';
96                                         $number *= 0.30 if $tn eq 't3';
97                                 }else{
98                                         $number /= 0.60 if $tn eq 't2';
99                                         $number /= 0.30 if $tn eq 't3';
100                                 }
101                                 $number = int($number);
102                                 $value = prettyValue($number*$t->{cost}/100);
103                                 my $name = shipColor($t->{name},$t->{type});
104                                 $text .= " $ND::B$number$ND::O $name ($t->{init}:$value),";
105                         }
106                         chop $text;
107                 }
108                 $ND::server->command("notice $ND::nick $text");
109         }
110 }
111
112 sub calcEff {
113         my ($s,$t,$amount,$eff) = @_;
114
115         my $number = 0;
116         if ($eff){
117                 $number = $s->{type} eq 'Emp' ?
118                         ($amount*$s->{guns}*(100-$t->{eres})/100)
119                         : ($amount*$s->{damage}/$t->{armor});
120         }else{
121                 $number = $t->{type} eq 'Emp' ?
122                         ($amount*100/(100 - $s->{eres})/$t->{guns})
123                         : ($amount*$s->{armor}/$t->{damage});
124         }
125
126         for my $tn ('t1','t2','t3'){
127                 my ($s1,$t1) = $eff ? ($s,$t) : ($t,$s);
128                 next unless (defined $t1->{$tn});
129                 next unless ($t1->{$tn} eq $s1->{class});
130
131                 if($t1->{init} <= $s1->{init}){
132                         $t->{init} = "${ND::C}04$t->{init}$ND::O";
133                 }else{
134                         $t->{init} = "${ND::C}12$t->{init}$ND::O";
135                 }
136         }
137         return $number;
138 }
139
140 sub shipColor {
141         my ($string,$type) = @_;
142         my $c = 04;
143         $c = 12 if $type eq 'Emp';
144         $c = 13 if $type eq 'Steal';
145         return "$ND::C$c$string$ND::O";
146 }
147
148 sub calcXp {
149         my ($msg) = @_;
150
151         my ($x,$y,$z,$roids,$cap);
152         if(defined $msg && $msg =~ /^(\d+)\D+(\d+)\D+(\d+)(?:[^\.\d]+(\d+))?(?:[^\.\d]+(\d*\.\d+))?$/){
153                 $x = $1;
154                 $y = $2;
155                 $z = $3;
156                 $roids = $4;
157                 $cap = $5;
158         }else{
159                 $ND::server->command("notice $ND::nick syntax: .xp X:Y:Z [roids] [cap] | if roids < 10 then it's taken as the wave, cap is a floating point number, defaults to 0.25");
160                 return;
161         }
162
163         my ($avalue,$ascore) = $ND::DBH->selectrow_array(q{
164                 SELECT value,score FROM current_planet_stats WHERE 
165                         id = (SELECT planet FROM users WHERE hostmask ILIKE ?);
166                 }, undef, $ND::address);
167         my ($tvalue,$tscore,$tsize) = $ND::DBH->selectrow_array(q{
168                 SELECT value,score,size FROM current_planet_stats WHERE 
169                 x = ? AND y = ? and z = ?;
170                 }, undef, $x,$y,$z);
171         $cap = 0.25 unless $cap;
172         unless($roids){
173                 $roids = int($tsize*$cap);
174         }elsif ($roids < 10){
175                 $tsize = ceil($tsize*.75**($roids-1));
176                 $roids = int($cap*$tsize);
177         }
178         $tsize -= $roids;
179         unless (defined $avalue && defined $ascore){
180                 $ND::server->command("notice $ND::nick You don't have a planet specified");
181                 return;
182         }
183         unless (defined $tvalue && defined $tscore){
184                 $ND::server->command("notice $ND::nick Doesn't seem to be a planet at $x:$y:$z");
185                 return;
186         }
187         my $xp = pa_xp($roids,$ascore,$avalue,$tscore,$tvalue);
188         my $score = 60 * $xp;
189         my $value = $roids*200;
190         my $totscore = prettyValue($score + $value);
191         $ND::server->command("notice $ND::nick You will gain $ND::B$xp$ND::B XP, $ND::B$score$ND::B score, if you steal $roids roids ($ND::B$value$ND::B value), from $ND::B$x:$y:$z$ND::B, who will have $ND::B$tsize$ND::B roids left, total score gain will be: $ND::B$totscore$ND::B in total,");
192 }
193
194 sub findCovOpper {
195         my ($stolen, $command) = @_;
196
197         my $tick = $ND::tick;
198         my $agents;
199
200         if (defined $stolen && $stolen =~ /(\d+) (\d+) (\d+)/){
201                 $tick = $1;
202                 $agents = $2;
203                 $stolen = $3;
204         }elsif (defined $stolen && $stolen =~ /(\d+) (\d+)/){
205                 $agents = $1;
206                 $stolen = $2;
207         }else{
208                 $ND::server->command("notice $ND::nick syntax: .$command [tick] agents stolen | tick can be omitted if you're doing this the same tick you got cov opped, if you have different amount of your resources stolen, specify the highest amount. Only works if less than 10% of your resources and < 10,000*agents were stolen");
209                 return;
210         }
211
212         my ($value,$score) = $ND::DBH->selectrow_array(q{
213                 SELECT value,score FROM planet_stats WHERE 
214                         id = (SELECT planet FROM users WHERE hostmask ILIKE ?) AND tick = ?;
215                 }, undef, $ND::address,$tick);
216         unless ($value){
217                 $ND::server->command("notice $ND::nick No value found for tick $tick, can't find your cov opper.");
218                 return;
219         }
220         my $attackers = $ND::DBH->prepare(q{
221                 SELECT coords(p.x,p.y,p.z), ruler, planet FROM current_planet_stats p JOIN planet_stats ps using (id) WHERE 
222                 ps.tick = $1 AND (2000.0*$2*$3/ps.value)::int = $4 ;
223                 });
224         $attackers->execute($tick,$agents,$value,$stolen);
225         if ($attackers->rows == 0){
226                 $ND::server->command("notice $ND::nick No cov opper found, did you specify the right tick, and was the stolen amount not capped?");
227                 return;
228         }
229         my $coords = '';
230         while (my $attacker = $attackers->fetchrow_hashref){
231                 $coords .= " ($attacker->{coords} : $attacker->{ruler} OF $attacker->{planet})";
232         }
233         $ND::server->command("notice $ND::nick The planet that cov opped you is one of: $coords");
234 }
235
236 sub tick_time {
237         my ($msg,$command) = @_;
238         my $tick = $ND::tick;
239         my $timezone = 'GMT';
240         if ($msg =~ /^(\d+)(?: (\S+))?/){
241                 $tick = $1 if defined $1;
242                 $timezone = $2 if defined $2;
243         }elsif ($msg =~ /^(\S+)/){
244                 $timezone = $1;
245         }elsif ($msg){
246                 $ND::server->command("notice $ND::nick syntax: .time [tick] [timezone] | Gives the time at the specied tick. Assumes GMT if no timezone is given and current tick if no tick is given.");
247                 return;
248         }
249         my $query = $ND::DBH->prepare(q{SELECT date_trunc('seconds',now() + (($1 - tick()) || ' hr')::interval) AT TIME ZONE $2});
250         $query->execute($tick,$timezone);
251         my $time = $query->fetchrow_array;
252         $ND::server->command("notice $ND::nick Time at tick $ND::B$tick$ND::O, timezone $ND::B$timezone$ND::O: $ND::B$time$ND::O");
253
254 }
255
256 1;