Tk.pm.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:25k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #########################################################################
  2. #  OpenKore - Tk Interface
  3. #
  4. #  Copyright (c) 2004 OpenKore development team 
  5. #
  6. #  This program is free software; you can redistribute it and/or modify
  7. #  it under the terms of the GNU General Public License as published by
  8. #  the Free Software Foundation; either version 2 of the License, or
  9. #  (at your option) any later version.
  10. #
  11. #  This program is distributed in the hope that it will be useful,
  12. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. #  GNU General Public License for more details.
  15. #
  16. #
  17. #  $Revision$
  18. #  $Id$
  19. #
  20. #########################################################################
  21. package Interface::Tk;
  22. use strict;
  23. use warnings;
  24. use Interface;
  25. use base qw/Interface/;
  26. use Plugins;
  27. use Globals;
  28. use Field;
  29. use Settings;
  30. use Misc;
  31. use Carp qw/carp croak confess/;
  32. use Time::HiRes qw/time usleep/;
  33. use Tk;
  34. use Tk::ROText;
  35. use Tk::BrowseEntry;
  36. use Tk::NoteBook;
  37. #these should go in a config file at some point.
  38. our $line_limit = 1000;
  39. ################################################################
  40. # Public Method
  41. ################################################################
  42. sub new {
  43. my $class = shift;
  44. my $self = {
  45. mw => undef,
  46. input_list => [],
  47. input_offset => 0,
  48. input_que => [],
  49. default_font=>"MS Sans Serif",
  50. input_type => "Command",
  51. input_pm => undef,
  52. total_lines => 0,
  53. last_line_end => 0,
  54. colors => {},
  55. };
  56. if ($buildType == 0) {
  57. eval "use Win32::API;";
  58. $self->{ShellExecute} = new Win32::API("shell32", "ShellExecute",
  59. "NPPPPN", "V");
  60. }
  61. bless $self, $class;
  62. $self->initTk;
  63. Plugins::addHook('mainLoop_pre', &updateHook, $self);
  64. Plugins::addHook('postloadfiles', &resetColors, $self);
  65. return $self;
  66. }
  67. sub getInput{
  68. my $self = shift;
  69. my $timeout = shift;
  70. my $msg;
  71. if ($timeout < 0) {
  72. until (defined $msg) {
  73. $self->update();
  74. if (@{ $self->{input_que} }) { 
  75. $msg = shift @{ $self->{input_que} }; 
  76. }
  77. } elsif ($timeout > 0) {
  78. my $end = time + $timeout;
  79. until ($end < time || defined $msg) {
  80. $self->update();
  81. if (@{ $self->{input_que} }) { 
  82. $msg = shift @{ $self->{input_que} }; 
  83. }
  84. } else {
  85. if (@{ $self->{input_que} }) { 
  86. $msg = shift @{ $self->{input_que} }; 
  87. }
  88. $self->update();
  89. $msg =~ s/n// if defined $msg;
  90. return $msg;
  91. }
  92. sub writeOutput {
  93. my $self = shift;
  94. my $type = shift || '';
  95. my $message = shift || '';
  96. my $domain = shift || '';
  97. my $scroll = 0;
  98. $scroll = 1 if (($self->{console}->yview)[1] == 1);
  99. #keep track of lines to limit the number of lines in the text widget
  100. $self->{total_lines} += $message =~ s/r?n/n/g;
  101. $self->{console}->insert('end', "n") if $self->{last_line_end};
  102. $self->{last_line_end} = $message =~ s/n$//;
  103. $self->{console}->insert('end', $message, "$type $type.$domain");
  104. #remove extra lines
  105. if ($self->{total_lines} > $line_limit) {
  106. my $overage = $self->{total_lines} - $line_limit;
  107. $self->{console}->delete('1.0', $overage+1 . ".0");
  108. $self->{total_lines} -= $overage;
  109. }
  110. $self->{console}->see('end') if $scroll;
  111. }
  112. sub updateHook {
  113. my $hookname = shift;
  114. my $r_args = shift;
  115. my $self = shift;
  116. return unless defined $self->{mw};
  117. $self->updatePos();
  118. $self->{mw}->update();
  119. $self->setAiText("@ai_seq");
  120. }
  121. sub update {
  122. my $self = shift;
  123. $self->{mw}->update();
  124. if ($buildType == 0 && $self->{SettingsObj}) {
  125. if ($self->{SettingsObj}->Wait(0)) {
  126. my $code;
  127. $self->{SettingsObj}->GetExitCode($code);
  128. Settings::parseReload("all") if $code == 0;
  129. delete $self->{SettingsObj};
  130. }
  131. }
  132. }
  133. sub title {
  134. my $self = shift;
  135. my $title = shift;
  136. if (defined $title) {
  137. if (!defined $self->{currentTitle} || $self->{currentTitle} ne $title) {
  138. $self->{mw}->title($title);
  139. $self->{currentTitle} = $title;
  140. }
  141. } else {
  142. return $self->{mw}->title();
  143. }
  144. }
  145. sub updatePos {
  146. my $self = shift;
  147. return unless defined($config{'char'}) && defined($chars[$config{'char'}]) && defined($char->{'pos_to'});
  148. my ($x,$y) = @{$char->{'pos_to'}}{'x', 'y'};
  149. $self->{status_posx}->configure( -text =>$x);
  150. $self->{status_posy}->configure( -text =>$y);
  151. if ($self->mapIsShown()) {
  152. if ($self->{map}{field} ne $field->name()) {
  153. $self->loadMap();
  154. }
  155. $self->{map}{canvas}->coords($self->{map}{ind}{player},
  156. $x - 2, $self->{map}{height} - $y - 2,
  157. $x + 2, $self->{map}{height} - $y + 2,
  158. );
  159. my $dis = $config{'attackDistance'};
  160. $self->{map}{canvas}->coords($self->{map}{ind}{range},
  161. $x - $dis, $self->{map}{height} - $y - $dis,
  162. $x + $dis, $self->{map}{height} - $y + $dis,
  163. );
  164. }
  165. }
  166. sub updateStatus {
  167. my $self = shift;
  168. my $text = shift;
  169. $self->{status_gen}->configure(-text => $text);
  170. }
  171. sub setTitle {
  172. my $self = shift;
  173. my $text = shift;
  174. $self->{mw}->title($text);
  175. }
  176. sub setAiText {
  177. my $self = shift;
  178. my ($text) = shift;
  179. $self->{status_ai}->configure(-text => $text);
  180. }
  181. sub addPM {
  182. my $self = shift;
  183. my $input_name = shift;
  184. my $found=1;
  185. my @pm_list = $self->{pminput}->cget('-choices');
  186. foreach (@pm_list){
  187. if ($_ eq $input_name) {
  188. $found = 0;
  189. last;
  190. }
  191. }
  192. if ($found) {
  193. $self->{pminput}->insert("end",$input_name);
  194. }
  195. }
  196. ################################################################
  197. # Private? Method
  198. ################################################################
  199. #FIXME many of thise methods don't support OO calls yet, update them and all their references
  200. sub initTk {
  201. my $self = shift;
  202. $self->{mw} = MainWindow->new();
  203. $self->{mw}->protocol('WM_DELETE_WINDOW', [&OnExit, $self]);
  204. #$self->{mw}->Icon(-image=>$self->{mw}->Photo(-file=>"hyb.gif"));
  205. $self->{mw}->title("$Settings::NAME");
  206. $self->{mw}->minsize(620,400);
  207. $self->{menuFont} = $self->{mw}->fontCreate(-family => $self->{default_font}, -size => 8, -weight => "bold");
  208. #------ Frame Control
  209. $self->{main_frame} = $self->{mw}->Frame()->pack(-side => 'top',-expand => 1,-fill => 'both',);
  210. $self->{btn_frame} = $self->{main_frame}->Frame()->pack(-side => 'right',-expand => 0,-fill => 'y',);
  211. $self->{console_frame} = $self->{main_frame}->Frame(-bg=>'black')->pack(-side => 'left',-expand => 1,-fill => 'both',);
  212. $self->{input_frame} = $self->{mw}->Frame(-bg=>'black')->pack(-side => 'top',-expand => 0,-fill => 'x',);
  213. $self->{status_frame} = $self->{mw}->Frame()->pack(-side => 'top',-expand => 0,-fill => 'x',);
  214. #------ subclass in console frame
  215. $self->{tabPane} = $self->{console_frame}->NoteBook(-relief=>'flat',-border=>1,-tabpadx=>1,-tabpady=>1,-font=>${$self->{menuFont}},-bg=>'#CDCDCD',-foreground=>'grey',-inactivebackground=>"#999999")->pack(-expand => 1,-fill => 'both',-side => 'top',);
  216. $self->{consoleTab} = $self->{tabPane}->add("Console",-label=>'Console');
  217. #$self->{chatTab} = $self->{tabPane}->add("Chat",-label=>'Chat');
  218. $self->{console} = $self->{consoleTab}->Scrolled('ROText',-bg=>'black',-fg=>'grey',
  219. -scrollbars => 'e',
  220. -height => 15,
  221. -wrap => 'word',
  222. -width => 55,
  223. -insertontime => 0,
  224. -background => 'black',
  225. -foreground => 'grey',
  226. -font=>[ -family => 'Courier' ,-size=>10,],
  227. -relief => 'sunken',
  228. )->pack(
  229. -expand => 1,
  230. -fill => 'both',
  231. -side => 'top',
  232. );
  233. if (0) {
  234. $self->{chatLog} = $self->{chatTab}->Scrolled('ROText',-bg=>'black',-fg=>'grey',
  235. -scrollbars => 'e',
  236. -height => 15,
  237. -wrap => 'word',
  238. -width => 55,
  239. -insertontime => 0,
  240. -background => 'black',
  241. -foreground => 'grey',
  242. -font=>[ -family => $self->{default_font} ,-size=>10,],
  243. -relief => 'sunken',
  244. )->pack(
  245. -expand => 1,
  246. -fill => 'both',
  247. -side => 'top',
  248. );
  249. }
  250. my $addButton = sub {
  251. my $label = shift;
  252. my $command = shift;
  253. return $self->{btn_frame}->Button(-text => $label, -command => $command , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  254. };
  255. $self->{mapBtn} = $addButton->(':: Map', [&mapToggle, $self]);
  256. $self->{helpBtn} = $addButton->(':: Help', [&showManual, $self]) if ($self->{ShellExecute});
  257. $self->{exitBtn} = $addButton->(':: Exit', [&OnExit, $self]);
  258. #$self->{statusBtn} = $self->{btn_frame}->Button(-text => ":: Status", -command =>[sub{push(@{$self->{input_list}}, "s");},$self] , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  259. #$self->{skillsBtn} = $self->{btn_frame}->Button(-text => ":: Skills", -command => sub{push(@{$self->{input_list}}, "skills");} , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  260. #$self->{inventBtn} = $self->{btn_frame}->Button(-text => ":: Inventory", -command =>sub{push(@{$self->{input_list}}, "i");} , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  261. #$self->{pplBtn} = $self->{btn_frame}->Button(-text => ":: Players", -command => sub{push(@{$self->{input_list}}, "pl");} , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  262. #$self->{monBtn} = $self->{btn_frame}->Button(-text => ":: Monsters", -command =>sub{push(@{$self->{input_list}}, "ml");} , -takefocus => 0, -font => $self->{menuFont}, -activeforeground => "white", -activebackground => "#004E98", -relief => "flat", -anchor => "w")->pack(-fill => "x", -side => "top");
  263. #------ subclass in input frame
  264. $self->{pminput} = $self->{input_frame}->BrowseEntry(
  265. -bg => 'white',
  266. -insertbackground => 'white',
  267. -variable => $self->{input_pm},
  268. -width => 8,
  269. -choices => $self->{pm_list},
  270. -state =>'normal',
  271. -relief => 'sunken',
  272. ); # ->pack(
  273. # -expand=>0,
  274. # -fill => 'x',
  275. # -side => 'left',
  276. #);
  277. $self->{input} = $self->{input_frame}->Entry(
  278. -bg => 'white',
  279. -insertbackground => 'white',
  280. -relief => 'sunken',
  281. -font=>[ -family => $self->{default_font} ,-size=>8,],
  282. )->pack(
  283. -expand=>1,
  284. -fill => 'x',
  285. -side => 'left',
  286. );
  287. $self->{sinput} = $self->{input_frame}->BrowseEntry(
  288. -bg=>'black',
  289. -fg=>'grey',
  290. -variable => $self->{input_type},
  291. -choices => [qw(Command Public Party Guild)],
  292. -width => 8,
  293. -state =>'readonly',
  294. -relief => 'sunken',
  295. );#->pack (
  296. # -expand=>0,
  297. # -fill => 'x',
  298. # -side => 'left',
  299. #);
  300. #------ subclass in status frame
  301. $self->{status_gen} = $self->{status_frame}->Label(
  302. -anchor => 'w',
  303. -text => 'Ready',
  304. -font => ['Arial', 8],
  305. -bd=>0,
  306. -relief => 'sunken',
  307. )->pack(
  308. -side => 'left',
  309. -expand => 1,
  310. -fill => 'x',
  311. );
  312. $self->{status_ai} = $self->{status_frame}->Label(
  313. -text => 'Ai - Status',
  314. -font => ['Arial', 8],
  315. -width => 25,
  316. -relief => 'ridge',
  317. )->pack(
  318. -side => 'left',
  319. -expand => 0,
  320. -fill => 'x',
  321. );
  322. $self->{status_posx} = $self->{status_frame}->Label(
  323. -text => '0',
  324. -font => ['Arial', 8],
  325. -width => 4,
  326. -relief => 'ridge',
  327. )->pack(
  328. -side => 'left',
  329. -expand => 0,
  330. -fill => 'x',
  331. );
  332. $self->{status_posy} = $self->{status_frame}->Label(
  333. -text => '0',
  334. -font => ['Arial', 8],
  335. -width => 4,
  336. -relief => 'ridge',
  337. )->pack(
  338. -side => 'left',
  339. -expand => 0,
  340. -fill => 'x',
  341. );
  342. if (0) {
  343. $self->{mw}->configure(-menu => $self->{mw}->Menu(-menuitems=>
  344. [ map 
  345. ['cascade', $_->[0], -tearoff=> 0, -font=>[-family=>"Tahoma",-size=>8], -menuitems => $_->[1]],
  346. # ['~modKore',
  347. # [[qw/command E~xit  -accelerator Ctrl+X/, -font=>[-family=>"Tahoma",-size=>8], -command=>[&OnExit]],]
  348. # ],
  349. ['~View',
  350. [
  351. # [qw/command Map  -accelerator Ctrl+M/, -font=>[-family=>"Tahoma",-size=>8], -command=>[&OpenMap, $class]],
  352. [qw/command Map  -accelerator Ctrl+M/, -font=>[-family=>"Tahoma",-size=>8], -command=>[&mapToggle, undef, $self]],
  353. # '',
  354. # [qw/command Status -accelerator Alt+D/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "s");}],
  355. # [qw/command Skill -accelerator Alt+S/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "skills");}],
  356. # [qw/command Equipment -accelerator Alt+Q/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "i eq");}],
  357. # [qw/command Stat -accelerator Alt+A/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "st");}],
  358. # [qw/command Usable -accelerator Alt+E/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "i u");}],
  359. # [qw/command Non-Usable -accelerator Alt+W/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "i nu");}],
  360. # [qw/command Exp -accelerator Alt+Z/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "exp");}],
  361. # [qw/command Cart -accelerator Alt+C/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "cart");}],
  362. # '',
  363. # [cascade=>"Guild", -tearoff=> 0, -font=>[-family=>"Tahoma",-size=>8], -menuitems =>
  364. # [
  365. # [qw/command Info -accelerator ALT+F/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "guild i");}],
  366. # [qw/command Member -accelerator ALT+G/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "guild m");}],
  367. # [qw/command Position -accelerator ALT+H/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "guild p");}],
  368. #  ],
  369. # ],
  370. # '',
  371. # [cascade=>"Font Weight", -tearoff=> 0, -font=>[-family=>"Tahoma",-size=>8], -menuitems => 
  372. # [
  373. # [Checkbutton  => '~Bold', -variable => $is_bold,-font=>[-family=>"Tahoma",-size=>8],-command => [&change_fontWeight]],
  374. # ]
  375. # ],
  376. ],
  377. ],
  378. # ['~Reload',
  379. # [
  380. # [qw/command config -accelerator Ctrl+C/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload conf");}],
  381. # [qw/command mon_control  -accelerator Ctrl+W/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload mon_");}],
  382. # [qw/command item_control  -accelerator Ctrl+Q/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload items_");}],
  383. # [qw/command cart_control  -accelerator Ctrl+E/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload cart_");}],
  384. # [qw/command ppl_control  -accelerator Ctrl+D/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload ppl_");}],
  385. # [qw/command timeouts  -accelerator Ctrl+Z/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload timeouts");}],
  386. # [qw/command pickupitems  -accelerator Ctrl+V/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload pick");}],
  387. # [qw/command chatAuto  -accelerator Ctrl+A/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload chatAuto");}],
  388. # '',
  389. # [qw/command All  -accelerator Ctrl+S/, -font=>[-family=>"Tahoma",-size=>8], -command=>sub{push(@input_que, "reload all");}],
  390. # ]
  391. # ],
  392. ]
  393. ));
  394. #Binding
  395. #FIXME Do I want to quit on cut? ... NO!
  396. #$self->{mw}->bind('all','<Control-x>'=>[&OnExit]);
  397. $self->{mw}->bind('all','<Control-m>'=>[&mapToggle, $self]);
  398. #FIXME hey that's copy....
  399. #$self->{mw}->bind('all','<Control-c>'=>sub{push(@input_que, "reload conf");});
  400. #$self->{mw}->bind('all','<Control-w>'=>sub{push(@input_que, "reload mon_");});
  401. #$self->{mw}->bind('all','<Control-q>'=>sub{push(@input_que, "reload items_");});
  402. #$self->{mw}->bind('all','<Control-e>'=>sub{push(@input_que, "reload cart_");});
  403. #$self->{mw}->bind('all','<Control-d>'=>sub{push(@input_que, "reload ppl_");});
  404. #$self->{mw}->bind('all','<Control-z>'=>sub{push(@input_que, "reload timeouts");});
  405. #FIXME hey that's paste....
  406. #$self->{mw}->bind('all','<Control-v>'=>sub{push(@input_que, "reload pick");});
  407. #$self->{mw}->bind('all','<Control-a>'=>sub{push(@input_que, "reload chatAuto");});
  408. #$self->{mw}->bind('all','<Control-s>'=>sub{push(@input_que, "reload all");});
  409. #$self->{mw}->bind('all','<Alt-d>'=>sub{push(@input_que, "s");});
  410. #$self->{mw}->bind('all','<Alt-s>'=>sub{push(@input_que, "skills");});
  411. #$self->{mw}->bind('all','<Alt-q>'=>sub{push(@input_que, "i eq");});
  412. #$self->{mw}->bind('all','<Alt-a>'=>sub{push(@input_que, "st");});
  413. #$self->{mw}->bind('all','<Alt-e>'=>sub{push(@input_que, "i u");});
  414. #$self->{mw}->bind('all','<Alt-w>'=>sub{push(@input_que, "i nu");});
  415. #$self->{mw}->bind('all','<Alt-z>'=>sub{push(@input_que, "exp");});
  416. #cookiemaster cart shortcut
  417. #$self->{mw}->bind('all','<Alt-c>'=>sub{push(@input_que, "cart");});
  418. #digitalpheer guild shortcut 
  419. #$self->{mw}->bind('all','<Alt-f>'=>sub{push(@input_que, "guild i");});
  420. #$self->{mw}->bind('all','<Alt-g>'=>sub{push(@input_que, "guild m");});
  421. #$self->{mw}->bind('all','<Alt-h>'=>sub{push(@input_que, "guild p");});
  422. }
  423. $self->{input}->bind('<Up>' => [&inputUp, $self]);
  424. $self->{input}->bind('<Down>' => [&inputDown, $self]);
  425. $self->{input}->bind('<Return>' => [&inputEnter, $self]);
  426. $self->{input}->focus();
  427. if ($buildType == 0) {
  428. $self->{input}->bind('<MouseWheel>' => [&w32mWheel, $self, Ev('k')]);
  429. $self->{console}->bind('<MouseWheel>' => [&w32mWheel, $self, Ev('k')]);
  430. my $console;
  431. eval 'use Win32::Console; $console = new Win32::Console(STD_OUTPUT_HANDLE);';
  432. $console->Free();
  433. } else {
  434. #I forgot the X code. will insert later
  435. }
  436. $self->{mw}->raise();
  437. }
  438. sub errorDialog {
  439. my $self = shift;
  440. my $msg = shift;
  441. $self->{mw}->messageBox(
  442. -icon => 'error',
  443. -message => $msg,
  444. -title => 'Error',
  445. -type => 'Ok'
  446. );
  447. }
  448. sub inputUp {
  449. my $inputarea = shift; #this is redundant =
  450. my $self = shift;
  451. my $line;
  452. chomp($line = $self->{input}->get);
  453. unless ($self->{input_offset}) {
  454. $self->{input_list}[$self->{input_offset}] = $line;
  455. }
  456. $self->{input_offset}++;
  457. $self->{input_offset} -= $#{$self->{input_list}} + 1 while $self->{input_offset} > $#{$self->{input_list}};
  458. $self->{input}->delete('0', 'end');
  459. $self->{input}->insert('end', "$self->{input_list}[$self->{input_offset}]");
  460. }
  461. sub inputDown {
  462. my $inputarea = shift; #this is redundant =
  463. my $self = shift;
  464. my $line;
  465. chomp($line = $self->{input}->get);
  466. unless ($self->{input_offset}) {
  467. $self->{input_list}[$self->{input_offset}] = $line;
  468. }
  469. $self->{input_offset}--;
  470. $self->{input_offset} += $#{$self->{input_list}} + 1 while $self->{input_offset} < 0;
  471. $self->{input}->delete('0', 'end');
  472. $self->{input}->insert('end', "$self->{input_list}[$self->{input_offset}]");
  473. }
  474. sub inputEnter {
  475. my $inputarea = shift; #this is redundant =
  476. my $self = shift;
  477. my $line;
  478. $line = $self->{input}->get;
  479. $self->{input}->delete('0', 'end');
  480. return unless defined $line;
  481. $self->{input_list}[0] = $line;
  482. unshift(@{$self->{input_list}}, "");
  483. $self->{input_offset} = 0;
  484. push(@{ $self->{input_que} }, $line);
  485. }
  486. sub inputPaste {
  487. my $inputarea = shift; #this is redundant =
  488. my $self = shift;
  489. my $line;
  490. $line = $self->{input}->get;
  491. # print "'$line'n";
  492. $self->{input}->delete('0', 'end');
  493. my @lines = split(/n/, $line);
  494. $line = pop(@lines);
  495. push(@{ $self->{input_que} }, @lines);
  496. $self->{input}->insert('end', $line) if $line;
  497. }
  498. sub w32mWheel {
  499. my $action_area = shift;
  500. my $self = shift;
  501. my $zDist = shift;
  502. $self->{console}->yview('scroll', -int($zDist/40), "units");
  503. }
  504. sub OnExit{
  505. my $self = shift;
  506. if ($conState) {
  507. push(@{ $self->{input_que} }, "n");
  508. quit();
  509. } else {
  510. exit();
  511. }
  512. }
  513. sub showManual {
  514. my $self = shift;
  515. $self->{ShellExecute}->Call(0, '', 'http://openkore.sourceforge.net/manual/', '', '', 1);
  516. }
  517. sub resetColors {
  518. my $hookname = shift;
  519. my $r_args = shift;
  520. my $self = shift;
  521. return if $hookname ne 'postloadfiles';
  522. my $colors_loaded = 0;
  523. foreach my $filehash (@{ $r_args->{files} }) {
  524. if ($filehash->{file} =~ /consolecolors.txt$/) {
  525. $colors_loaded = 1;
  526. last;
  527. }
  528. }
  529. return unless $colors_loaded;
  530. my %gdefault = (-foreground => 'grey', -background => 'black');
  531. eval {
  532. $self->{console}->configure(%gdefault);
  533. $self->{input}->configure(%gdefault);
  534. $self->{pminput}->configure(%gdefault);
  535. $self->{sinput}->configure(%gdefault);
  536. };
  537. if ($@) {
  538. if ($@ =~ /unknown color name "(.*)" at/) {
  539. Log::message("Color '$1' not recognised.n");
  540. return undef if !$consoleColors{''}{'useColors'}; #don't bother throwing a lot of errors in the next section.
  541. } else {
  542. die $@;
  543. }
  544. }
  545. foreach my $type (keys %consoleColors) {
  546. next if $type eq '';
  547. my %tdefault =%gdefault;
  548. if ($consoleColors{''}{'useColors'} && $consoleColors{$type}{'default'}) {
  549. $consoleColors{$type}{'default'} =~ m|([^/]*)(?:/(.*))?|;
  550. $tdefault{-foreground} = defined($1) && $1 ne 'default' ? $1 : $gdefault{-foreground};
  551. $tdefault{-background} = defined($2) && $2 ne 'default' ? $2 : $gdefault{-background};
  552. }
  553. eval {
  554. $self->{console}->tagConfigure($type, %tdefault);
  555. };
  556. if ($@) {
  557. if ($@ =~ /unknown color name "(.*)" at/) {
  558. Log::message("Color '$1' not recognised in consolecolors.txt at [$type]: default.n");
  559. } else {
  560. die $@;
  561. }
  562. }
  563. foreach my $domain (keys %{ $consoleColors{$type} }) {
  564. my %color = %tdefault;
  565. if ($consoleColors{''}{'useColors'} && $consoleColors{$type}{$domain}) {
  566. $consoleColors{$type}{$domain} =~ m|([^/]*)(?:/(.*))?|;
  567. $color{-foreground} = defined($1) && $1 ne 'default' ? $1 : $tdefault{-foreground};
  568. $color{-background} = defined($2) && $2 ne 'default' ? $2 : $tdefault{-background};
  569. }
  570. eval {
  571. $self->{console}->tagConfigure("$type.$domain", %color);
  572. };
  573. if ($@) {
  574. if ($@ =~ /unknown color name "(.*)" at/) {
  575. Log::message("Color '$1' not recognised in consolecolors.txt at [$type]: $domain.n");
  576. } else {
  577. die $@;
  578. }
  579. }
  580. }
  581. }
  582. }
  583. sub mapToggle {
  584. my ($self);
  585. if (@_ == 1) {
  586. $self = $_[0];
  587. } elsif (@_ == 2) {
  588. $self = $_[1];
  589. } else {
  590. die "wrong number of args to mapTogglen";
  591. }
  592. if (!defined($self->{map}) && $chars[$config{'char'}] && $field) {
  593. $self->{map}{window} = $self->{mw}->Toplevel();
  594. $self->{map}{window}->protocol('WM_DELETE_WINDOW', 
  595. sub {
  596. $self->mapToggle();
  597. }
  598. );
  599. $self->{map}{window}->resizable(0,0);
  600. $self->{map}{canvas} = $self->{map}{window}->Canvas(
  601. -width => 200,
  602. -height => 200,
  603. -background => 'white',
  604. )->pack(
  605. -side => 'top'
  606. );
  607. $self->loadMap();
  608. my $dis = $config{'attackDistance'};
  609. $self->{map}{ind}{range} = $self->{map}{canvas}->createOval(
  610. -$dis, $self->{map}{height} - $dis,
  611.  $dis, $self->{map}{height} + $dis,
  612. -outline => '#0000ff',
  613. );
  614. $self->{map}{ind}{player} = $self->{map}{canvas}->createOval(
  615. -2, $self->{map}{height} - 2,
  616.  2, $self->{map}{height} + 2,
  617. -fill => '#ffcccc',
  618. -outline => '#ff0000',
  619. );
  620. # if ($main::sys{'enableMoveClick'}) {
  621. # $map_mw->bind('<Double-1>', [&dblchk , Ev('x') , Ev('y')]);
  622. # }
  623. $self->{map}{window}->bind('<1>', [&mapMove, $self, Ev('x') , Ev('y'), 2]); 
  624. $self->{map}{window}->bind('<3>', [&mapMove, $self, Ev('x') , Ev('y'), 1]); 
  625. $self->{map}{window}->bind('<Motion>', [&pointchk, $self, Ev('x') , Ev('y')]); 
  626. $self->updatePos();
  627. } elsif (defined $self->{map}) {
  628. $self->{map}{window}->destroy();
  629. undef $self->{map}{canvas};
  630. undef $self->{map}{window};
  631. undef $self->{map};
  632. }
  633. }
  634. sub pointchk {
  635. my (undef, $self, $mvcpx, $mvcpy) = @_;
  636. if (@_ == 3) {
  637. ($self, $mvcpx, $mvcpy) = @_;
  638. } elsif (@_ == 4) {
  639. (undef, $self, $mvcpx, $mvcpy) = @_;
  640. } else {
  641. die "wrong number of args to pointchkn";
  642. }
  643. $mvcpy = $self->{map}{height} - $mvcpy;
  644. my ($x,$y) = @{$char->{'pos_to'}}{'x', 'y'};
  645. $self->{map}{window}->title(sprintf "Map View: %8s p:(%3d, %3d) m:(%3d, %3d)", $field->name(), $x, $y, $mvcpx, $mvcpy);
  646. $self->{map}{window}->update; 
  647. }
  648. sub mapMove {
  649. my (undef, $self, $mvcpx, $mvcpy, $moveAttack) = @_;
  650. if (@_ == 4) {
  651. ($self, $mvcpx, $mvcpy, $moveAttack) = @_;
  652. } elsif (@_ == 5) {
  653. (undef, $self, $mvcpx, $mvcpy, $moveAttack) = @_;
  654. } else {
  655. die "wrong number of args to pointchkn";
  656. }
  657. $mvcpy = $self->{map}{height} - $mvcpy;
  658. main::aiRemove("move");
  659. main::aiRemove("route");
  660. main::aiRemove("mapRoute");
  661. main::ai_route($field->name(), $mvcpx, $mvcpy,
  662. attackOnRoute => $moveAttack,
  663. noSitAuto => 1);
  664. }
  665. sub mapIsShown {
  666. my $self = shift;
  667. return defined($self->{map});
  668. }
  669. sub loadMap {
  670. my $self = shift;
  671. return if (!$self->mapIsShown());
  672. $self->{map}{field} = $field->name();
  673. $self->{map}{canvas}->delete('map');
  674. $self->{map}{canvas}->createText(50,20,-text =>'Processing..',-tags=>'loading');
  675. $self->{map_bitmap} = $self->{map}{canvas}->Bitmap(
  676. -data => ${xbmmake($field)}
  677. );
  678. $self->{map}{canvas}->createImage(2,2,
  679. -image => $self->{map_bitmap},
  680. -anchor => 'nw',
  681. -tags=>'map'
  682. );
  683. $self->{map}{canvas}->configure(
  684. -width => $field->width(),
  685. -height => $field->height()
  686. );
  687. $self->{map}{width} = $field->width();
  688. $self->{map}{height} = $field->height();
  689. $self->{map}{canvas}->delete('loading');
  690. my ($x,$y) = @{$char->{'pos_to'}}{'x', 'y'};
  691. $self->{map}{window}->title(sprintf "Map View: %8s p:(%3d, %3d)", $field->name(), $x, $y);
  692. }
  693. # should this cache xbm files?
  694. sub xbmmake {
  695. my $field = shift;
  696. my ($hx,$hy,$mvw_x,$mvw_y);
  697. my $line = 0;
  698. my $dump = 0;
  699. $mvw_x = $field->width();
  700. $mvw_y = $field->height();
  701. if (($mvw_x % 8) == 0) {
  702. $hx = $mvw_x;
  703. } else {
  704. $hx = $mvw_x+(8-($mvw_x % 8));
  705. }
  706. for (my $j = 0; $j < $mvw_y; $j++) {
  707. $hy = ($mvw_x*($mvw_y-$j-1));
  708. for (my $k = 0; $k < $hx; $k++) {
  709. $dump += 256 if (!$field->isWalkable($k, $field->height()-$j));
  710. $dump = $dump/2;
  711. if (($k % 8) == 7) {
  712. $line .= sprintf("0x%02x,",$dump);
  713. $dump = 0;
  714. }
  715. }
  716. }
  717. $line = "#define data_width $mvw_xn#define data_height $mvw_ynstatic unsigned char data_bits[] = {n".$line."};";
  718. return $line;
  719. }
  720. 1;