forked from council-of-rivendell/MeCCG-Linux-ES
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.functions
13201 lines (11930 loc) · 307 KB
/
client.functions
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#
# Gccg - Generic collectible card game.
# Copyright (C) 2001-2013 Tommi Ronkainen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program, in the file license.txt. If not, write
# to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
#############################################################################
#
# Function definitions for client
#
##############################################################################
#
# Constants:
#
# BOOK_ROWS - number of rows at card book
# BOOK_COLUMNS - number of columns at card book
# DECKBOX_SIZE - size of the columns of the deck listing.
# DELETE_TO_MINE - if set, Delete key will put to my own discard instead of owner.
# GAME - title of the game
# GAMEDIR - name of the directory of the game
# HELP{mode}{command} - (parameters,short description, users allowed or NULL if not restricted, long description)
# HIGHLIGHT_COLOR - color to use for highlighting touched objects
# IMAGE_FORMAT - default file extension expected by image files (including the dot)
# IMMOBILE_CARDS - list of card numbers not allowed to move with TryTransferTo()
# MENU{context} - menu entries for the given context
# MAX_MESSAGE - maximum length of the message line in pixels
# MAX_PLAYERS - maximum number of simultaneous players
# STRING_KEEP_TAPPED - keep-tapped flag text
# TABLES_X - number of tables in x-direction
# TABLES_Y - number of tables in y-direction
#
# Colors:
#
# COLORS{colorname} - preset colors for RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET, WHITE, BLACK
# BGCOLOR - generic background color
# FGCOLOR - generic foreground color
# BRCOLOR - generic border color
# BGCOLOR2 - play mode background color
# FGCOLOR2 - play mode foreground color
# BRCOLOR2 - play mode border color
# TXCOLOR - generic text color
# INCOLOR - input text color
# BKBGCOLOR - collection background color
# BKBRCOLOR - collection border color
# BKTXCOLOR - collection text color
# TABLE_SHADOW - if set, add {shadow} to table texts
#
# Variables:
#
# active - list of active set objects
# avatar{user name} - mapping from user names to last non-sleep avatars set
# avatar.image{avatar name} - image number of avatar
# avatar.name{player} - name of the avatar assigned to the player
# avatar.object{player} - object numbers of avatars
# away{username} - away status: old avatar name if away, NULL otherwise
# background.image - image number of the chat mode background
# background.object - object number of the chat mode background
# bind_next - if not null, next key press will bind contents of bind_next to the key
# bindk_next - if not null, next key press will bind contents of bindk_next to the key
# bind{key function} - line that overrides normal function of the pressed key
# bindk{key function} - string that overrides normal function of the pressed key
# book.cache - storage for the latest book state
# book.current_index - current filter/sort pair
# book.history - list of earlier filterings (newest is first)
# book.filter_version - a pair (filter code version, number of cards) used to create indices
# book.filter{filter expression} - precalculated filtered card lists
# book.index{(filter expression,sorting expression)} - precalculated book indices
# book_refresh - dictionary mapping card numbers to NULL or 1 if they are refreshed from server.
# books - list of object numbers used for card books
# booster - current real content of booster
# booster.box - box to display a booster/starter bought
# booster.open_at_once - 1 if booster should be opened immediately
# booster.manual_buy - 1 if booster was bought using /buy command
# booster.visible - current visible content of booster
# card.book - object number of my collection
# card.group{category}{group} - group data of the cards on table (see. location algorithm)
# card.width,card.height - pysical size of the cards
# card.design.width,card.design.height - size of the cards in design resolution
# card.book.width,card.book.height - size of the cards in the collection
# card.hand.width,card.hand.height - size of the cards in the hand
# card.deck.width,card.deck.height - size of the cards in the deck
# card.xstep,card.ystep - recommend space between cards during game
# cardmap{import/export}{format}{card} - Card import/export mapping from and to Gccg.
# con - connection number causing event
# deck - my playdeck object number
# deck.box - object number of deck editing list
# deck.groups{groupname} - contains decknames in each category
# decks{deckname}{part} - decks available (each part, i.e. "deck","sideboard", etc. contains list of card numbers)
# deck.name - name of the currently selected deck or NULL if not selected
# deck.objects[player]{name} - object numbers of the decks
# deck.class{object number} - map object number to general deck class
# deck.part - part of the deck under editing
# deck_content{object.number} - known content of the deck during play if any
# design.width,design.height - screen game design resolution
# discard - my discard deck object number
# drag.box - object number for draggable card object
# dragging - 1 while left dragging an object
# dragging.highlight - old state of highlighting when dragging started
# findspace.category - primary category of the card during location algorithm
# findspace.facedown - face down status set for last FindSpace request
# findspace.group - group of the card during location algorithm
# findspace.orientation - orientation set for last FindSpace request
# flag.logging - set when the logging is on
# flag.playing - set when the game is going
# function{name} - function callback table containing valid network events
# game.bindings - game specific bindings, if none given by the user
# game.data - structure holding generic game information (see. game_data())
# hand[player] - hand object numbers
# history - history of old inputs (newest is first)
# history.pos - current position in history or -1 if none
# table.image - image number for table
# info.box - box for displaying zoomed cardimages
# info.current - current card displayed in the infozoom, NULL if none
# input - current content of the input.box
# input.box - chat box at the bottom of the screen
# logs{log name} - collection of logs
# log.name - name of the current log
# menu - NULL if menu not shown, otherwise object number
# menu.object - object number to use for menu
# mode - "chat","shop","watch","play" current screen
# mode_object{mode} - mode specific objects to hide when changing mode
# modifier - list of modifier keys (Ctrl, Alt, Shift) being pressed
# money - current amount of money
# money.box - object number to show money
# me - my player number
# msg.box - message box at the top of the screen
# msgboxhighlight.color - background color for current line highlighting purposes
# msgboxhighlight.cpcolor - background color for copied line highlighting purposes
# msgbox.lastcutoff - last registered cutoff for the message box at the top of the screen
# obj - next free object number
# options{option} - client side options
# email (server option) - Your email
# nosound - Disable beep
# noalert - Disable visual alert
# log - Copy messages to the stdout if 'yes'
# plan (server option) - Additional whois data
# realname (server option) - Your name
# trade_limit - how many cards i need before trading
# options.game{option} - client side options during a game (reseted at the start of the game)
# "PutTableHook" - "on"/"off" enable/disable PutTableHook (default: on)
# options.debug - show debugging info
# options.export_set - If set, export set name always.
# panel_objects{panel name} - list of objects belonging to the panel.
# panel_options{panel name} - options for panel construction
# panel_structure{panel name} - construction info for the panel
# password{user name} - passwords
# players - number of players
# player.name{player number} - list of players during play
# player.icon{player number} - object number for player icon
# player.marker_color - currently selected marker color
# playmat.image - image number of the play mode background
# playmat.object - object number of the play mode background
# pm_name - name of current PM recipient
# port - server port
# price.default{rarity} - default prices for different rarities
# products{product name} - list of products
# 0 amount available
# 1 price
# 2 order code for factory server
# products.box - object number of products panel
# product.images{product name} - image number of the product picture
# product.objects{product name} - object numbers of products
# rarity.display{letter} - format code to apply when opening card of that rarity from pack
# room.players - players in chat room (see meta-server)
# room.tables - tables in chat room (see meta-server)
# rules.category - list of pairs (condition,category), which is used to map a name to category
# rules.coordinate - category to coordinate mapping (see. Mtg.include)
# score[player] - current score text for each player
# score.raw[player] - raw score structure for each players
# score.object[player] - scoreboard object numbers
# screen - name of the current screen
# screen.width,screen.height - screen physical resolution
# screen.has_focus - screen has input focus (0 or 1)
# screen.alert_enabled - visual notification is enabled (0 or 1)
# screen_panels{screen name} - list of panel names belonging to the screen
# search.box - object number of deck search box
# search.source - object number of the current source of search box content
# select.box - object for choosing a card
# select.expression - expression to evaluate for next selection
# select.source - card source for select box or NULL if none
# server - connection number for current game or meta server
# server.meta - connection number for meta server
# server.name - name of the game server set by --server or default
# server.name_backup - list of backup servers or NULL
# server.name_default - name of the default game server
# tab.type - type of tab completion to use ("player" or "command")
# tab.last_item - latest item name shown in tab completion
# tab.last_initial - latest initial part entered before pressing tab
# table.width,table.height - width of the playarea (screen size for <= 2-player)
# table.object[x][y] - object numbers for table images
# table.number[x][y] - connection numbers for table images or NULL if unused
# targeting_queue - list of cards waiting for targets; entries are (card number,)
# timer - list of timing event pairs (seconds,command) where is command is executed after seconds <= 0
# timer_minute - list of timing event pairs (trigger time,command) for minute based resolution
# transfer.options - special options to send by TryTransferTo()
# unbind_next - if not null, next key press will be unbound
# undo_buffer - list of (ID, qty, from_part, to_part) pairs reflecting recent changes to deck contents
# undo.pos - current position in undo_buffer when rewinding/forwarding
# username - name of the player
#
# Functions:
#
# See reference manual.
#
# CONSTANTS
# =========
# Z-levels (for deciding which objects should be placed on top of others)
Z_LOBBYCHAT = 1000;
Z_MENU = 100;
Z_SCORE = 99;
Z_ZOOM = 95;
Z_BOOSTER = 90;
Z_PRODUCTMENU = 80;
Z_DLIST = 70;
Z_COLLECTION = 70;
Z_ALERT = 60;
Z_SETASIDE = 40;
Z_HAND = 30;
Z_MBOX = 20;
Z_DECKS = 10;
# Version number of filtering algorithm.
BOOK_FILTER_VERSION="0.11";
# Mininum binary version required to use this script.
MINIMUM_VERSION="0.9.0";
# How many cards in a row at collection
BOOK_ROWS=3;
# How many cards in a column at collection
BOOK_COLUMNS=5;
# Default file extension expected by image files
IMAGE_FORMAT=".jpg";
# Maximum number of simultaneous players.
MAX_PLAYERS=8;
# Maximum number of characters in one message line in pixels.
MAX_MESSAGE=screen.width-10;
# 1: delete key always moves card to my own discard pile
# 0: delete key moves card to discard pile of its controller
DELETE_TO_MINE=0;
# How much we must move a card before removing it from the
# organizational group, when deciding card postions.
CLEAR_GROUP_DISTANCE=10;
# What to display on "keep tapped" cards.
STRING_KEEP_TAPPED="T";
# What to display on "keep untapped" cards.
STRING_KEEP_UNTAPPED="UNT";
# Game specific menu definitions.
GAME_MENU=(,);
# Extra menu entries provided by extension scripts.
EXTRA_MENU=(,);
# Default export format.
DEFAULT_EXPORT_FORMAT="Gccg";
# Color to use for highlighting touched objects.
HIGHLIGHT_COLOR=(150,0,0);
# Named colors
COLORS=(,);
COLORS{'RED'}=(250,0,0);
COLORS{'ORANGE'}=(250,130,30);
COLORS{'YELLOW'}=(220,220,0);
COLORS{'GREEN'}=(0,180,0);
COLORS{'BLUE'}=(20,20,250);
COLORS{'VIOLET'}=(160,0,160);
COLORS{'WHITE'}=(255,255,255);
COLORS{'BLACK'}=(0,0,0);
# Marker colors
MARKER_COLOR=array(10);
MARKER_COLOR[0]="Red";
MARKER_COLOR[1]="Green";
MARKER_COLOR[2]="Blue";
MARKER_COLOR[3]="Orange";
MARKER_COLOR[4]="Yellow";
MARKER_COLOR[5]="Black";
MARKER_COLOR[6]="White";
MARKER_COLOR[7]="Default";
DEFAULT_MARKER_COLOR=7;
# Initialize messagebox highlight
msgboxhighlight.color=(100,200,250,40);
msgboxhighlight.cpcolor=(30,250,30,40);
msgbox.lastcutoff=0;
# Default book order.
BOOK_DEFAULT_SORT=("[age]","[name]");
# Mapping from filter function names to a pair (type,short help text).
FILTER_FUNCTIONS=(,);
# Mapping from attribute types to data types:
# if GAME_ATTRIBUTES{attr}=="i", treat as int type
# if "r", treat as real type
# "s" is default, for string type, and in fact string attributes need not be listed
# It's also possible for this to contain "a:OtherAttr", in which case "attr" is treated as an alias for "OtherAttr".
GAME_ATTRIBUTES=(,);
# Common (server-side) basic table size (independent of the display size)
BASE_TABLE_WIDTH=1280;
BASE_TABLE_HEIGHT=768;
# Which load/save functions should be called? (for compatibility)
if(isfunction("binary_load"))
LOAD_FN="binary_load";
else
LOAD_FN="load";
if(isfunction("binary_save"))
SAVE_FN="binary_save";
else
SAVE_FN="save";
# Standard menu definitions
MENU=(,);
MENU{"Main Menu - "}=((1,"Quit","Ctrl+Q","quit()"),);
MENU{"Main Menu - Offline"}=(
('input!=""',"Copy","Ctrl+C",""),
(isfunction("clpbget"),"Paste","Ctrl+V",""),
(1,"Show/Hide Collection","Ctrl+B",""),
('deck.name!=NULL',"Edit/Hide deck","Ctrl+E",""),
('length(decks)>0',"Select deck","Ctrl+D",""),
(1,"Import deck","Ctrl+I",""),
(1,"Quit","/quit",""),
);
MENU{"Main Menu - Watch"}=(
("abs(2*(mouse.x-screen.width/2)) <= ObjW(msg.box) && mouse.y-5 <= ObjH(msg.box) && mouse.y >5","Select","Ctrl+left click",""),
('input!=""',"Copy","Ctrl+C",""),
(isfunction("clpbget"),"Paste","Ctrl+V",""),
(1,"Show/Hide Collection","Ctrl+B",""),
('deck.name!=NULL',"Edit/Hide deck","Ctrl+E",""),
('length(decks)>0',"Select deck","Ctrl+D",""),
(1,"Import deck","Ctrl+I",""),
(1,"Leave","/quit",""),
);
MENU{"Main Menu - Chat"}=(
("abs(2*(mouse.x-screen.width/2)) <= ObjW(msg.box) && mouse.y-5 <= ObjH(msg.box) && mouse.y >5","Select","Ctrl+left click",""),
('input!=""',"Copy","Ctrl+C",""),
(isfunction("clpbget"),"Paste","Ctrl+V",""),
(1,"Unbind a key binding","/unbind",""),
(1,"List key bindings","/bind",""),
(1,"{hr}","",""),
(1,"Show/Hide Collection","Ctrl+B",""),
(1,"Show/Hide Products","Ctrl+P",""),
(1,"Create new deck","","CreateEmptyDeck()"),
('deck.name!=NULL',"Edit/Hide deck","Ctrl+E",""),
(1,"Import deck","Ctrl+I",""),
('length(decks)>0',"Select deck","Ctrl+D",""),
(1,"Register full set...","","RegisterSubmenu()"),
(1,"Register full playset...","","RegisterPlaysetSubmenu()"),
(1,"{hr}","",""),
(1,"Show players online","/who",""),
("length(room.tables)>0","Describe tables","/tables",""),
(1,"Quit","/quit",""),
);
MENU{"Main Menu - Play"}=(
("abs(2*(mouse.x-screen.width/2)) <= ObjW(msg.box) && mouse.y-5 <= ObjH(msg.box) && mouse.y >5","Select","Ctrl+left click",""),
('input!=""',"Copy","Ctrl+C",""),
(isfunction("clpbget"),"Paste","Ctrl+V",""),
(1,"Unbind a key binding","/unbind",""),
(1,"List key bindings","/bind",""),
(1,"{hr}","",""),
(1,"Untap all","Ctrl+U",""),
(1,"End of my turn","Ctrl+E",""),
(1,"Roll dice","Ctrl+R",""),
('input==""',"Flip a coin","Ctrl+C",""),
(1,"Select counter color...","","CounterSubmenu()"),
(1,"{hr}","",""),
(1,"Declare win","/win",""),
(1,"Declare loss","/lose",""),
(1,"Declare draw","/draw",""),
(1,"Declare undecided","/undecided",""),
(1,"Accept result","/ok",""),
(1,"{hr}","",""),
(1,"Show/Hide deck","","set_attr(deck.box,'visible',!get_attr(deck.box,'visible'))"),
(1,"Show/Hide collection","Ctrl+B",""),
(1,"Save game","/savegame",""),
(1,"Load game","/loadgame",""),
(1,"Delete saved game","/delgame",""),
);
MENU{"Table"}=(
(1,"Sit down","left click",""),
(1,"Play or watch","middle click",""),
(1, "Leave table","/leavetable",""),
);
MENU{"Open Booster"}=(
(1,"Reveal one card","left click",""),
(1,"Reveal all cards","middle click",""),
(1,"{hr}","",""),
('card_back(card.number)!=card.number',"Show card text w/ errata","Ctrl+H",""),
('card_back(card.number)!=card.number',"Find from collection",'EVAL:"/find "+canonical_name(card.number)',""),
(1,"{hr}","",""),
(1,"Close","Esc",'del_cardbox_all_recenter(booster.box)'),
);
MENU{"Hand"}=(
(1,"Reveal/Hide hand","Ctrl+F",""),
(1,"Shuffle hand","Ctrl+S",""),
(1,"Shuffle to the deck","",'Send("Transfer",(length(hand(hand[me])),("hand",me,0),("deck.top",deck))); Send("ShuffleDeck",deck);'),
(1,"Touch","Ctrl+T",""),
(1,"{hr}","",""),
(1,"Big size","","SetHandSize(150)"),
(1,"Normal size","","SetHandSize(100)"),
(1,"Small size","","SetHandSize(66)"),
(1,"Normal layout","","set_attr(object.number,'compact',0)"),
(1,"Wide layout","","set_attr(object.number,'compact',1)"),
);
MENU{"Card Select Box"}=(
(1,"Close","Escape",""),
);
MENU{"Products"}=(
(1,"Close","Escape",""),
);
# Initialize help.
HELP=(,);
HELP{""}=(,);
HELP{"any"}=(,);
HELP{"play"}=(,);
HELP{"chat"}=(,);
HELP{"watch"}=(,);
HELP{"offline"}=(,);
# Help texts from serverside commands.
HELP{"chat"}{"addproduct"}=("n,id,t,prc","add product",("God","Salesman"),
"This command adds one product for sale. The ordering code of the product is '{yellow}id{white} {yellow}t{white}', where {yellow}id{white} is the abbreviation of the card set and {yellow}t{white} is the type of the product ('booster', 'starter', etc.). The ordering code is a string which describes the product for the factory server. Number of the sale items available is {yellow}n{white} and the price of them is {yellow}prc{white} apiece.");
HELP{"chat"}{"ban"}=("player","ban a player",("God","Guard"),
"Without any arguments, this command lists all banned users. Adding one or more player nicks as arguments, this commands adds them to the ban list. When a player is banned, he cannot login in to the game anymore. Additionally, if the banned player is online when this command is issued, he is kicked automatically from the server. See also {orange}/help restrict{white} and {orange}/help unban{white}.");
HELP{"chat"}{"bans"}=("","list bans",NULL,
"This command lists all banned users and restricted domains.");
HELP{"play"}{"bid"}=("bid","place a bid",NULL,
"Simple auction system works as follows: each player places their bids using this command. The bid can be any text. When each player has placed their bids, the auction results are displayed and book-keeping for bidding is reseted to be ready for next bidding.");
HELP{"chat"}{"canceldraft"}=("","cancel a draft",NULL,
"If you've reserved a draft and want to take it back, this command will free up the table to be reclaimed. Privileged users can also use this command with a numeric argument to reclaim a draft table with the given number, no matter who reserved it.");
HELP{"chat"}{"delproduct"}=("id,t","delete product",("God","Salesman"),
"This command removes one product. The ordering code {yellow}id t{white} is the same as in {yellow}/addproduct{white}.");
HELP{"chat"}{"have"}=("player","show player's have list",NULL,
"Asks the meta server for the have list of the given {yellow}player{white}. The have list contains all cards which you have marked as wanted and which are put for sale by the {yellow}player{white}.");
HELP{"chat"}{"grant"}=("player1,player2","copy password",NULL,
"If the {yellow}player2{white} is online, copy the password of {yellow}player1{white} to the {yellow}player2{white}. Every player can grant his or her password to anybody, but only God can grant others' passwords. After the password is copied, the {yellow}player2{white} who received the password, can log in as {yellow}player1{white}.");
HELP{"chat"}{"products"}=("","show products available",NULL,
"List the quantity and the price of each product for sale.");
HELP{"chat"}{"reboot"}=("","reboot the server",("God",),
"Send Quit-message to all players and game servers. After that, reboot the meta server.");
HELP{"chat"}{"register"}=("set","register complete set",NULL,
"If the player has collected all cards of the {yellow}set{white}, he or she is awarded by a bonus. The bonus is $0.50 per individual card in the set. If the player has not yet collected all cards, the number of missing cards is announced. The {yellow}set{white} must be given as an abbreviation of the card set (case insensitive). If the abbreviation is not valid, the list of valid abbreviations are shown.");
HELP{"chat"}{"registerplayset"}=("set","register playset",NULL,
"If the player has already registered the {yellow}set{white}, and has collected a full playset of each card in the set, he or she is awarded by a bonus. The bonus is $2 per distinct card in the set. If the player has not yet collected all cards, the number of missing cards is announced. The {yellow}set{white} must be given as an abbreviation of the card set (case insensitive). If the abbreviation is not valid, the list of valid abbreviations are shown.");
HELP{"chat"}{"removeuser"}=("player","delete user",("God",),
"This command deletes all data of {yellow}player{white}.");
HELP{"chat"}{"reproduce"}=("","add products",("God","Salesman"),
"Check all products. If there is a sold out product, then add a shipment of product with halved availability (compared to the previous shipment) and price increased by 10%.");
HELP{"chat"}{"restrict"}=("domain","restric access",("God","Guard"),
"Without any arguments, this command lists all restrictions currently in effect. Domain name can be exact or it can contain * as a joker character, for example *.cheaters.com. When the restriction is added to the domain, all existing players can connect but new players are not accepted any more. They get a message explaining the situation and how to get an account by email from the server administrator. See also {orange}/help ban{white} and {orange}/help unrestrict{white}.");
HELP{"chat"}{"ro"}=("","restore original deck",NULL,
"You can retrieve the original composition of the registered deck with this command. Be careful when using this command, since it overwrites your current deck with the content of the registered deck. See also {orange}/help rd{white}.");
HELP{"chat"}{"ro2"}=("","restore alternative original deck",NULL,
"You can retrieve the original composition of the alternative registered deck with this command. Be careful when using this command, since it overwrites your current deck with the content of the alternative registered deck. See also {orange}/help rd2{white}.");
HELP{"chat"}{"startdraft"}=("n,setcodes","start a draft",NULL,
"If there is an open draft table available, reserve a draft for {yellow}n{white} players using the chosen products; the server will automatically determine the price to enter the draft based on those products. Set codes can be separated by spaces, commas, hyphens, or slashes. If only one set code is given, it defaults to 3 copies of that set. If your game includes cubes, the additional syntax '/startdraft n cubename cube' is also accepted.");
HELP{"chat"}{"users"}=("pattern","list of users",NULL,
"Show list of all users matching wildcard {yellow}pattern{white} or all users if not given. The total number of users matching is shown instead if the list is too long.");
HELP{"chat"}{"want"}=("player","show player's want list",NULL,
"Asks the meta server for the want list of the given {yellow}player{white}. The have list contains all cards which he or she have marked as wanted. The cards you have for sale or you have more than {yellow}trade_limit{white}, are shown in green.");
HELP{"chat"}{"whisper"}=("player, message","whisper to user",NULL,
"Send a {yellow}message{white} that only the given {yellow}player{white} will receive.");
HELP{"chat"}{"whois"}=("player","show player info",NULL,
"Ask the meta server to describe a {yellow}player{white}. The personal data (realname, email, plan) set by the player is shown as well as his/her wealth and game play history.");
HELP{"chat"}{"kick"}=("player","disconnect player",("God","Guard"),
"This command forces disconnection for {yellow}player{white}.");
HELP{"chat"}{"kicktable"}=("tblnum","disconnect table",("God","Guard"),
"This command forces disconnection for table {yellow}tblnum{white}. Alternatively {orange}/kicktable all{white} removes all tables.");
HELP{"play"}{"savegame"}=("","save your game",NULL,
"Saves your current game status to the disk in the game server. Each player, player pair, player triple, etc. have one personal save file, which is overwritten each time using this command. Saving the game does not end it, but you can declare undecided result and continue later using {yellow}/loadgame{white}. This command is automatically applied when one of the players' network connection dies. See also {orange}/help delgame{white}.");
HELP{"play"}{"loadgame"}=("","restore your game",NULL,
"Searches if there is a saved game for current player(s) and restores it, if found. Note that you must be playing at the same server, where you saved your game - not necessarily at the same table. The game server announces at the beginning of the game, if there is a saved game available for your play group. Restoring the saved game does not remove it from the server; see also {orange}/help delgame{white}.");
HELP{"play"}{"delgame"}=("","delete your saved game",NULL,
"Remove a saved game for the current group of players. This command should be applied to save disk space on a server, when the saved game is not needed anymore.");
HELP{"play"}{"autopass"}=("","force a draft to proceed",NULL,
"If you are at a draft table, and it has been a while since the cards were last passed, you can use this command to force the server to randomly pick for the players who haven't made their most recent pick.");
HELP{"chat"}{"yell"}=("message","send message to all",NULL,
"This command echoes a {yellow}message{white} to all players, even those who are currently playing.");
HELP{"chat"}{"unban"}=("player","unban a player",("God","Guard"),
"Remove a player from the ban list. See also {orange}/help ban{white}.");
HELP{"chat"}{"unrestrict"}=("domain","remove restriction",("God","Guard"),
"Remove a domain from the restriction list. See also {orange}/help restrict{white}.");
HELP{"any"}{"rtfm"}=("","give some info",NULL,
"Show a link {green}http://gccg.sourceforge.net/pages/faq.php{white} for newbies. Optional arguments are added after the link in parenthesis, e.g. section number to check out.");
HELP{"chat"}{"faq"}=("entry","add FAQ entries",NULL,
"This command displays an {yellow}entry{white} using {cyan}cyan{white} text and adds a line to the FAQ proposals. All proposals are examined manually and added to the FAQ if they are useful. Please add questions starting with {green}Q:{white} and answers starting with {green}A:{white}. Without arguments, show current proposals for the FAQ.");
HELP{"chat"}{"giveticket"}=("u,n,s,p","give boosters",("God","Salesman","Judge"),
"Give {yellow}n{white} free product tickects, each allowing to buy one product {yellow}p{white} of the set {yellow}s{white} without charge, to the player {yellow}u{white}.");
HELP{"chat"}{"info"}=("player,[info]","set info field",("God","Judge"),
"Set, unset or display the system information for a {yellow}player{white}. Without {yellow}info{white} text, it displays the current system information field for the player. If the {yellow}info{white} text is {green}NULL{white}, the information is removed. Otherwise it is taken as a new value. The system information field is displayed in {green}/whois{white} query.");
# Callback table for protocol.
function=(,);
function{"add_text"}="add_text";
function{"AddMarker"}="AddMarker";
function{"AddRoomPlayer"}="AddRoomPlayer";
function{"AddRoomTable"}="AddRoomTable";
function{"Attach"}="Attach";
function{"Bid"}="Bid";
function{"Buy"}="Buy";
function{"ClearGame"}="ClearGame";
function{"ConnectServer"}="ConnectServer";
function{"CreateActive"}="CreateActive";
function{"CreatePlayerIcon"}="CreatePlayerIcon";
function{"CreateDeck"}="CreateDeck";
function{"CreateHand"}="CreateHand";
function{"DeckDelTable"}="DeckDelTable";
function{"del_all_texts"}="del_all_texts";
function{"DelActive"}="DelActive";
function{"DelDeck"}="DelDeck";
function{"DelDeckBottom"}="DelDeckBottom";
function{"DelDeckTop"}="DelDeckTop";
function{"DelHand"}="DelHand";
function{"DelMarker"}="DelMarker";
function{"DelRoomPlayer"}="DelRoomPlayer";
function{"DelRoomTable"}="DelRoomTable";
function{"DelTable"}="DelTable";
function{"Detach"}="Detach";
function{"EndGame"}="_EndGame";
function{"Flash"}="Flash";
function{"GameSetup"}="GameSetup";
function{"InitializeGame"}="_InitializeGame";
function{"JoinTable"}="JoinTable";
function{"LeaveTable"}="LeaveTable";
function{"LeaveTableToChat"}="LeaveTableToChat";
function{"Lower"}="Lower";
function{"Message"}="Message";
function{"MoveObject"}="MoveObject";
function{"Null"}="Null";
function{"Play"}="Play";
function{"PlaySound"}="PlaySound";
function{"PutActive"}="PutActive";
function{"PutDeck"}="PutDeckTop";
function{"PutDeckBottom"}="PutDeckBottom";
function{"PutHand"}="PutHand";
function{"PutTable"}="PutTable";
function{"Quit"}="Quit";
function{"Raise"}="Raise";
function{"ReplaceTable"}="ReplaceTable";
function{"RestoreDeck"}="RestoreDeck";
function{"Rotate"}="Rotate";
function{"Score"}="Score";
function{"SearchDeck"}="SearchDeck";
function{"SetActive"}="SetActive";
function{"SetCardbook"}="SetCardbook";
function{"SetDeck"}="SetDeck";
function{"SetDeckTop"}="SetDeckTop";
function{"SetHand"}="SetHand";
function{"SetJoinGame"}="SetJoinGame";
function{"SetMe"}="SetMe";
function{"SetMyName"}="SetMyName";
function{"SetMode"}="SetMode";
function{"SetMoney"}="SetMoney";
function{"SetOption"}="SetOption";
function{"SetPassword"}="SetPassword";
function{"SetPrice"}="SetPrice";
function{"SetProducts"}="SetProducts";
function{"Special"}="Special";
function{"StartGame"}="_StartGame";
function{"Times"}="Times";
function{"Torrent"}="Torrent";
function{"HaveList"}="HaveList";
function{"WantList"}="WantList";
def playerhas {
if(playerhave{ARG[0]} != NULL)
return (find(ARG[1],playerhave{ARG[0]}) != NULL);
else
return(0);
}
def playerwants {
if(playerwant{ARG[0]} != NULL)
return (find(ARG[1],playerwant{ARG[0]}) != NULL);
else
return(0);
}
modifier=" ";
#
# FUNCTIONS WAITING FOR C++ IMPLEMENTATION
# ========================================
#
# subobjects(object number) - Return all direct subobjects of the object.
#
def subobjects
{
return((object_data(ARG))[5]);
}
#
# root_object(object number) - Return the root object of the object.
#
def root_object
{
if((object_data(ARG))[4])
return(root_object((object_data(ARG))[4]));
else
return(ARG);
}
#
# is_object(object number) - Return 1 if the object exists.
#
def is_object
{
return(object_data(ARG)!=NULL);
}
#
# FUNCTIONS
# =========
#
# text_parser(text) - Helper function for PlayCommandSettext
#
def text_parser
{
if(length(ARG)>1 && toint(ARG[1])>0)
{
push(card_width);
push(characters);
push(clean_string);
push(current_line);
push(new_word);
push(new_string);
push(composite_string);
push(last_font);
push(last_color);
push(last_size);
push(last_align);
push(last_format);
push(i);
card_width=toint(ARG[1])-4;
characters=split(ARG[0],"");
composite_string=(,);
clean_string="";
new_word="";
last_font="{font0}";
last_color="{red}";
last_size="{sz12}";
last_align="{center}";
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format;
for(i)(length(characters))
{
new_string=characters[i];
if(characters[i]=="{")
{
while(characters[i]!="}" && i<length(characters)-1)
{
i=i+1;
new_string=new_string+characters[i];
}
if(find("font",new_string)==1 && (toint(strreplace(strreplace(new_string,"{font",""),"}",""))>0 || new_string=="{font0}"))
{
last_font=new_string;
}
else if((count(",",split(new_string,""))==2 && (toint(join(split(new_string,"")-(",","{","}"),""))>0 || join(split(new_string,"")-(",","{","}"),"")=="000")) || count(new_string,("{red}","{green}","{black}","{blue}","{yellow}","{white}","{brown}","{gold}","{gray}","{magenta}","{orange}","{cyan}")))
{
last_color=new_string;
}
else if(find("sz",new_string)==1 && toint(strreplace(strreplace(new_string,"{sz",""),"}",""))>0)
{
if(toint(strreplace(strreplace(new_string,"{sz",""),"}",""))>100)
{
Msg("{red}Maximum size allowed is 100. Excessive size"+strreplace(strreplace(new_string,"{sz",""),"}","")+" was set to 100.");
new_string="{sz100}";
}
last_size=new_string;
}
else if(new_string=="{left}" || new_string=="{right}" || new_string=="{center}")
{
last_align=new_string;
}
else if(new_string=="{reset}")
{
last_font="{font0}";
last_color="{red}";
last_size="{sz12}";
last_align="{center}";
new_string="";
}
else if(new_string=="{hr}")
{
Msg("{red}Please, refrain from using the {lb}hr{rb} tag. The tag has been removed.");
new_string="";
}
else
clean_string=clean_string+new_string;
}
if(text_width(0,12,new_word+new_string)>card_width)
{
composite_string=composite_string+(current_line,last_format+new_word);
new_word="";
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format+new_string;
}
else if(characters[i]==" ")
{
if(text_width(0,12,current_line+new_word)<card_width)
{
current_line=current_line+new_word;
new_word="";
if(text_width(0,12,current_line+" ")<card_width)
current_line=current_line+" ";
if(i>=length(characters)-1)
composite_string=composite_string+(current_line,);
}
else
{
composite_string=composite_string+(current_line,);
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format+new_word+" ";
new_word="";
}
}
else if(new_string=="\n")
{
if(text_width(0,12,current_line+new_word)<card_width)
{
current_line=current_line+new_word;
new_word="";
composite_string=composite_string+(current_line,);
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format+new_word+" ";
}
else
{
composite_string=composite_string+(current_line,last_format+new_word);
new_word="";
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format;
}
}
else if(i>=length(characters)-1)
{
if(text_width(0,12,current_line+new_word+new_string)<card_width)
current_line=current_line+new_word+new_string;
else
{
composite_string=composite_string+(current_line,);
last_format=last_align+last_size+last_color+last_font+"{shadow}";
current_line=last_format+new_word+new_string;
}
composite_string=composite_string+(current_line,);
}
else
{
new_word=new_word+new_string;
}
if(length(new_string)==1 && new_string!="\n")
clean_string=clean_string+new_string;
}
return(composite_string+(clean_string,));
i=pop();
last_format=pop();
last_align=pop();
last_size=pop();
last_color=pop();
last_font=pop();
composite_string=pop();
new_string=pop();
new_word=pop();
current_line=pop();
clean_string=pop();
characters=pop();
card_width=pop();
}
}
#
# PlayCommandText(text) - Appends the given text to the card under the mouse pointer.
#
def PlayCommandText
{
if(!length(ARG))
{
Msg("{red}Some text is required, see /help text.");
}
else
{
push(target);
# Context menu compatibility.
if((menu.shortcut=="/text "+strreplace(input,"{|}","") || menu.shortcut=="/settext "+strreplace(input,"{|}","")) && menu.object.number!=NULL)
{
if(object_type(menu.object.number)=="cardinplay")
target=menu.object.number;
else
target=object.number;
}
else
target=object.number;
if(target!=NULL)
{
if(object_type(target)=="cardinplay")
{
push(card_width);
push(str);
str=join(ARG," ");
card_width=min(((object_data(target))[2],(object_data(target))[3],));
str=text_parser(str,card_width);
Send("WriteText",(target,str));
if(join(ARG," ")==strreplace(input,"{|}",""))
{
InputNewline();
}
str=pop();
card_width=pop();
}
else
{
Msg("{red}You can only add text to cards in play.");
}
}
else
{
Msg("{red}You can only add text to cards in play.");
}
target=pop();
}
}
#
# PlayCommandTx(text) - Alias for /text.
#
def PlayCommandTx
{
PlayCommandText(ARG);
}
#
# PlayCommandDeltext() - Removes all text from the card under the mouse pointer.
#
def PlayCommandDeltext
{
push(target);
# Context menu compatibility.
if((menu.shortcut=="/deltext" || menu.shortcut=="/settext "+strreplace(input,"{|}","")) && menu.object.number!=NULL)
{
if(object_type(menu.object.number)=="cardinplay")
target=menu.object.number;
else
target=object.number;
}
else
target=object.number;
if(target!=NULL)
{
if(object_type(target)=="cardinplay")
{
Send("WriteText",(target,NULL));
}
else
{
Msg("{red}You can only remove text from cards in play.");
}
}
else
{
Msg("{red}You can only remove text from cards in play.");
}
target=pop();
}
#
# PlayCommandDtx() - Alias for /deltext.
#
def PlayCommandDtx
{
PlayCommandDeltext();
}
#
# PlayCommandSettext(text) - Clears previous text lines and writes new text on the card under the mouse pointer.
#
def PlayCommandSettext
{
push(target);
# Context menu compatibility.
if(menu.shortcut=="/settext "+strreplace(input,"{|}","") && menu.object.number!=NULL)
{
if(object_type(menu.object.number)=="cardinplay")
target=menu.object.number;
else
target=object.number;
}
else
target=object.number;
if(target!=NULL)
{
if(object_type(target)=="cardinplay")
{
PlayCommandDeltext();
PlayCommandText(ARG)
}
else
{
Msg("{red}You can only write text on cards in play.");
}
}
else
{
Msg("{red}You can only write text on cards in play.");
}
target=pop();
}
#
# PlayCommandStx(text) - Alias for /settext.
#
def PlayCommandStx
{
PlayCommandSettext(ARG);
}
HELP{"play"}{"text"}=("text","Append text to a card",NULL,
"Write {yellow}text{white} on the card under the mouse pointer.");
HELP{"play"}{"tx"}=("text","Append text to a card",NULL,
"Alias for /text.");
HELP{"play"}{"deltext"}=("","Remove all text from a card",NULL,
"Remove all text from the card under the mouse pointer.");
HELP{"play"}{"dx"}=("","Remove all text from a card",NULL,
"Alias for /deltext.");
HELP{"play"}{"settext"}=("text","Write new text on a card",NULL,
"Clear previous text lines and write {yellow}text{white} on the card under the mouse pointer.");
HELP{"play"}{"stx"}=("text","Write new text on a card",NULL,
"Alias for /settext.");
#
# msgbox_isvisible()- Helper function for Shift + Up/Down, checks whether the currently selected message is visible in the message box.
#
def msgbox_isvisible
{
push(current_height);
push(i);
push(found);
found=0;
current_height=text_height(0,12,msgboxhistory[max(length(msgboxhistory)-msgbox_scroll(msg.box,0)-1,0)])-1;
i=1;
while(current_height<ObjH(msg.box) && found==0 && length(msgboxhistory)-msgbox_scroll(msg.box,0)-i>0)